diff --git a/arch-config/.config/calibre/conversion/azw3_output.py b/arch-config/.config/calibre/conversion/azw3_output.py new file mode 100644 index 00000000..681a2974 --- /dev/null +++ b/arch-config/.config/calibre/conversion/azw3_output.py @@ -0,0 +1,8 @@ +json:{ + "prefer_author_sort": false, + "toc_title": null, + "mobi_toc_at_start": false, + "dont_compress": false, + "no_inline_toc": false, + "share_not_sync": false +} \ No newline at end of file diff --git a/arch-config/.config/calibre/conversion/comic_input.py b/arch-config/.config/calibre/conversion/comic_input.py new file mode 100644 index 00000000..c3bde18c --- /dev/null +++ b/arch-config/.config/calibre/conversion/comic_input.py @@ -0,0 +1,17 @@ +json:{ + "colors": 0, + "dont_normalize": false, + "keep_aspect_ratio": false, + "right2left": false, + "despeckle": false, + "no_sort": false, + "no_process": false, + "landscape": false, + "dont_sharpen": false, + "disable_trim": false, + "wide": false, + "output_format": "png", + "dont_grayscale": false, + "comic_image_size": null, + "dont_add_comic_pages_to_toc": false +} \ No newline at end of file diff --git a/arch-config/.config/calibre/conversion/debug.py b/arch-config/.config/calibre/conversion/debug.py new file mode 100644 index 00000000..e69de29b diff --git a/arch-config/.config/calibre/conversion/docx_input.py b/arch-config/.config/calibre/conversion/docx_input.py new file mode 100644 index 00000000..ffa08773 --- /dev/null +++ b/arch-config/.config/calibre/conversion/docx_input.py @@ -0,0 +1,5 @@ +json:{ + "docx_no_cover": false, + "docx_no_pagebreaks_between_notes": false, + "docx_inline_subsup": false +} \ No newline at end of file diff --git a/arch-config/.config/calibre/conversion/docx_output.py b/arch-config/.config/calibre/conversion/docx_output.py new file mode 100644 index 00000000..41c1d268 --- /dev/null +++ b/arch-config/.config/calibre/conversion/docx_output.py @@ -0,0 +1,11 @@ +json:{ + "docx_page_size": "letter", + "docx_custom_page_size": null, + "docx_no_cover": false, + "docx_no_toc": false, + "docx_page_margin_left": 72.0, + "docx_page_margin_top": 72.0, + "docx_page_margin_right": 72.0, + "docx_page_margin_bottom": 72.0, + "preserve_cover_aspect_ratio": false +} \ No newline at end of file diff --git a/arch-config/.config/calibre/conversion/epub_output.py b/arch-config/.config/calibre/conversion/epub_output.py new file mode 100644 index 00000000..cce8e2cf --- /dev/null +++ b/arch-config/.config/calibre/conversion/epub_output.py @@ -0,0 +1,12 @@ +json:{ + "dont_split_on_page_breaks": false, + "flow_size": 0, + "no_default_epub_cover": false, + "no_svg_cover": false, + "epub_inline_toc": false, + "epub_toc_at_end": false, + "toc_title": null, + "preserve_cover_aspect_ratio": false, + "epub_flatten": false, + "epub_version": "3" +} \ No newline at end of file diff --git a/arch-config/.config/calibre/conversion/fb2_input.py b/arch-config/.config/calibre/conversion/fb2_input.py new file mode 100644 index 00000000..8d80593c --- /dev/null +++ b/arch-config/.config/calibre/conversion/fb2_input.py @@ -0,0 +1,3 @@ +json:{ + "no_inline_fb2_toc": false +} \ No newline at end of file diff --git a/arch-config/.config/calibre/conversion/fb2_output.py b/arch-config/.config/calibre/conversion/fb2_output.py new file mode 100644 index 00000000..c5559969 --- /dev/null +++ b/arch-config/.config/calibre/conversion/fb2_output.py @@ -0,0 +1,4 @@ +json:{ + "sectionize": "files", + "fb2_genre": "antique" +} \ No newline at end of file diff --git a/arch-config/.config/calibre/conversion/heuristics.py b/arch-config/.config/calibre/conversion/heuristics.py new file mode 100644 index 00000000..d5bd50c4 --- /dev/null +++ b/arch-config/.config/calibre/conversion/heuristics.py @@ -0,0 +1,13 @@ +json:{ + "enable_heuristics": false, + "markup_chapter_headings": true, + "italicize_common_cases": true, + "fix_indents": true, + "html_unwrap_factor": 0.4, + "unwrap_lines": true, + "delete_blank_paragraphs": true, + "format_scene_breaks": true, + "replace_scene_breaks": "", + "dehyphenate": true, + "renumber_headings": true +} \ No newline at end of file diff --git a/arch-config/.config/calibre/conversion/htmlz_output.py b/arch-config/.config/calibre/conversion/htmlz_output.py new file mode 100644 index 00000000..a756f397 --- /dev/null +++ b/arch-config/.config/calibre/conversion/htmlz_output.py @@ -0,0 +1,5 @@ +json:{ + "htmlz_css_type": "class", + "htmlz_class_style": "external", + "htmlz_title_filename": false +} \ No newline at end of file diff --git a/arch-config/.config/calibre/conversion/kfx_input.py b/arch-config/.config/calibre/conversion/kfx_input.py new file mode 100644 index 00000000..69e74354 --- /dev/null +++ b/arch-config/.config/calibre/conversion/kfx_input.py @@ -0,0 +1,3 @@ +json:{ + "allow_conversion_with_errors": true +} \ No newline at end of file diff --git a/arch-config/.config/calibre/conversion/look_and_feel.py b/arch-config/.config/calibre/conversion/look_and_feel.py new file mode 100644 index 00000000..eaecbe36 --- /dev/null +++ b/arch-config/.config/calibre/conversion/look_and_feel.py @@ -0,0 +1,26 @@ +json:{ + "change_justification": "original", + "extra_css": null, + "base_font_size": 0.0, + "font_size_mapping": null, + "line_height": 0.0, + "minimum_line_height": 120.0, + "embed_font_family": null, + "embed_all_fonts": false, + "subset_embedded_fonts": false, + "smarten_punctuation": false, + "unsmarten_punctuation": false, + "disable_font_rescaling": false, + "insert_blank_line": false, + "remove_paragraph_spacing": false, + "remove_paragraph_spacing_indent_size": 1.5, + "insert_blank_line_size": 0.5, + "input_encoding": null, + "filter_css": "", + "expand_css": false, + "asciiize": false, + "keep_ligatures": false, + "linearize_tables": false, + "transform_css_rules": "[]", + "transform_html_rules": "[]" +} \ No newline at end of file diff --git a/arch-config/.config/calibre/conversion/lrf_output.py b/arch-config/.config/calibre/conversion/lrf_output.py new file mode 100644 index 00000000..10bd26df --- /dev/null +++ b/arch-config/.config/calibre/conversion/lrf_output.py @@ -0,0 +1,13 @@ +json:{ + "wordspace": 2.5, + "header": false, + "header_format": "%t by %a", + "minimum_indent": 0.0, + "serif_family": null, + "render_tables_as_images": false, + "sans_family": null, + "mono_family": null, + "text_size_multiplier_for_rendered_tables": 1.0, + "autorotation": false, + "header_separation": 0.0 +} \ No newline at end of file diff --git a/arch-config/.config/calibre/conversion/metadata.py b/arch-config/.config/calibre/conversion/metadata.py new file mode 100644 index 00000000..e69de29b diff --git a/arch-config/.config/calibre/conversion/mobi_output.py b/arch-config/.config/calibre/conversion/mobi_output.py new file mode 100644 index 00000000..f9c99dcb --- /dev/null +++ b/arch-config/.config/calibre/conversion/mobi_output.py @@ -0,0 +1,12 @@ +json:{ + "prefer_author_sort": false, + "toc_title": null, + "mobi_keep_original_images": false, + "mobi_ignore_margins": false, + "mobi_toc_at_start": false, + "dont_compress": false, + "no_inline_toc": false, + "share_not_sync": false, + "personal_doc": "[PDOC]", + "mobi_file_type": "old" +} \ No newline at end of file diff --git a/arch-config/.config/calibre/conversion/page_setup.py b/arch-config/.config/calibre/conversion/page_setup.py new file mode 100644 index 00000000..d4b5cfa0 --- /dev/null +++ b/arch-config/.config/calibre/conversion/page_setup.py @@ -0,0 +1,8 @@ +json:{ + "margin_top": 5.0, + "margin_left": 5.0, + "margin_right": 5.0, + "margin_bottom": 5.0, + "input_profile": "default", + "output_profile": "tablet" +} \ No newline at end of file diff --git a/arch-config/.config/calibre/conversion/pdb_output.py b/arch-config/.config/calibre/conversion/pdb_output.py new file mode 100644 index 00000000..2a92babe --- /dev/null +++ b/arch-config/.config/calibre/conversion/pdb_output.py @@ -0,0 +1,5 @@ +json:{ + "format": "doc", + "inline_toc": false, + "pdb_output_encoding": "cp1252" +} \ No newline at end of file diff --git a/arch-config/.config/calibre/conversion/pdf_input.py b/arch-config/.config/calibre/conversion/pdf_input.py new file mode 100644 index 00000000..f2a2b156 --- /dev/null +++ b/arch-config/.config/calibre/conversion/pdf_input.py @@ -0,0 +1,4 @@ +json:{ + "no_images": false, + "unwrap_factor": 0.45 +} \ No newline at end of file diff --git a/arch-config/.config/calibre/conversion/pdf_output.py b/arch-config/.config/calibre/conversion/pdf_output.py new file mode 100644 index 00000000..b84c5206 --- /dev/null +++ b/arch-config/.config/calibre/conversion/pdf_output.py @@ -0,0 +1,26 @@ +json:{ + "use_profile_size": false, + "paper_size": "letter", + "custom_size": null, + "pdf_hyphenate": false, + "preserve_cover_aspect_ratio": false, + "pdf_serif_family": "Nimbus Roman", + "unit": "inch", + "pdf_sans_family": "Nimbus Sans [UKWN]", + "pdf_mono_family": "Nimbus Mono PS", + "pdf_standard_font": "serif", + "pdf_default_font_size": 20, + "pdf_mono_font_size": 16, + "pdf_page_numbers": false, + "pdf_footer_template": null, + "pdf_header_template": null, + "pdf_add_toc": false, + "toc_title": null, + "pdf_page_margin_left": 72.0, + "pdf_page_margin_top": 72.0, + "pdf_page_margin_right": 72.0, + "pdf_page_margin_bottom": 72.0, + "pdf_use_document_margins": false, + "pdf_page_number_map": null, + "pdf_odd_even_offset": 0.0 +} \ No newline at end of file diff --git a/arch-config/.config/calibre/conversion/pmlz_output.py b/arch-config/.config/calibre/conversion/pmlz_output.py new file mode 100644 index 00000000..30cf9fe3 --- /dev/null +++ b/arch-config/.config/calibre/conversion/pmlz_output.py @@ -0,0 +1,5 @@ +json:{ + "inline_toc": false, + "full_image_depth": false, + "pml_output_encoding": "cp1252" +} \ No newline at end of file diff --git a/arch-config/.config/calibre/conversion/rb_output.py b/arch-config/.config/calibre/conversion/rb_output.py new file mode 100644 index 00000000..b2597a89 --- /dev/null +++ b/arch-config/.config/calibre/conversion/rb_output.py @@ -0,0 +1,3 @@ +json:{ + "inline_toc": false +} \ No newline at end of file diff --git a/arch-config/.config/calibre/conversion/rtf_input.py b/arch-config/.config/calibre/conversion/rtf_input.py new file mode 100644 index 00000000..b1f4b9a7 --- /dev/null +++ b/arch-config/.config/calibre/conversion/rtf_input.py @@ -0,0 +1,3 @@ +json:{ + "ignore_wmf": false +} \ No newline at end of file diff --git a/arch-config/.config/calibre/conversion/search_and_replace.py b/arch-config/.config/calibre/conversion/search_and_replace.py new file mode 100644 index 00000000..374755cc --- /dev/null +++ b/arch-config/.config/calibre/conversion/search_and_replace.py @@ -0,0 +1,9 @@ +json:{ + "search_replace": "[]", + "sr1_search": null, + "sr1_replace": null, + "sr2_search": null, + "sr2_replace": null, + "sr3_search": null, + "sr3_replace": null +} \ No newline at end of file diff --git a/arch-config/.config/calibre/conversion/snb_output.py b/arch-config/.config/calibre/conversion/snb_output.py new file mode 100644 index 00000000..febf1fdb --- /dev/null +++ b/arch-config/.config/calibre/conversion/snb_output.py @@ -0,0 +1,6 @@ +json:{ + "snb_insert_empty_line": false, + "snb_dont_indent_first_line": false, + "snb_hide_chapter_name": false, + "snb_full_screen": false +} \ No newline at end of file diff --git a/arch-config/.config/calibre/conversion/structure_detection.py b/arch-config/.config/calibre/conversion/structure_detection.py new file mode 100644 index 00000000..ecd37117 --- /dev/null +++ b/arch-config/.config/calibre/conversion/structure_detection.py @@ -0,0 +1,9 @@ +json:{ + "chapter": "//*[((name()='h1' or name()='h2') and re:test(., '\\s*((chapter|book|section|part)\\s+)|((prolog|prologue|epilogue)(\\s+|$))', 'i')) or @class = 'chapter']", + "chapter_mark": "pagebreak", + "start_reading_at": null, + "remove_first_image": false, + "remove_fake_margins": true, + "insert_metadata": false, + "page_breaks_before": "//*[name()='h1' or name()='h2']" +} \ No newline at end of file diff --git a/arch-config/.config/calibre/conversion/toc.py b/arch-config/.config/calibre/conversion/toc.py new file mode 100644 index 00000000..fbfd23c3 --- /dev/null +++ b/arch-config/.config/calibre/conversion/toc.py @@ -0,0 +1,11 @@ +json:{ + "level1_toc": null, + "level2_toc": null, + "level3_toc": null, + "toc_threshold": 6, + "max_toc_links": 50, + "no_chapters_in_toc": false, + "use_auto_toc": false, + "toc_filter": null, + "duplicate_links_in_toc": false +} \ No newline at end of file diff --git a/arch-config/.config/calibre/conversion/txt_input.py b/arch-config/.config/calibre/conversion/txt_input.py new file mode 100644 index 00000000..663b335e --- /dev/null +++ b/arch-config/.config/calibre/conversion/txt_input.py @@ -0,0 +1,7 @@ +json:{ + "paragraph_type": "auto", + "formatting_type": "auto", + "markdown_extensions": "footnotes, tables, toc", + "preserve_spaces": false, + "txt_in_remove_indents": false +} \ No newline at end of file diff --git a/arch-config/.config/calibre/conversion/txt_output.py b/arch-config/.config/calibre/conversion/txt_output.py new file mode 100644 index 00000000..18db2d8e --- /dev/null +++ b/arch-config/.config/calibre/conversion/txt_output.py @@ -0,0 +1,11 @@ +json:{ + "newline": "system", + "max_line_length": 0, + "force_max_line_length": false, + "inline_toc": false, + "txt_output_formatting": "plain", + "keep_links": false, + "keep_image_references": false, + "keep_color": false, + "txt_output_encoding": "utf-8" +} \ No newline at end of file diff --git a/arch-config/.config/calibre/conversion/txtz_output.py b/arch-config/.config/calibre/conversion/txtz_output.py new file mode 100644 index 00000000..18db2d8e --- /dev/null +++ b/arch-config/.config/calibre/conversion/txtz_output.py @@ -0,0 +1,11 @@ +json:{ + "newline": "system", + "max_line_length": 0, + "force_max_line_length": false, + "inline_toc": false, + "txt_output_formatting": "plain", + "keep_links": false, + "keep_image_references": false, + "keep_color": false, + "txt_output_encoding": "utf-8" +} \ No newline at end of file diff --git a/arch-config/.config/calibre/customize.py.json b/arch-config/.config/calibre/customize.py.json new file mode 100644 index 00000000..a8f07670 --- /dev/null +++ b/arch-config/.config/calibre/customize.py.json @@ -0,0 +1,20 @@ +{ + "disabled_plugins": { + "__class__": "set", + "__value__": [] + }, + "enabled_plugins": { + "__class__": "set", + "__value__": [ + "DeDRM" + ] + }, + "filetype_mapping": {}, + "plugin_customization": {}, + "plugins": { + "DeACSM": "/home/marc/.config/calibre/plugins/DeACSM.zip", + "DeDRM": "/home/marc/.config/calibre/plugins/DeDRM.zip", + "KFX Input": "/home/marc/.config/calibre/plugins/KFX Input.zip", + "Obok DeDRM": "/home/marc/.config/calibre/plugins/Obok DeDRM.zip" + } +} \ No newline at end of file diff --git a/arch-config/.config/calibre/dynamic.pickle.json b/arch-config/.config/calibre/dynamic.pickle.json new file mode 100644 index 00000000..c2005d04 --- /dev/null +++ b/arch-config/.config/calibre/dynamic.pickle.json @@ -0,0 +1,42 @@ +{ + "DeDRMexport_Kindle_for_Mac_and_PC_Key_keys": "/home/marc/Downloads/default_key.k4i", + "DeDRMimport_Adobe_Digital_Editions_Key_keys": "/home/marc/Nextcloud/backups", + "Export ADE activation files": "/home/marc/Nextcloud/backups/adobe_account_backup_uuid_2d6cfbec-33fd-43ca-bcf9-e8b281114a17.zip", + "Export ADE keys": "/home/marc/Nextcloud/backups/adobe_uuid_2d6cfbec-33fd-43ca-bcf9-e8b281114a17.der", + "add a plugin dialog": "/home/marc/Downloads", + "add books dialog dir": "/home/marc/Downloads", + "add books dialog dir-last-used-filter-spec-all-files": false, + "database location dialog": "/home/marc/Nextcloud/Books", + "library_delete_books_again": false, + "notified-version-updates": { + "__class__": "set", + "__value__": [ + "5.25", + "6.0", + "5.28", + "5.24" + ] + }, + "recursive book import root dir dialog": "/home/marc/Nextcloud/Books/Unterhaltung", + "save to disk dialog": "/home/marc/Downloads", + "sort_history": [ + [ + "title", + true + ], + [ + "series", + true + ], + [ + "title", + true + ], + [ + "timestamp", + false + ] + ], + "welcome_wizard_device": "default", + "welcome_wizard_was_run": true +} \ No newline at end of file diff --git a/arch-config/.config/calibre/fonts/scanner_cache.json b/arch-config/.config/calibre/fonts/scanner_cache.json new file mode 100644 index 00000000..23056000 --- /dev/null +++ b/arch-config/.config/calibre/fonts/scanner_cache.json @@ -0,0 +1,159485 @@ +{ + "fonts": { + "/home/marc/.local/share/fonts/Unknown Vendor/TrueType/Iosevka/Iosevka_Regular.ttf||261036:1606154803.798966": { + "family_name": "Iosevka", + "font-family": "Iosevka", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Iosevka", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 5, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/home/marc/.local/share/fonts/Unknown Vendor/TrueType/Iosevka/Iosevka_Regular.ttf", + "preferred_family_name": "Iosevka", + "preferred_subfamily_name": "Regular", + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/home/marc/.local/share/fonts/Unknown Vendor/TrueType/icomoon-feather/icomoon_feather_Regular.ttf||65208:1606154803.797966": { + "family_name": "icomoon-feather", + "font-family": "icomoon-feather", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "icomoon-feather", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/home/marc/.local/share/fonts/Unknown Vendor/TrueType/icomoon-feather/icomoon_feather_Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/home/marc/.local/share/fonts/all-the-icons.ttf||44732:1649690147.9776103": { + "family_name": "all-the-icons", + "font-family": "all-the-icons", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "all-the-icons", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/home/marc/.local/share/fonts/all-the-icons.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/home/marc/.local/share/fonts/file-icons.ttf||489672:1649690147.8116393": { + "family_name": "file-icons", + "font-family": "file-icons", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "file-icons", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/home/marc/.local/share/fonts/file-icons.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/home/marc/.local/share/fonts/fontawesome.ttf||152796:1649690147.5606835": { + "family_name": "FontAwesome", + "font-family": "FontAwesome", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "FontAwesome Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/home/marc/.local/share/fonts/fontawesome.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/home/marc/.local/share/fonts/material-design-icons.ttf||128180:1649690147.0187786": { + "family_name": "Material Icons", + "font-family": "Material Icons", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Material Icons", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 5, + 3, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/home/marc/.local/share/fonts/material-design-icons.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/home/marc/.local/share/fonts/octicons.ttf||52544:1649690147.364718": { + "family_name": "github-octicons", + "font-family": "github-octicons", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 8, + "full_name": "github-octicons", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 0, + 5, + 3, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/home/marc/.local/share/fonts/octicons.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/home/marc/.local/share/fonts/weathericons.ttf||99564:1649690147.1897485": { + "family_name": "Weather Icons", + "font-family": "Weather Icons", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 4, + "full_name": "Weather Icons Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 5, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/home/marc/.local/share/fonts/weathericons.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/calibre/fonts/liberation/LiberationMono-Bold.ttf||307996:1633027421.0": { + "family_name": "Liberation Mono", + "font-family": "Liberation Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Liberation Mono Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 7, + 7, + 9, + 2, + 2, + 5, + 2, + 4, + 4 + ], + "path": "/usr/share/calibre/fonts/liberation/LiberationMono-Bold.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/calibre/fonts/liberation/LiberationMono-BoldItalic.ttf||284068:1633027421.0": { + "family_name": "Liberation Mono", + "font-family": "Liberation Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Liberation Mono Bold Italic", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 7, + 7, + 9, + 2, + 2, + 5, + 9, + 4, + 4 + ], + "path": "/usr/share/calibre/fonts/liberation/LiberationMono-BoldItalic.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/calibre/fonts/liberation/LiberationMono-Italic.ttf||281536:1633027421.0": { + "family_name": "Liberation Mono", + "font-family": "Liberation Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Liberation Mono Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 7, + 4, + 9, + 2, + 2, + 5, + 9, + 4, + 4 + ], + "path": "/usr/share/calibre/fonts/liberation/LiberationMono-Italic.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/calibre/fonts/liberation/LiberationMono-Regular.ttf||319508:1633027421.0": { + "family_name": "Liberation Mono", + "font-family": "Liberation Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Liberation Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 7, + 4, + 9, + 2, + 2, + 5, + 2, + 4, + 4 + ], + "path": "/usr/share/calibre/fonts/liberation/LiberationMono-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/calibre/fonts/liberation/LiberationSans-Bold.ttf||414456:1633027421.0": { + "family_name": "Liberation Sans", + "font-family": "Liberation Sans", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Liberation Sans Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 7, + 4, + 2, + 2, + 2, + 2, + 2, + 4 + ], + "path": "/usr/share/calibre/fonts/liberation/LiberationSans-Bold.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/calibre/fonts/liberation/LiberationSans-BoldItalic.ttf||408996:1633027421.0": { + "family_name": "Liberation Sans", + "font-family": "Liberation Sans", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Liberation Sans Bold Italic", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 7, + 4, + 2, + 2, + 2, + 9, + 2, + 4 + ], + "path": "/usr/share/calibre/fonts/liberation/LiberationSans-BoldItalic.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/calibre/fonts/liberation/LiberationSans-Italic.ttf||415816:1633027421.0": { + "family_name": "Liberation Sans", + "font-family": "Liberation Sans", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Liberation Sans Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 6, + 4, + 2, + 2, + 2, + 9, + 2, + 4 + ], + "path": "/usr/share/calibre/fonts/liberation/LiberationSans-Italic.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/calibre/fonts/liberation/LiberationSans-Regular.ttf||410712:1633027421.0": { + "family_name": "Liberation Sans", + "font-family": "Liberation Sans", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Liberation Sans", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 6, + 4, + 2, + 2, + 2, + 2, + 2, + 4 + ], + "path": "/usr/share/calibre/fonts/liberation/LiberationSans-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/calibre/fonts/liberation/LiberationSerif-Bold.ttf||370096:1633027421.0": { + "family_name": "Liberation Serif", + "font-family": "Liberation Serif", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Liberation Serif Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 2, + 8, + 3, + 7, + 5, + 5, + 2, + 3, + 4 + ], + "path": "/usr/share/calibre/fonts/liberation/LiberationSerif-Bold.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/calibre/fonts/liberation/LiberationSerif-BoldItalic.ttf||376772:1633027421.0": { + "family_name": "Liberation Serif", + "font-family": "Liberation Serif", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Liberation Serif Bold Italic", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 2, + 7, + 3, + 6, + 5, + 5, + 9, + 3, + 4 + ], + "path": "/usr/share/calibre/fonts/liberation/LiberationSerif-BoldItalic.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/calibre/fonts/liberation/LiberationSerif-Italic.ttf||375632:1633027421.0": { + "family_name": "Liberation Serif", + "font-family": "Liberation Serif", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Liberation Serif Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 2, + 5, + 3, + 5, + 4, + 5, + 9, + 3, + 4 + ], + "path": "/usr/share/calibre/fonts/liberation/LiberationSerif-Italic.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/calibre/fonts/liberation/LiberationSerif-Regular.ttf||393576:1633027421.0": { + "family_name": "Liberation Serif", + "font-family": "Liberation Serif", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Liberation Serif", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 2, + 6, + 3, + 5, + 4, + 5, + 2, + 3, + 4 + ], + "path": "/usr/share/calibre/fonts/liberation/LiberationSerif-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/OTF/Distortion Dos Digital.otf||18572:1625256442.0": { + "family_name": "Distortion Dos Digital", + "font-family": "Distortion Dos Digital", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 8, + "full_name": "Distortion Dos Digital", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 0, + 5, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/OTF/Distortion Dos Digital.otf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/OTF/GohaTibebZemen.otf||334284:1598123828.0": { + "family_name": "Goha-Tibeb Zemen", + "font-family": "Goha-Tibeb Zemen", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Goha-Tibeb Zemen", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": true, + "is_wws": false, + "os2_version": 2, + "panose": [ + 0, + 0, + 5, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/OTF/GohaTibebZemen.otf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/OTF/PowerlineSymbols.otf||2264:1638492676.0": { + "family_name": "PowerlineSymbols", + "font-family": "PowerlineSymbols", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "PowerlineSymbols", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 6, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/OTF/PowerlineSymbols.otf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Medium", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/OTF/SyrCOMAdiabene.otf||280464:1598123828.0": { + "family_name": "East Syriac Adiabene", + "font-family": "East Syriac Adiabene", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 12, + "full_name": "East Syriac Adiabene", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 1, + "panose": [ + 0, + 0, + 4, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/OTF/SyrCOMAdiabene.otf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/OTF/SyrCOMAntioch.otf||106024:1598123828.0": { + "family_name": "Estrangelo Antioch", + "font-family": "Estrangelo Antioch", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 12, + "full_name": "Estrangelo Antioch", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 1, + "panose": [ + 0, + 0, + 4, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/OTF/SyrCOMAntioch.otf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/OTF/SyrCOMBatnan.otf||289840:1598123828.0": { + "family_name": "Serto Batnan", + "font-family": "Serto Batnan", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 12, + "full_name": "Serto Batnan", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 1, + "panose": [ + 0, + 0, + 4, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/OTF/SyrCOMBatnan.otf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/OTF/SyrCOMBatnanBold.otf||308212:1598123828.0": { + "family_name": "Serto Batnan", + "font-family": "Serto Batnan", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 12, + "full_name": "Serto Batnan Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 0, + 0, + 7, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/OTF/SyrCOMBatnanBold.otf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/OTF/SyrCOMCtesiphon.otf||102104:1598123828.0": { + "family_name": "East Syriac Ctesiphon", + "font-family": "East Syriac Ctesiphon", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 12, + "full_name": "East Syriac Ctesiphon", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 1, + "panose": [ + 0, + 0, + 4, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/OTF/SyrCOMCtesiphon.otf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/OTF/SyrCOMEdessa.otf||79668:1598123828.0": { + "family_name": "Estrangelo Edessa", + "font-family": "Estrangelo Edessa", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Estrangelo Edessa", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 1, + "panose": [ + 3, + 8, + 6, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/OTF/SyrCOMEdessa.otf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/OTF/SyrCOMJerusalem.otf||294696:1598123828.0": { + "family_name": "Serto Jerusalem", + "font-family": "Serto Jerusalem", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 12, + "full_name": "Serto Jerusalem", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 1, + "panose": [ + 0, + 0, + 4, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/OTF/SyrCOMJerusalem.otf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/OTF/SyrCOMJerusalemBold.otf||289584:1598123828.0": { + "family_name": "Serto Jerusalem", + "font-family": "Serto Jerusalem", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 12, + "full_name": "Serto Jerusalem Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 0, + 0, + 7, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/OTF/SyrCOMJerusalemBold.otf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/OTF/SyrCOMJerusalemItalic.otf||309024:1598123828.0": { + "family_name": "Serto Jerusalem", + "font-family": "Serto Jerusalem", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 12, + "full_name": "Serto Jerusalem Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 0, + 0, + 4, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/OTF/SyrCOMJerusalemItalic.otf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/OTF/SyrCOMJerusalemOutline.otf||702612:1598123828.0": { + "family_name": "Serto Jerusalem Outline", + "font-family": "Serto Jerusalem Outline", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 12, + "full_name": "Serto Jerusalem Outline", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 1, + "panose": [ + 0, + 0, + 4, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/OTF/SyrCOMJerusalemOutline.otf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/OTF/SyrCOMKharput.otf||309916:1598123828.0": { + "family_name": "Serto Kharput", + "font-family": "Serto Kharput", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 12, + "full_name": "Serto Kharput", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 1, + "panose": [ + 0, + 0, + 4, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/OTF/SyrCOMKharput.otf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/OTF/SyrCOMMalankara.otf||317316:1598123828.0": { + "family_name": "Serto Malankara", + "font-family": "Serto Malankara", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 12, + "full_name": "Serto Malankara", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 1, + "panose": [ + 0, + 0, + 4, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/OTF/SyrCOMMalankara.otf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/OTF/SyrCOMMardin.otf||290896:1598123828.0": { + "family_name": "Serto Mardin", + "font-family": "Serto Mardin", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 12, + "full_name": "Serto Mardin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 1, + "panose": [ + 0, + 0, + 4, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/OTF/SyrCOMMardin.otf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/OTF/SyrCOMMardinBold.otf||289728:1598123828.0": { + "family_name": "Serto Mardin", + "font-family": "Serto Mardin", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 12, + "full_name": "Serto Mardin Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 0, + 0, + 7, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/OTF/SyrCOMMardinBold.otf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/OTF/SyrCOMMidyat.otf||103020:1598123828.0": { + "family_name": "Estrangelo Midyat", + "font-family": "Estrangelo Midyat", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 12, + "full_name": "Estrangelo Midyat", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 1, + "panose": [ + 0, + 0, + 4, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/OTF/SyrCOMMidyat.otf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/OTF/SyrCOMNisibin.otf||105408:1598123828.0": { + "family_name": "Estrangelo Nisibin", + "font-family": "Estrangelo Nisibin", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 12, + "full_name": "Estrangelo Nisibin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 1, + "panose": [ + 0, + 0, + 4, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/OTF/SyrCOMNisibin.otf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/OTF/SyrCOMNisibinOutline.otf||642460:1598123828.0": { + "family_name": "Estrangelo Nisibin Outline", + "font-family": "Estrangelo Nisibin Outline", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 12, + "full_name": "Estrangelo Nisibin Outline", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 1, + "panose": [ + 0, + 0, + 4, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/OTF/SyrCOMNisibinOutline.otf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/OTF/SyrCOMQenNeshrin.otf||104056:1598123828.0": { + "family_name": "Estrangelo Quenneshrin", + "font-family": "Estrangelo Quenneshrin", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 12, + "full_name": "Estrangelo Quenneshrin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 1, + "panose": [ + 0, + 0, + 4, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/OTF/SyrCOMQenNeshrin.otf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/OTF/SyrCOMTalada.otf||102496:1598123828.0": { + "family_name": "Estrangelo Talada", + "font-family": "Estrangelo Talada", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 12, + "full_name": "Estrangelo Talada", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 1, + "panose": [ + 0, + 0, + 4, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/OTF/SyrCOMTalada.otf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/OTF/SyrCOMTurAbdin.otf||153512:1598123828.0": { + "family_name": "Estrangelo TurAbdin", + "font-family": "Estrangelo TurAbdin", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 12, + "full_name": "Estrangelo TurAbdin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 1, + "panose": [ + 0, + 0, + 4, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/OTF/SyrCOMTurAbdin.otf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/OTF/SyrCOMUrhoy.otf||294288:1598123828.0": { + "family_name": "Serto Urhoy", + "font-family": "Serto Urhoy", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 12, + "full_name": "Serto Urhoy", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 1, + "panose": [ + 0, + 0, + 4, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/OTF/SyrCOMUrhoy.otf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/OTF/SyrCOMUrhoyBold.otf||294304:1598123828.0": { + "family_name": "Serto Urhoy", + "font-family": "Serto Urhoy", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 12, + "full_name": "Serto Urhoy Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 0, + 0, + 7, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/OTF/SyrCOMUrhoyBold.otf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/1942.ttf||52168:1625256442.0": { + "family_name": "1942 report", + "font-family": "1942 report", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "1942 report", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 0, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/TTF/1942.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "1942 report", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Aliquam.ttf||78384:1625256442.0": { + "family_name": "Aliquam", + "font-family": "Aliquam", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "200", + "fs_type": 4, + "full_name": "Aliquam UltraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 0, + 5, + 6, + 0, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/Aliquam.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "UltraLight", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Aliquamulti.ttf||45784:1625256442.0": { + "family_name": "Aliquam", + "font-family": "Aliquam", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "200", + "fs_type": 4, + "full_name": "Aliquam Ultralight Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 0, + 5, + 6, + 0, + 0, + 0, + 9, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/Aliquamulti.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Ultralight Italic", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/AndaleMo.TTF||105468:1599643855.0": { + "family_name": "Andale Mono", + "font-family": "Andale Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 8, + "full_name": "Andale Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 5, + 9, + 0, + 0, + 0, + 0, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/AndaleMo.TTF", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/AriBlk.TTF||117028:1599643855.0": { + "family_name": "Arial Black", + "font-family": "Arial Black", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Arial Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 10, + 4, + 2, + 1, + 2, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/TTF/AriBlk.TTF", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Arial.TTF||275572:1599643855.0": { + "family_name": "Arial", + "font-family": "Arial", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Arial", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 6, + 4, + 2, + 2, + 2, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/TTF/Arial.TTF", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Arialbd.TTF||286620:1599643855.0": { + "family_name": "Arial", + "font-family": "Arial", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Arial Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 7, + 4, + 2, + 2, + 2, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/TTF/Arialbd.TTF", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Arialbi.TTF||224692:1599643855.0": { + "family_name": "Arial", + "font-family": "Arial", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Arial Bold Italic", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 7, + 4, + 2, + 2, + 2, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/TTF/Arialbi.TTF", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Ariali.TTF||206132:1599643855.0": { + "family_name": "Arial", + "font-family": "Arial", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Arial Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 6, + 4, + 2, + 2, + 2, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/TTF/Ariali.TTF", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Bootcamp-Regular.ttf||14108:1625256442.0": { + "family_name": "Bootcamp", + "font-family": "Bootcamp", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 8, + "full_name": "Bootcamp", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 5, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/TTF/Bootcamp-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Comic.TTF||126364:1599643855.0": { + "family_name": "Comic Sans MS", + "font-family": "Comic Sans MS", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Comic Sans MS", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 1, + "panose": [ + 3, + 15, + 7, + 2, + 3, + 3, + 2, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/TTF/Comic.TTF", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Comicbd.TTF||111476:1599643855.0": { + "family_name": "Comic Sans MS", + "font-family": "Comic Sans MS", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Comic Sans MS Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 3, + 15, + 9, + 2, + 3, + 3, + 2, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/TTF/Comicbd.TTF", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/DejaVuMathTeXGyre.ttf||577604:1616951817.0": { + "family_name": "DejaVu Math TeX Gyre", + "font-family": "DejaVu Math TeX Gyre", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 12, + "full_name": "DejaVuMathTeXGyre-Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 5, + 3, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/TTF/DejaVuMathTeXGyre.ttf", + "preferred_family_name": "DejaVu Math TeX Gyre", + "preferred_subfamily_name": "Regular", + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/DejaVuSans-Bold.ttf||705684:1616951817.0": { + "family_name": "DejaVu Sans", + "font-family": "DejaVu Sans", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "DejaVu Sans Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 8, + 3, + 3, + 6, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/TTF/DejaVuSans-Bold.ttf", + "preferred_family_name": "DejaVu Sans", + "preferred_subfamily_name": "Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/DejaVuSans-BoldOblique.ttf||643288:1616951817.0": { + "family_name": "DejaVu Sans", + "font-family": "DejaVu Sans", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "DejaVu Sans Bold Oblique", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 8, + 3, + 3, + 3, + 4, + 11, + 2, + 4 + ], + "path": "/usr/share/fonts/TTF/DejaVuSans-BoldOblique.ttf", + "preferred_family_name": "DejaVu Sans", + "preferred_subfamily_name": "Bold Oblique", + "subfamily_name": "Bold Oblique", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/DejaVuSans-ExtraLight.ttf||356760:1616951817.0": { + "family_name": "DejaVu Sans Light", + "font-family": "DejaVu Sans Light", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "DejaVu Sans ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 2, + 3, + 3, + 8, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/TTF/DejaVuSans-ExtraLight.ttf", + "preferred_family_name": "DejaVu Sans", + "preferred_subfamily_name": "ExtraLight", + "subfamily_name": "ExtraLight", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/DejaVuSans-Oblique.ttf||635412:1616951817.0": { + "family_name": "DejaVu Sans", + "font-family": "DejaVu Sans", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "DejaVu Sans Oblique", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 6, + 3, + 3, + 3, + 4, + 11, + 2, + 4 + ], + "path": "/usr/share/fonts/TTF/DejaVuSans-Oblique.ttf", + "preferred_family_name": "DejaVu Sans", + "preferred_subfamily_name": "Oblique", + "subfamily_name": "Oblique", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/DejaVuSans.ttf||757076:1616951817.0": { + "family_name": "DejaVu Sans", + "font-family": "DejaVu Sans", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "DejaVu Sans", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 6, + 3, + 3, + 8, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/TTF/DejaVuSans.ttf", + "preferred_family_name": "DejaVu Sans", + "preferred_subfamily_name": "Book", + "subfamily_name": "Book", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/DejaVuSansCondensed-Bold.ttf||703880:1616951817.0": { + "family_name": "DejaVu Sans Condensed", + "font-family": "DejaVu Sans Condensed", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "DejaVu Sans Condensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 8, + 6, + 3, + 6, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/TTF/DejaVuSansCondensed-Bold.ttf", + "preferred_family_name": "DejaVu Sans", + "preferred_subfamily_name": "Condensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/DejaVuSansCondensed-BoldOblique.ttf||641696:1616951817.0": { + "family_name": "DejaVu Sans Condensed", + "font-family": "DejaVu Sans Condensed", + "font-stretch": "semi-condensed", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "DejaVu Sans Condensed Bold Oblique", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 8, + 6, + 3, + 3, + 4, + 11, + 2, + 4 + ], + "path": "/usr/share/fonts/TTF/DejaVuSansCondensed-BoldOblique.ttf", + "preferred_family_name": "DejaVu Sans", + "preferred_subfamily_name": "Condensed Bold Oblique", + "subfamily_name": "Bold Oblique", + "weight": 700, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/DejaVuSansCondensed-Oblique.ttf||633824:1616951817.0": { + "family_name": "DejaVu Sans Condensed", + "font-family": "DejaVu Sans Condensed", + "font-stretch": "semi-condensed", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "DejaVu Sans Condensed Oblique", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 6, + 6, + 3, + 3, + 4, + 11, + 2, + 4 + ], + "path": "/usr/share/fonts/TTF/DejaVuSansCondensed-Oblique.ttf", + "preferred_family_name": "DejaVu Sans", + "preferred_subfamily_name": "Condensed Oblique", + "subfamily_name": "Oblique", + "weight": 400, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/DejaVuSansCondensed.ttf||755124:1616951817.0": { + "family_name": "DejaVu Sans Condensed", + "font-family": "DejaVu Sans Condensed", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "DejaVu Sans Condensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 6, + 6, + 3, + 8, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/TTF/DejaVuSansCondensed.ttf", + "preferred_family_name": "DejaVu Sans", + "preferred_subfamily_name": "Condensed", + "subfamily_name": "Book", + "weight": 400, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/DejaVuSansMono-Bold.ttf||331992:1616951817.0": { + "family_name": "DejaVu Sans Mono", + "font-family": "DejaVu Sans Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "DejaVu Sans Mono Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 7, + 9, + 3, + 6, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/TTF/DejaVuSansMono-Bold.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/DejaVuSansMono-BoldOblique.ttf||253580:1616951817.0": { + "family_name": "DejaVu Sans Mono", + "font-family": "DejaVu Sans Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "DejaVu Sans Mono Bold Oblique", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 7, + 9, + 3, + 3, + 4, + 11, + 2, + 4 + ], + "path": "/usr/share/fonts/TTF/DejaVuSansMono-BoldOblique.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold Oblique", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/DejaVuSansMono-Oblique.ttf||251932:1616951817.0": { + "family_name": "DejaVu Sans Mono", + "font-family": "DejaVu Sans Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "DejaVu Sans Mono Oblique", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 6, + 9, + 3, + 3, + 4, + 11, + 2, + 4 + ], + "path": "/usr/share/fonts/TTF/DejaVuSansMono-Oblique.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Oblique", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/DejaVuSansMono.ttf||340712:1616951817.0": { + "family_name": "DejaVu Sans Mono", + "font-family": "DejaVu Sans Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "DejaVu Sans Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 6, + 9, + 3, + 8, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/TTF/DejaVuSansMono.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Book", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/DejaVuSerif-Bold.ttf||356088:1616951817.0": { + "family_name": "DejaVu Serif", + "font-family": "DejaVu Serif", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "DejaVu Serif Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 6, + 8, + 3, + 5, + 6, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/TTF/DejaVuSerif-Bold.ttf", + "preferred_family_name": "DejaVu Serif", + "preferred_subfamily_name": "Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/DejaVuSerif-BoldItalic.ttf||358820:1616951817.0": { + "family_name": "DejaVu Serif", + "font-family": "DejaVu Serif", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "DejaVu Serif Bold Italic", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 6, + 8, + 3, + 5, + 3, + 5, + 11, + 2, + 4 + ], + "path": "/usr/share/fonts/TTF/DejaVuSerif-BoldItalic.ttf", + "preferred_family_name": "DejaVu Serif", + "preferred_subfamily_name": "Bold Italic", + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/DejaVuSerif-Italic.ttf||359000:1616951817.0": { + "family_name": "DejaVu Serif", + "font-family": "DejaVu Serif", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "DejaVu Serif Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 6, + 6, + 3, + 5, + 3, + 5, + 11, + 2, + 4 + ], + "path": "/usr/share/fonts/TTF/DejaVuSerif-Italic.ttf", + "preferred_family_name": "DejaVu Serif", + "preferred_subfamily_name": "Italic", + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/DejaVuSerif.ttf||380132:1616951817.0": { + "family_name": "DejaVu Serif", + "font-family": "DejaVu Serif", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "DejaVu Serif", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 6, + 6, + 3, + 5, + 6, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/TTF/DejaVuSerif.ttf", + "preferred_family_name": "DejaVu Serif", + "preferred_subfamily_name": "Book", + "subfamily_name": "Book", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/DejaVuSerifCondensed-Bold.ttf||355220:1616951817.0": { + "family_name": "DejaVu Serif Condensed", + "font-family": "DejaVu Serif Condensed", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "DejaVu Serif Condensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 6, + 8, + 6, + 5, + 6, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/TTF/DejaVuSerifCondensed-Bold.ttf", + "preferred_family_name": "DejaVu Serif", + "preferred_subfamily_name": "Condensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/DejaVuSerifCondensed-BoldItalic.ttf||357888:1616951817.0": { + "family_name": "DejaVu Serif Condensed", + "font-family": "DejaVu Serif Condensed", + "font-stretch": "semi-condensed", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "DejaVu Serif Condensed Bold Italic", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 6, + 8, + 6, + 5, + 3, + 5, + 11, + 2, + 4 + ], + "path": "/usr/share/fonts/TTF/DejaVuSerifCondensed-BoldItalic.ttf", + "preferred_family_name": "DejaVu Serif", + "preferred_subfamily_name": "Condensed Bold Italic", + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/DejaVuSerifCondensed-Italic.ttf||358324:1616951817.0": { + "family_name": "DejaVu Serif Condensed", + "font-family": "DejaVu Serif Condensed", + "font-stretch": "semi-condensed", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "DejaVu Serif Condensed Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 6, + 6, + 6, + 5, + 3, + 5, + 11, + 2, + 4 + ], + "path": "/usr/share/fonts/TTF/DejaVuSerifCondensed-Italic.ttf", + "preferred_family_name": "DejaVu Serif", + "preferred_subfamily_name": "Condensed Italic", + "subfamily_name": "Italic", + "weight": 400, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/DejaVuSerifCondensed.ttf||379296:1616951817.0": { + "family_name": "DejaVu Serif Condensed", + "font-family": "DejaVu Serif Condensed", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "DejaVu Serif Condensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 6, + 6, + 6, + 5, + 6, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/TTF/DejaVuSerifCondensed.ttf", + "preferred_family_name": "DejaVu Serif", + "preferred_subfamily_name": "Condensed", + "subfamily_name": "Book", + "weight": 400, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Delicious Adventures.ttf||41188:1625256442.0": { + "family_name": "Delicious Adventures", + "font-family": "Delicious Adventures", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 4, + "full_name": "Delicious Adventures", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/TTF/Delicious Adventures.ttf", + "preferred_family_name": "Delicious Adventures", + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Digital_Readout_Thick_Upright.ttf||27492:1625256442.0": { + "family_name": "Digital Readout Thick Upright", + "font-family": "Digital Readout Thick Upright", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 2, + "full_name": "Digital Readout Thick Upright", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 1, + "panose": [ + 0, + 0, + 4, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/TTF/Digital_Readout_Thick_Upright.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/FiraCode-Bold.ttf||319368:1650723952.0": { + "family_name": "Fira Code", + "font-family": "Fira Code", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Fira Code Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/TTF/FiraCode-Bold.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/FiraCode-Light.ttf||288380:1650723952.0": { + "family_name": "Fira Code Light", + "font-family": "Fira Code Light", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Fira Code Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/TTF/FiraCode-Light.ttf", + "preferred_family_name": "Fira Code", + "preferred_subfamily_name": "Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/FiraCode-Medium.ttf||283684:1650723952.0": { + "family_name": "Fira Code Medium", + "font-family": "Fira Code Medium", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Fira Code Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/TTF/FiraCode-Medium.ttf", + "preferred_family_name": "Fira Code", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/FiraCode-Regular.ttf||289624:1650723952.0": { + "family_name": "Fira Code", + "font-family": "Fira Code", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Fira Code Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/TTF/FiraCode-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/FiraCode-Retina.ttf||285428:1650723952.0": { + "family_name": "Fira Code Retina", + "font-family": "Fira Code Retina", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "450", + "fs_type": 0, + "full_name": "Fira Code Retina", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/TTF/FiraCode-Retina.ttf", + "preferred_family_name": "Fira Code", + "preferred_subfamily_name": "Retina", + "subfamily_name": "Regular", + "weight": 450, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/FiraCode-SemiBold.ttf||304248:1650723952.0": { + "family_name": "Fira Code SemiBold", + "font-family": "Fira Code SemiBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Fira Code SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/TTF/FiraCode-SemiBold.ttf", + "preferred_family_name": "Fira Code", + "preferred_subfamily_name": "SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/FiraSans-Bold.ttf||521312:1593159386.0": { + "family_name": "Fira Sans", + "font-family": "Fira Sans", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Fira Sans Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 3, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/FiraSans-Bold.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/FiraSans-BoldItalic.ttf||525912:1593159386.0": { + "family_name": "Fira Sans", + "font-family": "Fira Sans", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Fira Sans Bold Italic", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 3, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/FiraSans-BoldItalic.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/FiraSans-Book.ttf||487632:1593159386.0": { + "family_name": "Fira Sans Book", + "font-family": "Fira Sans Book", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "350", + "fs_type": 0, + "full_name": "Fira Sans Book", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 3, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/FiraSans-Book.ttf", + "preferred_family_name": "Fira Sans", + "preferred_subfamily_name": "Book", + "subfamily_name": "Regular", + "weight": 350, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/FiraSans-BookItalic.ttf||492648:1593159386.0": { + "family_name": "Fira Sans Book", + "font-family": "Fira Sans Book", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "350", + "fs_type": 0, + "full_name": "Fira Sans Book Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 3, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/FiraSans-BookItalic.ttf", + "preferred_family_name": "Fira Sans", + "preferred_subfamily_name": "Book Italic", + "subfamily_name": "Italic", + "weight": 350, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/FiraSans-Eight.ttf||465752:1593159386.0": { + "family_name": "Fira Sans Eight", + "font-family": "Fira Sans Eight", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Fira Sans Eight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 3, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/FiraSans-Eight.ttf", + "preferred_family_name": "Fira Sans", + "preferred_subfamily_name": "Eight", + "subfamily_name": "Regular", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/FiraSans-EightItalic.ttf||476940:1593159386.0": { + "family_name": "Fira Sans Eight", + "font-family": "Fira Sans Eight", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "100", + "fs_type": 0, + "full_name": "Fira Sans Eight Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 3, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/FiraSans-EightItalic.ttf", + "preferred_family_name": "Fira Sans", + "preferred_subfamily_name": "Eight Italic", + "subfamily_name": "Italic", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/FiraSans-ExtraBold.ttf||528632:1593159386.0": { + "family_name": "Fira Sans ExtraBold", + "font-family": "Fira Sans ExtraBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Fira Sans ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 3, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/FiraSans-ExtraBold.ttf", + "preferred_family_name": "Fira Sans", + "preferred_subfamily_name": "ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/FiraSans-ExtraBoldItalic.ttf||553344:1593159386.0": { + "family_name": "Fira Sans ExtraBold", + "font-family": "Fira Sans ExtraBold", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "800", + "fs_type": 0, + "full_name": "Fira Sans ExtraBold Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 3, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/FiraSans-ExtraBoldItalic.ttf", + "preferred_family_name": "Fira Sans", + "preferred_subfamily_name": "ExtraBold Italic", + "subfamily_name": "Italic", + "weight": 800, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/FiraSans-ExtraLight.ttf||477472:1593159386.0": { + "family_name": "Fira Sans ExtraLight", + "font-family": "Fira Sans ExtraLight", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Fira Sans ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 3, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/FiraSans-ExtraLight.ttf", + "preferred_family_name": "Fira Sans", + "preferred_subfamily_name": "ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/FiraSans-ExtraLightItalic.ttf||482528:1593159386.0": { + "family_name": "Fira Sans ExtraLight", + "font-family": "Fira Sans ExtraLight", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "200", + "fs_type": 0, + "full_name": "Fira Sans ExtraLight Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 3, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/FiraSans-ExtraLightItalic.ttf", + "preferred_family_name": "Fira Sans", + "preferred_subfamily_name": "ExtraLight Italic", + "subfamily_name": "Italic", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/FiraSans-Four.ttf||461860:1593159386.0": { + "family_name": "Fira Sans Four", + "font-family": "Fira Sans Four", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Fira Sans Four", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 3, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/FiraSans-Four.ttf", + "preferred_family_name": "Fira Sans", + "preferred_subfamily_name": "Four", + "subfamily_name": "Regular", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/FiraSans-FourItalic.ttf||473492:1593159386.0": { + "family_name": "Fira Sans Four", + "font-family": "Fira Sans Four", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "100", + "fs_type": 0, + "full_name": "Fira Sans Four Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 3, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/FiraSans-FourItalic.ttf", + "preferred_family_name": "Fira Sans", + "preferred_subfamily_name": "Four Italic", + "subfamily_name": "Italic", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/FiraSans-Hair.ttf||479128:1593159386.0": { + "family_name": "Fira Sans Hair", + "font-family": "Fira Sans Hair", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Fira Sans Hair", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 3, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/FiraSans-Hair.ttf", + "preferred_family_name": "Fira Sans", + "preferred_subfamily_name": "Hair", + "subfamily_name": "Regular", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/FiraSans-HairItalic.ttf||486456:1593159386.0": { + "family_name": "Fira Sans Hair", + "font-family": "Fira Sans Hair", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "100", + "fs_type": 0, + "full_name": "Fira Sans Hair Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 3, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/FiraSans-HairItalic.ttf", + "preferred_family_name": "Fira Sans", + "preferred_subfamily_name": "Hair Italic", + "subfamily_name": "Italic", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/FiraSans-Heavy.ttf||538924:1593159386.0": { + "family_name": "Fira Sans Heavy", + "font-family": "Fira Sans Heavy", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Fira Sans Heavy", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 3, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/FiraSans-Heavy.ttf", + "preferred_family_name": "Fira Sans", + "preferred_subfamily_name": "Heavy", + "subfamily_name": "Regular", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/FiraSans-HeavyItalic.ttf||544652:1593159386.0": { + "family_name": "Fira Sans Heavy", + "font-family": "Fira Sans Heavy", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "900", + "fs_type": 0, + "full_name": "Fira Sans Heavy Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 3, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/FiraSans-HeavyItalic.ttf", + "preferred_family_name": "Fira Sans", + "preferred_subfamily_name": "Heavy Italic", + "subfamily_name": "Italic", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/FiraSans-Italic.ttf||492148:1593159386.0": { + "family_name": "Fira Sans", + "font-family": "Fira Sans", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Fira Sans Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 3, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/FiraSans-Italic.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/FiraSans-Light.ttf||479600:1593159386.0": { + "family_name": "Fira Sans Light", + "font-family": "Fira Sans Light", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Fira Sans Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 3, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/FiraSans-Light.ttf", + "preferred_family_name": "Fira Sans", + "preferred_subfamily_name": "Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/FiraSans-LightItalic.ttf||483024:1593159386.0": { + "family_name": "Fira Sans Light", + "font-family": "Fira Sans Light", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "300", + "fs_type": 0, + "full_name": "Fira Sans Light Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 3, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/FiraSans-LightItalic.ttf", + "preferred_family_name": "Fira Sans", + "preferred_subfamily_name": "Light Italic", + "subfamily_name": "Italic", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/FiraSans-Medium.ttf||488960:1593159386.0": { + "family_name": "Fira Sans Medium", + "font-family": "Fira Sans Medium", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Fira Sans Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 3, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/FiraSans-Medium.ttf", + "preferred_family_name": "Fira Sans", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/FiraSans-MediumItalic.ttf||494048:1593159386.0": { + "family_name": "Fira Sans Medium", + "font-family": "Fira Sans Medium", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "500", + "fs_type": 0, + "full_name": "Fira Sans Medium Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 3, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/FiraSans-MediumItalic.ttf", + "preferred_family_name": "Fira Sans", + "preferred_subfamily_name": "Medium Italic", + "subfamily_name": "Italic", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/FiraSans-Regular.ttf||487472:1593159386.0": { + "family_name": "Fira Sans", + "font-family": "Fira Sans", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Fira Sans Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 3, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/FiraSans-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/FiraSans-SemiBold.ttf||520896:1593159386.0": { + "family_name": "Fira Sans SemiBold", + "font-family": "Fira Sans SemiBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Fira Sans SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 3, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/FiraSans-SemiBold.ttf", + "preferred_family_name": "Fira Sans", + "preferred_subfamily_name": "SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/FiraSans-SemiBoldItalic.ttf||526084:1593159386.0": { + "family_name": "Fira Sans SemiBold", + "font-family": "Fira Sans SemiBold", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "600", + "fs_type": 0, + "full_name": "Fira Sans SemiBold Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 3, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/FiraSans-SemiBoldItalic.ttf", + "preferred_family_name": "Fira Sans", + "preferred_subfamily_name": "SemiBold Italic", + "subfamily_name": "Italic", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/FiraSans-Thin.ttf||473512:1593159386.0": { + "family_name": "Fira Sans Thin", + "font-family": "Fira Sans Thin", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Fira Sans Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 3, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/FiraSans-Thin.ttf", + "preferred_family_name": "Fira Sans", + "preferred_subfamily_name": "Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/FiraSans-ThinItalic.ttf||478100:1593159386.0": { + "family_name": "Fira Sans Thin", + "font-family": "Fira Sans Thin", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "100", + "fs_type": 0, + "full_name": "Fira Sans Thin Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 3, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/FiraSans-ThinItalic.ttf", + "preferred_family_name": "Fira Sans", + "preferred_subfamily_name": "Thin Italic", + "subfamily_name": "Italic", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/FiraSans-Two.ttf||455964:1593159386.0": { + "family_name": "Fira Sans Two", + "font-family": "Fira Sans Two", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Fira Sans Two", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 3, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/FiraSans-Two.ttf", + "preferred_family_name": "Fira Sans", + "preferred_subfamily_name": "Two", + "subfamily_name": "Regular", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/FiraSans-TwoItalic.ttf||468388:1593159386.0": { + "family_name": "Fira Sans Two", + "font-family": "Fira Sans Two", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "100", + "fs_type": 0, + "full_name": "Fira Sans Two Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 3, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/FiraSans-TwoItalic.ttf", + "preferred_family_name": "Fira Sans", + "preferred_subfamily_name": "Two Italic", + "subfamily_name": "Italic", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/FiraSans-Ultra.ttf||562420:1593159386.0": { + "family_name": "Fira Sans Ultra", + "font-family": "Fira Sans Ultra", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "950", + "fs_type": 0, + "full_name": "Fira Sans Ultra", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 3, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/FiraSans-Ultra.ttf", + "preferred_family_name": "Fira Sans", + "preferred_subfamily_name": "Ultra", + "subfamily_name": "Regular", + "weight": 950, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/FiraSans-UltraItalic.ttf||566704:1593159386.0": { + "family_name": "Fira Sans Ultra", + "font-family": "Fira Sans Ultra", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "950", + "fs_type": 0, + "full_name": "Fira Sans Ultra Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 3, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/FiraSans-UltraItalic.ttf", + "preferred_family_name": "Fira Sans", + "preferred_subfamily_name": "Ultra Italic", + "subfamily_name": "Italic", + "weight": 950, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/FiraSans-UltraLight.ttf||475288:1593159386.0": { + "family_name": "Fira Sans UltraLight", + "font-family": "Fira Sans UltraLight", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Fira Sans UltraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 3, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/FiraSans-UltraLight.ttf", + "preferred_family_name": "Fira Sans", + "preferred_subfamily_name": "UltraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/FiraSans-UltraLightItalic.ttf||481852:1593159386.0": { + "family_name": "Fira Sans UltraLight", + "font-family": "Fira Sans UltraLight", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "200", + "fs_type": 0, + "full_name": "Fira Sans UltraLight Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 3, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/FiraSans-UltraLightItalic.ttf", + "preferred_family_name": "Fira Sans", + "preferred_subfamily_name": "UltraLight Italic", + "subfamily_name": "Italic", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/FiraSansCompressed-Bold.ttf||530600:1593159386.0": { + "family_name": "Fira Sans Compressed", + "font-family": "Fira Sans Compressed", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Fira Sans Compressed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 3, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/FiraSansCompressed-Bold.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/FiraSansCompressed-BoldItalic.ttf||535208:1593159386.0": { + "family_name": "Fira Sans Compressed", + "font-family": "Fira Sans Compressed", + "font-stretch": "ultra-condensed", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Fira Sans Compressed Bold Italic", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 3, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/FiraSansCompressed-BoldItalic.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/FiraSansCompressed-Book.ttf||487000:1593159386.0": { + "family_name": "Fira Sans Compressed Book", + "font-family": "Fira Sans Compressed Book", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "350", + "fs_type": 0, + "full_name": "Fira Sans Compressed Book", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 3, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/FiraSansCompressed-Book.ttf", + "preferred_family_name": "Fira Sans Compressed", + "preferred_subfamily_name": "Book", + "subfamily_name": "Regular", + "weight": 350, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/FiraSansCompressed-BookItalic.ttf||491100:1593159386.0": { + "family_name": "Fira Sans Compressed Book", + "font-family": "Fira Sans Compressed Book", + "font-stretch": "ultra-condensed", + "font-style": "italic", + "font-weight": "350", + "fs_type": 0, + "full_name": "Fira Sans Compressed Book Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 3, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/FiraSansCompressed-BookItalic.ttf", + "preferred_family_name": "Fira Sans Compressed", + "preferred_subfamily_name": "Book Italic", + "subfamily_name": "Italic", + "weight": 350, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/FiraSansCompressed-Eight.ttf||463848:1593159386.0": { + "family_name": "Fira Sans Compressed Eight", + "font-family": "Fira Sans Compressed Eight", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Fira Sans Compressed Eight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 3, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/FiraSansCompressed-Eight.ttf", + "preferred_family_name": "Fira Sans Compressed", + "preferred_subfamily_name": "Eight", + "subfamily_name": "Regular", + "weight": 100, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/FiraSansCompressed-EightItalic.ttf||474872:1593159386.0": { + "family_name": "Fira Sans Compressed Eight", + "font-family": "Fira Sans Compressed Eight", + "font-stretch": "ultra-condensed", + "font-style": "italic", + "font-weight": "100", + "fs_type": 0, + "full_name": "Fira Sans Compressed Eight Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 3, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/FiraSansCompressed-EightItalic.ttf", + "preferred_family_name": "Fira Sans Compressed", + "preferred_subfamily_name": "Eight Italic", + "subfamily_name": "Italic", + "weight": 100, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/FiraSansCompressed-ExtraBold.ttf||529924:1593159386.0": { + "family_name": "Fira Sans Compressed ExtraBold", + "font-family": "Fira Sans Compressed ExtraBold", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Fira Sans Compressed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 3, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/FiraSansCompressed-ExtraBold.ttf", + "preferred_family_name": "Fira Sans Compressed", + "preferred_subfamily_name": "ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/FiraSansCompressed-ExtraBoldItalic.ttf||534620:1593159386.0": { + "family_name": "Fira Sans Compressed ExtraBold", + "font-family": "Fira Sans Compressed ExtraBold", + "font-stretch": "ultra-condensed", + "font-style": "italic", + "font-weight": "800", + "fs_type": 0, + "full_name": "Fira Sans Compressed ExtraBold Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 3, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/FiraSansCompressed-ExtraBoldItalic.ttf", + "preferred_family_name": "Fira Sans Compressed", + "preferred_subfamily_name": "ExtraBold Italic", + "subfamily_name": "Italic", + "weight": 800, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/FiraSansCompressed-ExtraLight.ttf||474532:1593159386.0": { + "family_name": "Fira Sans Compressed ExtraLight", + "font-family": "Fira Sans Compressed ExtraLight", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Fira Sans Compressed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 3, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/FiraSansCompressed-ExtraLight.ttf", + "preferred_family_name": "Fira Sans Compressed", + "preferred_subfamily_name": "ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/FiraSansCompressed-ExtraLightItalic.ttf||480308:1593159386.0": { + "family_name": "Fira Sans Compressed ExtraLight", + "font-family": "Fira Sans Compressed ExtraLight", + "font-stretch": "ultra-condensed", + "font-style": "italic", + "font-weight": "200", + "fs_type": 0, + "full_name": "Fira Sans Compressed ExtraLight Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 3, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/FiraSansCompressed-ExtraLightItalic.ttf", + "preferred_family_name": "Fira Sans Compressed", + "preferred_subfamily_name": "ExtraLight Italic", + "subfamily_name": "Italic", + "weight": 200, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/FiraSansCompressed-Four.ttf||460140:1593159386.0": { + "family_name": "Fira Sans Compressed Four", + "font-family": "Fira Sans Compressed Four", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Fira Sans Compressed Four", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 3, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/FiraSansCompressed-Four.ttf", + "preferred_family_name": "Fira Sans Compressed", + "preferred_subfamily_name": "Four", + "subfamily_name": "Regular", + "weight": 100, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/FiraSansCompressed-FourItalic.ttf||472124:1593159386.0": { + "family_name": "Fira Sans Compressed Four", + "font-family": "Fira Sans Compressed Four", + "font-stretch": "ultra-condensed", + "font-style": "italic", + "font-weight": "100", + "fs_type": 0, + "full_name": "Fira Sans Compressed Four Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 3, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/FiraSansCompressed-FourItalic.ttf", + "preferred_family_name": "Fira Sans Compressed", + "preferred_subfamily_name": "Four Italic", + "subfamily_name": "Italic", + "weight": 100, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/FiraSansCompressed-Hair.ttf||477448:1593159386.0": { + "family_name": "Fira Sans Compressed Hair", + "font-family": "Fira Sans Compressed Hair", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Fira Sans Compressed Hair", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 3, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/FiraSansCompressed-Hair.ttf", + "preferred_family_name": "Fira Sans Compressed", + "preferred_subfamily_name": "Hair", + "subfamily_name": "Regular", + "weight": 100, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/FiraSansCompressed-HairItalic.ttf||484648:1593159386.0": { + "family_name": "Fira Sans Compressed Hair", + "font-family": "Fira Sans Compressed Hair", + "font-stretch": "ultra-condensed", + "font-style": "italic", + "font-weight": "100", + "fs_type": 0, + "full_name": "Fira Sans Compressed Hair Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 3, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/FiraSansCompressed-HairItalic.ttf", + "preferred_family_name": "Fira Sans Compressed", + "preferred_subfamily_name": "Hair Italic", + "subfamily_name": "Italic", + "weight": 100, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/FiraSansCompressed-Heavy.ttf||550312:1593159386.0": { + "family_name": "Fira Sans Compressed Heavy", + "font-family": "Fira Sans Compressed Heavy", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Fira Sans Compressed Heavy", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 3, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/FiraSansCompressed-Heavy.ttf", + "preferred_family_name": "Fira Sans Compressed", + "preferred_subfamily_name": "Heavy", + "subfamily_name": "Regular", + "weight": 900, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/FiraSansCompressed-HeavyItalic.ttf||559652:1593159386.0": { + "family_name": "Fira Sans Compressed Heavy", + "font-family": "Fira Sans Compressed Heavy", + "font-stretch": "ultra-condensed", + "font-style": "italic", + "font-weight": "900", + "fs_type": 0, + "full_name": "Fira Sans Compressed Heavy Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 3, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/FiraSansCompressed-HeavyItalic.ttf", + "preferred_family_name": "Fira Sans Compressed", + "preferred_subfamily_name": "Heavy Italic", + "subfamily_name": "Italic", + "weight": 900, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/FiraSansCompressed-Italic.ttf||492408:1593159386.0": { + "family_name": "Fira Sans Compressed", + "font-family": "Fira Sans Compressed", + "font-stretch": "ultra-condensed", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Fira Sans Compressed Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 3, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/FiraSansCompressed-Italic.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 400, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/FiraSansCompressed-Light.ttf||479196:1593159386.0": { + "family_name": "Fira Sans Compressed Light", + "font-family": "Fira Sans Compressed Light", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Fira Sans Compressed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 3, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/FiraSansCompressed-Light.ttf", + "preferred_family_name": "Fira Sans Compressed", + "preferred_subfamily_name": "Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/FiraSansCompressed-LightItalic.ttf||481480:1593159386.0": { + "family_name": "Fira Sans Compressed Light", + "font-family": "Fira Sans Compressed Light", + "font-stretch": "ultra-condensed", + "font-style": "italic", + "font-weight": "300", + "fs_type": 0, + "full_name": "Fira Sans Compressed Light Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 3, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/FiraSansCompressed-LightItalic.ttf", + "preferred_family_name": "Fira Sans Compressed", + "preferred_subfamily_name": "Light Italic", + "subfamily_name": "Italic", + "weight": 300, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/FiraSansCompressed-Medium.ttf||488560:1593159386.0": { + "family_name": "Fira Sans Compressed Medium", + "font-family": "Fira Sans Compressed Medium", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Fira Sans Compressed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 3, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/FiraSansCompressed-Medium.ttf", + "preferred_family_name": "Fira Sans Compressed", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/FiraSansCompressed-MediumItalic.ttf||492524:1593159386.0": { + "family_name": "Fira Sans Compressed Medium", + "font-family": "Fira Sans Compressed Medium", + "font-stretch": "ultra-condensed", + "font-style": "italic", + "font-weight": "500", + "fs_type": 0, + "full_name": "Fira Sans Compressed Medium Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 3, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/FiraSansCompressed-MediumItalic.ttf", + "preferred_family_name": "Fira Sans Compressed", + "preferred_subfamily_name": "Medium Italic", + "subfamily_name": "Italic", + "weight": 500, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/FiraSansCompressed-Regular.ttf||487628:1593159386.0": { + "family_name": "Fira Sans Compressed", + "font-family": "Fira Sans Compressed", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Fira Sans Compressed Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 3, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/FiraSansCompressed-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/FiraSansCompressed-SemiBold.ttf||517168:1593159386.0": { + "family_name": "Fira Sans Compressed SemiBold", + "font-family": "Fira Sans Compressed SemiBold", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Fira Sans Compressed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 3, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/FiraSansCompressed-SemiBold.ttf", + "preferred_family_name": "Fira Sans Compressed", + "preferred_subfamily_name": "SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/FiraSansCompressed-SemiBoldItalic.ttf||520848:1593159386.0": { + "family_name": "Fira Sans Compressed SemiBold", + "font-family": "Fira Sans Compressed SemiBold", + "font-stretch": "ultra-condensed", + "font-style": "italic", + "font-weight": "600", + "fs_type": 0, + "full_name": "Fira Sans Compressed SemiBold Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 3, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/FiraSansCompressed-SemiBoldItalic.ttf", + "preferred_family_name": "Fira Sans Compressed", + "preferred_subfamily_name": "SemiBold Italic", + "subfamily_name": "Italic", + "weight": 600, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/FiraSansCompressed-Thin.ttf||471748:1593159386.0": { + "family_name": "Fira Sans Compressed Thin", + "font-family": "Fira Sans Compressed Thin", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Fira Sans Compressed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 3, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/FiraSansCompressed-Thin.ttf", + "preferred_family_name": "Fira Sans Compressed", + "preferred_subfamily_name": "Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/FiraSansCompressed-ThinItalic.ttf||477000:1593159386.0": { + "family_name": "Fira Sans Compressed Thin", + "font-family": "Fira Sans Compressed Thin", + "font-stretch": "ultra-condensed", + "font-style": "italic", + "font-weight": "100", + "fs_type": 0, + "full_name": "Fira Sans Compressed Thin Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 3, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/FiraSansCompressed-ThinItalic.ttf", + "preferred_family_name": "Fira Sans Compressed", + "preferred_subfamily_name": "Thin Italic", + "subfamily_name": "Italic", + "weight": 100, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/FiraSansCompressed-Two.ttf||455800:1593159386.0": { + "family_name": "Fira Sans Compressed Two", + "font-family": "Fira Sans Compressed Two", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Fira Sans Compressed Two", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 3, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/FiraSansCompressed-Two.ttf", + "preferred_family_name": "Fira Sans Compressed", + "preferred_subfamily_name": "Two", + "subfamily_name": "Regular", + "weight": 100, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/FiraSansCompressed-TwoItalic.ttf||467212:1593159386.0": { + "family_name": "Fira Sans Compressed Two", + "font-family": "Fira Sans Compressed Two", + "font-stretch": "ultra-condensed", + "font-style": "italic", + "font-weight": "100", + "fs_type": 0, + "full_name": "Fira Sans Compressed Two Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 3, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/FiraSansCompressed-TwoItalic.ttf", + "preferred_family_name": "Fira Sans Compressed", + "preferred_subfamily_name": "Two Italic", + "subfamily_name": "Italic", + "weight": 100, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/FiraSansCompressed-UltraLight.ttf||473372:1593159386.0": { + "family_name": "Fira Sans Compressed UltraLight", + "font-family": "Fira Sans Compressed UltraLight", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Fira Sans Compressed UltraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 3, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/FiraSansCompressed-UltraLight.ttf", + "preferred_family_name": "Fira Sans Compressed", + "preferred_subfamily_name": "UltraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/FiraSansCompressed-UltraLightItalic.ttf||479812:1593159386.0": { + "family_name": "Fira Sans Compressed UltraLight", + "font-family": "Fira Sans Compressed UltraLight", + "font-stretch": "ultra-condensed", + "font-style": "italic", + "font-weight": "200", + "fs_type": 0, + "full_name": "Fira Sans Compressed UltraLight Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 3, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/FiraSansCompressed-UltraLightItalic.ttf", + "preferred_family_name": "Fira Sans Compressed", + "preferred_subfamily_name": "UltraLight Italic", + "subfamily_name": "Italic", + "weight": 200, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/FiraSansCondensed-Bold.ttf||520940:1593159386.0": { + "family_name": "Fira Sans Condensed", + "font-family": "Fira Sans Condensed", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Fira Sans Condensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 3, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/FiraSansCondensed-Bold.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/FiraSansCondensed-BoldItalic.ttf||534712:1593159386.0": { + "family_name": "Fira Sans Condensed", + "font-family": "Fira Sans Condensed", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Fira Sans Condensed Bold Italic", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 3, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/FiraSansCondensed-BoldItalic.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/FiraSansCondensed-Book.ttf||486916:1593159386.0": { + "family_name": "Fira Sans Condensed Book", + "font-family": "Fira Sans Condensed Book", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "350", + "fs_type": 0, + "full_name": "Fira Sans Condensed Book", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 3, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/FiraSansCondensed-Book.ttf", + "preferred_family_name": "Fira Sans Condensed", + "preferred_subfamily_name": "Book", + "subfamily_name": "Regular", + "weight": 350, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/FiraSansCondensed-BookItalic.ttf||492192:1593159386.0": { + "family_name": "Fira Sans Condensed Book", + "font-family": "Fira Sans Condensed Book", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "350", + "fs_type": 0, + "full_name": "Fira Sans Condensed Book Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 3, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/FiraSansCondensed-BookItalic.ttf", + "preferred_family_name": "Fira Sans Condensed", + "preferred_subfamily_name": "Book Italic", + "subfamily_name": "Italic", + "weight": 350, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/FiraSansCondensed-Eight.ttf||464932:1593159386.0": { + "family_name": "Fira Sans Condensed Eight", + "font-family": "Fira Sans Condensed Eight", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Fira Sans Condensed Eight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 3, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/FiraSansCondensed-Eight.ttf", + "preferred_family_name": "Fira Sans Condensed", + "preferred_subfamily_name": "Eight", + "subfamily_name": "Regular", + "weight": 100, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/FiraSansCondensed-EightItalic.ttf||476060:1593159386.0": { + "family_name": "Fira Sans Condensed Eight", + "font-family": "Fira Sans Condensed Eight", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "100", + "fs_type": 0, + "full_name": "Fira Sans Condensed Eight Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 3, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/FiraSansCondensed-EightItalic.ttf", + "preferred_family_name": "Fira Sans Condensed", + "preferred_subfamily_name": "Eight Italic", + "subfamily_name": "Italic", + "weight": 100, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/FiraSansCondensed-ExtraBold.ttf||528592:1593159386.0": { + "family_name": "Fira Sans Condensed ExtraBold", + "font-family": "Fira Sans Condensed ExtraBold", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Fira Sans Condensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 3, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/FiraSansCondensed-ExtraBold.ttf", + "preferred_family_name": "Fira Sans Condensed", + "preferred_subfamily_name": "ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/FiraSansCondensed-ExtraBoldItalic.ttf||552884:1593159386.0": { + "family_name": "Fira Sans Condensed ExtraBold", + "font-family": "Fira Sans Condensed ExtraBold", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "800", + "fs_type": 0, + "full_name": "Fira Sans Condensed ExtraBold Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 3, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/FiraSansCondensed-ExtraBoldItalic.ttf", + "preferred_family_name": "Fira Sans Condensed", + "preferred_subfamily_name": "ExtraBold Italic", + "subfamily_name": "Italic", + "weight": 800, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/FiraSansCondensed-ExtraLight.ttf||475848:1593159386.0": { + "family_name": "Fira Sans Condensed ExtraLight", + "font-family": "Fira Sans Condensed ExtraLight", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Fira Sans Condensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 3, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/FiraSansCondensed-ExtraLight.ttf", + "preferred_family_name": "Fira Sans Condensed", + "preferred_subfamily_name": "ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/FiraSansCondensed-ExtraLightItalic.ttf||480788:1593159386.0": { + "family_name": "Fira Sans Condensed ExtraLight", + "font-family": "Fira Sans Condensed ExtraLight", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "200", + "fs_type": 0, + "full_name": "Fira Sans Condensed ExtraLight Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 3, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/FiraSansCondensed-ExtraLightItalic.ttf", + "preferred_family_name": "Fira Sans Condensed", + "preferred_subfamily_name": "ExtraLight Italic", + "subfamily_name": "Italic", + "weight": 200, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/FiraSansCondensed-Four.ttf||461164:1593159386.0": { + "family_name": "Fira Sans Condensed Four", + "font-family": "Fira Sans Condensed Four", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Fira Sans Condensed Four", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 3, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/FiraSansCondensed-Four.ttf", + "preferred_family_name": "Fira Sans Condensed", + "preferred_subfamily_name": "Four", + "subfamily_name": "Regular", + "weight": 100, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/FiraSansCondensed-FourItalic.ttf||472676:1593159386.0": { + "family_name": "Fira Sans Condensed Four", + "font-family": "Fira Sans Condensed Four", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "100", + "fs_type": 0, + "full_name": "Fira Sans Condensed Four Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 3, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/FiraSansCondensed-FourItalic.ttf", + "preferred_family_name": "Fira Sans Condensed", + "preferred_subfamily_name": "Four Italic", + "subfamily_name": "Italic", + "weight": 100, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/FiraSansCondensed-Hair.ttf||477848:1593159386.0": { + "family_name": "Fira Sans Condensed Hair", + "font-family": "Fira Sans Condensed Hair", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Fira Sans Condensed Hair", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 3, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/FiraSansCondensed-Hair.ttf", + "preferred_family_name": "Fira Sans Condensed", + "preferred_subfamily_name": "Hair", + "subfamily_name": "Regular", + "weight": 100, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/FiraSansCondensed-HairItalic.ttf||485812:1593159386.0": { + "family_name": "Fira Sans Condensed Hair", + "font-family": "Fira Sans Condensed Hair", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "100", + "fs_type": 0, + "full_name": "Fira Sans Condensed Hair Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 3, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/FiraSansCondensed-HairItalic.ttf", + "preferred_family_name": "Fira Sans Condensed", + "preferred_subfamily_name": "Hair Italic", + "subfamily_name": "Italic", + "weight": 100, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/FiraSansCondensed-Heavy.ttf||549276:1593159386.0": { + "family_name": "Fira Sans Condensed Heavy", + "font-family": "Fira Sans Condensed Heavy", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Fira Sans Condensed Heavy", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 3, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/FiraSansCondensed-Heavy.ttf", + "preferred_family_name": "Fira Sans Condensed", + "preferred_subfamily_name": "Heavy", + "subfamily_name": "Regular", + "weight": 900, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/FiraSansCondensed-HeavyItalic.ttf||555728:1593159386.0": { + "family_name": "Fira Sans Condensed Heavy", + "font-family": "Fira Sans Condensed Heavy", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "900", + "fs_type": 0, + "full_name": "Fira Sans Condensed Heavy Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 3, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/FiraSansCondensed-HeavyItalic.ttf", + "preferred_family_name": "Fira Sans Condensed", + "preferred_subfamily_name": "Heavy Italic", + "subfamily_name": "Italic", + "weight": 900, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/FiraSansCondensed-Italic.ttf||492372:1593159386.0": { + "family_name": "Fira Sans Condensed", + "font-family": "Fira Sans Condensed", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Fira Sans Condensed Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 3, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/FiraSansCondensed-Italic.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 400, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/FiraSansCondensed-Light.ttf||480492:1593159386.0": { + "family_name": "Fira Sans Condensed Light", + "font-family": "Fira Sans Condensed Light", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Fira Sans Condensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 3, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/FiraSansCondensed-Light.ttf", + "preferred_family_name": "Fira Sans Condensed", + "preferred_subfamily_name": "Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/FiraSansCondensed-LightItalic.ttf||483144:1593159386.0": { + "family_name": "Fira Sans Condensed Light", + "font-family": "Fira Sans Condensed Light", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "300", + "fs_type": 0, + "full_name": "Fira Sans Condensed Light Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 3, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/FiraSansCondensed-LightItalic.ttf", + "preferred_family_name": "Fira Sans Condensed", + "preferred_subfamily_name": "Light Italic", + "subfamily_name": "Italic", + "weight": 300, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/FiraSansCondensed-Medium.ttf||488036:1593159386.0": { + "family_name": "Fira Sans Condensed Medium", + "font-family": "Fira Sans Condensed Medium", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Fira Sans Condensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 3, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/FiraSansCondensed-Medium.ttf", + "preferred_family_name": "Fira Sans Condensed", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/FiraSansCondensed-MediumItalic.ttf||493128:1593159386.0": { + "family_name": "Fira Sans Condensed Medium", + "font-family": "Fira Sans Condensed Medium", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "500", + "fs_type": 0, + "full_name": "Fira Sans Condensed Medium Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 3, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/FiraSansCondensed-MediumItalic.ttf", + "preferred_family_name": "Fira Sans Condensed", + "preferred_subfamily_name": "Medium Italic", + "subfamily_name": "Italic", + "weight": 500, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/FiraSansCondensed-Regular.ttf||490328:1593159386.0": { + "family_name": "Fira Sans Condensed", + "font-family": "Fira Sans Condensed", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Fira Sans Condensed Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 3, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/FiraSansCondensed-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/FiraSansCondensed-SemiBold.ttf||520080:1593159386.0": { + "family_name": "Fira Sans Condensed SemiBold", + "font-family": "Fira Sans Condensed SemiBold", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Fira Sans Condensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 3, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/FiraSansCondensed-SemiBold.ttf", + "preferred_family_name": "Fira Sans Condensed", + "preferred_subfamily_name": "SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/FiraSansCondensed-SemiBoldItalic.ttf||507052:1593159386.0": { + "family_name": "Fira Sans Condensed SemiBold", + "font-family": "Fira Sans Condensed SemiBold", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "600", + "fs_type": 0, + "full_name": "Fira Sans Condensed SemiBold Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 3, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/FiraSansCondensed-SemiBoldItalic.ttf", + "preferred_family_name": "Fira Sans Condensed", + "preferred_subfamily_name": "SemiBold Italic", + "subfamily_name": "Italic", + "weight": 600, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/FiraSansCondensed-Thin.ttf||472252:1593159386.0": { + "family_name": "Fira Sans Condensed Thin", + "font-family": "Fira Sans Condensed Thin", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Fira Sans Condensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 3, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/FiraSansCondensed-Thin.ttf", + "preferred_family_name": "Fira Sans Condensed", + "preferred_subfamily_name": "Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/FiraSansCondensed-ThinItalic.ttf||478228:1593159386.0": { + "family_name": "Fira Sans Condensed Thin", + "font-family": "Fira Sans Condensed Thin", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "100", + "fs_type": 0, + "full_name": "Fira Sans Condensed Thin Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 3, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/FiraSansCondensed-ThinItalic.ttf", + "preferred_family_name": "Fira Sans Condensed", + "preferred_subfamily_name": "Thin Italic", + "subfamily_name": "Italic", + "weight": 100, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/FiraSansCondensed-Two.ttf||456212:1593159386.0": { + "family_name": "Fira Sans Condensed Two", + "font-family": "Fira Sans Condensed Two", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Fira Sans Condensed Two", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 3, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/FiraSansCondensed-Two.ttf", + "preferred_family_name": "Fira Sans Condensed", + "preferred_subfamily_name": "Two", + "subfamily_name": "Regular", + "weight": 100, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/FiraSansCondensed-TwoItalic.ttf||467548:1593159386.0": { + "family_name": "Fira Sans Condensed Two", + "font-family": "Fira Sans Condensed Two", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "100", + "fs_type": 0, + "full_name": "Fira Sans Condensed Two Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 3, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/FiraSansCondensed-TwoItalic.ttf", + "preferred_family_name": "Fira Sans Condensed", + "preferred_subfamily_name": "Two Italic", + "subfamily_name": "Italic", + "weight": 100, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/FiraSansCondensed-UltraLight.ttf||474368:1593159386.0": { + "family_name": "Fira Sans Condensed UltraLight", + "font-family": "Fira Sans Condensed UltraLight", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Fira Sans Condensed UltraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 3, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/FiraSansCondensed-UltraLight.ttf", + "preferred_family_name": "Fira Sans Condensed", + "preferred_subfamily_name": "UltraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/FiraSansCondensed-UltraLightItalic.ttf||480536:1593159386.0": { + "family_name": "Fira Sans Condensed UltraLight", + "font-family": "Fira Sans Condensed UltraLight", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "200", + "fs_type": 0, + "full_name": "Fira Sans Condensed UltraLight Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 3, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/FiraSansCondensed-UltraLightItalic.ttf", + "preferred_family_name": "Fira Sans Condensed", + "preferred_subfamily_name": "UltraLight Italic", + "subfamily_name": "Italic", + "weight": 200, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Georgia.TTF||142964:1599643855.0": { + "family_name": "Georgia", + "font-family": "Georgia", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Georgia", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 4, + 5, + 2, + 5, + 4, + 5, + 2, + 3, + 3 + ], + "path": "/usr/share/fonts/TTF/Georgia.TTF", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Georgiab.TTF||139584:1599643855.0": { + "family_name": "Georgia", + "font-family": "Georgia", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Georgia Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 4, + 8, + 2, + 5, + 4, + 5, + 2, + 2, + 3 + ], + "path": "/usr/share/fonts/TTF/Georgiab.TTF", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Georgiai.TTF||156668:1599643855.0": { + "family_name": "Georgia", + "font-family": "Georgia", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Georgia Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 4, + 5, + 2, + 5, + 4, + 5, + 9, + 3, + 3 + ], + "path": "/usr/share/fonts/TTF/Georgiai.TTF", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Georgiaz.TTF||158796:1599643855.0": { + "family_name": "Georgia", + "font-family": "Georgia", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Georgia Bold Italic", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 4, + 8, + 2, + 5, + 4, + 5, + 9, + 2, + 3 + ], + "path": "/usr/share/fonts/TTF/Georgiaz.TTF", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/GohaTibebZemen.ttf||95352:1598123828.0": { + "family_name": "Goha-Tibeb Zemen", + "font-family": "Goha-Tibeb Zemen", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Goha-Tibeb Zemen", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 1, + "panose": [ + 0, + 0, + 5, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/TTF/GohaTibebZemen.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Hack-Bold.ttf||317628:1593423230.0": { + "family_name": "Hack", + "font-family": "Hack", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Hack Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 9, + 3, + 2, + 2, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/TTF/Hack-Bold.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Hack-BoldItalic.ttf||322288:1593423230.0": { + "family_name": "Hack", + "font-family": "Hack", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Hack Bold Italic", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 9, + 3, + 2, + 2, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/TTF/Hack-BoldItalic.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Hack-Italic.ttf||316156:1593423230.0": { + "family_name": "Hack", + "font-family": "Hack", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Hack Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 9, + 3, + 2, + 2, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/TTF/Hack-Italic.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Hack-Regular.ttf||309408:1593423230.0": { + "family_name": "Hack", + "font-family": "Hack", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Hack Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 9, + 3, + 2, + 2, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/TTF/Hack-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Impact.TTF||136076:1599643855.0": { + "family_name": "Impact", + "font-family": "Impact", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Impact", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 8, + 6, + 3, + 9, + 2, + 5, + 2, + 4 + ], + "path": "/usr/share/fonts/TTF/Impact.TTF", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Inconsolata-Black.ttf||110420:1616951293.0": { + "family_name": "Inconsolata Black", + "font-family": "Inconsolata Black", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Inconsolata Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/TTF/Inconsolata-Black.ttf", + "preferred_family_name": "Inconsolata", + "preferred_subfamily_name": "Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Inconsolata-Bold.ttf||109728:1616951293.0": { + "family_name": "Inconsolata", + "font-family": "Inconsolata", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Inconsolata Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/TTF/Inconsolata-Bold.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Inconsolata-Condensed.ttf||108264:1616951293.0": { + "family_name": "Inconsolata Condensed", + "font-family": "Inconsolata Condensed", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Inconsolata Condensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/TTF/Inconsolata-Condensed.ttf", + "preferred_family_name": "Inconsolata", + "preferred_subfamily_name": "Condensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Inconsolata-CondensedBlack.ttf||109588:1616951293.0": { + "family_name": "Inconsolata Condensed Black", + "font-family": "Inconsolata Condensed Black", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Inconsolata Condensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/TTF/Inconsolata-CondensedBlack.ttf", + "preferred_family_name": "Inconsolata", + "preferred_subfamily_name": "Condensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Inconsolata-CondensedBold.ttf||109696:1616951293.0": { + "family_name": "Inconsolata Condensed Bold", + "font-family": "Inconsolata Condensed Bold", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Inconsolata Condensed Bold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/TTF/Inconsolata-CondensedBold.ttf", + "preferred_family_name": "Inconsolata", + "preferred_subfamily_name": "Condensed Bold", + "subfamily_name": "Regular", + "weight": 700, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Inconsolata-CondensedExtraBold.ttf||109272:1616951293.0": { + "family_name": "Inconsolata Condensed ExtraBold", + "font-family": "Inconsolata Condensed ExtraBold", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Inconsolata Condensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/TTF/Inconsolata-CondensedExtraBold.ttf", + "preferred_family_name": "Inconsolata", + "preferred_subfamily_name": "Condensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Inconsolata-CondensedExtraLight.ttf||107876:1616951293.0": { + "family_name": "Inconsolata Condensed ExtraLight", + "font-family": "Inconsolata Condensed ExtraLight", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "275", + "fs_type": 0, + "full_name": "Inconsolata Condensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/TTF/Inconsolata-CondensedExtraLight.ttf", + "preferred_family_name": "Inconsolata", + "preferred_subfamily_name": "Condensed ExtraLight", + "subfamily_name": "Regular", + "weight": 275, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Inconsolata-CondensedLight.ttf||108656:1616951293.0": { + "family_name": "Inconsolata Condensed Light", + "font-family": "Inconsolata Condensed Light", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Inconsolata Condensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/TTF/Inconsolata-CondensedLight.ttf", + "preferred_family_name": "Inconsolata", + "preferred_subfamily_name": "Condensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Inconsolata-CondensedMedium.ttf||109196:1616951293.0": { + "family_name": "Inconsolata Condensed Medium", + "font-family": "Inconsolata Condensed Medium", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Inconsolata Condensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/TTF/Inconsolata-CondensedMedium.ttf", + "preferred_family_name": "Inconsolata", + "preferred_subfamily_name": "Condensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Inconsolata-CondensedSemiBold.ttf||109252:1616951293.0": { + "family_name": "Inconsolata Condensed SemiBold", + "font-family": "Inconsolata Condensed SemiBold", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Inconsolata Condensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/TTF/Inconsolata-CondensedSemiBold.ttf", + "preferred_family_name": "Inconsolata", + "preferred_subfamily_name": "Condensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Inconsolata-Expanded.ttf||109708:1616951293.0": { + "family_name": "Inconsolata Expanded", + "font-family": "Inconsolata Expanded", + "font-stretch": "expanded", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Inconsolata Expanded", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/TTF/Inconsolata-Expanded.ttf", + "preferred_family_name": "Inconsolata", + "preferred_subfamily_name": "Expanded", + "subfamily_name": "Regular", + "weight": 400, + "width": 7, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Inconsolata-ExpandedBlack.ttf||112092:1616951293.0": { + "family_name": "Inconsolata Expanded Black", + "font-family": "Inconsolata Expanded Black", + "font-stretch": "expanded", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Inconsolata Expanded Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/TTF/Inconsolata-ExpandedBlack.ttf", + "preferred_family_name": "Inconsolata", + "preferred_subfamily_name": "Expanded Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 7, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Inconsolata-ExpandedBold.ttf||110488:1616951293.0": { + "family_name": "Inconsolata Expanded Bold", + "font-family": "Inconsolata Expanded Bold", + "font-stretch": "expanded", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Inconsolata Expanded Bold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/TTF/Inconsolata-ExpandedBold.ttf", + "preferred_family_name": "Inconsolata", + "preferred_subfamily_name": "Expanded Bold", + "subfamily_name": "Regular", + "weight": 700, + "width": 7, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Inconsolata-ExpandedExtraBold.ttf||112016:1616951293.0": { + "family_name": "Inconsolata Expanded ExtraBold", + "font-family": "Inconsolata Expanded ExtraBold", + "font-stretch": "expanded", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Inconsolata Expanded ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/TTF/Inconsolata-ExpandedExtraBold.ttf", + "preferred_family_name": "Inconsolata", + "preferred_subfamily_name": "Expanded ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 7, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Inconsolata-ExpandedExtraLight.ttf||110168:1616951293.0": { + "family_name": "Inconsolata Expanded ExtraLight", + "font-family": "Inconsolata Expanded ExtraLight", + "font-stretch": "expanded", + "font-style": "normal", + "font-weight": "275", + "fs_type": 0, + "full_name": "Inconsolata Expanded ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/TTF/Inconsolata-ExpandedExtraLight.ttf", + "preferred_family_name": "Inconsolata", + "preferred_subfamily_name": "Expanded ExtraLight", + "subfamily_name": "Regular", + "weight": 275, + "width": 7, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Inconsolata-ExpandedLight.ttf||110208:1616951293.0": { + "family_name": "Inconsolata Expanded Light", + "font-family": "Inconsolata Expanded Light", + "font-stretch": "expanded", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Inconsolata Expanded Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/TTF/Inconsolata-ExpandedLight.ttf", + "preferred_family_name": "Inconsolata", + "preferred_subfamily_name": "Expanded Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 7, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Inconsolata-ExpandedMedium.ttf||110512:1616951293.0": { + "family_name": "Inconsolata Expanded Medium", + "font-family": "Inconsolata Expanded Medium", + "font-stretch": "expanded", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Inconsolata Expanded Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/TTF/Inconsolata-ExpandedMedium.ttf", + "preferred_family_name": "Inconsolata", + "preferred_subfamily_name": "Expanded Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 7, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Inconsolata-ExpandedSemiBold.ttf||110532:1616951293.0": { + "family_name": "Inconsolata Expanded SemiBold", + "font-family": "Inconsolata Expanded SemiBold", + "font-stretch": "expanded", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Inconsolata Expanded SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/TTF/Inconsolata-ExpandedSemiBold.ttf", + "preferred_family_name": "Inconsolata", + "preferred_subfamily_name": "Expanded SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 7, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Inconsolata-ExtraBold.ttf||109544:1616951293.0": { + "family_name": "Inconsolata ExtraBold", + "font-family": "Inconsolata ExtraBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Inconsolata ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/TTF/Inconsolata-ExtraBold.ttf", + "preferred_family_name": "Inconsolata", + "preferred_subfamily_name": "ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Inconsolata-ExtraCondensed.ttf||108220:1616951293.0": { + "family_name": "Inconsolata Extra Condensed", + "font-family": "Inconsolata Extra Condensed", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Inconsolata Extra Condensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/TTF/Inconsolata-ExtraCondensed.ttf", + "preferred_family_name": "Inconsolata", + "preferred_subfamily_name": "Extra Condensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Inconsolata-ExtraCondensedBlack.ttf||109256:1616951293.0": { + "family_name": "Inconsolata Extra Condensed Black", + "font-family": "Inconsolata Extra Condensed Black", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Inconsolata Extra Condensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/TTF/Inconsolata-ExtraCondensedBlack.ttf", + "preferred_family_name": "Inconsolata", + "preferred_subfamily_name": "Extra Condensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Inconsolata-ExtraCondensedBold.ttf||109652:1616951293.0": { + "family_name": "Inconsolata Extra Condensed Bold", + "font-family": "Inconsolata Extra Condensed Bold", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Inconsolata Extra Condensed Bold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/TTF/Inconsolata-ExtraCondensedBold.ttf", + "preferred_family_name": "Inconsolata", + "preferred_subfamily_name": "Extra Condensed Bold", + "subfamily_name": "Regular", + "weight": 700, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Inconsolata-ExtraCondensedExtraBold.ttf||108992:1616951293.0": { + "family_name": "Inconsolata Extra Condensed ExtraBold", + "font-family": "Inconsolata Extra Condensed ExtraBold", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Inconsolata Extra Condensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/TTF/Inconsolata-ExtraCondensedExtraBold.ttf", + "preferred_family_name": "Inconsolata", + "preferred_subfamily_name": "Extra Condensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Inconsolata-ExtraCondensedExtraLight.ttf||107236:1616951293.0": { + "family_name": "Inconsolata Extra Condensed ExtraLight", + "font-family": "Inconsolata Extra Condensed ExtraLight", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "275", + "fs_type": 0, + "full_name": "Inconsolata Extra Condensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/TTF/Inconsolata-ExtraCondensedExtraLight.ttf", + "preferred_family_name": "Inconsolata", + "preferred_subfamily_name": "Extra Condensed ExtraLight", + "subfamily_name": "Regular", + "weight": 275, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Inconsolata-ExtraCondensedLight.ttf||107940:1616951293.0": { + "family_name": "Inconsolata Extra Condensed Light", + "font-family": "Inconsolata Extra Condensed Light", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Inconsolata Extra Condensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/TTF/Inconsolata-ExtraCondensedLight.ttf", + "preferred_family_name": "Inconsolata", + "preferred_subfamily_name": "Extra Condensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Inconsolata-ExtraCondensedMedium.ttf||108528:1616951293.0": { + "family_name": "Inconsolata Extra Condensed Medium", + "font-family": "Inconsolata Extra Condensed Medium", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Inconsolata Extra Condensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/TTF/Inconsolata-ExtraCondensedMedium.ttf", + "preferred_family_name": "Inconsolata", + "preferred_subfamily_name": "Extra Condensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Inconsolata-ExtraCondensedSemiBold.ttf||109448:1616951293.0": { + "family_name": "Inconsolata Extra Condensed SemiBold", + "font-family": "Inconsolata Extra Condensed SemiBold", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Inconsolata Extra Condensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/TTF/Inconsolata-ExtraCondensedSemiBold.ttf", + "preferred_family_name": "Inconsolata", + "preferred_subfamily_name": "Extra Condensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Inconsolata-ExtraExpanded.ttf||109968:1616951293.0": { + "family_name": "Inconsolata Extra Expanded", + "font-family": "Inconsolata Extra Expanded", + "font-stretch": "extra-expanded", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Inconsolata Extra Expanded", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/TTF/Inconsolata-ExtraExpanded.ttf", + "preferred_family_name": "Inconsolata", + "preferred_subfamily_name": "Extra Expanded", + "subfamily_name": "Regular", + "weight": 400, + "width": 8, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Inconsolata-ExtraExpandedBlack.ttf||113276:1616951293.0": { + "family_name": "Inconsolata Extra Expanded Black", + "font-family": "Inconsolata Extra Expanded Black", + "font-stretch": "extra-expanded", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Inconsolata Extra Expanded Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/TTF/Inconsolata-ExtraExpandedBlack.ttf", + "preferred_family_name": "Inconsolata", + "preferred_subfamily_name": "Extra Expanded Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 8, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Inconsolata-ExtraExpandedBold.ttf||112776:1616951293.0": { + "family_name": "Inconsolata Extra Expanded Bold", + "font-family": "Inconsolata Extra Expanded Bold", + "font-stretch": "extra-expanded", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Inconsolata Extra Expanded Bold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/TTF/Inconsolata-ExtraExpandedBold.ttf", + "preferred_family_name": "Inconsolata", + "preferred_subfamily_name": "Extra Expanded Bold", + "subfamily_name": "Regular", + "weight": 700, + "width": 8, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Inconsolata-ExtraExpandedExtraBold.ttf||112760:1616951293.0": { + "family_name": "Inconsolata Extra Expanded ExtraBold", + "font-family": "Inconsolata Extra Expanded ExtraBold", + "font-stretch": "extra-expanded", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Inconsolata Extra Expanded ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/TTF/Inconsolata-ExtraExpandedExtraBold.ttf", + "preferred_family_name": "Inconsolata", + "preferred_subfamily_name": "Extra Expanded ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 8, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Inconsolata-ExtraExpandedExtraLight.ttf||111124:1616951293.0": { + "family_name": "Inconsolata Extra Expanded ExtraLight", + "font-family": "Inconsolata Extra Expanded ExtraLight", + "font-stretch": "extra-expanded", + "font-style": "normal", + "font-weight": "275", + "fs_type": 0, + "full_name": "Inconsolata Extra Expanded ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/TTF/Inconsolata-ExtraExpandedExtraLight.ttf", + "preferred_family_name": "Inconsolata", + "preferred_subfamily_name": "Extra Expanded ExtraLight", + "subfamily_name": "Regular", + "weight": 275, + "width": 8, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Inconsolata-ExtraExpandedLight.ttf||111720:1616951293.0": { + "family_name": "Inconsolata Extra Expanded Light", + "font-family": "Inconsolata Extra Expanded Light", + "font-stretch": "extra-expanded", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Inconsolata Extra Expanded Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/TTF/Inconsolata-ExtraExpandedLight.ttf", + "preferred_family_name": "Inconsolata", + "preferred_subfamily_name": "Extra Expanded Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 8, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Inconsolata-ExtraExpandedMedium.ttf||111508:1616951293.0": { + "family_name": "Inconsolata Extra Expanded Medium", + "font-family": "Inconsolata Extra Expanded Medium", + "font-stretch": "extra-expanded", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Inconsolata Extra Expanded Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/TTF/Inconsolata-ExtraExpandedMedium.ttf", + "preferred_family_name": "Inconsolata", + "preferred_subfamily_name": "Extra Expanded Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 8, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Inconsolata-ExtraExpandedSemiBold.ttf||111444:1616951293.0": { + "family_name": "Inconsolata Extra Expanded SemiBold", + "font-family": "Inconsolata Extra Expanded SemiBold", + "font-stretch": "extra-expanded", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Inconsolata Extra Expanded SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/TTF/Inconsolata-ExtraExpandedSemiBold.ttf", + "preferred_family_name": "Inconsolata", + "preferred_subfamily_name": "Extra Expanded SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 8, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Inconsolata-ExtraLight.ttf||108108:1616951293.0": { + "family_name": "Inconsolata ExtraLight", + "font-family": "Inconsolata ExtraLight", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "275", + "fs_type": 0, + "full_name": "Inconsolata ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/TTF/Inconsolata-ExtraLight.ttf", + "preferred_family_name": "Inconsolata", + "preferred_subfamily_name": "ExtraLight", + "subfamily_name": "Regular", + "weight": 275, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Inconsolata-Light.ttf||108348:1616951293.0": { + "family_name": "Inconsolata Light", + "font-family": "Inconsolata Light", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Inconsolata Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/TTF/Inconsolata-Light.ttf", + "preferred_family_name": "Inconsolata", + "preferred_subfamily_name": "Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Inconsolata-Medium.ttf||109080:1616951293.0": { + "family_name": "Inconsolata Medium", + "font-family": "Inconsolata Medium", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Inconsolata Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/TTF/Inconsolata-Medium.ttf", + "preferred_family_name": "Inconsolata", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Inconsolata-Regular.ttf||108684:1616951293.0": { + "family_name": "Inconsolata", + "font-family": "Inconsolata", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Inconsolata Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/TTF/Inconsolata-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Inconsolata-SemiBold.ttf||109332:1616951293.0": { + "family_name": "Inconsolata SemiBold", + "font-family": "Inconsolata SemiBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Inconsolata SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/TTF/Inconsolata-SemiBold.ttf", + "preferred_family_name": "Inconsolata", + "preferred_subfamily_name": "SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Inconsolata-SemiCondensed.ttf||108612:1616951293.0": { + "family_name": "Inconsolata Semi Condensed", + "font-family": "Inconsolata Semi Condensed", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Inconsolata Semi Condensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/TTF/Inconsolata-SemiCondensed.ttf", + "preferred_family_name": "Inconsolata", + "preferred_subfamily_name": "Semi Condensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Inconsolata-SemiCondensedBlack.ttf||111260:1616951293.0": { + "family_name": "Inconsolata Semi Condensed Black", + "font-family": "Inconsolata Semi Condensed Black", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Inconsolata Semi Condensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/TTF/Inconsolata-SemiCondensedBlack.ttf", + "preferred_family_name": "Inconsolata", + "preferred_subfamily_name": "Semi Condensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Inconsolata-SemiCondensedBold.ttf||109760:1616951293.0": { + "family_name": "Inconsolata Semi Condensed Bold", + "font-family": "Inconsolata Semi Condensed Bold", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Inconsolata Semi Condensed Bold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/TTF/Inconsolata-SemiCondensedBold.ttf", + "preferred_family_name": "Inconsolata", + "preferred_subfamily_name": "Semi Condensed Bold", + "subfamily_name": "Regular", + "weight": 700, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Inconsolata-SemiCondensedExtraBold.ttf||109992:1616951293.0": { + "family_name": "Inconsolata Semi Condensed ExtraBold", + "font-family": "Inconsolata Semi Condensed ExtraBold", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Inconsolata Semi Condensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/TTF/Inconsolata-SemiCondensedExtraBold.ttf", + "preferred_family_name": "Inconsolata", + "preferred_subfamily_name": "Semi Condensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Inconsolata-SemiCondensedExtraLight.ttf||108612:1616951293.0": { + "family_name": "Inconsolata Semi Condensed ExtraLight", + "font-family": "Inconsolata Semi Condensed ExtraLight", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "275", + "fs_type": 0, + "full_name": "Inconsolata Semi Condensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/TTF/Inconsolata-SemiCondensedExtraLight.ttf", + "preferred_family_name": "Inconsolata", + "preferred_subfamily_name": "Semi Condensed ExtraLight", + "subfamily_name": "Regular", + "weight": 275, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Inconsolata-SemiCondensedLight.ttf||109024:1616951293.0": { + "family_name": "Inconsolata Semi Condensed Light", + "font-family": "Inconsolata Semi Condensed Light", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Inconsolata Semi Condensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/TTF/Inconsolata-SemiCondensedLight.ttf", + "preferred_family_name": "Inconsolata", + "preferred_subfamily_name": "Semi Condensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Inconsolata-SemiCondensedMedium.ttf||109548:1616951293.0": { + "family_name": "Inconsolata Semi Condensed Medium", + "font-family": "Inconsolata Semi Condensed Medium", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Inconsolata Semi Condensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/TTF/Inconsolata-SemiCondensedMedium.ttf", + "preferred_family_name": "Inconsolata", + "preferred_subfamily_name": "Semi Condensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Inconsolata-SemiCondensedSemiBold.ttf||109000:1616951293.0": { + "family_name": "Inconsolata Semi Condensed SemiBold", + "font-family": "Inconsolata Semi Condensed SemiBold", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Inconsolata Semi Condensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/TTF/Inconsolata-SemiCondensedSemiBold.ttf", + "preferred_family_name": "Inconsolata", + "preferred_subfamily_name": "Semi Condensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Inconsolata-SemiExpanded.ttf||109432:1616951293.0": { + "family_name": "Inconsolata Semi Expanded", + "font-family": "Inconsolata Semi Expanded", + "font-stretch": "semi-expanded", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Inconsolata Semi Expanded", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/TTF/Inconsolata-SemiExpanded.ttf", + "preferred_family_name": "Inconsolata", + "preferred_subfamily_name": "Semi Expanded", + "subfamily_name": "Regular", + "weight": 400, + "width": 6, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Inconsolata-SemiExpandedBlack.ttf||111976:1616951293.0": { + "family_name": "Inconsolata Semi Expanded Black", + "font-family": "Inconsolata Semi Expanded Black", + "font-stretch": "semi-expanded", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Inconsolata Semi Expanded Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/TTF/Inconsolata-SemiExpandedBlack.ttf", + "preferred_family_name": "Inconsolata", + "preferred_subfamily_name": "Semi Expanded Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 6, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Inconsolata-SemiExpandedBold.ttf||110620:1616951293.0": { + "family_name": "Inconsolata Semi Expanded Bold", + "font-family": "Inconsolata Semi Expanded Bold", + "font-stretch": "semi-expanded", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Inconsolata Semi Expanded Bold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/TTF/Inconsolata-SemiExpandedBold.ttf", + "preferred_family_name": "Inconsolata", + "preferred_subfamily_name": "Semi Expanded Bold", + "subfamily_name": "Regular", + "weight": 700, + "width": 6, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Inconsolata-SemiExpandedExtraBold.ttf||110852:1616951293.0": { + "family_name": "Inconsolata Semi Expanded ExtraBold", + "font-family": "Inconsolata Semi Expanded ExtraBold", + "font-stretch": "semi-expanded", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Inconsolata Semi Expanded ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/TTF/Inconsolata-SemiExpandedExtraBold.ttf", + "preferred_family_name": "Inconsolata", + "preferred_subfamily_name": "Semi Expanded ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 6, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Inconsolata-SemiExpandedExtraLight.ttf||110000:1616951293.0": { + "family_name": "Inconsolata Semi Expanded ExtraLight", + "font-family": "Inconsolata Semi Expanded ExtraLight", + "font-stretch": "semi-expanded", + "font-style": "normal", + "font-weight": "275", + "fs_type": 0, + "full_name": "Inconsolata Semi Expanded ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/TTF/Inconsolata-SemiExpandedExtraLight.ttf", + "preferred_family_name": "Inconsolata", + "preferred_subfamily_name": "Semi Expanded ExtraLight", + "subfamily_name": "Regular", + "weight": 275, + "width": 6, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Inconsolata-SemiExpandedLight.ttf||108992:1616951293.0": { + "family_name": "Inconsolata Semi Expanded Light", + "font-family": "Inconsolata Semi Expanded Light", + "font-stretch": "semi-expanded", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Inconsolata Semi Expanded Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/TTF/Inconsolata-SemiExpandedLight.ttf", + "preferred_family_name": "Inconsolata", + "preferred_subfamily_name": "Semi Expanded Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 6, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Inconsolata-SemiExpandedMedium.ttf||109772:1616951293.0": { + "family_name": "Inconsolata Semi Expanded Medium", + "font-family": "Inconsolata Semi Expanded Medium", + "font-stretch": "semi-expanded", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Inconsolata Semi Expanded Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/TTF/Inconsolata-SemiExpandedMedium.ttf", + "preferred_family_name": "Inconsolata", + "preferred_subfamily_name": "Semi Expanded Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 6, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Inconsolata-SemiExpandedSemiBold.ttf||110324:1616951293.0": { + "family_name": "Inconsolata Semi Expanded SemiBold", + "font-family": "Inconsolata Semi Expanded SemiBold", + "font-stretch": "semi-expanded", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Inconsolata Semi Expanded SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/TTF/Inconsolata-SemiExpandedSemiBold.ttf", + "preferred_family_name": "Inconsolata", + "preferred_subfamily_name": "Semi Expanded SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 6, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Inconsolata-UltraCondensed.ttf||107420:1616951293.0": { + "family_name": "Inconsolata Ultra Condensed", + "font-family": "Inconsolata Ultra Condensed", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Inconsolata Ultra Condensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/TTF/Inconsolata-UltraCondensed.ttf", + "preferred_family_name": "Inconsolata", + "preferred_subfamily_name": "Ultra Condensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Inconsolata-UltraCondensedBlack.ttf||109476:1616951293.0": { + "family_name": "Inconsolata Ultra Condensed Black", + "font-family": "Inconsolata Ultra Condensed Black", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Inconsolata Ultra Condensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/TTF/Inconsolata-UltraCondensedBlack.ttf", + "preferred_family_name": "Inconsolata", + "preferred_subfamily_name": "Ultra Condensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Inconsolata-UltraCondensedBold.ttf||109124:1616951293.0": { + "family_name": "Inconsolata Ultra Condensed Bold", + "font-family": "Inconsolata Ultra Condensed Bold", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Inconsolata Ultra Condensed Bold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/TTF/Inconsolata-UltraCondensedBold.ttf", + "preferred_family_name": "Inconsolata", + "preferred_subfamily_name": "Ultra Condensed Bold", + "subfamily_name": "Regular", + "weight": 700, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Inconsolata-UltraCondensedExtraBold.ttf||108928:1616951293.0": { + "family_name": "Inconsolata Ultra Condensed ExtraBold", + "font-family": "Inconsolata Ultra Condensed ExtraBold", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Inconsolata Ultra Condensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/TTF/Inconsolata-UltraCondensedExtraBold.ttf", + "preferred_family_name": "Inconsolata", + "preferred_subfamily_name": "Ultra Condensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Inconsolata-UltraCondensedExtraLight.ttf||107512:1616951293.0": { + "family_name": "Inconsolata Ultra Condensed ExtraLight", + "font-family": "Inconsolata Ultra Condensed ExtraLight", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "275", + "fs_type": 0, + "full_name": "Inconsolata Ultra Condensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/TTF/Inconsolata-UltraCondensedExtraLight.ttf", + "preferred_family_name": "Inconsolata", + "preferred_subfamily_name": "Ultra Condensed ExtraLight", + "subfamily_name": "Regular", + "weight": 275, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Inconsolata-UltraCondensedLight.ttf||107468:1616951293.0": { + "family_name": "Inconsolata Ultra Condensed Light", + "font-family": "Inconsolata Ultra Condensed Light", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Inconsolata Ultra Condensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/TTF/Inconsolata-UltraCondensedLight.ttf", + "preferred_family_name": "Inconsolata", + "preferred_subfamily_name": "Ultra Condensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Inconsolata-UltraCondensedMedium.ttf||108540:1616951293.0": { + "family_name": "Inconsolata Ultra Condensed Medium", + "font-family": "Inconsolata Ultra Condensed Medium", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Inconsolata Ultra Condensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/TTF/Inconsolata-UltraCondensedMedium.ttf", + "preferred_family_name": "Inconsolata", + "preferred_subfamily_name": "Ultra Condensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Inconsolata-UltraCondensedSemiBold.ttf||108580:1616951293.0": { + "family_name": "Inconsolata Ultra Condensed SemiBold", + "font-family": "Inconsolata Ultra Condensed SemiBold", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Inconsolata Ultra Condensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/TTF/Inconsolata-UltraCondensedSemiBold.ttf", + "preferred_family_name": "Inconsolata", + "preferred_subfamily_name": "Ultra Condensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Inconsolata-UltraExpanded.ttf||111600:1616951293.0": { + "family_name": "Inconsolata Ultra Expanded", + "font-family": "Inconsolata Ultra Expanded", + "font-stretch": "ultra-expanded", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Inconsolata Ultra Expanded", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/TTF/Inconsolata-UltraExpanded.ttf", + "preferred_family_name": "Inconsolata", + "preferred_subfamily_name": "Ultra Expanded", + "subfamily_name": "Regular", + "weight": 400, + "width": 9, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Inconsolata-UltraExpandedBlack.ttf||113856:1616951293.0": { + "family_name": "Inconsolata Ultra Expanded Black", + "font-family": "Inconsolata Ultra Expanded Black", + "font-stretch": "ultra-expanded", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Inconsolata Ultra Expanded Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/TTF/Inconsolata-UltraExpandedBlack.ttf", + "preferred_family_name": "Inconsolata", + "preferred_subfamily_name": "Ultra Expanded Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 9, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Inconsolata-UltraExpandedBold.ttf||114668:1616951293.0": { + "family_name": "Inconsolata Ultra Expanded Bold", + "font-family": "Inconsolata Ultra Expanded Bold", + "font-stretch": "ultra-expanded", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Inconsolata Ultra Expanded Bold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/TTF/Inconsolata-UltraExpandedBold.ttf", + "preferred_family_name": "Inconsolata", + "preferred_subfamily_name": "Ultra Expanded Bold", + "subfamily_name": "Regular", + "weight": 700, + "width": 9, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Inconsolata-UltraExpandedExtraBold.ttf||113784:1616951293.0": { + "family_name": "Inconsolata Ultra Expanded ExtraBold", + "font-family": "Inconsolata Ultra Expanded ExtraBold", + "font-stretch": "ultra-expanded", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Inconsolata Ultra Expanded ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/TTF/Inconsolata-UltraExpandedExtraBold.ttf", + "preferred_family_name": "Inconsolata", + "preferred_subfamily_name": "Ultra Expanded ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 9, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Inconsolata-UltraExpandedExtraLight.ttf||112288:1616951293.0": { + "family_name": "Inconsolata Ultra Expanded ExtraLight", + "font-family": "Inconsolata Ultra Expanded ExtraLight", + "font-stretch": "ultra-expanded", + "font-style": "normal", + "font-weight": "275", + "fs_type": 0, + "full_name": "Inconsolata Ultra Expanded ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/TTF/Inconsolata-UltraExpandedExtraLight.ttf", + "preferred_family_name": "Inconsolata", + "preferred_subfamily_name": "Ultra Expanded ExtraLight", + "subfamily_name": "Regular", + "weight": 275, + "width": 9, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Inconsolata-UltraExpandedLight.ttf||112828:1616951293.0": { + "family_name": "Inconsolata Ultra Expanded Light", + "font-family": "Inconsolata Ultra Expanded Light", + "font-stretch": "ultra-expanded", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Inconsolata Ultra Expanded Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/TTF/Inconsolata-UltraExpandedLight.ttf", + "preferred_family_name": "Inconsolata", + "preferred_subfamily_name": "Ultra Expanded Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 9, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Inconsolata-UltraExpandedMedium.ttf||112656:1616951293.0": { + "family_name": "Inconsolata Ultra Expanded Medium", + "font-family": "Inconsolata Ultra Expanded Medium", + "font-stretch": "ultra-expanded", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Inconsolata Ultra Expanded Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/TTF/Inconsolata-UltraExpandedMedium.ttf", + "preferred_family_name": "Inconsolata", + "preferred_subfamily_name": "Ultra Expanded Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 9, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Inconsolata-UltraExpandedSemiBold.ttf||113444:1616951293.0": { + "family_name": "Inconsolata Ultra Expanded SemiBold", + "font-family": "Inconsolata Ultra Expanded SemiBold", + "font-stretch": "ultra-expanded", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Inconsolata Ultra Expanded SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/TTF/Inconsolata-UltraExpandedSemiBold.ttf", + "preferred_family_name": "Inconsolata", + "preferred_subfamily_name": "Ultra Expanded SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 9, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Ligconsolata-Bold.ttf||112048:1616951293.0": { + "family_name": "Ligconsolata", + "font-family": "Ligconsolata", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Ligconsolata Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 8, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/TTF/Ligconsolata-Bold.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Ligconsolata-Regular.ttf||112072:1616951293.0": { + "family_name": "Ligconsolata", + "font-family": "Ligconsolata", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Ligconsolata Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 5, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/TTF/Ligconsolata-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/OpenSans-Bold.ttf||224452:1593427773.0": { + "family_name": "Open Sans", + "font-family": "Open Sans", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Open Sans Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 8, + 6, + 3, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/TTF/OpenSans-Bold.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/OpenSans-BoldItalic.ttf||213168:1593427773.0": { + "family_name": "Open Sans", + "font-family": "Open Sans", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Open Sans Bold Italic", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 8, + 6, + 3, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/TTF/OpenSans-BoldItalic.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/OpenSans-ExtraBold.ttf||222424:1593427773.0": { + "family_name": "Open Sans ExtraBold", + "font-family": "Open Sans ExtraBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Open Sans ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 9, + 6, + 3, + 8, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/TTF/OpenSans-ExtraBold.ttf", + "preferred_family_name": "Open Sans", + "preferred_subfamily_name": "ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/OpenSans-ExtraBoldItalic.ttf||213336:1593427773.0": { + "family_name": "Open Sans ExtraBold", + "font-family": "Open Sans ExtraBold", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "800", + "fs_type": 0, + "full_name": "Open Sans ExtraBold Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 9, + 6, + 3, + 8, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/TTF/OpenSans-ExtraBoldItalic.ttf", + "preferred_family_name": "Open Sans", + "preferred_subfamily_name": "ExtraBold Italic", + "subfamily_name": "Italic", + "weight": 800, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/OpenSans-Italic.ttf||212760:1593427773.0": { + "family_name": "Open Sans", + "font-family": "Open Sans", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Open Sans Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 6, + 6, + 3, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/TTF/OpenSans-Italic.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/OpenSans-Light.ttf||222236:1593427773.0": { + "family_name": "Open Sans Light", + "font-family": "Open Sans Light", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Open Sans Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 3, + 6, + 3, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/TTF/OpenSans-Light.ttf", + "preferred_family_name": "Open Sans", + "preferred_subfamily_name": "Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/OpenSans-LightItalic.ttf||213024:1593427773.0": { + "family_name": "Open Sans Light", + "font-family": "Open Sans Light", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "300", + "fs_type": 0, + "full_name": "Open Sans Light Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 3, + 6, + 3, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/TTF/OpenSans-LightItalic.ttf", + "preferred_family_name": "Open Sans", + "preferred_subfamily_name": "Light Italic", + "subfamily_name": "Italic", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/OpenSans-Regular.ttf||217276:1593427773.0": { + "family_name": "Open Sans", + "font-family": "Open Sans", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Open Sans Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 6, + 6, + 3, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/TTF/OpenSans-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/OpenSans-SemiBold.ttf||221164:1593427773.0": { + "family_name": "Open Sans SemiBold", + "font-family": "Open Sans SemiBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Open Sans SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 7, + 6, + 3, + 8, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/TTF/OpenSans-SemiBold.ttf", + "preferred_family_name": "Open Sans", + "preferred_subfamily_name": "SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/OpenSans-SemiBoldItalic.ttf||212732:1593427773.0": { + "family_name": "Open Sans SemiBold", + "font-family": "Open Sans SemiBold", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "600", + "fs_type": 0, + "full_name": "Open Sans SemiBold Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 7, + 6, + 3, + 8, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/TTF/OpenSans-SemiBoldItalic.ttf", + "preferred_family_name": "Open Sans", + "preferred_subfamily_name": "SemiBold Italic", + "subfamily_name": "Italic", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/OpenSansCondensed-Bold.ttf||264856:1593427773.0": { + "family_name": "Open Sans Condensed", + "font-family": "Open Sans Condensed", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Open Sans Condensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 8, + 6, + 3, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/TTF/OpenSansCondensed-Bold.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/OpenSansCondensed-Light.ttf||220940:1593427773.0": { + "family_name": "Open Sans Condensed Light", + "font-family": "Open Sans Condensed Light", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Open Sans Condensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 3, + 6, + 3, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/TTF/OpenSansCondensed-Light.ttf", + "preferred_family_name": "Open Sans Condensed", + "preferred_subfamily_name": "Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/OpenSansCondensed-LightItalic.ttf||210720:1593427773.0": { + "family_name": "Open Sans Condensed Light", + "font-family": "Open Sans Condensed Light", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "300", + "fs_type": 0, + "full_name": "Open Sans Condensed Light Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 3, + 6, + 3, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/TTF/OpenSansCondensed-LightItalic.ttf", + "preferred_family_name": "Open Sans Condensed", + "preferred_subfamily_name": "Light Italic", + "subfamily_name": "Italic", + "weight": 300, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Poky.ttf||25192:1625256442.0": { + "family_name": "Poky", + "font-family": "Poky", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 4, + "full_name": "PokyRegular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/TTF/Poky.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Roboto-Black.ttf||289480:1593428738.0": { + "family_name": "Roboto", + "font-family": "Roboto", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Roboto Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/TTF/Roboto-Black.ttf", + "preferred_family_name": "Roboto", + "preferred_subfamily_name": "Black", + "subfamily_name": "Black", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Roboto-BlackItalic.ttf||310260:1593428738.0": { + "family_name": "Roboto", + "font-family": "Roboto", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "900", + "fs_type": 0, + "full_name": "Roboto Black Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/TTF/Roboto-BlackItalic.ttf", + "preferred_family_name": "Roboto", + "preferred_subfamily_name": "Black Italic", + "subfamily_name": "Black Italic", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Roboto-Bold.ttf||288872:1593428738.0": { + "family_name": "Roboto", + "font-family": "Roboto", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Roboto Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/TTF/Roboto-Bold.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Roboto-BoldItalic.ttf||312608:1593428738.0": { + "family_name": "Roboto", + "font-family": "Roboto", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Roboto Bold Italic", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/TTF/Roboto-BoldItalic.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Roboto-Italic.ttf||311960:1593428738.0": { + "family_name": "Roboto", + "font-family": "Roboto", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Roboto Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/TTF/Roboto-Italic.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Roboto-Light.ttf||291788:1593428738.0": { + "family_name": "Roboto", + "font-family": "Roboto", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Roboto Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/TTF/Roboto-Light.ttf", + "preferred_family_name": "Roboto", + "preferred_subfamily_name": "Light", + "subfamily_name": "Light", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Roboto-LightItalic.ttf||315360:1593428738.0": { + "family_name": "Roboto", + "font-family": "Roboto", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "300", + "fs_type": 0, + "full_name": "Roboto Light Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/TTF/Roboto-LightItalic.ttf", + "preferred_family_name": "Roboto", + "preferred_subfamily_name": "Light Italic", + "subfamily_name": "Light Italic", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Roboto-Medium.ttf||289080:1593428738.0": { + "family_name": "Roboto", + "font-family": "Roboto", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Roboto Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/TTF/Roboto-Medium.ttf", + "preferred_family_name": "Roboto", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Medium", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Roboto-MediumItalic.ttf||309776:1593428738.0": { + "family_name": "Roboto", + "font-family": "Roboto", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "500", + "fs_type": 0, + "full_name": "Roboto Medium Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/TTF/Roboto-MediumItalic.ttf", + "preferred_family_name": "Roboto", + "preferred_subfamily_name": "Medium Italic", + "subfamily_name": "Medium Italic", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Roboto-Regular.ttf||292752:1593428738.0": { + "family_name": "Roboto", + "font-family": "Roboto", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Roboto Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/TTF/Roboto-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Roboto-Thin.ttf||294860:1593428738.0": { + "family_name": "Roboto", + "font-family": "Roboto", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "250", + "fs_type": 0, + "full_name": "Roboto Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/TTF/Roboto-Thin.ttf", + "preferred_family_name": "Roboto", + "preferred_subfamily_name": "Thin", + "subfamily_name": "Thin", + "weight": 250, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Roboto-ThinItalic.ttf||314240:1593428738.0": { + "family_name": "Roboto", + "font-family": "Roboto", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "250", + "fs_type": 0, + "full_name": "Roboto Thin Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/TTF/Roboto-ThinItalic.ttf", + "preferred_family_name": "Roboto", + "preferred_subfamily_name": "Thin Italic", + "subfamily_name": "Thin Italic", + "weight": 250, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/RobotoCondensed-Bold.ttf||285996:1593428738.0": { + "family_name": "Roboto Condensed", + "font-family": "Roboto Condensed", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Roboto Condensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/TTF/RobotoCondensed-Bold.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/RobotoCondensed-BoldItalic.ttf||306884:1593428738.0": { + "family_name": "Roboto Condensed", + "font-family": "Roboto Condensed", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Roboto Condensed Bold Italic", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/TTF/RobotoCondensed-BoldItalic.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/RobotoCondensed-Italic.ttf||309776:1593428738.0": { + "family_name": "Roboto Condensed", + "font-family": "Roboto Condensed", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Roboto Condensed Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/TTF/RobotoCondensed-Italic.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/RobotoCondensed-Light.ttf||286564:1593428738.0": { + "family_name": "Roboto Condensed", + "font-family": "Roboto Condensed", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Roboto Condensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/TTF/RobotoCondensed-Light.ttf", + "preferred_family_name": "Roboto Condensed", + "preferred_subfamily_name": "Light", + "subfamily_name": "Light", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/RobotoCondensed-LightItalic.ttf||311400:1593428738.0": { + "family_name": "Roboto Condensed", + "font-family": "Roboto Condensed", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "300", + "fs_type": 0, + "full_name": "Roboto Condensed Light Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/TTF/RobotoCondensed-LightItalic.ttf", + "preferred_family_name": "Roboto Condensed", + "preferred_subfamily_name": "Light Italic", + "subfamily_name": "Light Italic", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/RobotoCondensed-Regular.ttf||287876:1593428738.0": { + "family_name": "Roboto Condensed", + "font-family": "Roboto Condensed", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Roboto Condensed Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/TTF/RobotoCondensed-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Santana-Black.ttf||54400:1625256442.0": { + "family_name": "Santana-Black", + "font-family": "Santana-Black", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Santana-Black", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 0, + "panose": [ + 2, + 0, + 10, + 3, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/Santana-Black.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Santana-BlackCondensed.ttf||41592:1625256442.0": { + "family_name": "Santana-BlackCondensed", + "font-family": "Santana-BlackCondensed", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Santana-BlackCondensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 0, + "panose": [ + 2, + 0, + 0, + 6, + 6, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/Santana-BlackCondensed.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Santana-Bold.ttf||46520:1625256442.0": { + "family_name": "Santana", + "font-family": "Santana", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Santana-Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 0, + "panose": [ + 2, + 0, + 8, + 3, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/Santana-Bold.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Santana-RegularCondensed.ttf||41856:1625256442.0": { + "family_name": "Santana-RegularCondensed", + "font-family": "Santana-RegularCondensed", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Santana-RegularCondensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 0, + "panose": [ + 2, + 0, + 0, + 6, + 4, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/Santana-RegularCondensed.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Santana.ttf||44788:1625256442.0": { + "family_name": "Santana", + "font-family": "Santana", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Santana", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 0, + "panose": [ + 2, + 0, + 4, + 3, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/Santana.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/SantanaXtraCondensed.ttf||35716:1625256442.0": { + "family_name": "SantanaXtraCondensed", + "font-family": "SantanaXtraCondensed", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "SantanaXtraCondensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 0, + "panose": [ + 2, + 0, + 6, + 8, + 4, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/SantanaXtraCondensed.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/StyleBats.TTF||21296:1625256442.0": { + "family_name": "StyleBats", + "font-family": "StyleBats", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "StyleBats", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 1, + "panose": [ + 0, + 0, + 4, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/TTF/StyleBats.TTF", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "CleanCut", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/TechnicalCE.TTF||87232:1625256442.0": { + "family_name": "Technical CE", + "font-family": "Technical CE", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 1, + "full_name": "Technical CE", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 0, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/TTF/TechnicalCE.TTF", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Normal", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Times.TTF||330412:1599643855.0": { + "family_name": "Times New Roman", + "font-family": "Times New Roman", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Times New Roman", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 2, + 6, + 3, + 5, + 4, + 5, + 2, + 3, + 4 + ], + "path": "/usr/share/fonts/TTF/Times.TTF", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Timesbd.TTF||333900:1599643855.0": { + "family_name": "Times New Roman", + "font-family": "Times New Roman", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Times New Roman Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 2, + 8, + 3, + 7, + 5, + 5, + 2, + 3, + 4 + ], + "path": "/usr/share/fonts/TTF/Timesbd.TTF", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Timesbi.TTF||238612:1599643855.0": { + "family_name": "Times New Roman", + "font-family": "Times New Roman", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Times New Roman Bold Italic", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 2, + 7, + 3, + 6, + 5, + 5, + 9, + 3, + 4 + ], + "path": "/usr/share/fonts/TTF/Timesbi.TTF", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Timesi.TTF||247092:1599643855.0": { + "family_name": "Times New Roman", + "font-family": "Times New Roman", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Times New Roman Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 2, + 5, + 3, + 5, + 4, + 5, + 9, + 3, + 4 + ], + "path": "/usr/share/fonts/TTF/Timesi.TTF", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Trebucbd.ttf||123828:1599643855.0": { + "family_name": "Trebuchet MS", + "font-family": "Trebuchet MS", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 8, + "full_name": "Trebuchet MS Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 7, + 3, + 2, + 2, + 2, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/TTF/Trebucbd.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Vera.ttf||65932:1593432604.0": { + "family_name": "Bitstream Vera Sans", + "font-family": "Bitstream Vera Sans", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 4, + "full_name": "Bitstream Vera Sans", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 6, + 3, + 3, + 8, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/TTF/Vera.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Roman", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/VeraBI.ttf||63208:1593432604.0": { + "family_name": "Bitstream Vera Sans", + "font-family": "Bitstream Vera Sans", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 4, + "full_name": "Bitstream Vera Sans Bold Oblique", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 8, + 3, + 3, + 3, + 4, + 11, + 2, + 4 + ], + "path": "/usr/share/fonts/TTF/VeraBI.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold Oblique", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/VeraBd.ttf||58716:1593432604.0": { + "family_name": "Bitstream Vera Sans", + "font-family": "Bitstream Vera Sans", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 4, + "full_name": "Bitstream Vera Sans Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 8, + 3, + 3, + 6, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/TTF/VeraBd.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/VeraIt.ttf||63684:1593432604.0": { + "family_name": "Bitstream Vera Sans", + "font-family": "Bitstream Vera Sans", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 4, + "full_name": "Bitstream Vera Sans Oblique", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 6, + 3, + 3, + 3, + 4, + 11, + 2, + 4 + ], + "path": "/usr/share/fonts/TTF/VeraIt.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Oblique", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/VeraMoBI.ttf||55032:1593432604.0": { + "family_name": "Bitstream Vera Sans Mono", + "font-family": "Bitstream Vera Sans Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 4, + "full_name": "Bitstream Vera Sans Mono Bold Oblique", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 7, + 9, + 3, + 3, + 4, + 11, + 2, + 4 + ], + "path": "/usr/share/fonts/TTF/VeraMoBI.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold Oblique", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/VeraMoBd.ttf||49052:1593432604.0": { + "family_name": "Bitstream Vera Sans Mono", + "font-family": "Bitstream Vera Sans Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 4, + "full_name": "Bitstream Vera Sans Mono Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 7, + 9, + 3, + 6, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/TTF/VeraMoBd.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/VeraMoIt.ttf||54508:1593432604.0": { + "family_name": "Bitstream Vera Sans Mono", + "font-family": "Bitstream Vera Sans Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 4, + "full_name": "Bitstream Vera Sans Mono Oblique", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 6, + 9, + 3, + 3, + 4, + 11, + 2, + 4 + ], + "path": "/usr/share/fonts/TTF/VeraMoIt.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Oblique", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/VeraMono.ttf||49224:1593432604.0": { + "family_name": "Bitstream Vera Sans Mono", + "font-family": "Bitstream Vera Sans Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 4, + "full_name": "Bitstream Vera Sans Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 6, + 9, + 3, + 8, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/TTF/VeraMono.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Roman", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/VeraSe.ttf||60280:1593432604.0": { + "family_name": "Bitstream Vera Serif", + "font-family": "Bitstream Vera Serif", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 4, + "full_name": "Bitstream Vera Serif", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 6, + 6, + 3, + 5, + 6, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/TTF/VeraSe.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Roman", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/VeraSeBd.ttf||58736:1593432604.0": { + "family_name": "Bitstream Vera Serif", + "font-family": "Bitstream Vera Serif", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 4, + "full_name": "Bitstream Vera Serif Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 6, + 8, + 3, + 5, + 6, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/TTF/VeraSeBd.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Verdana.TTF||139640:1599643855.0": { + "family_name": "Verdana", + "font-family": "Verdana", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Verdana", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 6, + 4, + 3, + 5, + 4, + 4, + 2, + 4 + ], + "path": "/usr/share/fonts/TTF/Verdana.TTF", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Verdanab.TTF||136032:1599643855.0": { + "family_name": "Verdana", + "font-family": "Verdana", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Verdana Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 8, + 4, + 3, + 5, + 4, + 4, + 2, + 4 + ], + "path": "/usr/share/fonts/TTF/Verdanab.TTF", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Verdanai.TTF||154264:1599643855.0": { + "family_name": "Verdana", + "font-family": "Verdana", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Verdana Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 6, + 4, + 3, + 5, + 4, + 11, + 2, + 4 + ], + "path": "/usr/share/fonts/TTF/Verdanai.TTF", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Verdanaz.TTF||153324:1599643855.0": { + "family_name": "Verdana", + "font-family": "Verdana", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Verdana Bold Italic", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 8, + 4, + 3, + 5, + 4, + 11, + 2, + 4 + ], + "path": "/usr/share/fonts/TTF/Verdanaz.TTF", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/Webdings.TTF||118752:1599643855.0": { + "family_name": "Webdings", + "font-family": "Webdings", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Webdings", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 1, + "panose": [ + 5, + 3, + 1, + 2, + 1, + 5, + 9, + 6, + 7, + 3 + ], + "path": "/usr/share/fonts/TTF/Webdings.TTF", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/calibri.ttf||811052:1634564747.0": { + "family_name": "Calibri", + "font-family": "Calibri", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 8, + "full_name": "Calibri", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 15, + 5, + 2, + 2, + 2, + 4, + 3, + 2, + 4 + ], + "path": "/usr/share/fonts/TTF/calibri.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/calibrib.ttf||848720:1634564747.0": { + "family_name": "Calibri", + "font-family": "Calibri", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 8, + "full_name": "Calibri Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 15, + 7, + 2, + 3, + 4, + 4, + 3, + 2, + 4 + ], + "path": "/usr/share/fonts/TTF/calibrib.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/calibrii.ttf||853348:1634564747.0": { + "family_name": "Calibri", + "font-family": "Calibri", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 8, + "full_name": "Calibri Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 15, + 5, + 2, + 2, + 2, + 4, + 10, + 2, + 4 + ], + "path": "/usr/share/fonts/TTF/calibrii.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/calibriz.ttf||899560:1634564747.0": { + "family_name": "Calibri", + "font-family": "Calibri", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 8, + "full_name": "Calibri Bold Italic", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 15, + 7, + 2, + 3, + 4, + 4, + 10, + 2, + 4 + ], + "path": "/usr/share/fonts/TTF/calibriz.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/cambria-math.ttf||1273712:1634564747.0": { + "family_name": "Cambria Math", + "font-family": "Cambria Math", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 8, + "full_name": "Cambria Math", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 4, + 5, + 3, + 5, + 4, + 6, + 3, + 2, + 4 + ], + "path": "/usr/share/fonts/TTF/cambria-math.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/cambria.ttf||993912:1634564747.0": { + "family_name": "Cambria", + "font-family": "Cambria", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 8, + "full_name": "Cambria", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 4, + 5, + 3, + 5, + 4, + 6, + 3, + 2, + 4 + ], + "path": "/usr/share/fonts/TTF/cambria.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/cambriab.ttf||792488:1634564747.0": { + "family_name": "Cambria", + "font-family": "Cambria", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 8, + "full_name": "Cambria Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 4, + 8, + 3, + 5, + 4, + 6, + 3, + 2, + 4 + ], + "path": "/usr/share/fonts/TTF/cambriab.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/cambriai.ttf||827080:1634564747.0": { + "family_name": "Cambria", + "font-family": "Cambria", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 8, + "full_name": "Cambria Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 4, + 5, + 3, + 5, + 4, + 6, + 10, + 2, + 4 + ], + "path": "/usr/share/fonts/TTF/cambriai.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/cambriaz.ttf||805864:1634564747.0": { + "family_name": "Cambria", + "font-family": "Cambria", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 8, + "full_name": "Cambria Bold Italic", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 4, + 8, + 3, + 5, + 4, + 6, + 10, + 2, + 4 + ], + "path": "/usr/share/fonts/TTF/cambriaz.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/candara.ttf||218504:1634564747.0": { + "family_name": "Candara", + "font-family": "Candara", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 8, + "full_name": "Candara", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 14, + 5, + 2, + 3, + 3, + 3, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/TTF/candara.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/candarab.ttf||226564:1634564747.0": { + "family_name": "Candara", + "font-family": "Candara", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 8, + "full_name": "Candara Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 14, + 7, + 2, + 3, + 3, + 3, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/TTF/candarab.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/candarai.ttf||226604:1634564747.0": { + "family_name": "Candara", + "font-family": "Candara", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 8, + "full_name": "Candara Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 14, + 5, + 2, + 3, + 3, + 3, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/TTF/candarai.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/candaraz.ttf||228304:1634564747.0": { + "family_name": "Candara", + "font-family": "Candara", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 8, + "full_name": "Candara Bold Italic", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 14, + 7, + 2, + 3, + 3, + 3, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/TTF/candaraz.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/consola.ttf||358256:1634564747.0": { + "family_name": "Consolas", + "font-family": "Consolas", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 8, + "full_name": "Consolas", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 6, + 9, + 2, + 2, + 4, + 3, + 2, + 4 + ], + "path": "/usr/share/fonts/TTF/consola.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/consolab.ttf||368520:1634564747.0": { + "family_name": "Consolas", + "font-family": "Consolas", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 8, + "full_name": "Consolas Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 7, + 9, + 2, + 2, + 4, + 3, + 2, + 4 + ], + "path": "/usr/share/fonts/TTF/consolab.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/consolai.ttf||364864:1634564747.0": { + "family_name": "Consolas", + "font-family": "Consolas", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 8, + "full_name": "Consolas Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 6, + 9, + 2, + 2, + 4, + 10, + 2, + 4 + ], + "path": "/usr/share/fonts/TTF/consolai.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/consolaz.ttf||375056:1634564747.0": { + "family_name": "Consolas", + "font-family": "Consolas", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 8, + "full_name": "Consolas Bold Italic", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 7, + 9, + 2, + 2, + 4, + 10, + 2, + 4 + ], + "path": "/usr/share/fonts/TTF/consolaz.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/constan.ttf||448768:1634564747.0": { + "family_name": "Constantia", + "font-family": "Constantia", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 8, + "full_name": "Constantia", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 3, + 6, + 2, + 5, + 3, + 6, + 3, + 3, + 3 + ], + "path": "/usr/share/fonts/TTF/constan.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/constanb.ttf||450848:1634564747.0": { + "family_name": "Constantia", + "font-family": "Constantia", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 8, + "full_name": "Constantia Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 3, + 7, + 2, + 6, + 3, + 6, + 3, + 3, + 3 + ], + "path": "/usr/share/fonts/TTF/constanb.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/constani.ttf||447772:1634564747.0": { + "family_name": "Constantia", + "font-family": "Constantia", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 8, + "full_name": "Constantia Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 3, + 6, + 2, + 5, + 3, + 6, + 10, + 3, + 3 + ], + "path": "/usr/share/fonts/TTF/constani.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/constanz.ttf||454588:1634564747.0": { + "family_name": "Constantia", + "font-family": "Constantia", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 8, + "full_name": "Constantia Bold Italic", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 3, + 7, + 2, + 6, + 3, + 6, + 10, + 3, + 3 + ], + "path": "/usr/share/fonts/TTF/constanz.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/corbel.ttf||260648:1634564747.0": { + "family_name": "Corbel", + "font-family": "Corbel", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 8, + "full_name": "Corbel", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 5, + 3, + 2, + 2, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/TTF/corbel.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/corbelb.ttf||274388:1634564747.0": { + "family_name": "Corbel", + "font-family": "Corbel", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 8, + "full_name": "Corbel Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 7, + 3, + 2, + 2, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/TTF/corbelb.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/corbeli.ttf||269048:1634564747.0": { + "family_name": "Corbel", + "font-family": "Corbel", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 8, + "full_name": "Corbel Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 5, + 3, + 2, + 2, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/TTF/corbeli.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/corbelz.ttf||279400:1634564747.0": { + "family_name": "Corbel", + "font-family": "Corbel", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 8, + "full_name": "Corbel Bold Italic", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 7, + 3, + 2, + 2, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/TTF/corbelz.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/cour.ttf||302688:1599643855.0": { + "family_name": "Courier New", + "font-family": "Courier New", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Courier New", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 7, + 3, + 9, + 2, + 2, + 5, + 2, + 4, + 4 + ], + "path": "/usr/share/fonts/TTF/cour.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/courbd.ttf||311508:1599643855.0": { + "family_name": "Courier New", + "font-family": "Courier New", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Courier New Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 7, + 6, + 9, + 2, + 2, + 5, + 2, + 4, + 4 + ], + "path": "/usr/share/fonts/TTF/courbd.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/courbi.ttf||234788:1599643855.0": { + "family_name": "Courier New", + "font-family": "Courier New", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Courier New Bold Italic", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 7, + 6, + 9, + 2, + 2, + 5, + 9, + 4, + 4 + ], + "path": "/usr/share/fonts/TTF/courbi.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/couri.ttf||244156:1599643855.0": { + "family_name": "Courier New", + "font-family": "Courier New", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Courier New Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 7, + 4, + 9, + 2, + 2, + 5, + 9, + 4, + 4 + ], + "path": "/usr/share/fonts/TTF/couri.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/desyrel.ttf||90928:1625256442.0": { + "family_name": "Desyrel", + "font-family": "Desyrel", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Desyrel", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 0, + 6, + 3, + 5, + 0, + 0, + 2, + 0, + 3 + ], + "path": "/usr/share/fonts/TTF/desyrel.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/fa-brands-400.ttf||181852:1648385325.0": { + "family_name": "Font Awesome 6 Brands Regular", + "font-family": "Font Awesome 6 Brands Regular", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Font Awesome 6 Brands Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 5, + 3, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/TTF/fa-brands-400.ttf", + "preferred_family_name": "Font Awesome 6 Brands", + "preferred_subfamily_name": "Regular", + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/fa-regular-400.ttf||60520:1648385325.0": { + "family_name": "Font Awesome 6 Free Regular", + "font-family": "Font Awesome 6 Free Regular", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Font Awesome 6 Free Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 5, + 3, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/TTF/fa-regular-400.ttf", + "preferred_family_name": "Font Awesome 6 Free", + "preferred_subfamily_name": "Regular", + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/fa-solid-900.ttf||388460:1648385325.0": { + "family_name": "Font Awesome 6 Free Solid", + "font-family": "Font Awesome 6 Free Solid", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Font Awesome 6 Free Solid", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 9, + 3, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/TTF/fa-solid-900.ttf", + "preferred_family_name": "Font Awesome 6 Free", + "preferred_subfamily_name": "Solid", + "subfamily_name": "Solid", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/fa-v4compatibility.ttf||10556:1648385325.0": { + "family_name": "Font Awesome v4 Compatibility Regular", + "font-family": "Font Awesome v4 Compatibility Regular", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Font Awesome v4 Compatibility Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 5, + 3, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/TTF/fa-v4compatibility.ttf", + "preferred_family_name": "Font Awesome v4 Compatibility", + "preferred_subfamily_name": "Regular", + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/iosevka-bold.ttf||6082836:1658693493.0": { + "family_name": "Iosevka", + "font-family": "Iosevka", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Iosevka Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 8, + 9, + 3, + 0, + 0, + 0, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/iosevka-bold.ttf", + "preferred_family_name": "Iosevka", + "preferred_subfamily_name": "Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": "Iosevka", + "wws_subfamily_name": "Bold" + }, + "/usr/share/fonts/TTF/iosevka-bolditalic.ttf||6315324:1658693493.0": { + "family_name": "Iosevka", + "font-family": "Iosevka", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Iosevka Bold Italic", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 8, + 9, + 3, + 0, + 0, + 0, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/iosevka-bolditalic.ttf", + "preferred_family_name": "Iosevka", + "preferred_subfamily_name": "Bold Italic", + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 5, + "wws_family_name": "Iosevka", + "wws_subfamily_name": "Bold Italic" + }, + "/usr/share/fonts/TTF/iosevka-boldoblique.ttf||6299712:1658693493.0": { + "family_name": "Iosevka Oblique", + "font-family": "Iosevka Oblique", + "font-stretch": "normal", + "font-style": "oblique", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Iosevka Bold Oblique", + "is_bold": true, + "is_italic": true, + "is_oblique": true, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 8, + 9, + 3, + 0, + 0, + 0, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/iosevka-boldoblique.ttf", + "preferred_family_name": "Iosevka", + "preferred_subfamily_name": "Bold Oblique", + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": "Iosevka", + "wws_subfamily_name": "Bold Oblique" + }, + "/usr/share/fonts/TTF/iosevka-extended.ttf||5765816:1658693493.0": { + "family_name": "Iosevka Extended", + "font-family": "Iosevka Extended", + "font-stretch": "expanded", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Iosevka Extended", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 5, + 9, + 3, + 0, + 0, + 0, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/iosevka-extended.ttf", + "preferred_family_name": "Iosevka", + "preferred_subfamily_name": "Extended", + "subfamily_name": "Regular", + "weight": 400, + "width": 7, + "wws_family_name": "Iosevka", + "wws_subfamily_name": "Extended" + }, + "/usr/share/fonts/TTF/iosevka-extendedbold.ttf||5794652:1658693493.0": { + "family_name": "Iosevka Extended", + "font-family": "Iosevka Extended", + "font-stretch": "expanded", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Iosevka Bold Extended", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 8, + 9, + 3, + 0, + 0, + 0, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/iosevka-extendedbold.ttf", + "preferred_family_name": "Iosevka", + "preferred_subfamily_name": "Bold Extended", + "subfamily_name": "Bold", + "weight": 700, + "width": 7, + "wws_family_name": "Iosevka", + "wws_subfamily_name": "Bold Extended" + }, + "/usr/share/fonts/TTF/iosevka-extendedbolditalic.ttf||6009252:1658693493.0": { + "family_name": "Iosevka Extended", + "font-family": "Iosevka Extended", + "font-stretch": "expanded", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Iosevka Bold Extended Italic", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 8, + 9, + 3, + 0, + 0, + 0, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/iosevka-extendedbolditalic.ttf", + "preferred_family_name": "Iosevka", + "preferred_subfamily_name": "Bold Extended Italic", + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 7, + "wws_family_name": "Iosevka", + "wws_subfamily_name": "Bold Extended Italic" + }, + "/usr/share/fonts/TTF/iosevka-extendedboldoblique.ttf||5993668:1658693493.0": { + "family_name": "Iosevka Extended Oblique", + "font-family": "Iosevka Extended Oblique", + "font-stretch": "expanded", + "font-style": "oblique", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Iosevka Bold Extended Oblique", + "is_bold": true, + "is_italic": true, + "is_oblique": true, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 8, + 9, + 3, + 0, + 0, + 0, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/iosevka-extendedboldoblique.ttf", + "preferred_family_name": "Iosevka", + "preferred_subfamily_name": "Bold Extended Oblique", + "subfamily_name": "Bold", + "weight": 700, + "width": 7, + "wws_family_name": "Iosevka", + "wws_subfamily_name": "Bold Extended Oblique" + }, + "/usr/share/fonts/TTF/iosevka-extendedextrabold.ttf||5807036:1658693493.0": { + "family_name": "Iosevka Extrabold Extended", + "font-family": "Iosevka Extrabold Extended", + "font-stretch": "expanded", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Iosevka Extrabold Extended", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 9, + 9, + 3, + 0, + 0, + 0, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/iosevka-extendedextrabold.ttf", + "preferred_family_name": "Iosevka", + "preferred_subfamily_name": "Extrabold Extended", + "subfamily_name": "Regular", + "weight": 800, + "width": 7, + "wws_family_name": "Iosevka", + "wws_subfamily_name": "Extrabold Extended" + }, + "/usr/share/fonts/TTF/iosevka-extendedextrabolditalic.ttf||6042792:1658693493.0": { + "family_name": "Iosevka Extrabold Extended", + "font-family": "Iosevka Extrabold Extended", + "font-stretch": "expanded", + "font-style": "italic", + "font-weight": "800", + "fs_type": 0, + "full_name": "Iosevka Extrabold Extended Italic", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 9, + 9, + 3, + 0, + 0, + 0, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/iosevka-extendedextrabolditalic.ttf", + "preferred_family_name": "Iosevka", + "preferred_subfamily_name": "Extrabold Extended Italic", + "subfamily_name": "Italic", + "weight": 800, + "width": 7, + "wws_family_name": "Iosevka", + "wws_subfamily_name": "Extrabold Extended Italic" + }, + "/usr/share/fonts/TTF/iosevka-extendedextraboldoblique.ttf||6025664:1658693493.0": { + "family_name": "Iosevka XBdExObl", + "font-family": "Iosevka XBdExObl", + "font-stretch": "expanded", + "font-style": "oblique", + "font-weight": "800", + "fs_type": 0, + "full_name": "Iosevka Extrabold Extended Oblique", + "is_bold": true, + "is_italic": true, + "is_oblique": true, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 9, + 9, + 3, + 0, + 0, + 0, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/iosevka-extendedextraboldoblique.ttf", + "preferred_family_name": "Iosevka", + "preferred_subfamily_name": "Extrabold Extended Oblique", + "subfamily_name": "Regular", + "weight": 800, + "width": 7, + "wws_family_name": "Iosevka", + "wws_subfamily_name": "Extrabold Extended Oblique" + }, + "/usr/share/fonts/TTF/iosevka-extendedextralight.ttf||5631420:1658693493.0": { + "family_name": "Iosevka Extralight Extended", + "font-family": "Iosevka Extralight Extended", + "font-stretch": "expanded", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Iosevka Extralight Extended", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 3, + 9, + 3, + 0, + 0, + 0, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/iosevka-extendedextralight.ttf", + "preferred_family_name": "Iosevka", + "preferred_subfamily_name": "Extralight Extended", + "subfamily_name": "Regular", + "weight": 200, + "width": 7, + "wws_family_name": "Iosevka", + "wws_subfamily_name": "Extralight Extended" + }, + "/usr/share/fonts/TTF/iosevka-extendedextralightitalic.ttf||5841952:1658693493.0": { + "family_name": "Iosevka Extralight Extended", + "font-family": "Iosevka Extralight Extended", + "font-stretch": "expanded", + "font-style": "italic", + "font-weight": "200", + "fs_type": 0, + "full_name": "Iosevka Extralight Extended Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 3, + 9, + 3, + 0, + 0, + 0, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/iosevka-extendedextralightitalic.ttf", + "preferred_family_name": "Iosevka", + "preferred_subfamily_name": "Extralight Extended Italic", + "subfamily_name": "Italic", + "weight": 200, + "width": 7, + "wws_family_name": "Iosevka", + "wws_subfamily_name": "Extralight Extended Italic" + }, + "/usr/share/fonts/TTF/iosevka-extendedextralightoblique.ttf||5823892:1658693493.0": { + "family_name": "Iosevka XLtExObl", + "font-family": "Iosevka XLtExObl", + "font-stretch": "expanded", + "font-style": "oblique", + "font-weight": "200", + "fs_type": 0, + "full_name": "Iosevka Extralight Extended Oblique", + "is_bold": false, + "is_italic": true, + "is_oblique": true, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 3, + 9, + 3, + 0, + 0, + 0, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/iosevka-extendedextralightoblique.ttf", + "preferred_family_name": "Iosevka", + "preferred_subfamily_name": "Extralight Extended Oblique", + "subfamily_name": "Regular", + "weight": 200, + "width": 7, + "wws_family_name": "Iosevka", + "wws_subfamily_name": "Extralight Extended Oblique" + }, + "/usr/share/fonts/TTF/iosevka-extendedheavy.ttf||5864860:1658693493.0": { + "family_name": "Iosevka Heavy Extended", + "font-family": "Iosevka Heavy Extended", + "font-stretch": "expanded", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Iosevka Heavy Extended", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 10, + 9, + 3, + 0, + 0, + 0, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/iosevka-extendedheavy.ttf", + "preferred_family_name": "Iosevka", + "preferred_subfamily_name": "Heavy Extended", + "subfamily_name": "Regular", + "weight": 900, + "width": 7, + "wws_family_name": "Iosevka", + "wws_subfamily_name": "Heavy Extended" + }, + "/usr/share/fonts/TTF/iosevka-extendedheavyitalic.ttf||6050964:1658693493.0": { + "family_name": "Iosevka Heavy Extended", + "font-family": "Iosevka Heavy Extended", + "font-stretch": "expanded", + "font-style": "italic", + "font-weight": "900", + "fs_type": 0, + "full_name": "Iosevka Heavy Extended Italic", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 10, + 9, + 3, + 0, + 0, + 0, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/iosevka-extendedheavyitalic.ttf", + "preferred_family_name": "Iosevka", + "preferred_subfamily_name": "Heavy Extended Italic", + "subfamily_name": "Italic", + "weight": 900, + "width": 7, + "wws_family_name": "Iosevka", + "wws_subfamily_name": "Heavy Extended Italic" + }, + "/usr/share/fonts/TTF/iosevka-extendedheavyoblique.ttf||6043512:1658693493.0": { + "family_name": "Iosevka Heavy Extended Oblique", + "font-family": "Iosevka Heavy Extended Oblique", + "font-stretch": "expanded", + "font-style": "oblique", + "font-weight": "900", + "fs_type": 0, + "full_name": "Iosevka Heavy Extended Oblique", + "is_bold": true, + "is_italic": true, + "is_oblique": true, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 10, + 9, + 3, + 0, + 0, + 0, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/iosevka-extendedheavyoblique.ttf", + "preferred_family_name": "Iosevka", + "preferred_subfamily_name": "Heavy Extended Oblique", + "subfamily_name": "Regular", + "weight": 900, + "width": 7, + "wws_family_name": "Iosevka", + "wws_subfamily_name": "Heavy Extended Oblique" + }, + "/usr/share/fonts/TTF/iosevka-extendeditalic.ttf||5989508:1658693493.0": { + "family_name": "Iosevka Extended", + "font-family": "Iosevka Extended", + "font-stretch": "expanded", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Iosevka Extended Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 5, + 9, + 3, + 0, + 0, + 0, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/iosevka-extendeditalic.ttf", + "preferred_family_name": "Iosevka", + "preferred_subfamily_name": "Extended Italic", + "subfamily_name": "Italic", + "weight": 400, + "width": 7, + "wws_family_name": "Iosevka", + "wws_subfamily_name": "Extended Italic" + }, + "/usr/share/fonts/TTF/iosevka-extendedlight.ttf||5738532:1658693493.0": { + "family_name": "Iosevka Light Extended", + "font-family": "Iosevka Light Extended", + "font-stretch": "expanded", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Iosevka Light Extended", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 4, + 9, + 3, + 0, + 0, + 0, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/iosevka-extendedlight.ttf", + "preferred_family_name": "Iosevka", + "preferred_subfamily_name": "Light Extended", + "subfamily_name": "Regular", + "weight": 300, + "width": 7, + "wws_family_name": "Iosevka", + "wws_subfamily_name": "Light Extended" + }, + "/usr/share/fonts/TTF/iosevka-extendedlightitalic.ttf||5944888:1658693493.0": { + "family_name": "Iosevka Light Extended", + "font-family": "Iosevka Light Extended", + "font-stretch": "expanded", + "font-style": "italic", + "font-weight": "300", + "fs_type": 0, + "full_name": "Iosevka Light Extended Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 4, + 9, + 3, + 0, + 0, + 0, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/iosevka-extendedlightitalic.ttf", + "preferred_family_name": "Iosevka", + "preferred_subfamily_name": "Light Extended Italic", + "subfamily_name": "Italic", + "weight": 300, + "width": 7, + "wws_family_name": "Iosevka", + "wws_subfamily_name": "Light Extended Italic" + }, + "/usr/share/fonts/TTF/iosevka-extendedlightoblique.ttf||5924116:1658693493.0": { + "family_name": "Iosevka Light Extended Oblique", + "font-family": "Iosevka Light Extended Oblique", + "font-stretch": "expanded", + "font-style": "oblique", + "font-weight": "300", + "fs_type": 0, + "full_name": "Iosevka Light Extended Oblique", + "is_bold": false, + "is_italic": true, + "is_oblique": true, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 4, + 9, + 3, + 0, + 0, + 0, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/iosevka-extendedlightoblique.ttf", + "preferred_family_name": "Iosevka", + "preferred_subfamily_name": "Light Extended Oblique", + "subfamily_name": "Regular", + "weight": 300, + "width": 7, + "wws_family_name": "Iosevka", + "wws_subfamily_name": "Light Extended Oblique" + }, + "/usr/share/fonts/TTF/iosevka-extendedmedium.ttf||5713116:1658693493.0": { + "family_name": "Iosevka Medium Extended", + "font-family": "Iosevka Medium Extended", + "font-stretch": "expanded", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Iosevka Medium Extended", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 6, + 9, + 3, + 0, + 0, + 0, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/iosevka-extendedmedium.ttf", + "preferred_family_name": "Iosevka", + "preferred_subfamily_name": "Medium Extended", + "subfamily_name": "Regular", + "weight": 500, + "width": 7, + "wws_family_name": "Iosevka", + "wws_subfamily_name": "Medium Extended" + }, + "/usr/share/fonts/TTF/iosevka-extendedmediumitalic.ttf||5971156:1658693493.0": { + "family_name": "Iosevka Medium Extended", + "font-family": "Iosevka Medium Extended", + "font-stretch": "expanded", + "font-style": "italic", + "font-weight": "500", + "fs_type": 0, + "full_name": "Iosevka Medium Extended Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 6, + 9, + 3, + 0, + 0, + 0, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/iosevka-extendedmediumitalic.ttf", + "preferred_family_name": "Iosevka", + "preferred_subfamily_name": "Medium Extended Italic", + "subfamily_name": "Italic", + "weight": 500, + "width": 7, + "wws_family_name": "Iosevka", + "wws_subfamily_name": "Medium Extended Italic" + }, + "/usr/share/fonts/TTF/iosevka-extendedmediumoblique.ttf||5951376:1658693493.0": { + "family_name": "Iosevka MdExObl", + "font-family": "Iosevka MdExObl", + "font-stretch": "expanded", + "font-style": "oblique", + "font-weight": "500", + "fs_type": 0, + "full_name": "Iosevka Medium Extended Oblique", + "is_bold": false, + "is_italic": true, + "is_oblique": true, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 6, + 9, + 3, + 0, + 0, + 0, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/iosevka-extendedmediumoblique.ttf", + "preferred_family_name": "Iosevka", + "preferred_subfamily_name": "Medium Extended Oblique", + "subfamily_name": "Regular", + "weight": 500, + "width": 7, + "wws_family_name": "Iosevka", + "wws_subfamily_name": "Medium Extended Oblique" + }, + "/usr/share/fonts/TTF/iosevka-extendedoblique.ttf||5968620:1658693493.0": { + "family_name": "Iosevka Extended Oblique", + "font-family": "Iosevka Extended Oblique", + "font-stretch": "expanded", + "font-style": "oblique", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Iosevka Extended Oblique", + "is_bold": false, + "is_italic": true, + "is_oblique": true, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 5, + 9, + 3, + 0, + 0, + 0, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/iosevka-extendedoblique.ttf", + "preferred_family_name": "Iosevka", + "preferred_subfamily_name": "Extended Oblique", + "subfamily_name": "Regular", + "weight": 400, + "width": 7, + "wws_family_name": "Iosevka", + "wws_subfamily_name": "Extended Oblique" + }, + "/usr/share/fonts/TTF/iosevka-extendedsemibold.ttf||5770320:1658693493.0": { + "family_name": "Iosevka Semibold Extended", + "font-family": "Iosevka Semibold Extended", + "font-stretch": "expanded", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Iosevka Semibold Extended", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 7, + 9, + 3, + 0, + 0, + 0, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/iosevka-extendedsemibold.ttf", + "preferred_family_name": "Iosevka", + "preferred_subfamily_name": "Semibold Extended", + "subfamily_name": "Regular", + "weight": 600, + "width": 7, + "wws_family_name": "Iosevka", + "wws_subfamily_name": "Semibold Extended" + }, + "/usr/share/fonts/TTF/iosevka-extendedsemibolditalic.ttf||6008944:1658693493.0": { + "family_name": "Iosevka Semibold Extended", + "font-family": "Iosevka Semibold Extended", + "font-stretch": "expanded", + "font-style": "italic", + "font-weight": "600", + "fs_type": 0, + "full_name": "Iosevka Semibold Extended Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 7, + 9, + 3, + 0, + 0, + 0, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/iosevka-extendedsemibolditalic.ttf", + "preferred_family_name": "Iosevka", + "preferred_subfamily_name": "Semibold Extended Italic", + "subfamily_name": "Italic", + "weight": 600, + "width": 7, + "wws_family_name": "Iosevka", + "wws_subfamily_name": "Semibold Extended Italic" + }, + "/usr/share/fonts/TTF/iosevka-extendedsemiboldoblique.ttf||5989552:1658693493.0": { + "family_name": "Iosevka SmBdExObl", + "font-family": "Iosevka SmBdExObl", + "font-stretch": "expanded", + "font-style": "oblique", + "font-weight": "600", + "fs_type": 0, + "full_name": "Iosevka Semibold Extended Oblique", + "is_bold": false, + "is_italic": true, + "is_oblique": true, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 7, + 9, + 3, + 0, + 0, + 0, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/iosevka-extendedsemiboldoblique.ttf", + "preferred_family_name": "Iosevka", + "preferred_subfamily_name": "Semibold Extended Oblique", + "subfamily_name": "Regular", + "weight": 600, + "width": 7, + "wws_family_name": "Iosevka", + "wws_subfamily_name": "Semibold Extended Oblique" + }, + "/usr/share/fonts/TTF/iosevka-extendedthin.ttf||5568848:1658693493.0": { + "family_name": "Iosevka Thin Extended", + "font-family": "Iosevka Thin Extended", + "font-stretch": "expanded", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Iosevka Thin Extended", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 2, + 9, + 3, + 0, + 0, + 0, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/iosevka-extendedthin.ttf", + "preferred_family_name": "Iosevka", + "preferred_subfamily_name": "Thin Extended", + "subfamily_name": "Regular", + "weight": 100, + "width": 7, + "wws_family_name": "Iosevka", + "wws_subfamily_name": "Thin Extended" + }, + "/usr/share/fonts/TTF/iosevka-extendedthinitalic.ttf||5754300:1658693493.0": { + "family_name": "Iosevka Thin Extended", + "font-family": "Iosevka Thin Extended", + "font-stretch": "expanded", + "font-style": "italic", + "font-weight": "100", + "fs_type": 0, + "full_name": "Iosevka Thin Extended Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 2, + 9, + 3, + 0, + 0, + 0, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/iosevka-extendedthinitalic.ttf", + "preferred_family_name": "Iosevka", + "preferred_subfamily_name": "Thin Extended Italic", + "subfamily_name": "Italic", + "weight": 100, + "width": 7, + "wws_family_name": "Iosevka", + "wws_subfamily_name": "Thin Extended Italic" + }, + "/usr/share/fonts/TTF/iosevka-extendedthinoblique.ttf||5734348:1658693493.0": { + "family_name": "Iosevka Thin Extended Oblique", + "font-family": "Iosevka Thin Extended Oblique", + "font-stretch": "expanded", + "font-style": "oblique", + "font-weight": "100", + "fs_type": 0, + "full_name": "Iosevka Thin Extended Oblique", + "is_bold": false, + "is_italic": true, + "is_oblique": true, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 2, + 9, + 3, + 0, + 0, + 0, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/iosevka-extendedthinoblique.ttf", + "preferred_family_name": "Iosevka", + "preferred_subfamily_name": "Thin Extended Oblique", + "subfamily_name": "Regular", + "weight": 100, + "width": 7, + "wws_family_name": "Iosevka", + "wws_subfamily_name": "Thin Extended Oblique" + }, + "/usr/share/fonts/TTF/iosevka-extrabold.ttf||6090772:1658693493.0": { + "family_name": "Iosevka Extrabold", + "font-family": "Iosevka Extrabold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Iosevka Extrabold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 9, + 9, + 3, + 0, + 0, + 0, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/iosevka-extrabold.ttf", + "preferred_family_name": "Iosevka", + "preferred_subfamily_name": "Extrabold", + "subfamily_name": "Regular", + "weight": 800, + "width": 5, + "wws_family_name": "Iosevka", + "wws_subfamily_name": "Extrabold" + }, + "/usr/share/fonts/TTF/iosevka-extrabolditalic.ttf||6339500:1658693493.0": { + "family_name": "Iosevka Extrabold", + "font-family": "Iosevka Extrabold", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "800", + "fs_type": 0, + "full_name": "Iosevka Extrabold Italic", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 9, + 9, + 3, + 0, + 0, + 0, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/iosevka-extrabolditalic.ttf", + "preferred_family_name": "Iosevka", + "preferred_subfamily_name": "Extrabold Italic", + "subfamily_name": "Italic", + "weight": 800, + "width": 5, + "wws_family_name": "Iosevka", + "wws_subfamily_name": "Extrabold Italic" + }, + "/usr/share/fonts/TTF/iosevka-extraboldoblique.ttf||6324448:1658693493.0": { + "family_name": "Iosevka Extrabold Oblique", + "font-family": "Iosevka Extrabold Oblique", + "font-stretch": "normal", + "font-style": "oblique", + "font-weight": "800", + "fs_type": 0, + "full_name": "Iosevka Extrabold Oblique", + "is_bold": true, + "is_italic": true, + "is_oblique": true, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 9, + 9, + 3, + 0, + 0, + 0, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/iosevka-extraboldoblique.ttf", + "preferred_family_name": "Iosevka", + "preferred_subfamily_name": "Extrabold Oblique", + "subfamily_name": "Regular", + "weight": 800, + "width": 5, + "wws_family_name": "Iosevka", + "wws_subfamily_name": "Extrabold Oblique" + }, + "/usr/share/fonts/TTF/iosevka-extralight.ttf||5749876:1658693493.0": { + "family_name": "Iosevka Extralight", + "font-family": "Iosevka Extralight", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Iosevka Extralight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 3, + 9, + 3, + 0, + 0, + 0, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/iosevka-extralight.ttf", + "preferred_family_name": "Iosevka", + "preferred_subfamily_name": "Extralight", + "subfamily_name": "Regular", + "weight": 200, + "width": 5, + "wws_family_name": "Iosevka", + "wws_subfamily_name": "Extralight" + }, + "/usr/share/fonts/TTF/iosevka-extralightitalic.ttf||5972652:1658693493.0": { + "family_name": "Iosevka Extralight", + "font-family": "Iosevka Extralight", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "200", + "fs_type": 0, + "full_name": "Iosevka Extralight Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 3, + 9, + 3, + 0, + 0, + 0, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/iosevka-extralightitalic.ttf", + "preferred_family_name": "Iosevka", + "preferred_subfamily_name": "Extralight Italic", + "subfamily_name": "Italic", + "weight": 200, + "width": 5, + "wws_family_name": "Iosevka", + "wws_subfamily_name": "Extralight Italic" + }, + "/usr/share/fonts/TTF/iosevka-extralightoblique.ttf||5956440:1658693493.0": { + "family_name": "Iosevka Extralight Oblique", + "font-family": "Iosevka Extralight Oblique", + "font-stretch": "normal", + "font-style": "oblique", + "font-weight": "200", + "fs_type": 0, + "full_name": "Iosevka Extralight Oblique", + "is_bold": false, + "is_italic": true, + "is_oblique": true, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 3, + 9, + 3, + 0, + 0, + 0, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/iosevka-extralightoblique.ttf", + "preferred_family_name": "Iosevka", + "preferred_subfamily_name": "Extralight Oblique", + "subfamily_name": "Regular", + "weight": 200, + "width": 5, + "wws_family_name": "Iosevka", + "wws_subfamily_name": "Extralight Oblique" + }, + "/usr/share/fonts/TTF/iosevka-heavy.ttf||6083968:1658693493.0": { + "family_name": "Iosevka Heavy", + "font-family": "Iosevka Heavy", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Iosevka Heavy", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 10, + 9, + 3, + 0, + 0, + 0, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/iosevka-heavy.ttf", + "preferred_family_name": "Iosevka", + "preferred_subfamily_name": "Heavy", + "subfamily_name": "Regular", + "weight": 900, + "width": 5, + "wws_family_name": "Iosevka", + "wws_subfamily_name": "Heavy" + }, + "/usr/share/fonts/TTF/iosevka-heavyitalic.ttf||6321924:1658693493.0": { + "family_name": "Iosevka Heavy", + "font-family": "Iosevka Heavy", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "900", + "fs_type": 0, + "full_name": "Iosevka Heavy Italic", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 10, + 9, + 3, + 0, + 0, + 0, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/iosevka-heavyitalic.ttf", + "preferred_family_name": "Iosevka", + "preferred_subfamily_name": "Heavy Italic", + "subfamily_name": "Italic", + "weight": 900, + "width": 5, + "wws_family_name": "Iosevka", + "wws_subfamily_name": "Heavy Italic" + }, + "/usr/share/fonts/TTF/iosevka-heavyoblique.ttf||6304232:1658693493.0": { + "family_name": "Iosevka Heavy Oblique", + "font-family": "Iosevka Heavy Oblique", + "font-stretch": "normal", + "font-style": "oblique", + "font-weight": "900", + "fs_type": 0, + "full_name": "Iosevka Heavy Oblique", + "is_bold": true, + "is_italic": true, + "is_oblique": true, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 10, + 9, + 3, + 0, + 0, + 0, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/iosevka-heavyoblique.ttf", + "preferred_family_name": "Iosevka", + "preferred_subfamily_name": "Heavy Oblique", + "subfamily_name": "Regular", + "weight": 900, + "width": 5, + "wws_family_name": "Iosevka", + "wws_subfamily_name": "Heavy Oblique" + }, + "/usr/share/fonts/TTF/iosevka-italic.ttf||6312348:1658693493.0": { + "family_name": "Iosevka", + "font-family": "Iosevka", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Iosevka Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 5, + 9, + 3, + 0, + 0, + 0, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/iosevka-italic.ttf", + "preferred_family_name": "Iosevka", + "preferred_subfamily_name": "Italic", + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": "Iosevka", + "wws_subfamily_name": "Italic" + }, + "/usr/share/fonts/TTF/iosevka-light.ttf||5937616:1658693493.0": { + "family_name": "Iosevka Light", + "font-family": "Iosevka Light", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Iosevka Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 4, + 9, + 3, + 0, + 0, + 0, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/iosevka-light.ttf", + "preferred_family_name": "Iosevka", + "preferred_subfamily_name": "Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": "Iosevka", + "wws_subfamily_name": "Light" + }, + "/usr/share/fonts/TTF/iosevka-lightitalic.ttf||6156300:1658693493.0": { + "family_name": "Iosevka Light", + "font-family": "Iosevka Light", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "300", + "fs_type": 0, + "full_name": "Iosevka Light Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 4, + 9, + 3, + 0, + 0, + 0, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/iosevka-lightitalic.ttf", + "preferred_family_name": "Iosevka", + "preferred_subfamily_name": "Light Italic", + "subfamily_name": "Italic", + "weight": 300, + "width": 5, + "wws_family_name": "Iosevka", + "wws_subfamily_name": "Light Italic" + }, + "/usr/share/fonts/TTF/iosevka-lightoblique.ttf||6137052:1658693493.0": { + "family_name": "Iosevka Light Oblique", + "font-family": "Iosevka Light Oblique", + "font-stretch": "normal", + "font-style": "oblique", + "font-weight": "300", + "fs_type": 0, + "full_name": "Iosevka Light Oblique", + "is_bold": false, + "is_italic": true, + "is_oblique": true, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 4, + 9, + 3, + 0, + 0, + 0, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/iosevka-lightoblique.ttf", + "preferred_family_name": "Iosevka", + "preferred_subfamily_name": "Light Oblique", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": "Iosevka", + "wws_subfamily_name": "Light Oblique" + }, + "/usr/share/fonts/TTF/iosevka-medium.ttf||6098960:1658693493.0": { + "family_name": "Iosevka Medium", + "font-family": "Iosevka Medium", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Iosevka Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 6, + 9, + 3, + 0, + 0, + 0, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/iosevka-medium.ttf", + "preferred_family_name": "Iosevka", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": "Iosevka", + "wws_subfamily_name": "Medium" + }, + "/usr/share/fonts/TTF/iosevka-mediumitalic.ttf||6321056:1658693493.0": { + "family_name": "Iosevka Medium", + "font-family": "Iosevka Medium", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "500", + "fs_type": 0, + "full_name": "Iosevka Medium Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 6, + 9, + 3, + 0, + 0, + 0, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/iosevka-mediumitalic.ttf", + "preferred_family_name": "Iosevka", + "preferred_subfamily_name": "Medium Italic", + "subfamily_name": "Italic", + "weight": 500, + "width": 5, + "wws_family_name": "Iosevka", + "wws_subfamily_name": "Medium Italic" + }, + "/usr/share/fonts/TTF/iosevka-mediumoblique.ttf||6304468:1658693493.0": { + "family_name": "Iosevka Medium Oblique", + "font-family": "Iosevka Medium Oblique", + "font-stretch": "normal", + "font-style": "oblique", + "font-weight": "500", + "fs_type": 0, + "full_name": "Iosevka Medium Oblique", + "is_bold": false, + "is_italic": true, + "is_oblique": true, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 6, + 9, + 3, + 0, + 0, + 0, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/iosevka-mediumoblique.ttf", + "preferred_family_name": "Iosevka", + "preferred_subfamily_name": "Medium Oblique", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": "Iosevka", + "wws_subfamily_name": "Medium Oblique" + }, + "/usr/share/fonts/TTF/iosevka-oblique.ttf||6293880:1658693493.0": { + "family_name": "Iosevka Oblique", + "font-family": "Iosevka Oblique", + "font-stretch": "normal", + "font-style": "oblique", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Iosevka Oblique", + "is_bold": false, + "is_italic": true, + "is_oblique": true, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 5, + 9, + 3, + 0, + 0, + 0, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/iosevka-oblique.ttf", + "preferred_family_name": "Iosevka", + "preferred_subfamily_name": "Oblique", + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": "Iosevka", + "wws_subfamily_name": "Oblique" + }, + "/usr/share/fonts/TTF/iosevka-regular.ttf||6084120:1658693493.0": { + "family_name": "Iosevka", + "font-family": "Iosevka", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Iosevka", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 5, + 9, + 3, + 0, + 0, + 0, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/iosevka-regular.ttf", + "preferred_family_name": "Iosevka", + "preferred_subfamily_name": "Regular", + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": "Iosevka", + "wws_subfamily_name": "Regular" + }, + "/usr/share/fonts/TTF/iosevka-semibold.ttf||6092500:1658693493.0": { + "family_name": "Iosevka Semibold", + "font-family": "Iosevka Semibold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Iosevka Semibold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 7, + 9, + 3, + 0, + 0, + 0, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/iosevka-semibold.ttf", + "preferred_family_name": "Iosevka", + "preferred_subfamily_name": "Semibold", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": "Iosevka", + "wws_subfamily_name": "Semibold" + }, + "/usr/share/fonts/TTF/iosevka-semibolditalic.ttf||6323196:1658693493.0": { + "family_name": "Iosevka Semibold", + "font-family": "Iosevka Semibold", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "600", + "fs_type": 0, + "full_name": "Iosevka Semibold Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 7, + 9, + 3, + 0, + 0, + 0, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/iosevka-semibolditalic.ttf", + "preferred_family_name": "Iosevka", + "preferred_subfamily_name": "Semibold Italic", + "subfamily_name": "Italic", + "weight": 600, + "width": 5, + "wws_family_name": "Iosevka", + "wws_subfamily_name": "Semibold Italic" + }, + "/usr/share/fonts/TTF/iosevka-semiboldoblique.ttf||6307072:1658693493.0": { + "family_name": "Iosevka Semibold Oblique", + "font-family": "Iosevka Semibold Oblique", + "font-stretch": "normal", + "font-style": "oblique", + "font-weight": "600", + "fs_type": 0, + "full_name": "Iosevka Semibold Oblique", + "is_bold": false, + "is_italic": true, + "is_oblique": true, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 7, + 9, + 3, + 0, + 0, + 0, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/iosevka-semiboldoblique.ttf", + "preferred_family_name": "Iosevka", + "preferred_subfamily_name": "Semibold Oblique", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": "Iosevka", + "wws_subfamily_name": "Semibold Oblique" + }, + "/usr/share/fonts/TTF/iosevka-thin.ttf||5763180:1658693493.0": { + "family_name": "Iosevka Thin", + "font-family": "Iosevka Thin", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Iosevka Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 2, + 9, + 3, + 0, + 0, + 0, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/iosevka-thin.ttf", + "preferred_family_name": "Iosevka", + "preferred_subfamily_name": "Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 5, + "wws_family_name": "Iosevka", + "wws_subfamily_name": "Thin" + }, + "/usr/share/fonts/TTF/iosevka-thinitalic.ttf||5951316:1658693493.0": { + "family_name": "Iosevka Thin", + "font-family": "Iosevka Thin", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "100", + "fs_type": 0, + "full_name": "Iosevka Thin Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 2, + 9, + 3, + 0, + 0, + 0, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/iosevka-thinitalic.ttf", + "preferred_family_name": "Iosevka", + "preferred_subfamily_name": "Thin Italic", + "subfamily_name": "Italic", + "weight": 100, + "width": 5, + "wws_family_name": "Iosevka", + "wws_subfamily_name": "Thin Italic" + }, + "/usr/share/fonts/TTF/iosevka-thinoblique.ttf||5932748:1658693493.0": { + "family_name": "Iosevka Thin Oblique", + "font-family": "Iosevka Thin Oblique", + "font-stretch": "normal", + "font-style": "oblique", + "font-weight": "100", + "fs_type": 0, + "full_name": "Iosevka Thin Oblique", + "is_bold": false, + "is_italic": true, + "is_oblique": true, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 2, + 9, + 3, + 0, + 0, + 0, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/iosevka-thinoblique.ttf", + "preferred_family_name": "Iosevka", + "preferred_subfamily_name": "Thin Oblique", + "subfamily_name": "Regular", + "weight": 100, + "width": 5, + "wws_family_name": "Iosevka", + "wws_subfamily_name": "Thin Oblique" + }, + "/usr/share/fonts/TTF/openlogos.ttf||80584:1625256442.0": { + "family_name": "OpenLogos", + "font-family": "OpenLogos", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 8, + "full_name": "OpenLogos", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/TTF/openlogos.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/paskowy.ttf||26404:1625256442.0": { + "family_name": "Paskowy", + "font-family": "Paskowy", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 2, + "full_name": "Paskowy", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 1, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/TTF/paskowy.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/pf_tempesta_five_condensed.ttf||22312:1625256442.0": { + "family_name": "PF Tempesta Five Condensed", + "font-family": "PF Tempesta Five Condensed", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "PF Tempesta Five Condensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 4, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/TTF/pf_tempesta_five_condensed.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/space age.ttf||26736:1625256442.0": { + "family_name": "Space Age", + "font-family": "Space Age", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Space Age", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 0, + "panose": [ + 2, + 0, + 5, + 0, + 2, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/TTF/space age.ttf", + "preferred_family_name": "Space Age", + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/tahoma.ttf||143884:1604955711.0": { + "family_name": "Tahoma", + "font-family": "Tahoma", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Tahoma", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 2, + "panose": [ + 2, + 11, + 6, + 4, + 3, + 5, + 4, + 4, + 2, + 4 + ], + "path": "/usr/share/fonts/TTF/tahoma.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/tahomabd.ttf||137272:1604955711.0": { + "family_name": "Tahoma", + "font-family": "Tahoma", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Tahoma Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 2, + "panose": [ + 2, + 11, + 8, + 4, + 3, + 5, + 4, + 4, + 2, + 4 + ], + "path": "/usr/share/fonts/TTF/tahomabd.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/trebuc.ttf||126796:1599643855.0": { + "family_name": "Trebuchet MS", + "font-family": "Trebuchet MS", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 8, + "full_name": "Trebuchet MS", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 6, + 3, + 2, + 2, + 2, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/TTF/trebuc.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/trebucbi.ttf||131188:1599643855.0": { + "family_name": "Trebuchet MS", + "font-family": "Trebuchet MS", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 8, + "full_name": "Trebuchet MS Bold Italic", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 7, + 3, + 2, + 2, + 2, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/TTF/trebucbi.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/trebucit.ttf||139288:1599643855.0": { + "family_name": "Trebuchet MS", + "font-family": "Trebuchet MS", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 8, + "full_name": "Trebuchet MS Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 6, + 3, + 2, + 2, + 2, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/TTF/trebucit.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/xirod.ttf||69000:1625256442.0": { + "family_name": "Xirod", + "font-family": "Xirod", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 4, + "full_name": "Xirod-Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 4, + 1, + 4, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/TTF/xirod.ttf", + "preferred_family_name": "Xirod", + "preferred_subfamily_name": "Regular", + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/TTF/zekton rg.ttf||86964:1625256442.0": { + "family_name": "Zekton Rg", + "font-family": "Zekton Rg", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 4, + "full_name": "ZektonRg-Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 6, + 4, + 2, + 2, + 2, + 8, + 2, + 4 + ], + "path": "/usr/share/fonts/TTF/zekton rg.ttf", + "preferred_family_name": "Zekton", + "preferred_subfamily_name": "Regular", + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/adobe-source-code-pro/SourceCodePro-Black.otf||134872:1610835204.0": { + "family_name": "Source Code Pro Black", + "font-family": "Source Code Pro Black", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Source Code Pro Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 8, + 9, + 3, + 4, + 3, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/adobe-source-code-pro/SourceCodePro-Black.otf", + "preferred_family_name": "Source Code Pro", + "preferred_subfamily_name": "Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/adobe-source-code-pro/SourceCodePro-BlackIt.otf||112036:1610835204.0": { + "family_name": "Source Code Pro Black", + "font-family": "Source Code Pro Black", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "900", + "fs_type": 0, + "full_name": "Source Code Pro Black Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 8, + 9, + 3, + 4, + 3, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/adobe-source-code-pro/SourceCodePro-BlackIt.otf", + "preferred_family_name": "Source Code Pro", + "preferred_subfamily_name": "Black Italic", + "subfamily_name": "Italic", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/adobe-source-code-pro/SourceCodePro-Bold.otf||134764:1610835204.0": { + "family_name": "Source Code Pro", + "font-family": "Source Code Pro", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Source Code Pro Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 7, + 9, + 3, + 4, + 3, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/adobe-source-code-pro/SourceCodePro-Bold.otf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/adobe-source-code-pro/SourceCodePro-BoldIt.otf||110648:1610835204.0": { + "family_name": "Source Code Pro", + "font-family": "Source Code Pro", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Source Code Pro Bold Italic", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 7, + 9, + 3, + 4, + 3, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/adobe-source-code-pro/SourceCodePro-BoldIt.otf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/adobe-source-code-pro/SourceCodePro-ExtraLight.otf||127080:1610835204.0": { + "family_name": "Source Code Pro ExtraLight", + "font-family": "Source Code Pro ExtraLight", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Source Code Pro ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 3, + 9, + 3, + 4, + 3, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/adobe-source-code-pro/SourceCodePro-ExtraLight.otf", + "preferred_family_name": "Source Code Pro", + "preferred_subfamily_name": "ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/adobe-source-code-pro/SourceCodePro-ExtraLightIt.otf||107332:1610835204.0": { + "family_name": "Source Code Pro ExtraLight", + "font-family": "Source Code Pro ExtraLight", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "200", + "fs_type": 0, + "full_name": "Source Code Pro ExtraLight Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 3, + 9, + 3, + 4, + 3, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/adobe-source-code-pro/SourceCodePro-ExtraLightIt.otf", + "preferred_family_name": "Source Code Pro", + "preferred_subfamily_name": "ExtraLight Italic", + "subfamily_name": "Italic", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/adobe-source-code-pro/SourceCodePro-It.otf||108148:1610835204.0": { + "family_name": "Source Code Pro", + "font-family": "Source Code Pro", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Source Code Pro Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 5, + 9, + 3, + 4, + 3, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/adobe-source-code-pro/SourceCodePro-It.otf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/adobe-source-code-pro/SourceCodePro-Light.otf||131784:1610835204.0": { + "family_name": "Source Code Pro Light", + "font-family": "Source Code Pro Light", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Source Code Pro Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 4, + 9, + 3, + 4, + 3, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/adobe-source-code-pro/SourceCodePro-Light.otf", + "preferred_family_name": "Source Code Pro", + "preferred_subfamily_name": "Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/adobe-source-code-pro/SourceCodePro-LightIt.otf||108068:1610835204.0": { + "family_name": "Source Code Pro Light", + "font-family": "Source Code Pro Light", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "300", + "fs_type": 0, + "full_name": "Source Code Pro Light Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 4, + 9, + 3, + 4, + 3, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/adobe-source-code-pro/SourceCodePro-LightIt.otf", + "preferred_family_name": "Source Code Pro", + "preferred_subfamily_name": "Light Italic", + "subfamily_name": "Italic", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/adobe-source-code-pro/SourceCodePro-Medium.otf||132096:1610835204.0": { + "family_name": "Source Code Pro Medium", + "font-family": "Source Code Pro Medium", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Source Code Pro Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 5, + 9, + 3, + 4, + 3, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/adobe-source-code-pro/SourceCodePro-Medium.otf", + "preferred_family_name": "Source Code Pro", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/adobe-source-code-pro/SourceCodePro-MediumIt.otf||108488:1610835204.0": { + "family_name": "Source Code Pro Medium", + "font-family": "Source Code Pro Medium", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "500", + "fs_type": 0, + "full_name": "Source Code Pro Medium Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 5, + 9, + 3, + 4, + 3, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/adobe-source-code-pro/SourceCodePro-MediumIt.otf", + "preferred_family_name": "Source Code Pro", + "preferred_subfamily_name": "Medium Italic", + "subfamily_name": "Italic", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/adobe-source-code-pro/SourceCodePro-Regular.otf||132740:1610835204.0": { + "family_name": "Source Code Pro", + "font-family": "Source Code Pro", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Source Code Pro", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 5, + 9, + 3, + 4, + 3, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/adobe-source-code-pro/SourceCodePro-Regular.otf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/adobe-source-code-pro/SourceCodePro-Semibold.otf||133404:1610835204.0": { + "family_name": "Source Code Pro Semibold", + "font-family": "Source Code Pro Semibold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Source Code Pro Semibold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 6, + 9, + 3, + 4, + 3, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/adobe-source-code-pro/SourceCodePro-Semibold.otf", + "preferred_family_name": "Source Code Pro", + "preferred_subfamily_name": "Semibold", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/adobe-source-code-pro/SourceCodePro-SemiboldIt.otf||109592:1610835204.0": { + "family_name": "Source Code Pro Semibold", + "font-family": "Source Code Pro Semibold", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "600", + "fs_type": 0, + "full_name": "Source Code Pro Semibold Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 6, + 9, + 3, + 4, + 3, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/adobe-source-code-pro/SourceCodePro-SemiboldIt.otf", + "preferred_family_name": "Source Code Pro", + "preferred_subfamily_name": "Semibold Italic", + "subfamily_name": "Italic", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/adobe-source-code-pro/SourceCodeVariable-Italic.otf||112460:1610835204.0": { + "family_name": "Source Code Variable", + "font-family": "Source Code Variable", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "200", + "fs_type": 0, + "full_name": "Source Code Variable Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 3, + 9, + 3, + 4, + 3, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/adobe-source-code-pro/SourceCodeVariable-Italic.otf", + "preferred_family_name": null, + "preferred_subfamily_name": "Italic Master 0", + "subfamily_name": "Italic", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/adobe-source-code-pro/SourceCodeVariable-Roman.otf||137124:1610835204.0": { + "family_name": "Source Code Variable", + "font-family": "Source Code Variable", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Source Code Variable", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 3, + 9, + 3, + 4, + 3, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/adobe-source-code-pro/SourceCodeVariable-Roman.otf", + "preferred_family_name": null, + "preferred_subfamily_name": "Roman Master 0", + "subfamily_name": "Regular", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/adobe-source-han-sans/SourceHanSansCN-Bold.otf||8543504:1622647719.0": { + "family_name": "Source Han Sans CN", + "font-family": "Source Han Sans CN", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Source Han Sans CN Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 8, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/adobe-source-han-sans/SourceHanSansCN-Bold.otf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/adobe-source-han-sans/SourceHanSansCN-ExtraLight.otf||7575136:1622647719.0": { + "family_name": "Source Han Sans CN ExtraLight", + "font-family": "Source Han Sans CN ExtraLight", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "250", + "fs_type": 0, + "full_name": "Source Han Sans CN ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 2, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/adobe-source-han-sans/SourceHanSansCN-ExtraLight.otf", + "preferred_family_name": "Source Han Sans CN", + "preferred_subfamily_name": "ExtraLight", + "subfamily_name": "Regular", + "weight": 250, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/adobe-source-han-sans/SourceHanSansCN-Heavy.otf||8856264:1622647719.0": { + "family_name": "Source Han Sans CN Heavy", + "font-family": "Source Han Sans CN Heavy", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Source Han Sans CN Heavy", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 10, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/adobe-source-han-sans/SourceHanSansCN-Heavy.otf", + "preferred_family_name": "Source Han Sans CN", + "preferred_subfamily_name": "Heavy", + "subfamily_name": "Regular", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/adobe-source-han-sans/SourceHanSansCN-Light.otf||8299448:1622647719.0": { + "family_name": "Source Han Sans CN Light", + "font-family": "Source Han Sans CN Light", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Source Han Sans CN Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 3, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/adobe-source-han-sans/SourceHanSansCN-Light.otf", + "preferred_family_name": "Source Han Sans CN", + "preferred_subfamily_name": "Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/adobe-source-han-sans/SourceHanSansCN-Medium.otf||8345780:1622647719.0": { + "family_name": "Source Han Sans CN Medium", + "font-family": "Source Han Sans CN Medium", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Source Han Sans CN Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 6, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/adobe-source-han-sans/SourceHanSansCN-Medium.otf", + "preferred_family_name": "Source Han Sans CN", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/adobe-source-han-sans/SourceHanSansCN-Normal.otf||8326204:1622647719.0": { + "family_name": "Source Han Sans CN Normal", + "font-family": "Source Han Sans CN Normal", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "350", + "fs_type": 0, + "full_name": "Source Han Sans CN Normal", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 4, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/adobe-source-han-sans/SourceHanSansCN-Normal.otf", + "preferred_family_name": "Source Han Sans CN", + "preferred_subfamily_name": "Normal", + "subfamily_name": "Regular", + "weight": 350, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/adobe-source-han-sans/SourceHanSansCN-Regular.otf||8331636:1622647719.0": { + "family_name": "Source Han Sans CN", + "font-family": "Source Han Sans CN", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Source Han Sans CN", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 5, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/adobe-source-han-sans/SourceHanSansCN-Regular.otf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/adobe-source-han-sans/SourceHanSansJP-Bold.otf||4656796:1622647719.0": { + "family_name": "Source Han Sans JP", + "font-family": "Source Han Sans JP", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Source Han Sans JP Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 8, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/adobe-source-han-sans/SourceHanSansJP-Bold.otf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/adobe-source-han-sans/SourceHanSansJP-ExtraLight.otf||4235524:1622647719.0": { + "family_name": "Source Han Sans JP ExtraLight", + "font-family": "Source Han Sans JP ExtraLight", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "250", + "fs_type": 0, + "full_name": "Source Han Sans JP ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 2, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/adobe-source-han-sans/SourceHanSansJP-ExtraLight.otf", + "preferred_family_name": "Source Han Sans JP", + "preferred_subfamily_name": "ExtraLight", + "subfamily_name": "Regular", + "weight": 250, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/adobe-source-han-sans/SourceHanSansJP-Heavy.otf||4855572:1622647719.0": { + "family_name": "Source Han Sans JP Heavy", + "font-family": "Source Han Sans JP Heavy", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Source Han Sans JP Heavy", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 10, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/adobe-source-han-sans/SourceHanSansJP-Heavy.otf", + "preferred_family_name": "Source Han Sans JP", + "preferred_subfamily_name": "Heavy", + "subfamily_name": "Regular", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/adobe-source-han-sans/SourceHanSansJP-Light.otf||4514324:1622647719.0": { + "family_name": "Source Han Sans JP Light", + "font-family": "Source Han Sans JP Light", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Source Han Sans JP Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 3, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/adobe-source-han-sans/SourceHanSansJP-Light.otf", + "preferred_family_name": "Source Han Sans JP", + "preferred_subfamily_name": "Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/adobe-source-han-sans/SourceHanSansJP-Medium.otf||4549492:1622647719.0": { + "family_name": "Source Han Sans JP Medium", + "font-family": "Source Han Sans JP Medium", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Source Han Sans JP Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 6, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/adobe-source-han-sans/SourceHanSansJP-Medium.otf", + "preferred_family_name": "Source Han Sans JP", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/adobe-source-han-sans/SourceHanSansJP-Normal.otf||4529712:1622647719.0": { + "family_name": "Source Han Sans JP Normal", + "font-family": "Source Han Sans JP Normal", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "350", + "fs_type": 0, + "full_name": "Source Han Sans JP Normal", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 4, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/adobe-source-han-sans/SourceHanSansJP-Normal.otf", + "preferred_family_name": "Source Han Sans JP", + "preferred_subfamily_name": "Normal", + "subfamily_name": "Regular", + "weight": 350, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/adobe-source-han-sans/SourceHanSansJP-Regular.otf||4533336:1622647719.0": { + "family_name": "Source Han Sans JP", + "font-family": "Source Han Sans JP", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Source Han Sans JP", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 5, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/adobe-source-han-sans/SourceHanSansJP-Regular.otf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/adobe-source-han-sans/SourceHanSansKR-Bold.otf||4816376:1622647719.0": { + "family_name": "Source Han Sans KR", + "font-family": "Source Han Sans KR", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Source Han Sans KR Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 8, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/adobe-source-han-sans/SourceHanSansKR-Bold.otf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/adobe-source-han-sans/SourceHanSansKR-ExtraLight.otf||4254544:1622647719.0": { + "family_name": "Source Han Sans KR ExtraLight", + "font-family": "Source Han Sans KR ExtraLight", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "250", + "fs_type": 0, + "full_name": "Source Han Sans KR ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 2, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/adobe-source-han-sans/SourceHanSansKR-ExtraLight.otf", + "preferred_family_name": "Source Han Sans KR", + "preferred_subfamily_name": "ExtraLight", + "subfamily_name": "Regular", + "weight": 250, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/adobe-source-han-sans/SourceHanSansKR-Heavy.otf||5033592:1622647719.0": { + "family_name": "Source Han Sans KR Heavy", + "font-family": "Source Han Sans KR Heavy", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Source Han Sans KR Heavy", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 10, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/adobe-source-han-sans/SourceHanSansKR-Heavy.otf", + "preferred_family_name": "Source Han Sans KR", + "preferred_subfamily_name": "Heavy", + "subfamily_name": "Regular", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/adobe-source-han-sans/SourceHanSansKR-Light.otf||4629396:1622647719.0": { + "family_name": "Source Han Sans KR Light", + "font-family": "Source Han Sans KR Light", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Source Han Sans KR Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 3, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/adobe-source-han-sans/SourceHanSansKR-Light.otf", + "preferred_family_name": "Source Han Sans KR", + "preferred_subfamily_name": "Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/adobe-source-han-sans/SourceHanSansKR-Medium.otf||4670160:1622647719.0": { + "family_name": "Source Han Sans KR Medium", + "font-family": "Source Han Sans KR Medium", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Source Han Sans KR Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 6, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/adobe-source-han-sans/SourceHanSansKR-Medium.otf", + "preferred_family_name": "Source Han Sans KR", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/adobe-source-han-sans/SourceHanSansKR-Normal.otf||4651968:1622647719.0": { + "family_name": "Source Han Sans KR Normal", + "font-family": "Source Han Sans KR Normal", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "350", + "fs_type": 0, + "full_name": "Source Han Sans KR Normal", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 4, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/adobe-source-han-sans/SourceHanSansKR-Normal.otf", + "preferred_family_name": "Source Han Sans KR", + "preferred_subfamily_name": "Normal", + "subfamily_name": "Regular", + "weight": 350, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/adobe-source-han-sans/SourceHanSansKR-Regular.otf||4645048:1622647719.0": { + "family_name": "Source Han Sans KR", + "font-family": "Source Han Sans KR", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Source Han Sans KR", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 5, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/adobe-source-han-sans/SourceHanSansKR-Regular.otf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/adobe-source-sans/SourceSans3-Black.otf||340208:1626253592.0": { + "family_name": "Source Sans 3 Black", + "font-family": "Source Sans 3 Black", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Source Sans 3 Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 8, + 3, + 3, + 4, + 3, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/adobe-source-sans/SourceSans3-Black.otf", + "preferred_family_name": "Source Sans 3", + "preferred_subfamily_name": "Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/adobe-source-sans/SourceSans3-BlackIt.otf||244556:1626253592.0": { + "family_name": "Source Sans 3 Black", + "font-family": "Source Sans 3 Black", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "900", + "fs_type": 0, + "full_name": "Source Sans 3 Black Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 8, + 3, + 3, + 4, + 3, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/adobe-source-sans/SourceSans3-BlackIt.otf", + "preferred_family_name": "Source Sans 3", + "preferred_subfamily_name": "Black Italic", + "subfamily_name": "Italic", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/adobe-source-sans/SourceSans3-Bold.otf||349232:1626253592.0": { + "family_name": "Source Sans 3", + "font-family": "Source Sans 3", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Source Sans 3 Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 7, + 3, + 3, + 4, + 3, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/adobe-source-sans/SourceSans3-Bold.otf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/adobe-source-sans/SourceSans3-BoldIt.otf||248036:1626253592.0": { + "family_name": "Source Sans 3", + "font-family": "Source Sans 3", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Source Sans 3 Bold Italic", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 7, + 3, + 3, + 4, + 3, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/adobe-source-sans/SourceSans3-BoldIt.otf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/adobe-source-sans/SourceSans3-ExtraLight.otf||318820:1626253592.0": { + "family_name": "Source Sans 3 ExtraLight", + "font-family": "Source Sans 3 ExtraLight", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Source Sans 3 ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 3, + 3, + 3, + 4, + 3, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/adobe-source-sans/SourceSans3-ExtraLight.otf", + "preferred_family_name": "Source Sans 3", + "preferred_subfamily_name": "ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/adobe-source-sans/SourceSans3-ExtraLightIt.otf||228120:1626253592.0": { + "family_name": "Source Sans 3 ExtraLight", + "font-family": "Source Sans 3 ExtraLight", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "200", + "fs_type": 0, + "full_name": "Source Sans 3 ExtraLight Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 3, + 3, + 3, + 4, + 3, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/adobe-source-sans/SourceSans3-ExtraLightIt.otf", + "preferred_family_name": "Source Sans 3", + "preferred_subfamily_name": "ExtraLight Italic", + "subfamily_name": "Italic", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/adobe-source-sans/SourceSans3-It.otf||241788:1626253592.0": { + "family_name": "Source Sans 3", + "font-family": "Source Sans 3", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Source Sans 3 Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 5, + 3, + 3, + 4, + 3, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/adobe-source-sans/SourceSans3-It.otf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/adobe-source-sans/SourceSans3-Light.otf||330248:1626253592.0": { + "family_name": "Source Sans 3 Light", + "font-family": "Source Sans 3 Light", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Source Sans 3 Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 4, + 3, + 3, + 4, + 3, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/adobe-source-sans/SourceSans3-Light.otf", + "preferred_family_name": "Source Sans 3", + "preferred_subfamily_name": "Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/adobe-source-sans/SourceSans3-LightIt.otf||236764:1626253592.0": { + "family_name": "Source Sans 3 Light", + "font-family": "Source Sans 3 Light", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "300", + "fs_type": 0, + "full_name": "Source Sans 3 Light Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 4, + 3, + 3, + 4, + 3, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/adobe-source-sans/SourceSans3-LightIt.otf", + "preferred_family_name": "Source Sans 3", + "preferred_subfamily_name": "Light Italic", + "subfamily_name": "Italic", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/adobe-source-sans/SourceSans3-Regular.otf||339844:1626253592.0": { + "family_name": "Source Sans 3", + "font-family": "Source Sans 3", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Source Sans 3", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 5, + 3, + 3, + 4, + 3, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/adobe-source-sans/SourceSans3-Regular.otf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/adobe-source-sans/SourceSans3-Semibold.otf||343612:1626253592.0": { + "family_name": "Source Sans 3 Semibold", + "font-family": "Source Sans 3 Semibold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Source Sans 3 Semibold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 6, + 3, + 3, + 4, + 3, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/adobe-source-sans/SourceSans3-Semibold.otf", + "preferred_family_name": "Source Sans 3", + "preferred_subfamily_name": "Semibold", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/adobe-source-sans/SourceSans3-SemiboldIt.otf||243680:1626253592.0": { + "family_name": "Source Sans 3 Semibold", + "font-family": "Source Sans 3 Semibold", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "600", + "fs_type": 0, + "full_name": "Source Sans 3 Semibold Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 6, + 3, + 3, + 4, + 3, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/adobe-source-sans/SourceSans3-SemiboldIt.otf", + "preferred_family_name": "Source Sans 3", + "preferred_subfamily_name": "Semibold Italic", + "subfamily_name": "Italic", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/adobe-source-sans/SourceSans3VF-Italic.otf||290340:1626253592.0": { + "family_name": "Source Sans 3 VF", + "font-family": "Source Sans 3 VF", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "200", + "fs_type": 0, + "full_name": "Source Sans 3 VF Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 3, + 3, + 3, + 4, + 3, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/adobe-source-sans/SourceSans3VF-Italic.otf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/adobe-source-sans/SourceSans3VF-Roman.otf||537360:1626253592.0": { + "family_name": "Source Sans 3 VF", + "font-family": "Source Sans 3 VF", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Source Sans 3 VF", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 3, + 3, + 3, + 4, + 3, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/adobe-source-sans/SourceSans3VF-Roman.otf", + "preferred_family_name": null, + "preferred_subfamily_name": "Roman", + "subfamily_name": "Regular", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/adobe-source-sans/SourceSansPro-Black.otf||295500:1626253592.0": { + "family_name": "Source Sans Pro Black", + "font-family": "Source Sans Pro Black", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Source Sans Pro Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 8, + 3, + 3, + 4, + 3, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/adobe-source-sans/SourceSansPro-Black.otf", + "preferred_family_name": "Source Sans Pro", + "preferred_subfamily_name": "Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/adobe-source-sans/SourceSansPro-BlackIt.otf||212660:1626253592.0": { + "family_name": "Source Sans Pro Black", + "font-family": "Source Sans Pro Black", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "900", + "fs_type": 0, + "full_name": "Source Sans Pro Black Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 8, + 3, + 3, + 4, + 3, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/adobe-source-sans/SourceSansPro-BlackIt.otf", + "preferred_family_name": "Source Sans Pro", + "preferred_subfamily_name": "Black Italic", + "subfamily_name": "Italic", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/adobe-source-sans/SourceSansPro-Bold.otf||298076:1626253592.0": { + "family_name": "Source Sans Pro", + "font-family": "Source Sans Pro", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Source Sans Pro Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 7, + 3, + 3, + 4, + 3, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/adobe-source-sans/SourceSansPro-Bold.otf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/adobe-source-sans/SourceSansPro-BoldIt.otf||212380:1626253592.0": { + "family_name": "Source Sans Pro", + "font-family": "Source Sans Pro", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Source Sans Pro Bold Italic", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 7, + 3, + 3, + 4, + 3, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/adobe-source-sans/SourceSansPro-BoldIt.otf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/adobe-source-sans/SourceSansPro-ExtraLight.otf||282200:1626253592.0": { + "family_name": "Source Sans Pro ExtraLight", + "font-family": "Source Sans Pro ExtraLight", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Source Sans Pro ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 3, + 3, + 3, + 4, + 3, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/adobe-source-sans/SourceSansPro-ExtraLight.otf", + "preferred_family_name": "Source Sans Pro", + "preferred_subfamily_name": "ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/adobe-source-sans/SourceSansPro-ExtraLightIt.otf||198324:1626253592.0": { + "family_name": "Source Sans Pro ExtraLight", + "font-family": "Source Sans Pro ExtraLight", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "200", + "fs_type": 0, + "full_name": "Source Sans Pro ExtraLight Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 3, + 3, + 3, + 4, + 3, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/adobe-source-sans/SourceSansPro-ExtraLightIt.otf", + "preferred_family_name": "Source Sans Pro", + "preferred_subfamily_name": "ExtraLight Italic", + "subfamily_name": "Italic", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/adobe-source-sans/SourceSansPro-It.otf||208408:1626253592.0": { + "family_name": "Source Sans Pro", + "font-family": "Source Sans Pro", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Source Sans Pro Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 5, + 3, + 3, + 4, + 3, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/adobe-source-sans/SourceSansPro-It.otf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/adobe-source-sans/SourceSansPro-Light.otf||290464:1626253592.0": { + "family_name": "Source Sans Pro Light", + "font-family": "Source Sans Pro Light", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Source Sans Pro Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 4, + 3, + 3, + 4, + 3, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/adobe-source-sans/SourceSansPro-Light.otf", + "preferred_family_name": "Source Sans Pro", + "preferred_subfamily_name": "Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/adobe-source-sans/SourceSansPro-LightIt.otf||204752:1626253592.0": { + "family_name": "Source Sans Pro Light", + "font-family": "Source Sans Pro Light", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "300", + "fs_type": 0, + "full_name": "Source Sans Pro Light Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 4, + 3, + 3, + 4, + 3, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/adobe-source-sans/SourceSansPro-LightIt.otf", + "preferred_family_name": "Source Sans Pro", + "preferred_subfamily_name": "Light Italic", + "subfamily_name": "Italic", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/adobe-source-sans/SourceSansPro-Regular.otf||293200:1626253592.0": { + "family_name": "Source Sans Pro", + "font-family": "Source Sans Pro", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Source Sans Pro", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 5, + 3, + 3, + 4, + 3, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/adobe-source-sans/SourceSansPro-Regular.otf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/adobe-source-sans/SourceSansPro-Semibold.otf||295952:1626253592.0": { + "family_name": "Source Sans Pro Semibold", + "font-family": "Source Sans Pro Semibold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Source Sans Pro Semibold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 6, + 3, + 3, + 4, + 3, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/adobe-source-sans/SourceSansPro-Semibold.otf", + "preferred_family_name": "Source Sans Pro", + "preferred_subfamily_name": "Semibold", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/adobe-source-sans/SourceSansPro-SemiboldIt.otf||210012:1626253592.0": { + "family_name": "Source Sans Pro Semibold", + "font-family": "Source Sans Pro Semibold", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "600", + "fs_type": 0, + "full_name": "Source Sans Pro Semibold Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 6, + 3, + 3, + 4, + 3, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/adobe-source-sans/SourceSansPro-SemiboldIt.otf", + "preferred_family_name": "Source Sans Pro", + "preferred_subfamily_name": "Semibold Italic", + "subfamily_name": "Italic", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/adobe-source-sans/SourceSansVariable-Italic.otf||252284:1626253592.0": { + "family_name": "Source Sans Variable", + "font-family": "Source Sans Variable", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "200", + "fs_type": 0, + "full_name": "Source Sans Variable Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 3, + 3, + 3, + 4, + 3, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/adobe-source-sans/SourceSansVariable-Italic.otf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/adobe-source-sans/SourceSansVariable-Roman.otf||467920:1626253592.0": { + "family_name": "Source Sans Variable", + "font-family": "Source Sans Variable", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Source Sans Variable", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 3, + 3, + 3, + 4, + 3, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/adobe-source-sans/SourceSansVariable-Roman.otf", + "preferred_family_name": null, + "preferred_subfamily_name": "Roman", + "subfamily_name": "Regular", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/awesome-terminal-fonts/devicons-regular.ttf||125484:1616952208.0": { + "family_name": "icomoon", + "font-family": "icomoon", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "icomoon", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/awesome-terminal-fonts/devicons-regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/awesome-terminal-fonts/fontawesome-regular.ttf||165548:1616952208.0": { + "family_name": "FontAwesome", + "font-family": "FontAwesome", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "FontAwesome", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/awesome-terminal-fonts/fontawesome-regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/awesome-terminal-fonts/octicons-regular.ttf||35580:1616952208.0": { + "family_name": "octicons", + "font-family": "octicons", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "octicons", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 6, + 3, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/awesome-terminal-fonts/octicons-regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Medium", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/awesome-terminal-fonts/pomicons-regular.ttf||8664:1616952208.0": { + "family_name": "Pomodoro", + "font-family": "Pomodoro", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 4, + "full_name": "Pomodoro", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/awesome-terminal-fonts/pomicons-regular.ttf", + "preferred_family_name": "Pomodoro", + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/cantarell/Cantarell-VF.otf||170588:1639135458.0": { + "family_name": "Cantarell", + "font-family": "Cantarell", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Cantarell Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 5, + 3, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/cantarell/Cantarell-VF.otf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/carlito/Carlito-Bold.ttf||690516:1616568110.0": { + "family_name": "Carlito", + "font-family": "Carlito", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Carlito Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 15, + 5, + 2, + 2, + 2, + 4, + 3, + 2, + 4 + ], + "path": "/usr/share/fonts/carlito/Carlito-Bold.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/carlito/Carlito-BoldItalic.ttf||816716:1616568110.0": { + "family_name": "Carlito", + "font-family": "Carlito", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Carlito Bold Italic", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 15, + 5, + 2, + 2, + 2, + 4, + 3, + 2, + 4 + ], + "path": "/usr/share/fonts/carlito/Carlito-BoldItalic.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/carlito/Carlito-Italic.ttf||623416:1616568110.0": { + "family_name": "Carlito", + "font-family": "Carlito", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Carlito Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 15, + 5, + 2, + 2, + 2, + 4, + 3, + 2, + 4 + ], + "path": "/usr/share/fonts/carlito/Carlito-Italic.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/carlito/Carlito-Regular.ttf||635996:1616568110.0": { + "family_name": "Carlito", + "font-family": "Carlito", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Carlito", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 15, + 5, + 2, + 2, + 2, + 4, + 3, + 2, + 4 + ], + "path": "/usr/share/fonts/carlito/Carlito-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/droid/DroidKufi-Bold.ttf||81220:1616720154.0": { + "family_name": "Droid Arabic Kufi", + "font-family": "Droid Arabic Kufi", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 8, + "full_name": "Droid Arabic Kufi Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 8, + 6, + 3, + 8, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/droid/DroidKufi-Bold.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/droid/DroidKufi-Regular.ttf||81224:1616720154.0": { + "family_name": "Droid Arabic Kufi", + "font-family": "Droid Arabic Kufi", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 8, + "full_name": "Droid Arabic Kufi", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 6, + 6, + 3, + 8, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/droid/DroidKufi-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/droid/DroidNaskh-Bold.ttf||94620:1616720154.0": { + "family_name": "Droid Arabic Naskh", + "font-family": "Droid Arabic Naskh", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 8, + "full_name": "Droid Arabic Naskh Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 8, + 6, + 3, + 8, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/droid/DroidNaskh-Bold.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/droid/DroidNaskh-Regular-SystemUI.ttf||158148:1616720154.0": { + "family_name": "Droid Naskh Shift Alt", + "font-family": "Droid Naskh Shift Alt", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 8, + "full_name": "Droid Naskh Shift Alt", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 6, + 6, + 3, + 8, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/droid/DroidNaskh-Regular-SystemUI.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/droid/DroidNaskh-Regular.ttf||91340:1616720154.0": { + "family_name": "Droid Arabic Naskh", + "font-family": "Droid Arabic Naskh", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 8, + "full_name": "Droid Arabic Naskh", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 6, + 6, + 3, + 8, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/droid/DroidNaskh-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/droid/DroidSans-Bold.ttf||194488:1616720154.0": { + "family_name": "Droid Sans", + "font-family": "Droid Sans", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 8, + "full_name": "Droid Sans Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 8, + 6, + 3, + 8, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/droid/DroidSans-Bold.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/droid/DroidSans.ttf||190776:1616720154.0": { + "family_name": "Droid Sans", + "font-family": "Droid Sans", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 8, + "full_name": "Droid Sans", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 6, + 6, + 3, + 8, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/droid/DroidSans.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/droid/DroidSansArabic.ttf||35880:1616720154.0": { + "family_name": "Droid Sans Arabic", + "font-family": "Droid Sans Arabic", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 8, + "full_name": "Droid Sans Arabic", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 6, + 0, + 3, + 5, + 0, + 5, + 0, + 0 + ], + "path": "/usr/share/fonts/droid/DroidSansArabic.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/droid/DroidSansArmenian.ttf||13856:1616720154.0": { + "family_name": "Droid Sans Armenian", + "font-family": "Droid Sans Armenian", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 8, + "full_name": "Droid Sans Armenian", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 6, + 6, + 3, + 8, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/droid/DroidSansArmenian.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/droid/DroidSansDevanagari-Regular.ttf||123372:1616720154.0": { + "family_name": "Droid Sans Devanagari", + "font-family": "Droid Sans Devanagari", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 8, + "full_name": "Droid Sans Devanagari", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 6, + 6, + 3, + 8, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/droid/DroidSansDevanagari-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/droid/DroidSansEthiopic-Bold.ttf||222592:1616720154.0": { + "family_name": "Droid Sans Ethiopic", + "font-family": "Droid Sans Ethiopic", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 8, + "full_name": "Droid Sans Ethiopic Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 8, + 6, + 3, + 8, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/droid/DroidSansEthiopic-Bold.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/droid/DroidSansEthiopic-Regular.ttf||227928:1616720154.0": { + "family_name": "Droid Sans Ethiopic", + "font-family": "Droid Sans Ethiopic", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 8, + "full_name": "Droid Sans Ethiopic", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 6, + 6, + 3, + 8, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/droid/DroidSansEthiopic-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/droid/DroidSansFallback.ttf||3838696:1616720154.0": { + "family_name": "Droid Sans Fallback", + "font-family": "Droid Sans Fallback", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 8, + "full_name": "Droid Sans Fallback", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 5, + 2, + 0, + 0, + 0, + 0, + 0, + 1 + ], + "path": "/usr/share/fonts/droid/DroidSansFallback.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/droid/DroidSansFallbackFull.ttf||5398328:1616720154.0": { + "family_name": "Droid Sans Fallback", + "font-family": "Droid Sans Fallback", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 8, + "full_name": "Droid Sans Fallback", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 5, + 2, + 0, + 0, + 0, + 0, + 0, + 1 + ], + "path": "/usr/share/fonts/droid/DroidSansFallbackFull.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/droid/DroidSansFallbackLegacy.ttf||3081908:1616720154.0": { + "family_name": "Droid Sans Fallback", + "font-family": "Droid Sans Fallback", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 8, + "full_name": "Droid Sans Fallback", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 5, + 2, + 0, + 0, + 0, + 0, + 0, + 1 + ], + "path": "/usr/share/fonts/droid/DroidSansFallbackLegacy.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/droid/DroidSansGeorgian.ttf||21096:1616720154.0": { + "family_name": "Droid Sans Georgian", + "font-family": "Droid Sans Georgian", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 8, + "full_name": "Droid Sans Georgian", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 6, + 6, + 3, + 8, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/droid/DroidSansGeorgian.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/droid/DroidSansHebrew-Bold.ttf||30280:1616720154.0": { + "family_name": "Droid Sans Hebrew", + "font-family": "Droid Sans Hebrew", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 8, + "full_name": "Droid Sans Hebrew Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 8, + 0, + 3, + 5, + 0, + 5, + 0, + 0 + ], + "path": "/usr/share/fonts/droid/DroidSansHebrew-Bold.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/droid/DroidSansHebrew-Regular.ttf||30024:1616720154.0": { + "family_name": "Droid Sans Hebrew", + "font-family": "Droid Sans Hebrew", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 8, + "full_name": "Droid Sans Hebrew", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 6, + 0, + 3, + 5, + 0, + 5, + 0, + 0 + ], + "path": "/usr/share/fonts/droid/DroidSansHebrew-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/droid/DroidSansJapanese.ttf||1173140:1616720154.0": { + "family_name": "Droid Sans Japanese", + "font-family": "Droid Sans Japanese", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 8, + "full_name": "Droid Sans Japanese", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 5, + 2, + 0, + 0, + 0, + 0, + 0, + 1 + ], + "path": "/usr/share/fonts/droid/DroidSansJapanese.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/droid/DroidSansMono.ttf||119380:1616720154.0": { + "family_name": "Droid Sans Mono", + "font-family": "Droid Sans Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 8, + "full_name": "Droid Sans Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 6, + 9, + 3, + 8, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/droid/DroidSansMono.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/droid/DroidSansTamil-Bold.ttf||36448:1616720154.0": { + "family_name": "Droid Sans Tamil", + "font-family": "Droid Sans Tamil", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 8, + "full_name": "Droid Sans Tamil Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 8, + 6, + 3, + 8, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/droid/DroidSansTamil-Bold.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/droid/DroidSansTamil-Regular.ttf||36308:1616720154.0": { + "family_name": "Droid Sans Tamil", + "font-family": "Droid Sans Tamil", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 8, + "full_name": "Droid Sans Tamil", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 6, + 6, + 3, + 8, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/droid/DroidSansTamil-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/droid/DroidSansThai.ttf||35584:1616720154.0": { + "family_name": "Droid Sans Thai", + "font-family": "Droid Sans Thai", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 8, + "full_name": "Droid Sans Thai", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 6, + 6, + 3, + 8, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/droid/DroidSansThai.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/droid/DroidSerif-Bold.ttf||185228:1616720154.0": { + "family_name": "Droid Serif", + "font-family": "Droid Serif", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 8, + "full_name": "Droid Serif Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 2, + 8, + 0, + 6, + 5, + 0, + 2, + 2, + 0 + ], + "path": "/usr/share/fonts/droid/DroidSerif-Bold.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/droid/DroidSerif-BoldItalic.ttf||190304:1616720154.0": { + "family_name": "Droid Serif", + "font-family": "Droid Serif", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 8, + "full_name": "Droid Serif Bold Italic", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 2, + 8, + 0, + 6, + 5, + 0, + 9, + 2, + 0 + ], + "path": "/usr/share/fonts/droid/DroidSerif-BoldItalic.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/droid/DroidSerif-Italic.ttf||177560:1616720154.0": { + "family_name": "Droid Serif", + "font-family": "Droid Serif", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 8, + "full_name": "Droid Serif Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 2, + 6, + 0, + 6, + 5, + 0, + 9, + 2, + 0 + ], + "path": "/usr/share/fonts/droid/DroidSerif-Italic.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/droid/DroidSerif-Regular.ttf||172916:1616720154.0": { + "family_name": "Droid Serif", + "font-family": "Droid Serif", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 8, + "full_name": "Droid Serif", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 2, + 6, + 0, + 6, + 5, + 0, + 2, + 2, + 0 + ], + "path": "/usr/share/fonts/droid/DroidSerif-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/gnu-free/FreeMono.otf||430884:1589880580.0": { + "family_name": "FreeMono", + "font-family": "FreeMono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "FreeMono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 15, + 4, + 9, + 2, + 2, + 5, + 2, + 4, + 4 + ], + "path": "/usr/share/fonts/gnu-free/FreeMono.otf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/gnu-free/FreeMonoBold.otf||203376:1589880580.0": { + "family_name": "FreeMono", + "font-family": "FreeMono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "FreeMono Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 15, + 6, + 9, + 2, + 8, + 5, + 2, + 4, + 4 + ], + "path": "/usr/share/fonts/gnu-free/FreeMonoBold.otf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/gnu-free/FreeMonoBoldOblique.otf||194716:1589880580.0": { + "family_name": "FreeMono", + "font-family": "FreeMono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "FreeMono Bold Oblique", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 15, + 6, + 9, + 2, + 2, + 5, + 9, + 4, + 4 + ], + "path": "/usr/share/fonts/gnu-free/FreeMonoBoldOblique.otf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold Oblique", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/gnu-free/FreeMonoOblique.otf||245408:1589880580.0": { + "family_name": "FreeMono", + "font-family": "FreeMono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "FreeMono Oblique", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 15, + 4, + 9, + 2, + 2, + 5, + 9, + 4, + 4 + ], + "path": "/usr/share/fonts/gnu-free/FreeMonoOblique.otf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Oblique", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/gnu-free/FreeSans.otf||856800:1589880580.0": { + "family_name": "FreeSans", + "font-family": "FreeSans", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "FreeSans", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 5, + 4, + 2, + 2, + 2, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/gnu-free/FreeSans.otf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/gnu-free/FreeSansBold.otf||305436:1589880580.0": { + "family_name": "FreeSans", + "font-family": "FreeSans", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "FreeSans Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 7, + 4, + 2, + 2, + 2, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/gnu-free/FreeSansBold.otf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/gnu-free/FreeSansBoldOblique.otf||233476:1589880580.0": { + "family_name": "FreeSans", + "font-family": "FreeSans", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "600", + "fs_type": 0, + "full_name": "FreeSans Bold Oblique", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 7, + 4, + 2, + 2, + 2, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/gnu-free/FreeSansBoldOblique.otf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold Oblique", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/gnu-free/FreeSansOblique.otf||473976:1589880580.0": { + "family_name": "FreeSans", + "font-family": "FreeSans", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "FreeSans Oblique", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 5, + 4, + 2, + 2, + 2, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/gnu-free/FreeSansOblique.otf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Oblique", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/gnu-free/FreeSerif.otf||2047320:1589880580.0": { + "family_name": "FreeSerif", + "font-family": "FreeSerif", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "FreeSerif", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 2, + 6, + 3, + 5, + 4, + 5, + 2, + 3, + 4 + ], + "path": "/usr/share/fonts/gnu-free/FreeSerif.otf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/gnu-free/FreeSerifBold.otf||954748:1589880580.0": { + "family_name": "FreeSerif", + "font-family": "FreeSerif", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "FreeSerif Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 2, + 8, + 3, + 7, + 5, + 5, + 2, + 3, + 4 + ], + "path": "/usr/share/fonts/gnu-free/FreeSerifBold.otf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/gnu-free/FreeSerifBoldItalic.otf||425684:1589880580.0": { + "family_name": "FreeSerif", + "font-family": "FreeSerif", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "FreeSerif Bold Italic", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 2, + 8, + 3, + 6, + 5, + 5, + 9, + 3, + 4 + ], + "path": "/usr/share/fonts/gnu-free/FreeSerifBoldItalic.otf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/gnu-free/FreeSerifItalic.otf||597888:1589880580.0": { + "family_name": "FreeSerif", + "font-family": "FreeSerif", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "FreeSerif Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 2, + 6, + 3, + 5, + 4, + 5, + 9, + 3, + 4 + ], + "path": "/usr/share/fonts/gnu-free/FreeSerifItalic.otf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/gsfonts/C059-BdIta.otf||103444:1616704737.0": { + "family_name": "C059", + "font-family": "C059", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 4, + "full_name": "C059-BdIta", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 8, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/gsfonts/C059-BdIta.otf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/gsfonts/C059-Bold.otf||100692:1616704737.0": { + "family_name": "C059", + "font-family": "C059", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 4, + "full_name": "C059-Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 8, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/gsfonts/C059-Bold.otf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/gsfonts/C059-Italic.otf||101324:1616704737.0": { + "family_name": "C059", + "font-family": "C059", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 4, + "full_name": "C059-Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 5, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/gsfonts/C059-Italic.otf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/gsfonts/C059-Roman.otf||97476:1616704737.0": { + "family_name": "C059", + "font-family": "C059", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 4, + "full_name": "C059-Roman", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 5, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/gsfonts/C059-Roman.otf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Roman", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/gsfonts/D050000L.otf||29832:1616704737.0": { + "family_name": "D050000L", + "font-family": "D050000L", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "D050000L", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 1, + 1, + 6, + 1, + 1, + 1, + 1, + 1, + 1, + 1 + ], + "path": "/usr/share/fonts/gsfonts/D050000L.otf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/gsfonts/NimbusMonoPS-Bold.otf||87520:1616704737.0": { + "family_name": "Nimbus Mono PS", + "font-family": "Nimbus Mono PS", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 4, + "full_name": "NimbusMonoPS-Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 8, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/gsfonts/NimbusMonoPS-Bold.otf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/gsfonts/NimbusMonoPS-BoldItalic.otf||89580:1616704737.0": { + "family_name": "Nimbus Mono PS", + "font-family": "Nimbus Mono PS", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 4, + "full_name": "NimbusMonoPS-BoldItalic", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 8, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/gsfonts/NimbusMonoPS-BoldItalic.otf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/gsfonts/NimbusMonoPS-Italic.otf||82648:1616704737.0": { + "family_name": "Nimbus Mono PS", + "font-family": "Nimbus Mono PS", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 4, + "full_name": "NimbusMonoPS-Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 5, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/gsfonts/NimbusMonoPS-Italic.otf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/gsfonts/NimbusMonoPS-Regular.otf||77936:1616704737.0": { + "family_name": "Nimbus Mono PS", + "font-family": "Nimbus Mono PS", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 4, + "full_name": "NimbusMonoPS-Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 5, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/gsfonts/NimbusMonoPS-Regular.otf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/gsfonts/NimbusRoman-Bold.otf||100984:1616704737.0": { + "family_name": "Nimbus Roman", + "font-family": "Nimbus Roman", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 4, + "full_name": "NimbusRoman-Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 8, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/gsfonts/NimbusRoman-Bold.otf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/gsfonts/NimbusRoman-BoldItalic.otf||104772:1616704737.0": { + "family_name": "Nimbus Roman", + "font-family": "Nimbus Roman", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 4, + "full_name": "NimbusRoman-BoldItalic", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 8, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/gsfonts/NimbusRoman-BoldItalic.otf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/gsfonts/NimbusRoman-Italic.otf||105684:1616704737.0": { + "family_name": "Nimbus Roman", + "font-family": "Nimbus Roman", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 4, + "full_name": "NimbusRoman-Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 5, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/gsfonts/NimbusRoman-Italic.otf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/gsfonts/NimbusRoman-Regular.otf||98200:1616704737.0": { + "family_name": "Nimbus Roman", + "font-family": "Nimbus Roman", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 4, + "full_name": "NimbusRoman-Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 5, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/gsfonts/NimbusRoman-Regular.otf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/gsfonts/NimbusSans-Bold.otf||83264:1616704737.0": { + "family_name": "Nimbus Sans", + "font-family": "Nimbus Sans", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 4, + "full_name": "NimbusSans-Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 8, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/gsfonts/NimbusSans-Bold.otf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/gsfonts/NimbusSans-BoldItalic.otf||95396:1616704737.0": { + "family_name": "Nimbus Sans", + "font-family": "Nimbus Sans", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 4, + "full_name": "NimbusSans-BoldItalic", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 8, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/gsfonts/NimbusSans-BoldItalic.otf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/gsfonts/NimbusSans-Italic.otf||95244:1616704737.0": { + "family_name": "Nimbus Sans", + "font-family": "Nimbus Sans", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 4, + "full_name": "NimbusSans-Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 5, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/gsfonts/NimbusSans-Italic.otf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/gsfonts/NimbusSans-Regular.otf||82264:1616704737.0": { + "family_name": "Nimbus Sans", + "font-family": "Nimbus Sans", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 4, + "full_name": "NimbusSans-Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 5, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/gsfonts/NimbusSans-Regular.otf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/gsfonts/NimbusSansNarrow-Bold.otf||81340:1616704737.0": { + "family_name": "Nimbus Sans Narrow", + "font-family": "Nimbus Sans Narrow", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 4, + "full_name": "NimbusSansNarrow-Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 8, + 6, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/gsfonts/NimbusSansNarrow-Bold.otf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/gsfonts/NimbusSansNarrow-BoldOblique.otf||87956:1616704737.0": { + "family_name": "Nimbus Sans Narrow", + "font-family": "Nimbus Sans Narrow", + "font-stretch": "semi-condensed", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 4, + "full_name": "NimbusSansNarrow-BoldOblique", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 8, + 6, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/gsfonts/NimbusSansNarrow-BoldOblique.otf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold Oblique", + "weight": 700, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/gsfonts/NimbusSansNarrow-Oblique.otf||87068:1616704737.0": { + "family_name": "Nimbus Sans Narrow", + "font-family": "Nimbus Sans Narrow", + "font-stretch": "semi-condensed", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 4, + "full_name": "NimbusSansNarrow-Oblique", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 5, + 6, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/gsfonts/NimbusSansNarrow-Oblique.otf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Oblique", + "weight": 400, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/gsfonts/NimbusSansNarrow-Regular.otf||80864:1616704737.0": { + "family_name": "Nimbus Sans Narrow", + "font-family": "Nimbus Sans Narrow", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 4, + "full_name": "NimbusSansNarrow-Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 5, + 6, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/gsfonts/NimbusSansNarrow-Regular.otf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/gsfonts/P052-Bold.otf||110980:1616704737.0": { + "family_name": "P052", + "font-family": "P052", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 4, + "full_name": "P052-Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 8, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/gsfonts/P052-Bold.otf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/gsfonts/P052-BoldItalic.otf||110928:1616704737.0": { + "family_name": "P052", + "font-family": "P052", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 4, + "full_name": "P052-BoldItalic", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 8, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/gsfonts/P052-BoldItalic.otf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/gsfonts/P052-Italic.otf||109824:1616704737.0": { + "family_name": "P052", + "font-family": "P052", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 4, + "full_name": "P052-Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 5, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/gsfonts/P052-Italic.otf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/gsfonts/P052-Roman.otf||110236:1616704737.0": { + "family_name": "P052", + "font-family": "P052", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 4, + "full_name": "P052-Roman", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 5, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/gsfonts/P052-Roman.otf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Roman", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/gsfonts/StandardSymbolsPS.otf||21176:1616704737.0": { + "family_name": "Standard Symbols PS", + "font-family": "Standard Symbols PS", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 4, + "full_name": "Standard Symbols PS", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 5, + 5, + 1, + 2, + 1, + 7, + 6, + 2, + 5, + 7 + ], + "path": "/usr/share/fonts/gsfonts/StandardSymbolsPS.otf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/gsfonts/URWBookman-Demi.otf||97208:1616704737.0": { + "family_name": "URW Bookman", + "font-family": "URW Bookman", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 4, + "full_name": "URWBookman-Demi", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 7, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/gsfonts/URWBookman-Demi.otf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Demi", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/gsfonts/URWBookman-DemiItalic.otf||101584:1616704737.0": { + "family_name": "URW Bookman", + "font-family": "URW Bookman", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "600", + "fs_type": 4, + "full_name": "URWBookman-DemiItalic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 7, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/gsfonts/URWBookman-DemiItalic.otf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Demi Italic", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/gsfonts/URWBookman-Light.otf||98396:1616704737.0": { + "family_name": "URW Bookman", + "font-family": "URW Bookman", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 4, + "full_name": "URWBookman-Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 4, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/gsfonts/URWBookman-Light.otf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Light", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/gsfonts/URWBookman-LightItalic.otf||102764:1616704737.0": { + "family_name": "URW Bookman", + "font-family": "URW Bookman", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "300", + "fs_type": 4, + "full_name": "URWBookman-LightItalic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 4, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/gsfonts/URWBookman-LightItalic.otf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Light Italic", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/gsfonts/URWGothic-Book.otf||82968:1616704737.0": { + "family_name": "URW Gothic", + "font-family": "URW Gothic", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 4, + "full_name": "URWGothic-Book", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 5, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/gsfonts/URWGothic-Book.otf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Book", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/gsfonts/URWGothic-BookOblique.otf||85336:1616704737.0": { + "family_name": "URW Gothic", + "font-family": "URW Gothic", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 4, + "full_name": "URWGothic-BookOblique", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 5, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/gsfonts/URWGothic-BookOblique.otf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Book Oblique", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/gsfonts/URWGothic-Demi.otf||83580:1616704737.0": { + "family_name": "URW Gothic", + "font-family": "URW Gothic", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 4, + "full_name": "URWGothic-Demi", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 7, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/gsfonts/URWGothic-Demi.otf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Demi", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/gsfonts/URWGothic-DemiOblique.otf||86232:1616704737.0": { + "family_name": "URW Gothic", + "font-family": "URW Gothic", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "600", + "fs_type": 4, + "full_name": "URWGothic-DemiOblique", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 7, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/gsfonts/URWGothic-DemiOblique.otf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Demi Oblique", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/gsfonts/Z003-MediumItalic.otf||114052:1616704737.0": { + "family_name": "Z003", + "font-family": "Z003", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "500", + "fs_type": 4, + "full_name": "Z003-MediumItalic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 6, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/gsfonts/Z003-MediumItalic.otf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Medium Italic", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/liberation/LiberationMono-Bold.ttf||307996:1633027421.0": { + "family_name": "Liberation Mono", + "font-family": "Liberation Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Liberation Mono Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 7, + 7, + 9, + 2, + 2, + 5, + 2, + 4, + 4 + ], + "path": "/usr/share/fonts/liberation/LiberationMono-Bold.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/liberation/LiberationMono-BoldItalic.ttf||284068:1633027421.0": { + "family_name": "Liberation Mono", + "font-family": "Liberation Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Liberation Mono Bold Italic", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 7, + 7, + 9, + 2, + 2, + 5, + 9, + 4, + 4 + ], + "path": "/usr/share/fonts/liberation/LiberationMono-BoldItalic.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/liberation/LiberationMono-Italic.ttf||281536:1633027421.0": { + "family_name": "Liberation Mono", + "font-family": "Liberation Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Liberation Mono Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 7, + 4, + 9, + 2, + 2, + 5, + 9, + 4, + 4 + ], + "path": "/usr/share/fonts/liberation/LiberationMono-Italic.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/liberation/LiberationMono-Regular.ttf||319508:1633027421.0": { + "family_name": "Liberation Mono", + "font-family": "Liberation Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Liberation Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 7, + 4, + 9, + 2, + 2, + 5, + 2, + 4, + 4 + ], + "path": "/usr/share/fonts/liberation/LiberationMono-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/liberation/LiberationSans-Bold.ttf||414456:1633027421.0": { + "family_name": "Liberation Sans", + "font-family": "Liberation Sans", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Liberation Sans Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 7, + 4, + 2, + 2, + 2, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/liberation/LiberationSans-Bold.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/liberation/LiberationSans-BoldItalic.ttf||408996:1633027421.0": { + "family_name": "Liberation Sans", + "font-family": "Liberation Sans", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Liberation Sans Bold Italic", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 7, + 4, + 2, + 2, + 2, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/liberation/LiberationSans-BoldItalic.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/liberation/LiberationSans-Italic.ttf||415816:1633027421.0": { + "family_name": "Liberation Sans", + "font-family": "Liberation Sans", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Liberation Sans Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 6, + 4, + 2, + 2, + 2, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/liberation/LiberationSans-Italic.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/liberation/LiberationSans-Regular.ttf||410712:1633027421.0": { + "family_name": "Liberation Sans", + "font-family": "Liberation Sans", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Liberation Sans", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 6, + 4, + 2, + 2, + 2, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/liberation/LiberationSans-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/liberation/LiberationSerif-Bold.ttf||370096:1633027421.0": { + "family_name": "Liberation Serif", + "font-family": "Liberation Serif", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Liberation Serif Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 2, + 8, + 3, + 7, + 5, + 5, + 2, + 3, + 4 + ], + "path": "/usr/share/fonts/liberation/LiberationSerif-Bold.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/liberation/LiberationSerif-BoldItalic.ttf||376772:1633027421.0": { + "family_name": "Liberation Serif", + "font-family": "Liberation Serif", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Liberation Serif Bold Italic", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 2, + 7, + 3, + 6, + 5, + 5, + 9, + 3, + 4 + ], + "path": "/usr/share/fonts/liberation/LiberationSerif-BoldItalic.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/liberation/LiberationSerif-Italic.ttf||375632:1633027421.0": { + "family_name": "Liberation Serif", + "font-family": "Liberation Serif", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Liberation Serif Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 2, + 5, + 3, + 5, + 4, + 5, + 9, + 3, + 4 + ], + "path": "/usr/share/fonts/liberation/LiberationSerif-Italic.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/liberation/LiberationSerif-Regular.ttf||393576:1633027421.0": { + "family_name": "Liberation Serif", + "font-family": "Liberation Serif", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Liberation Serif", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 2, + 6, + 3, + 5, + 4, + 5, + 2, + 3, + 4 + ], + "path": "/usr/share/fonts/liberation/LiberationSerif-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/3270 Narrow Nerd Font Complete Mono.otf||3381936:1634564302.0": { + "family_name": "3270Narrow Nerd Font Mono", + "font-family": "3270Narrow Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "3270 Narrow Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 6, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/3270 Narrow Nerd Font Complete Mono.otf", + "preferred_family_name": "3270Narrow Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Medium", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/3270 Narrow Nerd Font Complete.otf||2186232:1634564302.0": { + "family_name": "3270Narrow Nerd Font", + "font-family": "3270Narrow Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "3270 Narrow Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 6, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/3270 Narrow Nerd Font Complete.otf", + "preferred_family_name": "3270Narrow Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Medium", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/3270 Semi-Narrow Nerd Font Complete Mono.otf||3375712:1634564302.0": { + "family_name": "3270SemiNarrow Nerd Font Mono", + "font-family": "3270SemiNarrow Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "3270 Semi-Narrow Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 6, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/3270 Semi-Narrow Nerd Font Complete Mono.otf", + "preferred_family_name": "3270SemiNarrow Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Medium", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/3270 Semi-Narrow Nerd Font Complete.otf||2186324:1634564302.0": { + "family_name": "3270SemiNarrow Nerd Font", + "font-family": "3270SemiNarrow Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "3270 Semi-Narrow Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 6, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/3270 Semi-Narrow Nerd Font Complete.otf", + "preferred_family_name": "3270SemiNarrow Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Medium", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/3270-Medium Nerd Font Complete Mono.otf||3387916:1634564302.0": { + "family_name": "3270Medium Nerd Font Mono", + "font-family": "3270Medium Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "3270-Medium Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 6, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/3270-Medium Nerd Font Complete Mono.otf", + "preferred_family_name": "3270Medium Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Medium", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/3270-Medium Nerd Font Complete.otf||2191828:1634564302.0": { + "family_name": "3270Medium Nerd Font", + "font-family": "3270Medium Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "3270-Medium Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 6, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/3270-Medium Nerd Font Complete.otf", + "preferred_family_name": "3270Medium Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Medium", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/AurulentSansMono-Regular Nerd Font Complete Mono.otf||3255588:1634564302.0": { + "family_name": "AurulentSansMono Nerd Font Mono", + "font-family": "AurulentSansMono Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "AurulentSansMono-Regular Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 0, + 5, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/AurulentSansMono-Regular Nerd Font Complete Mono.otf", + "preferred_family_name": "AurulentSansMono Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/AurulentSansMono-Regular Nerd Font Complete.otf||2110108:1634564302.0": { + "family_name": "AurulentSansMono Nerd Font", + "font-family": "AurulentSansMono Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "AurulentSansMono-Regular Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 0, + 5, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/AurulentSansMono-Regular Nerd Font Complete.otf", + "preferred_family_name": "AurulentSansMono Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Code New Roman Bold Nerd Font Complete Mono.otf||4244856:1634564302.0": { + "family_name": "CodeNewRoman Nerd Font Mono", + "font-family": "CodeNewRoman Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Code New Roman Bold Nerd Font Complete Mono", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 7, + 9, + 2, + 2, + 4, + 3, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Code New Roman Bold Nerd Font Complete Mono.otf", + "preferred_family_name": "CodeNewRoman Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Code New Roman Bold Nerd Font Complete.otf||3128404:1634564302.0": { + "family_name": "CodeNewRoman Nerd Font", + "font-family": "CodeNewRoman Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Code New Roman Bold Nerd Font Complete", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 7, + 9, + 2, + 2, + 4, + 3, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Code New Roman Bold Nerd Font Complete.otf", + "preferred_family_name": "CodeNewRoman Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Code New Roman Italic Nerd Font Complete Mono.otf||4277172:1634564302.0": { + "family_name": "CodeNewRoman Nerd Font Mono", + "font-family": "CodeNewRoman Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Code New Roman Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 6, + 9, + 2, + 2, + 4, + 10, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Code New Roman Italic Nerd Font Complete Mono.otf", + "preferred_family_name": "CodeNewRoman Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Code New Roman Italic Nerd Font Complete.otf||3160740:1634564302.0": { + "family_name": "CodeNewRoman Nerd Font", + "font-family": "CodeNewRoman Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Code New Roman Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 6, + 9, + 2, + 2, + 4, + 10, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Code New Roman Italic Nerd Font Complete.otf", + "preferred_family_name": "CodeNewRoman Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Code New Roman Nerd Font Complete Mono.otf||4239312:1634564302.0": { + "family_name": "CodeNewRoman Nerd Font Mono", + "font-family": "CodeNewRoman Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Code New Roman Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 6, + 9, + 2, + 2, + 4, + 3, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Code New Roman Nerd Font Complete Mono.otf", + "preferred_family_name": "CodeNewRoman Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Book", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Code New Roman Nerd Font Complete.otf||3122844:1634564302.0": { + "family_name": "CodeNewRoman Nerd Font", + "font-family": "CodeNewRoman Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Code New Roman Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 6, + 9, + 2, + 2, + 4, + 3, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Code New Roman Nerd Font Complete.otf", + "preferred_family_name": "CodeNewRoman Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Book", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Droid Sans Mono Nerd Font Complete Mono.otf||3419992:1634564302.0": { + "family_name": "DroidSansMono Nerd Font Mono", + "font-family": "DroidSansMono Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 8, + "full_name": "Droid Sans Mono Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 6, + 9, + 3, + 8, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Droid Sans Mono Nerd Font Complete Mono.otf", + "preferred_family_name": "DroidSansMono Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Book", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Droid Sans Mono Nerd Font Complete.otf||2096384:1634564302.0": { + "family_name": "DroidSansMono Nerd Font", + "font-family": "DroidSansMono Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 8, + "full_name": "Droid Sans Mono Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 6, + 9, + 3, + 8, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Droid Sans Mono Nerd Font Complete.otf", + "preferred_family_name": "DroidSansMono Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Book", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Fira Code Bold Nerd Font Complete Mono.otf||3471168:1634564302.0": { + "family_name": "FiraCode Nerd Font Mono", + "font-family": "FiraCode Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Fira Code Bold Nerd Font Complete Mono", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 9, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Fira Code Bold Nerd Font Complete Mono.otf", + "preferred_family_name": "FiraCode Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Fira Code Bold Nerd Font Complete.otf||2341000:1634564302.0": { + "family_name": "FiraCode Nerd Font", + "font-family": "FiraCode Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Fira Code Bold Nerd Font Complete", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 9, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Fira Code Bold Nerd Font Complete.otf", + "preferred_family_name": "FiraCode Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Fira Code Light Nerd Font Complete Mono.otf||3471744:1634564302.0": { + "family_name": "FiraCode Nerd Font Mono", + "font-family": "FiraCode Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Fira Code Light Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 9, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Fira Code Light Nerd Font Complete Mono.otf", + "preferred_family_name": "FiraCode Nerd Font Mono", + "preferred_subfamily_name": "Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Fira Code Light Nerd Font Complete.otf||2338112:1634564302.0": { + "family_name": "FiraCode Nerd Font", + "font-family": "FiraCode Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Fira Code Light Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 9, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Fira Code Light Nerd Font Complete.otf", + "preferred_family_name": "FiraCode Nerd Font", + "preferred_subfamily_name": "Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Fira Code Medium Nerd Font Complete Mono.otf||3474532:1634564302.0": { + "family_name": "FiraCode Nerd Font Mono", + "font-family": "FiraCode Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Fira Code Medium Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 9, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Fira Code Medium Nerd Font Complete Mono.otf", + "preferred_family_name": "FiraCode Nerd Font Mono", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Fira Code Medium Nerd Font Complete.otf||2342560:1634564302.0": { + "family_name": "FiraCode Nerd Font", + "font-family": "FiraCode Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Fira Code Medium Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 9, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Fira Code Medium Nerd Font Complete.otf", + "preferred_family_name": "FiraCode Nerd Font", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Fira Code Regular Nerd Font Complete Mono.otf||3475004:1634564302.0": { + "family_name": "FiraCode Nerd Font Mono", + "font-family": "FiraCode Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Fira Code Regular Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 9, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Fira Code Regular Nerd Font Complete Mono.otf", + "preferred_family_name": "FiraCode Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Fira Code Regular Nerd Font Complete.otf||2341136:1634564302.0": { + "family_name": "FiraCode Nerd Font", + "font-family": "FiraCode Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Fira Code Regular Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 9, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Fira Code Regular Nerd Font Complete.otf", + "preferred_family_name": "FiraCode Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Fira Code Retina Nerd Font Complete Mono.otf||3471432:1634564302.0": { + "family_name": "FiraCode Nerd Font Mono", + "font-family": "FiraCode Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "450", + "fs_type": 0, + "full_name": "Fira Code Retina Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 9, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Fira Code Retina Nerd Font Complete Mono.otf", + "preferred_family_name": "FiraCode Nerd Font Mono", + "preferred_subfamily_name": "Retina", + "subfamily_name": "Regular", + "weight": 450, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Fira Code Retina Nerd Font Complete.otf||2338788:1634564302.0": { + "family_name": "FiraCode Nerd Font", + "font-family": "FiraCode Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "450", + "fs_type": 0, + "full_name": "Fira Code Retina Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 9, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Fira Code Retina Nerd Font Complete.otf", + "preferred_family_name": "FiraCode Nerd Font", + "preferred_subfamily_name": "Retina", + "subfamily_name": "Regular", + "weight": 450, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Fira Mono Bold Nerd Font Complete Mono.otf||3369324:1634564302.0": { + "family_name": "FiraMono Nerd Font Mono", + "font-family": "FiraMono Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 8, + "full_name": "Fira Mono Bold Nerd Font Complete Mono", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 8, + 9, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Fira Mono Bold Nerd Font Complete Mono.otf", + "preferred_family_name": "FiraMono Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Fira Mono Bold Nerd Font Complete.otf||2188416:1634564302.0": { + "family_name": "FiraMono Nerd Font", + "font-family": "FiraMono Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 8, + "full_name": "Fira Mono Bold Nerd Font Complete", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 8, + 9, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Fira Mono Bold Nerd Font Complete.otf", + "preferred_family_name": "FiraMono Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Fira Mono Medium Nerd Font Complete Mono.otf||3367008:1634564302.0": { + "family_name": "FiraMono Nerd Font Mono", + "font-family": "FiraMono Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 8, + "full_name": "Fira Mono Medium Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 6, + 9, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Fira Mono Medium Nerd Font Complete Mono.otf", + "preferred_family_name": "FiraMono Nerd Font Mono", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Fira Mono Medium Nerd Font Complete.otf||2185068:1634564302.0": { + "family_name": "FiraMono Nerd Font", + "font-family": "FiraMono Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 8, + "full_name": "Fira Mono Medium Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 6, + 9, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Fira Mono Medium Nerd Font Complete.otf", + "preferred_family_name": "FiraMono Nerd Font", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Fira Mono Regular Nerd Font Complete Mono.otf||3364984:1634564302.0": { + "family_name": "FiraMono Nerd Font Mono", + "font-family": "FiraMono Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 8, + "full_name": "Fira Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 5, + 9, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Fira Mono Regular Nerd Font Complete Mono.otf", + "preferred_family_name": "FiraMono Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Fira Mono Regular Nerd Font Complete.otf||2182844:1634564302.0": { + "family_name": "FiraMono Nerd Font", + "font-family": "FiraMono Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 8, + "full_name": "Fira Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 5, + 9, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Fira Mono Regular Nerd Font Complete.otf", + "preferred_family_name": "FiraMono Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Fura Code Bold Nerd Font Complete Mono.otf||3434540:1634564302.0": { + "family_name": "FuraCode Nerd Font Mono", + "font-family": "FuraCode Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Fura Code Bold Nerd Font Complete Mono", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 9, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Fura Code Bold Nerd Font Complete Mono.otf", + "preferred_family_name": "FuraCode Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Fura Code Bold Nerd Font Complete.otf||2295024:1634564302.0": { + "family_name": "FuraCode Nerd Font", + "font-family": "FuraCode Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Fura Code Bold Nerd Font Complete", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 9, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Fura Code Bold Nerd Font Complete.otf", + "preferred_family_name": "FuraCode Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Fura Code Light Nerd Font Complete Mono.otf||3482780:1634564302.0": { + "family_name": "FuraCode Nerd Font Mono", + "font-family": "FuraCode Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Fura Code Light Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 9, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Fura Code Light Nerd Font Complete Mono.otf", + "preferred_family_name": "FuraCode Nerd Font Mono", + "preferred_subfamily_name": "Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Fura Code Light Nerd Font Complete.otf||2288836:1634564302.0": { + "family_name": "FuraCode Nerd Font", + "font-family": "FuraCode Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Fura Code Light Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 9, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Fura Code Light Nerd Font Complete.otf", + "preferred_family_name": "FuraCode Nerd Font", + "preferred_subfamily_name": "Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Fura Code Medium Nerd Font Complete Mono.otf||3485220:1634564302.0": { + "family_name": "FuraCode Nerd Font Mono", + "font-family": "FuraCode Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Fura Code Medium Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 9, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Fura Code Medium Nerd Font Complete Mono.otf", + "preferred_family_name": "FuraCode Nerd Font Mono", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Fura Code Medium Nerd Font Complete.otf||2291728:1634564302.0": { + "family_name": "FuraCode Nerd Font", + "font-family": "FuraCode Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Fura Code Medium Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 9, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Fura Code Medium Nerd Font Complete.otf", + "preferred_family_name": "FuraCode Nerd Font", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Fura Code Regular Nerd Font Complete Mono.otf||3483680:1634564302.0": { + "family_name": "FuraCode Nerd Font Mono", + "font-family": "FuraCode Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Fura Code Regular Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 9, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Fura Code Regular Nerd Font Complete Mono.otf", + "preferred_family_name": "FuraCode Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Fura Code Regular Nerd Font Complete.otf||2290112:1634564302.0": { + "family_name": "FuraCode Nerd Font", + "font-family": "FuraCode Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Fura Code Regular Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 9, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Fura Code Regular Nerd Font Complete.otf", + "preferred_family_name": "FuraCode Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Fura Code Retina Nerd Font Complete Mono.otf||3483588:1634564302.0": { + "family_name": "FuraCode Nerd Font Mono", + "font-family": "FuraCode Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "450", + "fs_type": 0, + "full_name": "Fura Code Retina Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 9, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Fura Code Retina Nerd Font Complete Mono.otf", + "preferred_family_name": "FuraCode Nerd Font Mono", + "preferred_subfamily_name": "Retina", + "subfamily_name": "Regular", + "weight": 450, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Fura Code Retina Nerd Font Complete.otf||2289900:1634564302.0": { + "family_name": "FuraCode Nerd Font", + "font-family": "FuraCode Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "450", + "fs_type": 0, + "full_name": "Fura Code Retina Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 9, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Fura Code Retina Nerd Font Complete.otf", + "preferred_family_name": "FuraCode Nerd Font", + "preferred_subfamily_name": "Retina", + "subfamily_name": "Regular", + "weight": 450, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Fura Mono Bold Nerd Font Complete Mono.otf||3379136:1634564302.0": { + "family_name": "FuraMono Nerd Font Mono", + "font-family": "FuraMono Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 8, + "full_name": "Fura Mono Bold Nerd Font Complete Mono", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 8, + 9, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Fura Mono Bold Nerd Font Complete Mono.otf", + "preferred_family_name": "FuraMono Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Fura Mono Bold Nerd Font Complete.otf||2193528:1634564302.0": { + "family_name": "FuraMono Nerd Font", + "font-family": "FuraMono Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 8, + "full_name": "Fura Mono Bold Nerd Font Complete", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 8, + 9, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Fura Mono Bold Nerd Font Complete.otf", + "preferred_family_name": "FuraMono Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Fura Mono Medium Nerd Font Complete Mono.otf||3376832:1634564302.0": { + "family_name": "FuraMono Nerd Font Mono", + "font-family": "FuraMono Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 8, + "full_name": "Fura Mono Medium Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 6, + 9, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Fura Mono Medium Nerd Font Complete Mono.otf", + "preferred_family_name": "FuraMono Nerd Font Mono", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Fura Mono Medium Nerd Font Complete.otf||2190180:1634564302.0": { + "family_name": "FuraMono Nerd Font", + "font-family": "FuraMono Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 8, + "full_name": "Fura Mono Medium Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 6, + 9, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Fura Mono Medium Nerd Font Complete.otf", + "preferred_family_name": "FuraMono Nerd Font", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Fura Mono Regular Nerd Font Complete Mono.otf||3374796:1634564302.0": { + "family_name": "FuraMono Nerd Font Mono", + "font-family": "FuraMono Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 8, + "full_name": "Fira Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 5, + 9, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Fura Mono Regular Nerd Font Complete Mono.otf", + "preferred_family_name": "FuraMono Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Fura Mono Regular Nerd Font Complete.otf||2187956:1634564302.0": { + "family_name": "FuraMono Nerd Font", + "font-family": "FuraMono Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 8, + "full_name": "Fira Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 5, + 9, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Fura Mono Regular Nerd Font Complete.otf", + "preferred_family_name": "FuraMono Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Hasklug Black Italic Nerd Font Complete Mono.otf||3356444:1634564302.0": { + "family_name": "Hasklig Black", + "font-family": "Hasklig Black", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "900", + "fs_type": 0, + "full_name": "Hasklug Black Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 8, + 9, + 3, + 4, + 3, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Hasklug Black Italic Nerd Font Complete Mono.otf", + "preferred_family_name": "Hasklug Nerd Font Mono", + "preferred_subfamily_name": "Black Italic", + "subfamily_name": "Italic", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Hasklug Black Italic Nerd Font Complete.otf||2220068:1634564302.0": { + "family_name": "Hasklig Black", + "font-family": "Hasklig Black", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "900", + "fs_type": 0, + "full_name": "Hasklug Black Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 8, + 9, + 3, + 4, + 3, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Hasklug Black Italic Nerd Font Complete.otf", + "preferred_family_name": "Hasklug Nerd Font", + "preferred_subfamily_name": "Black Italic", + "subfamily_name": "Italic", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Hasklug Black Nerd Font Complete Mono.otf||3383584:1634564302.0": { + "family_name": "Hasklig Black", + "font-family": "Hasklig Black", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Hasklug Black Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 8, + 9, + 3, + 4, + 3, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Hasklug Black Nerd Font Complete Mono.otf", + "preferred_family_name": "Hasklug Nerd Font Mono", + "preferred_subfamily_name": "Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Hasklug Black Nerd Font Complete.otf||2237332:1634564302.0": { + "family_name": "Hasklig Black", + "font-family": "Hasklig Black", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Hasklug Black Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 8, + 9, + 3, + 4, + 3, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Hasklug Black Nerd Font Complete.otf", + "preferred_family_name": "Hasklug Nerd Font", + "preferred_subfamily_name": "Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Hasklug Bold Italic Nerd Font Complete Mono.otf||3354252:1634564302.0": { + "family_name": "Hasklug Nerd Font Mono", + "font-family": "Hasklug Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Hasklug Bold Italic Nerd Font Complete Mono", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 7, + 9, + 3, + 4, + 3, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Hasklug Bold Italic Nerd Font Complete Mono.otf", + "preferred_family_name": "Hasklug Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Hasklug Bold Italic Nerd Font Complete.otf||2218452:1634564302.0": { + "family_name": "Hasklug Nerd Font", + "font-family": "Hasklug Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Hasklug Bold Italic Nerd Font Complete", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 7, + 9, + 3, + 4, + 3, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Hasklug Bold Italic Nerd Font Complete.otf", + "preferred_family_name": "Hasklug Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Hasklug Bold Nerd Font Complete Mono.otf||3382028:1634564302.0": { + "family_name": "Hasklug Nerd Font Mono", + "font-family": "Hasklug Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Hasklug Bold Nerd Font Complete Mono", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 7, + 9, + 3, + 4, + 3, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Hasklug Bold Nerd Font Complete Mono.otf", + "preferred_family_name": "Hasklug Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Hasklug Bold Nerd Font Complete.otf||2236364:1634564302.0": { + "family_name": "Hasklug Nerd Font", + "font-family": "Hasklug Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Hasklug Bold Nerd Font Complete", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 7, + 9, + 3, + 4, + 3, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Hasklug Bold Nerd Font Complete.otf", + "preferred_family_name": "Hasklug Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Hasklug ExtraLight Italic Nerd Font Complete Mono.otf||3350044:1634564302.0": { + "family_name": "Hasklig ExtraLight", + "font-family": "Hasklig ExtraLight", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "200", + "fs_type": 0, + "full_name": "Hasklug ExtraLight Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 3, + 9, + 3, + 4, + 3, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Hasklug ExtraLight Italic Nerd Font Complete Mono.otf", + "preferred_family_name": "Hasklug Nerd Font Mono", + "preferred_subfamily_name": "ExtraLight Italic", + "subfamily_name": "Italic", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Hasklug ExtraLight Italic Nerd Font Complete.otf||2214708:1634564302.0": { + "family_name": "Hasklig ExtraLight", + "font-family": "Hasklig ExtraLight", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "200", + "fs_type": 0, + "full_name": "Hasklug ExtraLight Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 3, + 9, + 3, + 4, + 3, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Hasklug ExtraLight Italic Nerd Font Complete.otf", + "preferred_family_name": "Hasklug Nerd Font", + "preferred_subfamily_name": "ExtraLight Italic", + "subfamily_name": "Italic", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Hasklug ExtraLight Nerd Font Complete Mono.otf||3373812:1634564302.0": { + "family_name": "Hasklig ExtraLight", + "font-family": "Hasklig ExtraLight", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Hasklug ExtraLight Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 3, + 9, + 3, + 4, + 3, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Hasklug ExtraLight Nerd Font Complete Mono.otf", + "preferred_family_name": "Hasklug Nerd Font Mono", + "preferred_subfamily_name": "ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Hasklug ExtraLight Nerd Font Complete.otf||2228640:1634564302.0": { + "family_name": "Hasklig ExtraLight", + "font-family": "Hasklig ExtraLight", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Hasklug ExtraLight Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 3, + 9, + 3, + 4, + 3, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Hasklug ExtraLight Nerd Font Complete.otf", + "preferred_family_name": "Hasklug Nerd Font", + "preferred_subfamily_name": "ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Hasklug Italic Nerd Font Complete Mono.otf||3352312:1634564302.0": { + "family_name": "Hasklug Nerd Font Mono", + "font-family": "Hasklug Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Hasklug Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 5, + 9, + 3, + 4, + 3, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Hasklug Italic Nerd Font Complete Mono.otf", + "preferred_family_name": "Hasklug Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Hasklug Italic Nerd Font Complete.otf||2214952:1634564302.0": { + "family_name": "Hasklug Nerd Font", + "font-family": "Hasklug Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Hasklug Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 5, + 9, + 3, + 4, + 3, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Hasklug Italic Nerd Font Complete.otf", + "preferred_family_name": "Hasklug Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Hasklug Light Italic Nerd Font Complete Mono.otf||3351740:1634564302.0": { + "family_name": "Hasklig Light", + "font-family": "Hasklig Light", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "300", + "fs_type": 0, + "full_name": "Hasklug Light Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 4, + 9, + 3, + 4, + 3, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Hasklug Light Italic Nerd Font Complete Mono.otf", + "preferred_family_name": "Hasklug Nerd Font Mono", + "preferred_subfamily_name": "Light Italic", + "subfamily_name": "Italic", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Hasklug Light Italic Nerd Font Complete.otf||2215788:1634564302.0": { + "family_name": "Hasklig Light", + "font-family": "Hasklig Light", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "300", + "fs_type": 0, + "full_name": "Hasklug Light Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 4, + 9, + 3, + 4, + 3, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Hasklug Light Italic Nerd Font Complete.otf", + "preferred_family_name": "Hasklug Nerd Font", + "preferred_subfamily_name": "Light Italic", + "subfamily_name": "Italic", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Hasklug Light Nerd Font Complete Mono.otf||3378544:1634564302.0": { + "family_name": "Hasklig Light", + "font-family": "Hasklig Light", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Hasklug Light Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 4, + 9, + 3, + 4, + 3, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Hasklug Light Nerd Font Complete Mono.otf", + "preferred_family_name": "Hasklug Nerd Font Mono", + "preferred_subfamily_name": "Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Hasklug Light Nerd Font Complete.otf||2232732:1634564302.0": { + "family_name": "Hasklig Light", + "font-family": "Hasklig Light", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Hasklug Light Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 4, + 9, + 3, + 4, + 3, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Hasklug Light Nerd Font Complete.otf", + "preferred_family_name": "Hasklug Nerd Font", + "preferred_subfamily_name": "Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Hasklug Medium Italic Nerd Font Complete Mono.otf||3352600:1634564302.0": { + "family_name": "Hasklig Medium", + "font-family": "Hasklig Medium", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "500", + "fs_type": 0, + "full_name": "Hasklug Medium Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 5, + 9, + 3, + 4, + 3, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Hasklug Medium Italic Nerd Font Complete Mono.otf", + "preferred_family_name": "Hasklug Nerd Font Mono", + "preferred_subfamily_name": "Medium Italic", + "subfamily_name": "Italic", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Hasklug Medium Italic Nerd Font Complete.otf||2215636:1634564302.0": { + "family_name": "Hasklig Medium", + "font-family": "Hasklig Medium", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "500", + "fs_type": 0, + "full_name": "Hasklug Medium Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 5, + 9, + 3, + 4, + 3, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Hasklug Medium Italic Nerd Font Complete.otf", + "preferred_family_name": "Hasklug Nerd Font", + "preferred_subfamily_name": "Medium Italic", + "subfamily_name": "Italic", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Hasklug Medium Nerd Font Complete Mono.otf||3378616:1634564302.0": { + "family_name": "Hasklig Medium", + "font-family": "Hasklig Medium", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Hasklug Medium Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 5, + 9, + 3, + 4, + 3, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Hasklug Medium Nerd Font Complete Mono.otf", + "preferred_family_name": "Hasklug Nerd Font Mono", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Hasklug Medium Nerd Font Complete.otf||2231788:1634564302.0": { + "family_name": "Hasklig Medium", + "font-family": "Hasklig Medium", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Hasklug Medium Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 5, + 9, + 3, + 4, + 3, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Hasklug Medium Nerd Font Complete.otf", + "preferred_family_name": "Hasklug Nerd Font", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Hasklug Nerd Font Complete Mono.otf||3379568:1634564302.0": { + "family_name": "Hasklug Nerd Font Mono", + "font-family": "Hasklug Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Hasklug Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 5, + 9, + 3, + 4, + 3, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Hasklug Nerd Font Complete Mono.otf", + "preferred_family_name": "Hasklug Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Hasklug Nerd Font Complete.otf||2232352:1634564302.0": { + "family_name": "Hasklug Nerd Font", + "font-family": "Hasklug Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Hasklug Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 5, + 9, + 3, + 4, + 3, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Hasklug Nerd Font Complete.otf", + "preferred_family_name": "Hasklug Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Hasklug Semibold Italic Nerd Font Complete Mono.otf||3353272:1634564302.0": { + "family_name": "Hasklig Semibold", + "font-family": "Hasklig Semibold", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "600", + "fs_type": 0, + "full_name": "Hasklug Semibold Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 6, + 9, + 3, + 4, + 3, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Hasklug Semibold Italic Nerd Font Complete Mono.otf", + "preferred_family_name": "Hasklug Nerd Font Mono", + "preferred_subfamily_name": "Semibold Italic", + "subfamily_name": "Italic", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Hasklug Semibold Italic Nerd Font Complete.otf||2216376:1634564302.0": { + "family_name": "Hasklig Semibold", + "font-family": "Hasklig Semibold", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "600", + "fs_type": 0, + "full_name": "Hasklug Semibold Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 6, + 9, + 3, + 4, + 3, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Hasklug Semibold Italic Nerd Font Complete.otf", + "preferred_family_name": "Hasklug Nerd Font", + "preferred_subfamily_name": "Semibold Italic", + "subfamily_name": "Italic", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Hasklug Semibold Nerd Font Complete Mono.otf||3380864:1634564302.0": { + "family_name": "Hasklig Semibold", + "font-family": "Hasklig Semibold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Hasklug Semibold Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 6, + 9, + 3, + 4, + 3, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Hasklug Semibold Nerd Font Complete Mono.otf", + "preferred_family_name": "Hasklug Nerd Font Mono", + "preferred_subfamily_name": "Semibold", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Hasklug Semibold Nerd Font Complete.otf||2234124:1634564302.0": { + "family_name": "Hasklig Semibold", + "font-family": "Hasklig Semibold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Hasklug Semibold Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 6, + 9, + 3, + 4, + 3, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Hasklug Semibold Nerd Font Complete.otf", + "preferred_family_name": "Hasklug Nerd Font", + "preferred_subfamily_name": "Semibold", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Hurmit Bold Nerd Font Complete Mono.otf||3288816:1634564302.0": { + "family_name": "Hurmit Nerd Font Mono", + "font-family": "Hurmit Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 8, + "full_name": "Hurmit Bold Nerd Font Complete Mono", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 8, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Hurmit Bold Nerd Font Complete Mono.otf", + "preferred_family_name": "Hurmit Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Hurmit Bold Nerd Font Complete.otf||2104364:1634564302.0": { + "family_name": "Hurmit Nerd Font", + "font-family": "Hurmit Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 8, + "full_name": "Hurmit Bold Nerd Font Complete", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 8, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Hurmit Bold Nerd Font Complete.otf", + "preferred_family_name": "Hurmit Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Hurmit Light Nerd Font Complete Mono.otf||3295960:1634564302.0": { + "family_name": "Hurmit Nerd Font Mono", + "font-family": "Hurmit Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 8, + "full_name": "Hurmit Light Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 3, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Hurmit Light Nerd Font Complete Mono.otf", + "preferred_family_name": "Hurmit Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "light", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Hurmit Light Nerd Font Complete.otf||2103168:1634564302.0": { + "family_name": "Hurmit Nerd Font", + "font-family": "Hurmit Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 8, + "full_name": "Hurmit Light Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 3, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Hurmit Light Nerd Font Complete.otf", + "preferred_family_name": "Hurmit Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "light", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Hurmit Medium Nerd Font Complete Mono.otf||3295816:1634564302.0": { + "family_name": "Hurmit Nerd Font Mono", + "font-family": "Hurmit Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 8, + "full_name": "Hurmit Medium Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 6, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Hurmit Medium Nerd Font Complete Mono.otf", + "preferred_family_name": "Hurmit Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "medium", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Hurmit Medium Nerd Font Complete.otf||2102016:1634564302.0": { + "family_name": "Hurmit Nerd Font", + "font-family": "Hurmit Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 8, + "full_name": "Hurmit Medium Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 6, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Hurmit Medium Nerd Font Complete.otf", + "preferred_family_name": "Hurmit Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "medium", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Inconsolata Bold Nerd Font Complete Mono.otf||3281924:1634564302.0": { + "family_name": "Inconsolata Nerd Font Mono", + "font-family": "Inconsolata Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Inconsolata Bold Nerd Font Complete Mono", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 8, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Inconsolata Bold Nerd Font Complete Mono.otf", + "preferred_family_name": "Inconsolata Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Inconsolata Bold Nerd Font Complete.otf||2179436:1634564302.0": { + "family_name": "Inconsolata Nerd Font", + "font-family": "Inconsolata Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Inconsolata Bold Nerd Font Complete", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 8, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Inconsolata Bold Nerd Font Complete.otf", + "preferred_family_name": "Inconsolata Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Inconsolata Nerd Font Complete Mono.otf||3222768:1634564302.0": { + "family_name": "Inconsolata Nerd Font Mono", + "font-family": "Inconsolata Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 8, + "full_name": "Inconsolata Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 6, + 9, + 3, + 0, + 3, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Inconsolata Nerd Font Complete Mono.otf", + "preferred_family_name": "Inconsolata Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Medium", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Inconsolata Nerd Font Complete.otf||2113436:1634564302.0": { + "family_name": "Inconsolata Nerd Font", + "font-family": "Inconsolata Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 8, + "full_name": "Inconsolata Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 6, + 9, + 3, + 0, + 3, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Inconsolata Nerd Font Complete.otf", + "preferred_family_name": "Inconsolata Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Medium", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Inconsolata Regular Nerd Font Complete Mono.otf||3281652:1634564302.0": { + "family_name": "Inconsolata Nerd Font Mono", + "font-family": "Inconsolata Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Inconsolata Regular Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 5, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Inconsolata Regular Nerd Font Complete Mono.otf", + "preferred_family_name": "Inconsolata Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Inconsolata Regular Nerd Font Complete.otf||2177972:1634564302.0": { + "family_name": "Inconsolata Nerd Font", + "font-family": "Inconsolata Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Inconsolata Regular Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 5, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Inconsolata Regular Nerd Font Complete.otf", + "preferred_family_name": "Inconsolata Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/OpenDyslexic Bold Italic Nerd Font Complete Mono.otf||3246604:1634564302.0": { + "family_name": "OpenDyslexic Nerd Font Mono", + "font-family": "OpenDyslexic Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "OpenDyslexic Bold Italic Nerd Font Complete Mono", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 8, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/OpenDyslexic Bold Italic Nerd Font Complete Mono.otf", + "preferred_family_name": "OpenDyslexic Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/OpenDyslexic Bold Italic Nerd Font Complete.otf||2174476:1634564302.0": { + "family_name": "OpenDyslexic Nerd Font", + "font-family": "OpenDyslexic Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "OpenDyslexic Bold Italic Nerd Font Complete", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 8, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/OpenDyslexic Bold Italic Nerd Font Complete.otf", + "preferred_family_name": "OpenDyslexic Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/OpenDyslexic Bold Nerd Font Complete Mono.otf||3212100:1634564302.0": { + "family_name": "OpenDyslexic Nerd Font Mono", + "font-family": "OpenDyslexic Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "OpenDyslexic Bold Nerd Font Complete Mono", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 8, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/OpenDyslexic Bold Nerd Font Complete Mono.otf", + "preferred_family_name": "OpenDyslexic Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/OpenDyslexic Bold Nerd Font Complete.otf||2136792:1634564302.0": { + "family_name": "OpenDyslexic Nerd Font", + "font-family": "OpenDyslexic Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "OpenDyslexic Bold Nerd Font Complete", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 8, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/OpenDyslexic Bold Nerd Font Complete.otf", + "preferred_family_name": "OpenDyslexic Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/OpenDyslexic Italic Nerd Font Complete Mono.otf||3238404:1634564302.0": { + "family_name": "OpenDyslexic Nerd Font Mono", + "font-family": "OpenDyslexic Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "OpenDyslexic Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 5, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/OpenDyslexic Italic Nerd Font Complete Mono.otf", + "preferred_family_name": "OpenDyslexic Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/OpenDyslexic Italic Nerd Font Complete.otf||2165428:1634564302.0": { + "family_name": "OpenDyslexic Nerd Font", + "font-family": "OpenDyslexic Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "OpenDyslexic Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 5, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/OpenDyslexic Italic Nerd Font Complete.otf", + "preferred_family_name": "OpenDyslexic Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/OpenDyslexic Regular Nerd Font Complete Mono.otf||3207184:1634564302.0": { + "family_name": "OpenDyslexic Nerd Font Mono", + "font-family": "OpenDyslexic Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "OpenDyslexic", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 5, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/OpenDyslexic Regular Nerd Font Complete Mono.otf", + "preferred_family_name": "OpenDyslexic Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/OpenDyslexic Regular Nerd Font Complete.otf||2139964:1634564302.0": { + "family_name": "OpenDyslexic Nerd Font", + "font-family": "OpenDyslexic Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "OpenDyslexic", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 5, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/OpenDyslexic Regular Nerd Font Complete.otf", + "preferred_family_name": "OpenDyslexic Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/OpenDyslexicAlta Bold Italic Nerd Font Complete Mono.otf||3223428:1634564302.0": { + "family_name": "OpenDyslexicAlta Nerd Font Mono", + "font-family": "OpenDyslexicAlta Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "OpenDyslexicAlta Bold Italic Nerd Font Complete Mono", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 8, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/OpenDyslexicAlta Bold Italic Nerd Font Complete Mono.otf", + "preferred_family_name": "OpenDyslexicAlta Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/OpenDyslexicAlta Bold Italic Nerd Font Complete.otf||2177524:1634564302.0": { + "family_name": "OpenDyslexicAlta Nerd Font", + "font-family": "OpenDyslexicAlta Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "OpenDyslexicAlta Bold Italic Nerd Font Complete", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 8, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/OpenDyslexicAlta Bold Italic Nerd Font Complete.otf", + "preferred_family_name": "OpenDyslexicAlta Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/OpenDyslexicAlta Bold Nerd Font Complete Mono.otf||3211260:1634564302.0": { + "family_name": "OpenDyslexicAlta Nerd Font Mono", + "font-family": "OpenDyslexicAlta Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "OpenDyslexicAlta Bold Nerd Font Complete Mono", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 8, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/OpenDyslexicAlta Bold Nerd Font Complete Mono.otf", + "preferred_family_name": "OpenDyslexicAlta Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/OpenDyslexicAlta Bold Nerd Font Complete.otf||2135940:1634564302.0": { + "family_name": "OpenDyslexicAlta Nerd Font", + "font-family": "OpenDyslexicAlta Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "OpenDyslexicAlta Bold Nerd Font Complete", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 8, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/OpenDyslexicAlta Bold Nerd Font Complete.otf", + "preferred_family_name": "OpenDyslexicAlta Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/OpenDyslexicAlta Italic Nerd Font Complete Mono.otf||3225076:1634564302.0": { + "family_name": "OpenDyslexicAlta Nerd Font Mono", + "font-family": "OpenDyslexicAlta Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "OpenDyslexicAlta Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 5, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/OpenDyslexicAlta Italic Nerd Font Complete Mono.otf", + "preferred_family_name": "OpenDyslexicAlta Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/OpenDyslexicAlta Italic Nerd Font Complete.otf||2152700:1634564302.0": { + "family_name": "OpenDyslexicAlta Nerd Font", + "font-family": "OpenDyslexicAlta Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "OpenDyslexicAlta Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 5, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/OpenDyslexicAlta Italic Nerd Font Complete.otf", + "preferred_family_name": "OpenDyslexicAlta Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/OpenDyslexicAlta Regular Nerd Font Complete Mono.otf||3201552:1634564302.0": { + "family_name": "OpenDyslexicAlta Nerd Font Mono", + "font-family": "OpenDyslexicAlta Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "OpenDyslexicAlta", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 5, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/OpenDyslexicAlta Regular Nerd Font Complete Mono.otf", + "preferred_family_name": "OpenDyslexicAlta Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/OpenDyslexicAlta Regular Nerd Font Complete.otf||2133488:1634564302.0": { + "family_name": "OpenDyslexicAlta Nerd Font", + "font-family": "OpenDyslexicAlta Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "OpenDyslexicAlta", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 5, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/OpenDyslexicAlta Regular Nerd Font Complete.otf", + "preferred_family_name": "OpenDyslexicAlta Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/OpenDyslexicMono Regular Nerd Font Complete Mono.otf||3204300:1634564302.0": { + "family_name": "OpenDyslexicMono Nerd Font Mono", + "font-family": "OpenDyslexicMono Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "OpenDyslexicMono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 5, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/OpenDyslexicMono Regular Nerd Font Complete Mono.otf", + "preferred_family_name": "OpenDyslexicMono Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/OpenDyslexicMono Regular Nerd Font Complete.otf||2147744:1634564302.0": { + "family_name": "OpenDyslexicMono Nerd Font", + "font-family": "OpenDyslexicMono Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "OpenDyslexicMono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 5, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/OpenDyslexicMono Regular Nerd Font Complete.otf", + "preferred_family_name": "OpenDyslexicMono Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Overpass Bold Italic Nerd Font Complete Mono.otf||3288712:1634564302.0": { + "family_name": "Overpass Nerd Font Mono", + "font-family": "Overpass Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Overpass Bold Italic Nerd Font Complete Mono", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 8, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Overpass Bold Italic Nerd Font Complete Mono.otf", + "preferred_family_name": "Overpass Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Overpass Bold Italic Nerd Font Complete.otf||2160768:1634564302.0": { + "family_name": "Overpass Nerd Font", + "font-family": "Overpass Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Overpass Bold Italic Nerd Font Complete", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 8, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Overpass Bold Italic Nerd Font Complete.otf", + "preferred_family_name": "Overpass Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Overpass Bold Nerd Font Complete Mono.otf||3246532:1634564302.0": { + "family_name": "Overpass Nerd Font Mono", + "font-family": "Overpass Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Overpass Bold Nerd Font Complete Mono", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 8, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Overpass Bold Nerd Font Complete Mono.otf", + "preferred_family_name": "Overpass Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Overpass Bold Nerd Font Complete.otf||2157920:1634564302.0": { + "family_name": "Overpass Nerd Font", + "font-family": "Overpass Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Overpass Bold Nerd Font Complete", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 8, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Overpass Bold Nerd Font Complete.otf", + "preferred_family_name": "Overpass Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Overpass ExtraBold Italic Nerd Font Complete Mono.otf||3285888:1634564302.0": { + "family_name": "Overpass Nerd Font Mono", + "font-family": "Overpass Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "800", + "fs_type": 0, + "full_name": "Overpass ExtraBold Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 9, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Overpass ExtraBold Italic Nerd Font Complete Mono.otf", + "preferred_family_name": "Overpass Nerd Font Mono", + "preferred_subfamily_name": "ExtraBold Italic", + "subfamily_name": "Italic", + "weight": 800, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Overpass ExtraBold Italic Nerd Font Complete.otf||2160228:1634564302.0": { + "family_name": "Overpass Nerd Font", + "font-family": "Overpass Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "800", + "fs_type": 0, + "full_name": "Overpass ExtraBold Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 9, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Overpass ExtraBold Italic Nerd Font Complete.otf", + "preferred_family_name": "Overpass Nerd Font", + "preferred_subfamily_name": "ExtraBold Italic", + "subfamily_name": "Italic", + "weight": 800, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Overpass ExtraBold Nerd Font Complete Mono.otf||3282588:1634564302.0": { + "family_name": "Overpass Nerd Font Mono", + "font-family": "Overpass Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Overpass ExtraBold Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 9, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Overpass ExtraBold Nerd Font Complete Mono.otf", + "preferred_family_name": "Overpass Nerd Font Mono", + "preferred_subfamily_name": "ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Overpass ExtraBold Nerd Font Complete.otf||2156128:1634564302.0": { + "family_name": "Overpass Nerd Font", + "font-family": "Overpass Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Overpass ExtraBold Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 9, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Overpass ExtraBold Nerd Font Complete.otf", + "preferred_family_name": "Overpass Nerd Font", + "preferred_subfamily_name": "ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Overpass ExtraLight Italic Nerd Font Complete Mono.otf||3293172:1634564302.0": { + "family_name": "Overpass Nerd Font Mono", + "font-family": "Overpass Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "200", + "fs_type": 0, + "full_name": "Overpass ExtraLight Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 3, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Overpass ExtraLight Italic Nerd Font Complete Mono.otf", + "preferred_family_name": "Overpass Nerd Font Mono", + "preferred_subfamily_name": "ExtraLight Italic", + "subfamily_name": "Italic", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Overpass ExtraLight Italic Nerd Font Complete.otf||2160464:1634564302.0": { + "family_name": "Overpass Nerd Font", + "font-family": "Overpass Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "200", + "fs_type": 0, + "full_name": "Overpass ExtraLight Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 3, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Overpass ExtraLight Italic Nerd Font Complete.otf", + "preferred_family_name": "Overpass Nerd Font", + "preferred_subfamily_name": "ExtraLight Italic", + "subfamily_name": "Italic", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Overpass ExtraLight Nerd Font Complete Mono.otf||3276932:1634564302.0": { + "family_name": "Overpass Nerd Font Mono", + "font-family": "Overpass Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Overpass ExtraLight Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 3, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Overpass ExtraLight Nerd Font Complete Mono.otf", + "preferred_family_name": "Overpass Nerd Font Mono", + "preferred_subfamily_name": "ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Overpass ExtraLight Nerd Font Complete.otf||2158484:1634564302.0": { + "family_name": "Overpass Nerd Font", + "font-family": "Overpass Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Overpass ExtraLight Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 3, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Overpass ExtraLight Nerd Font Complete.otf", + "preferred_family_name": "Overpass Nerd Font", + "preferred_subfamily_name": "ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Overpass Heavy Italic Nerd Font Complete Mono.otf||3280780:1634564302.0": { + "family_name": "Overpass Nerd Font Mono", + "font-family": "Overpass Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "900", + "fs_type": 0, + "full_name": "Overpass Heavy Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 10, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Overpass Heavy Italic Nerd Font Complete Mono.otf", + "preferred_family_name": "Overpass Nerd Font Mono", + "preferred_subfamily_name": "Heavy Italic", + "subfamily_name": "Italic", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Overpass Heavy Italic Nerd Font Complete.otf||2161952:1634564302.0": { + "family_name": "Overpass Nerd Font", + "font-family": "Overpass Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "900", + "fs_type": 0, + "full_name": "Overpass Heavy Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 10, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Overpass Heavy Italic Nerd Font Complete.otf", + "preferred_family_name": "Overpass Nerd Font", + "preferred_subfamily_name": "Heavy Italic", + "subfamily_name": "Italic", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Overpass Heavy Nerd Font Complete Mono.otf||3232628:1634564302.0": { + "family_name": "Overpass Nerd Font Mono", + "font-family": "Overpass Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Overpass Heavy Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 10, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Overpass Heavy Nerd Font Complete Mono.otf", + "preferred_family_name": "Overpass Nerd Font Mono", + "preferred_subfamily_name": "Heavy", + "subfamily_name": "Regular", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Overpass Heavy Nerd Font Complete.otf||2159740:1634564302.0": { + "family_name": "Overpass Nerd Font", + "font-family": "Overpass Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Overpass Heavy Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 10, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Overpass Heavy Nerd Font Complete.otf", + "preferred_family_name": "Overpass Nerd Font", + "preferred_subfamily_name": "Heavy", + "subfamily_name": "Regular", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Overpass Italic Nerd Font Complete Mono.otf||3293292:1634564302.0": { + "family_name": "Overpass Nerd Font Mono", + "font-family": "Overpass Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Overpass Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 5, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Overpass Italic Nerd Font Complete Mono.otf", + "preferred_family_name": "Overpass Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Overpass Italic Nerd Font Complete.otf||2160628:1634564302.0": { + "family_name": "Overpass Nerd Font", + "font-family": "Overpass Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Overpass Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 5, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Overpass Italic Nerd Font Complete.otf", + "preferred_family_name": "Overpass Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Overpass Light Italic Nerd Font Complete Mono.otf||3245908:1634564302.0": { + "family_name": "Overpass Nerd Font Mono", + "font-family": "Overpass Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "300", + "fs_type": 0, + "full_name": "Overpass Light Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 4, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Overpass Light Italic Nerd Font Complete Mono.otf", + "preferred_family_name": "Overpass Nerd Font Mono", + "preferred_subfamily_name": "Light Italic", + "subfamily_name": "Italic", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Overpass Light Italic Nerd Font Complete.otf||2159524:1634564302.0": { + "family_name": "Overpass Nerd Font", + "font-family": "Overpass Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "300", + "fs_type": 0, + "full_name": "Overpass Light Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 4, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Overpass Light Italic Nerd Font Complete.otf", + "preferred_family_name": "Overpass Nerd Font", + "preferred_subfamily_name": "Light Italic", + "subfamily_name": "Italic", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Overpass Light Nerd Font Complete Mono.otf||3290920:1634564302.0": { + "family_name": "Overpass Nerd Font Mono", + "font-family": "Overpass Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Overpass Light Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 4, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Overpass Light Nerd Font Complete Mono.otf", + "preferred_family_name": "Overpass Nerd Font Mono", + "preferred_subfamily_name": "Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Overpass Light Nerd Font Complete.otf||2157264:1634564302.0": { + "family_name": "Overpass Nerd Font", + "font-family": "Overpass Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Overpass Light Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 4, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Overpass Light Nerd Font Complete.otf", + "preferred_family_name": "Overpass Nerd Font", + "preferred_subfamily_name": "Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Overpass Mono Bold Nerd Font Complete Mono.otf||3251624:1634564302.0": { + "family_name": "OverpassMono Nerd Font Mono", + "font-family": "OverpassMono Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Overpass Mono Bold Nerd Font Complete Mono", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 8, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Overpass Mono Bold Nerd Font Complete Mono.otf", + "preferred_family_name": "OverpassMono Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Overpass Mono Bold Nerd Font Complete.otf||2189856:1634564302.0": { + "family_name": "OverpassMono Nerd Font", + "font-family": "OverpassMono Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Overpass Mono Bold Nerd Font Complete", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 8, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Overpass Mono Bold Nerd Font Complete.otf", + "preferred_family_name": "OverpassMono Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Overpass Mono Light Nerd Font Complete Mono.otf||3250736:1634564302.0": { + "family_name": "OverpassMono Nerd Font Mono", + "font-family": "OverpassMono Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Overpass Mono Light Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 4, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Overpass Mono Light Nerd Font Complete Mono.otf", + "preferred_family_name": "OverpassMono Nerd Font Mono", + "preferred_subfamily_name": "Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Overpass Mono Light Nerd Font Complete.otf||2188456:1634564302.0": { + "family_name": "OverpassMono Nerd Font", + "font-family": "OverpassMono Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Overpass Mono Light Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 4, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Overpass Mono Light Nerd Font Complete.otf", + "preferred_family_name": "OverpassMono Nerd Font", + "preferred_subfamily_name": "Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Overpass Mono Regular Nerd Font Complete Mono.otf||3251068:1634564302.0": { + "family_name": "OverpassMono Nerd Font Mono", + "font-family": "OverpassMono Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Overpass Mono Regular Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 5, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Overpass Mono Regular Nerd Font Complete Mono.otf", + "preferred_family_name": "OverpassMono Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Overpass Mono Regular Nerd Font Complete.otf||2188844:1634564302.0": { + "family_name": "OverpassMono Nerd Font", + "font-family": "OverpassMono Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Overpass Mono Regular Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 5, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Overpass Mono Regular Nerd Font Complete.otf", + "preferred_family_name": "OverpassMono Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Overpass Mono SemiBold Nerd Font Complete Mono.otf||3250896:1634564302.0": { + "family_name": "OverpassMono Nerd Font Mono", + "font-family": "OverpassMono Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Overpass Mono SemiBold Nerd Font Complete Mono", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 7, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Overpass Mono SemiBold Nerd Font Complete Mono.otf", + "preferred_family_name": "OverpassMono Nerd Font Mono", + "preferred_subfamily_name": "SemiBold", + "subfamily_name": "Bold", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Overpass Mono SemiBold Nerd Font Complete.otf||2188672:1634564302.0": { + "family_name": "OverpassMono Nerd Font", + "font-family": "OverpassMono Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Overpass Mono SemiBold Nerd Font Complete", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 7, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Overpass Mono SemiBold Nerd Font Complete.otf", + "preferred_family_name": "OverpassMono Nerd Font", + "preferred_subfamily_name": "SemiBold", + "subfamily_name": "Bold", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Overpass Regular Nerd Font Complete Mono.otf||3291348:1634564302.0": { + "family_name": "Overpass Nerd Font Mono", + "font-family": "Overpass Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Overpass Regular Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 5, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Overpass Regular Nerd Font Complete Mono.otf", + "preferred_family_name": "Overpass Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Overpass Regular Nerd Font Complete.otf||2158032:1634564302.0": { + "family_name": "Overpass Nerd Font", + "font-family": "Overpass Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Overpass Regular Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 5, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Overpass Regular Nerd Font Complete.otf", + "preferred_family_name": "Overpass Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Overpass SemiBold Italic Nerd Font Complete Mono.otf||3284840:1634564302.0": { + "family_name": "Overpass Nerd Font Mono", + "font-family": "Overpass Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "600", + "fs_type": 0, + "full_name": "Overpass SemiBold Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 7, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Overpass SemiBold Italic Nerd Font Complete Mono.otf", + "preferred_family_name": "Overpass Nerd Font Mono", + "preferred_subfamily_name": "SemiBold Italic", + "subfamily_name": "Italic", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Overpass SemiBold Italic Nerd Font Complete.otf||2159628:1634564302.0": { + "family_name": "Overpass Nerd Font", + "font-family": "Overpass Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "600", + "fs_type": 0, + "full_name": "Overpass SemiBold Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 7, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Overpass SemiBold Italic Nerd Font Complete.otf", + "preferred_family_name": "Overpass Nerd Font", + "preferred_subfamily_name": "SemiBold Italic", + "subfamily_name": "Italic", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Overpass SemiBold Nerd Font Complete Mono.otf||3287084:1634564302.0": { + "family_name": "Overpass Nerd Font Mono", + "font-family": "Overpass Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Overpass SemiBold Nerd Font Complete Mono", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 7, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Overpass SemiBold Nerd Font Complete Mono.otf", + "preferred_family_name": "Overpass Nerd Font Mono", + "preferred_subfamily_name": "SemiBold", + "subfamily_name": "Bold", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Overpass SemiBold Nerd Font Complete.otf||2153536:1634564302.0": { + "family_name": "Overpass Nerd Font", + "font-family": "Overpass Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Overpass SemiBold Nerd Font Complete", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 7, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Overpass SemiBold Nerd Font Complete.otf", + "preferred_family_name": "Overpass Nerd Font", + "preferred_subfamily_name": "SemiBold", + "subfamily_name": "Bold", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Overpass Thin Italic Nerd Font Complete Mono.otf||3292812:1634564302.0": { + "family_name": "Overpass Nerd Font Mono", + "font-family": "Overpass Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "100", + "fs_type": 0, + "full_name": "Overpass Thin Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 2, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Overpass Thin Italic Nerd Font Complete Mono.otf", + "preferred_family_name": "Overpass Nerd Font Mono", + "preferred_subfamily_name": "Thin Italic", + "subfamily_name": "Italic", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Overpass Thin Italic Nerd Font Complete.otf||2159308:1634564302.0": { + "family_name": "Overpass Nerd Font", + "font-family": "Overpass Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "100", + "fs_type": 0, + "full_name": "Overpass Thin Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 2, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Overpass Thin Italic Nerd Font Complete.otf", + "preferred_family_name": "Overpass Nerd Font", + "preferred_subfamily_name": "Thin Italic", + "subfamily_name": "Italic", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Overpass Thin Nerd Font Complete Mono.otf||3291976:1634564302.0": { + "family_name": "Overpass Nerd Font Mono", + "font-family": "Overpass Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Overpass Thin Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 2, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Overpass Thin Nerd Font Complete Mono.otf", + "preferred_family_name": "Overpass Nerd Font Mono", + "preferred_subfamily_name": "Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/Overpass Thin Nerd Font Complete.otf||2156708:1634564302.0": { + "family_name": "Overpass Nerd Font", + "font-family": "Overpass Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Overpass Thin Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 2, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/Overpass Thin Nerd Font Complete.otf", + "preferred_family_name": "Overpass Nerd Font", + "preferred_subfamily_name": "Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/iM Writing Duospace Bold Nerd Font Complete Mono.otf||3286576:1634564302.0": { + "family_name": "iMWritingDuospace Nerd Font Mono", + "font-family": "iMWritingDuospace Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 8, + "full_name": "iM Writing Duospace Bold Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 8, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/iM Writing Duospace Bold Nerd Font Complete Mono.otf", + "preferred_family_name": "iMWritingDuospace Nerd Font Mono", + "preferred_subfamily_name": "Bold", + "subfamily_name": "Regular", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/iM Writing Duospace Bold Nerd Font Complete.otf||2197032:1634564302.0": { + "family_name": "iMWritingDuospace Nerd Font", + "font-family": "iMWritingDuospace Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 8, + "full_name": "iM Writing Duospace Bold Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 8, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/iM Writing Duospace Bold Nerd Font Complete.otf", + "preferred_family_name": "iMWritingDuospace Nerd Font", + "preferred_subfamily_name": "Bold", + "subfamily_name": "Regular", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/iM Writing Duospace BoldItalic Nerd Font Complete Mono.otf||3293796:1634564302.0": { + "family_name": "iMWritingDuospace Nerd Font Mono", + "font-family": "iMWritingDuospace Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 8, + "full_name": "iM Writing Duospace BoldItalic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 8, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/iM Writing Duospace BoldItalic Nerd Font Complete Mono.otf", + "preferred_family_name": "iMWritingDuospace Nerd Font Mono", + "preferred_subfamily_name": "BoldItalic", + "subfamily_name": "Italic", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/iM Writing Duospace BoldItalic Nerd Font Complete.otf||2204136:1634564302.0": { + "family_name": "iMWritingDuospace Nerd Font", + "font-family": "iMWritingDuospace Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 8, + "full_name": "iM Writing Duospace BoldItalic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 8, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/iM Writing Duospace BoldItalic Nerd Font Complete.otf", + "preferred_family_name": "iMWritingDuospace Nerd Font", + "preferred_subfamily_name": "BoldItalic", + "subfamily_name": "Italic", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/iM Writing Duospace Italic Nerd Font Complete Mono.otf||3285820:1634564302.0": { + "family_name": "iMWritingDuospace Nerd Font Mono", + "font-family": "iMWritingDuospace Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 8, + "full_name": "iM Writing Duospace Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 5, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/iM Writing Duospace Italic Nerd Font Complete Mono.otf", + "preferred_family_name": "iMWritingDuospace Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/iM Writing Duospace Italic Nerd Font Complete.otf||2196164:1634564302.0": { + "family_name": "iMWritingDuospace Nerd Font", + "font-family": "iMWritingDuospace Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 8, + "full_name": "iM Writing Duospace Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": true, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 5, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/iM Writing Duospace Italic Nerd Font Complete.otf", + "preferred_family_name": "iMWritingDuospace Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/iM Writing Duospace Regular Nerd Font Complete Mono.otf||3280464:1634564302.0": { + "family_name": "iMWritingDuospace Nerd Font Mono", + "font-family": "iMWritingDuospace Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 8, + "full_name": "iM Writing Duospace Regular Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 5, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/iM Writing Duospace Regular Nerd Font Complete Mono.otf", + "preferred_family_name": "iMWritingDuospace Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/OTF/iM Writing Duospace Regular Nerd Font Complete.otf||2190896:1634564302.0": { + "family_name": "iMWritingDuospace Nerd Font", + "font-family": "iMWritingDuospace Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 8, + "full_name": "iM Writing Duospace Regular Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": true, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 5, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/OTF/iM Writing Duospace Regular Nerd Font Complete.otf", + "preferred_family_name": "iMWritingDuospace Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Anonymice Nerd Font Complete Mono.ttf||921848:1634564302.0": { + "family_name": "Anonymice Nerd Font Mono", + "font-family": "Anonymice Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Anonymice Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 6, + 6, + 9, + 3, + 2, + 2, + 0, + 5, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Anonymice Nerd Font Complete Mono.ttf", + "preferred_family_name": "Anonymice Nerd Font Mono", + "preferred_subfamily_name": "Regular", + "subfamily_name": "Book", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Anonymice Nerd Font Complete.ttf||948352:1634564302.0": { + "family_name": "Anonymice Nerd Font", + "font-family": "Anonymice Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Anonymice Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 6, + 6, + 9, + 3, + 2, + 2, + 0, + 5, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Anonymice Nerd Font Complete.ttf", + "preferred_family_name": "Anonymice Nerd Font", + "preferred_subfamily_name": "Regular", + "subfamily_name": "Book", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Arimo Bold Italic Nerd Font Complete Mono.ttf||1235232:1634564302.0": { + "family_name": "Arimo Nerd Font Mono", + "font-family": "Arimo Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Arimo Bold Italic Nerd Font Complete Mono", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 7, + 4, + 2, + 2, + 2, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Arimo Bold Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "Arimo Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Arimo Bold Italic Nerd Font Complete.ttf||1241208:1634564302.0": { + "family_name": "Arimo Nerd Font", + "font-family": "Arimo Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Arimo Bold Italic Nerd Font Complete", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 7, + 4, + 2, + 2, + 2, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Arimo Bold Italic Nerd Font Complete.ttf", + "preferred_family_name": "Arimo Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Arimo Bold Nerd Font Complete Mono.ttf||1238332:1634564302.0": { + "family_name": "Arimo Nerd Font Mono", + "font-family": "Arimo Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Arimo Bold Nerd Font Complete Mono", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 7, + 4, + 2, + 2, + 2, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Arimo Bold Nerd Font Complete Mono.ttf", + "preferred_family_name": "Arimo Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Arimo Bold Nerd Font Complete.ttf||1244316:1634564302.0": { + "family_name": "Arimo Nerd Font", + "font-family": "Arimo Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Arimo Bold Nerd Font Complete", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 7, + 4, + 2, + 2, + 2, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Arimo Bold Nerd Font Complete.ttf", + "preferred_family_name": "Arimo Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Arimo Italic Nerd Font Complete Mono.ttf||1241208:1634564302.0": { + "family_name": "Arimo Nerd Font Mono", + "font-family": "Arimo Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Arimo Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 6, + 4, + 2, + 2, + 2, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Arimo Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "Arimo Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Arimo Italic Nerd Font Complete.ttf||1246756:1634564302.0": { + "family_name": "Arimo Nerd Font", + "font-family": "Arimo Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Arimo Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 6, + 4, + 2, + 2, + 2, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Arimo Italic Nerd Font Complete.ttf", + "preferred_family_name": "Arimo Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Arimo Regular Nerd Font Complete Mono.ttf||1235544:1634564302.0": { + "family_name": "Arimo Nerd Font Mono", + "font-family": "Arimo Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Arimo Regular Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 6, + 4, + 2, + 2, + 2, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Arimo Regular Nerd Font Complete Mono.ttf", + "preferred_family_name": "Arimo Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Arimo Regular Nerd Font Complete.ttf||1241088:1634564302.0": { + "family_name": "Arimo Nerd Font", + "font-family": "Arimo Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Arimo Regular Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 6, + 4, + 2, + 2, + 2, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Arimo Regular Nerd Font Complete.ttf", + "preferred_family_name": "Arimo Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Bitstream Vera Sans Mono Bold Nerd Font Complete Mono.ttf||856332:1634564302.0": { + "family_name": "BitstreamVeraSansMono Nerd Font Mono", + "font-family": "BitstreamVeraSansMono Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 4, + "full_name": "Bitstream Vera Sans Mono Bold Nerd Font Complete Mono", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 7, + 9, + 3, + 6, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Bitstream Vera Sans Mono Bold Nerd Font Complete Mono.ttf", + "preferred_family_name": "BitstreamVeraSansMono Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Bitstream Vera Sans Mono Bold Nerd Font Complete.ttf||876728:1634564302.0": { + "family_name": "BitstreamVeraSansMono Nerd Font", + "font-family": "BitstreamVeraSansMono Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 4, + "full_name": "Bitstream Vera Sans Mono Bold Nerd Font Complete", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 7, + 9, + 3, + 6, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Bitstream Vera Sans Mono Bold Nerd Font Complete.ttf", + "preferred_family_name": "BitstreamVeraSansMono Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Bitstream Vera Sans Mono Bold Oblique Nerd Font Complete Mono.ttf||862168:1634564302.0": { + "family_name": "BitstreamVeraSansMono Nerd Font Mono", + "font-family": "BitstreamVeraSansMono Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 4, + "full_name": "Bitstream Vera Sans Mono Bold Oblique Nerd Font Complete Mono", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 7, + 9, + 3, + 3, + 4, + 11, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Bitstream Vera Sans Mono Bold Oblique Nerd Font Complete Mono.ttf", + "preferred_family_name": "BitstreamVeraSansMono Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Bold Oblique", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Bitstream Vera Sans Mono Bold Oblique Nerd Font Complete.ttf||882564:1634564302.0": { + "family_name": "BitstreamVeraSansMono Nerd Font", + "font-family": "BitstreamVeraSansMono Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 4, + "full_name": "Bitstream Vera Sans Mono Bold Oblique Nerd Font Complete", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 7, + 9, + 3, + 3, + 4, + 11, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Bitstream Vera Sans Mono Bold Oblique Nerd Font Complete.ttf", + "preferred_family_name": "BitstreamVeraSansMono Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Bold Oblique", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Bitstream Vera Sans Mono Nerd Font Complete Mono.ttf||856460:1634564302.0": { + "family_name": "BitstreamVeraSansMono Nerd Font Mono", + "font-family": "BitstreamVeraSansMono Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 4, + "full_name": "Bitstream Vera Sans Mono Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 6, + 9, + 3, + 8, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Bitstream Vera Sans Mono Nerd Font Complete Mono.ttf", + "preferred_family_name": "BitstreamVeraSansMono Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Roman", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Bitstream Vera Sans Mono Nerd Font Complete.ttf||876852:1634564302.0": { + "family_name": "BitstreamVeraSansMono Nerd Font", + "font-family": "BitstreamVeraSansMono Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 4, + "full_name": "Bitstream Vera Sans Mono Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 6, + 9, + 3, + 8, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Bitstream Vera Sans Mono Nerd Font Complete.ttf", + "preferred_family_name": "BitstreamVeraSansMono Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Roman", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Bitstream Vera Sans Mono Oblique Nerd Font Complete Mono.ttf||861604:1634564302.0": { + "family_name": "BitstreamVeraSansMono Nerd Font Mono", + "font-family": "BitstreamVeraSansMono Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 4, + "full_name": "Bitstream Vera Sans Mono Oblique Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 6, + 9, + 3, + 3, + 4, + 11, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Bitstream Vera Sans Mono Oblique Nerd Font Complete Mono.ttf", + "preferred_family_name": "BitstreamVeraSansMono Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Oblique", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Bitstream Vera Sans Mono Oblique Nerd Font Complete.ttf||881996:1634564302.0": { + "family_name": "BitstreamVeraSansMono Nerd Font", + "font-family": "BitstreamVeraSansMono Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 4, + "full_name": "Bitstream Vera Sans Mono Oblique Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 6, + 9, + 3, + 3, + 4, + 11, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Bitstream Vera Sans Mono Oblique Nerd Font Complete.ttf", + "preferred_family_name": "BitstreamVeraSansMono Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Oblique", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Blex Mono Bold Italic Nerd Font Complete Mono.ttf||887720:1634564302.0": { + "family_name": "BlexMono Nerd Font Mono", + "font-family": "BlexMono Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Blex Mono Bold Italic Nerd Font Complete Mono", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 8, + 9, + 5, + 2, + 3, + 0, + 2, + 3 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Blex Mono Bold Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "BlexMono Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Blex Mono Bold Italic Nerd Font Complete.ttf||905656:1634564302.0": { + "family_name": "BlexMono Nerd Font", + "font-family": "BlexMono Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Blex Mono Bold Italic Nerd Font Complete", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 8, + 9, + 5, + 2, + 3, + 0, + 2, + 3 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Blex Mono Bold Italic Nerd Font Complete.ttf", + "preferred_family_name": "BlexMono Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Blex Mono Bold Nerd Font Complete Mono.ttf||881264:1634564302.0": { + "family_name": "BlexMono Nerd Font Mono", + "font-family": "BlexMono Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Blex Mono Bold Nerd Font Complete Mono", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 8, + 9, + 5, + 2, + 3, + 0, + 2, + 3 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Blex Mono Bold Nerd Font Complete Mono.ttf", + "preferred_family_name": "BlexMono Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Blex Mono Bold Nerd Font Complete.ttf||899200:1634564302.0": { + "family_name": "BlexMono Nerd Font", + "font-family": "BlexMono Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Blex Mono Bold Nerd Font Complete", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 8, + 9, + 5, + 2, + 3, + 0, + 2, + 3 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Blex Mono Bold Nerd Font Complete.ttf", + "preferred_family_name": "BlexMono Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Blex Mono ExtraLight Italic Nerd Font Complete Mono.ttf||887944:1634564302.0": { + "family_name": "BlexMono Nerd Font Mono", + "font-family": "BlexMono Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "200", + "fs_type": 0, + "full_name": "Blex Mono ExtraLight Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 3, + 9, + 5, + 2, + 3, + 0, + 2, + 3 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Blex Mono ExtraLight Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "BlexMono Nerd Font Mono", + "preferred_subfamily_name": "ExtraLight Italic", + "subfamily_name": "Italic", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Blex Mono ExtraLight Italic Nerd Font Complete.ttf||905884:1634564302.0": { + "family_name": "BlexMono Nerd Font", + "font-family": "BlexMono Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "200", + "fs_type": 0, + "full_name": "Blex Mono ExtraLight Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 3, + 9, + 5, + 2, + 3, + 0, + 2, + 3 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Blex Mono ExtraLight Italic Nerd Font Complete.ttf", + "preferred_family_name": "BlexMono Nerd Font", + "preferred_subfamily_name": "ExtraLight Italic", + "subfamily_name": "Italic", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Blex Mono ExtraLight Nerd Font Complete Mono.ttf||879644:1634564302.0": { + "family_name": "BlexMono Nerd Font Mono", + "font-family": "BlexMono Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Blex Mono ExtraLight Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 3, + 9, + 5, + 2, + 3, + 0, + 2, + 3 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Blex Mono ExtraLight Nerd Font Complete Mono.ttf", + "preferred_family_name": "BlexMono Nerd Font Mono", + "preferred_subfamily_name": "ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Blex Mono ExtraLight Nerd Font Complete.ttf||897580:1634564302.0": { + "family_name": "BlexMono Nerd Font", + "font-family": "BlexMono Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Blex Mono ExtraLight Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 3, + 9, + 5, + 2, + 3, + 0, + 2, + 3 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Blex Mono ExtraLight Nerd Font Complete.ttf", + "preferred_family_name": "BlexMono Nerd Font", + "preferred_subfamily_name": "ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Blex Mono Italic Nerd Font Complete Mono.ttf||887128:1634564302.0": { + "family_name": "BlexMono Nerd Font Mono", + "font-family": "BlexMono Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Blex Mono Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 5, + 9, + 5, + 2, + 3, + 0, + 2, + 3 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Blex Mono Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "BlexMono Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Blex Mono Italic Nerd Font Complete.ttf||905064:1634564302.0": { + "family_name": "BlexMono Nerd Font", + "font-family": "BlexMono Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Blex Mono Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 5, + 9, + 5, + 2, + 3, + 0, + 2, + 3 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Blex Mono Italic Nerd Font Complete.ttf", + "preferred_family_name": "BlexMono Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Blex Mono Light Italic Nerd Font Complete Mono.ttf||886668:1634564302.0": { + "family_name": "BlexMono Nerd Font Mono", + "font-family": "BlexMono Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "300", + "fs_type": 0, + "full_name": "Blex Mono Light Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 4, + 9, + 5, + 2, + 3, + 0, + 2, + 3 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Blex Mono Light Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "BlexMono Nerd Font Mono", + "preferred_subfamily_name": "Light Italic", + "subfamily_name": "Italic", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Blex Mono Light Italic Nerd Font Complete.ttf||904608:1634564302.0": { + "family_name": "BlexMono Nerd Font", + "font-family": "BlexMono Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "300", + "fs_type": 0, + "full_name": "Blex Mono Light Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 4, + 9, + 5, + 2, + 3, + 0, + 2, + 3 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Blex Mono Light Italic Nerd Font Complete.ttf", + "preferred_family_name": "BlexMono Nerd Font", + "preferred_subfamily_name": "Light Italic", + "subfamily_name": "Italic", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Blex Mono Light Nerd Font Complete Mono.ttf||878796:1634564302.0": { + "family_name": "BlexMono Nerd Font Mono", + "font-family": "BlexMono Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Blex Mono Light Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 4, + 9, + 5, + 2, + 3, + 0, + 2, + 3 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Blex Mono Light Nerd Font Complete Mono.ttf", + "preferred_family_name": "BlexMono Nerd Font Mono", + "preferred_subfamily_name": "Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Blex Mono Light Nerd Font Complete.ttf||896732:1634564302.0": { + "family_name": "BlexMono Nerd Font", + "font-family": "BlexMono Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Blex Mono Light Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 4, + 9, + 5, + 2, + 3, + 0, + 2, + 3 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Blex Mono Light Nerd Font Complete.ttf", + "preferred_family_name": "BlexMono Nerd Font", + "preferred_subfamily_name": "Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Blex Mono Medium Italic Nerd Font Complete Mono.ttf||887220:1634564302.0": { + "family_name": "BlexMono Nerd Font Mono", + "font-family": "BlexMono Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "500", + "fs_type": 0, + "full_name": "Blex Mono Medium Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 6, + 9, + 5, + 2, + 3, + 0, + 2, + 3 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Blex Mono Medium Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "BlexMono Nerd Font Mono", + "preferred_subfamily_name": "Medium Italic", + "subfamily_name": "Italic", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Blex Mono Medium Italic Nerd Font Complete.ttf||905160:1634564302.0": { + "family_name": "BlexMono Nerd Font", + "font-family": "BlexMono Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "500", + "fs_type": 0, + "full_name": "Blex Mono Medium Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 6, + 9, + 5, + 2, + 3, + 0, + 2, + 3 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Blex Mono Medium Italic Nerd Font Complete.ttf", + "preferred_family_name": "BlexMono Nerd Font", + "preferred_subfamily_name": "Medium Italic", + "subfamily_name": "Italic", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Blex Mono Medium Nerd Font Complete Mono.ttf||880264:1634564302.0": { + "family_name": "BlexMono Nerd Font Mono", + "font-family": "BlexMono Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Blex Mono Medium Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 6, + 9, + 5, + 2, + 3, + 0, + 2, + 3 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Blex Mono Medium Nerd Font Complete Mono.ttf", + "preferred_family_name": "BlexMono Nerd Font Mono", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Blex Mono Medium Nerd Font Complete.ttf||898200:1634564302.0": { + "family_name": "BlexMono Nerd Font", + "font-family": "BlexMono Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Blex Mono Medium Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 6, + 9, + 5, + 2, + 3, + 0, + 2, + 3 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Blex Mono Medium Nerd Font Complete.ttf", + "preferred_family_name": "BlexMono Nerd Font", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Blex Mono Nerd Font Complete Mono.ttf||879100:1634564302.0": { + "family_name": "BlexMono Nerd Font Mono", + "font-family": "BlexMono Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Blex Mono Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 5, + 9, + 5, + 2, + 3, + 0, + 2, + 3 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Blex Mono Nerd Font Complete Mono.ttf", + "preferred_family_name": "BlexMono Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Book", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Blex Mono Nerd Font Complete.ttf||897036:1634564302.0": { + "family_name": "BlexMono Nerd Font", + "font-family": "BlexMono Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Blex Mono Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 5, + 9, + 5, + 2, + 3, + 0, + 2, + 3 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Blex Mono Nerd Font Complete.ttf", + "preferred_family_name": "BlexMono Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Book", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Blex Mono SemiBold Italic Nerd Font Complete Mono.ttf||887536:1634564302.0": { + "family_name": "BlexMono Nerd Font Mono", + "font-family": "BlexMono Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "600", + "fs_type": 0, + "full_name": "Blex Mono SemiBold Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 7, + 9, + 5, + 2, + 3, + 0, + 2, + 3 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Blex Mono SemiBold Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "BlexMono Nerd Font Mono", + "preferred_subfamily_name": "SemiBold Italic", + "subfamily_name": "Italic", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Blex Mono SemiBold Italic Nerd Font Complete.ttf||905476:1634564302.0": { + "family_name": "BlexMono Nerd Font", + "font-family": "BlexMono Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "600", + "fs_type": 0, + "full_name": "Blex Mono SemiBold Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 7, + 9, + 5, + 2, + 3, + 0, + 2, + 3 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Blex Mono SemiBold Italic Nerd Font Complete.ttf", + "preferred_family_name": "BlexMono Nerd Font", + "preferred_subfamily_name": "SemiBold Italic", + "subfamily_name": "Italic", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Blex Mono SemiBold Nerd Font Complete Mono.ttf||880732:1634564302.0": { + "family_name": "BlexMono Nerd Font Mono", + "font-family": "BlexMono Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Blex Mono SemiBold Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 7, + 9, + 5, + 2, + 3, + 0, + 2, + 3 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Blex Mono SemiBold Nerd Font Complete Mono.ttf", + "preferred_family_name": "BlexMono Nerd Font Mono", + "preferred_subfamily_name": "SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Blex Mono SemiBold Nerd Font Complete.ttf||898668:1634564302.0": { + "family_name": "BlexMono Nerd Font", + "font-family": "BlexMono Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Blex Mono SemiBold Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 7, + 9, + 5, + 2, + 3, + 0, + 2, + 3 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Blex Mono SemiBold Nerd Font Complete.ttf", + "preferred_family_name": "BlexMono Nerd Font", + "preferred_subfamily_name": "SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Blex Mono Text Italic Nerd Font Complete Mono.ttf||886288:1634564302.0": { + "family_name": "BlexMono Nerd Font Mono", + "font-family": "BlexMono Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "450", + "fs_type": 0, + "full_name": "Blex Mono Text Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 5, + 9, + 5, + 2, + 3, + 0, + 2, + 3 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Blex Mono Text Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "BlexMono Nerd Font Mono", + "preferred_subfamily_name": "Text Italic", + "subfamily_name": "Italic", + "weight": 450, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Blex Mono Text Italic Nerd Font Complete.ttf||904228:1634564302.0": { + "family_name": "BlexMono Nerd Font", + "font-family": "BlexMono Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "450", + "fs_type": 0, + "full_name": "Blex Mono Text Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 5, + 9, + 5, + 2, + 3, + 0, + 2, + 3 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Blex Mono Text Italic Nerd Font Complete.ttf", + "preferred_family_name": "BlexMono Nerd Font", + "preferred_subfamily_name": "Text Italic", + "subfamily_name": "Italic", + "weight": 450, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Blex Mono Text Nerd Font Complete Mono.ttf||878984:1634564302.0": { + "family_name": "BlexMono Nerd Font Mono", + "font-family": "BlexMono Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "450", + "fs_type": 0, + "full_name": "Blex Mono Text Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 5, + 9, + 5, + 2, + 3, + 0, + 2, + 3 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Blex Mono Text Nerd Font Complete Mono.ttf", + "preferred_family_name": "BlexMono Nerd Font Mono", + "preferred_subfamily_name": "Text", + "subfamily_name": "Regular", + "weight": 450, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Blex Mono Text Nerd Font Complete.ttf||896920:1634564302.0": { + "family_name": "BlexMono Nerd Font", + "font-family": "BlexMono Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "450", + "fs_type": 0, + "full_name": "Blex Mono Text Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 5, + 9, + 5, + 2, + 3, + 0, + 2, + 3 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Blex Mono Text Nerd Font Complete.ttf", + "preferred_family_name": "BlexMono Nerd Font", + "preferred_subfamily_name": "Text", + "subfamily_name": "Regular", + "weight": 450, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Blex Mono Thin Italic Nerd Font Complete Mono.ttf||889444:1634564302.0": { + "family_name": "BlexMono Nerd Font Mono", + "font-family": "BlexMono Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "100", + "fs_type": 0, + "full_name": "Blex Mono Thin Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 3, + 9, + 5, + 2, + 3, + 0, + 2, + 3 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Blex Mono Thin Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "BlexMono Nerd Font Mono", + "preferred_subfamily_name": "Thin Italic", + "subfamily_name": "Italic", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Blex Mono Thin Italic Nerd Font Complete.ttf||907384:1634564302.0": { + "family_name": "BlexMono Nerd Font", + "font-family": "BlexMono Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "100", + "fs_type": 0, + "full_name": "Blex Mono Thin Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 3, + 9, + 5, + 2, + 3, + 0, + 2, + 3 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Blex Mono Thin Italic Nerd Font Complete.ttf", + "preferred_family_name": "BlexMono Nerd Font", + "preferred_subfamily_name": "Thin Italic", + "subfamily_name": "Italic", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Blex Mono Thin Nerd Font Complete Mono.ttf||881464:1634564302.0": { + "family_name": "BlexMono Nerd Font Mono", + "font-family": "BlexMono Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Blex Mono Thin Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 3, + 9, + 5, + 2, + 3, + 0, + 2, + 3 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Blex Mono Thin Nerd Font Complete Mono.ttf", + "preferred_family_name": "BlexMono Nerd Font Mono", + "preferred_subfamily_name": "Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Blex Mono Thin Nerd Font Complete.ttf||899400:1634564302.0": { + "family_name": "BlexMono Nerd Font", + "font-family": "BlexMono Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Blex Mono Thin Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 3, + 9, + 5, + 2, + 3, + 0, + 2, + 3 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Blex Mono Thin Nerd Font Complete.ttf", + "preferred_family_name": "BlexMono Nerd Font", + "preferred_subfamily_name": "Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Caskaydia Cove Nerd Font Complete Mono.ttf||886740:1634564302.0": { + "family_name": "CaskaydiaCove Nerd Font Mono", + "font-family": "CaskaydiaCove Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 8, + "full_name": "Caskaydia Cove Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 5, + 9, + 2, + 2, + 4, + 3, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Caskaydia Cove Nerd Font Complete Mono.ttf", + "preferred_family_name": "CaskaydiaCove Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Book", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Caskaydia Cove Nerd Font Complete.ttf||908392:1634564302.0": { + "family_name": "CaskaydiaCove Nerd Font", + "font-family": "CaskaydiaCove Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 8, + "full_name": "Caskaydia Cove Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 5, + 9, + 2, + 2, + 4, + 3, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Caskaydia Cove Nerd Font Complete.ttf", + "preferred_family_name": "CaskaydiaCove Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Book", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Cousine Bold Italic Nerd Font Complete Mono.ttf||1076988:1634564302.0": { + "family_name": "Cousine Nerd Font Mono", + "font-family": "Cousine Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Cousine Bold Italic Nerd Font Complete Mono", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 7, + 7, + 9, + 2, + 2, + 5, + 9, + 4, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Cousine Bold Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "Cousine Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Cousine Bold Italic Nerd Font Complete.ttf||1109924:1634564302.0": { + "family_name": "Cousine Nerd Font", + "font-family": "Cousine Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Cousine Bold Italic Nerd Font Complete", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 7, + 7, + 9, + 2, + 2, + 5, + 9, + 4, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Cousine Bold Italic Nerd Font Complete.ttf", + "preferred_family_name": "Cousine Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Cousine Bold Nerd Font Complete Mono.ttf||1099984:1634564302.0": { + "family_name": "Cousine Nerd Font Mono", + "font-family": "Cousine Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Cousine Bold Nerd Font Complete Mono", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 7, + 7, + 9, + 2, + 2, + 5, + 2, + 4, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Cousine Bold Nerd Font Complete Mono.ttf", + "preferred_family_name": "Cousine Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Cousine Bold Nerd Font Complete.ttf||1132916:1634564302.0": { + "family_name": "Cousine Nerd Font", + "font-family": "Cousine Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Cousine Bold Nerd Font Complete", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 7, + 7, + 9, + 2, + 2, + 5, + 2, + 4, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Cousine Bold Nerd Font Complete.ttf", + "preferred_family_name": "Cousine Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Cousine Italic Nerd Font Complete Mono.ttf||1075060:1634564302.0": { + "family_name": "Cousine Nerd Font Mono", + "font-family": "Cousine Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Cousine Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 7, + 4, + 9, + 2, + 2, + 5, + 9, + 4, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Cousine Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "Cousine Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Cousine Italic Nerd Font Complete.ttf||1107988:1634564302.0": { + "family_name": "Cousine Nerd Font", + "font-family": "Cousine Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Cousine Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 7, + 4, + 9, + 2, + 2, + 5, + 9, + 4, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Cousine Italic Nerd Font Complete.ttf", + "preferred_family_name": "Cousine Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Cousine Regular Nerd Font Complete Mono.ttf||1112204:1634564302.0": { + "family_name": "Cousine Nerd Font Mono", + "font-family": "Cousine Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Cousine Regular Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 7, + 4, + 9, + 2, + 2, + 5, + 2, + 4, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Cousine Regular Nerd Font Complete Mono.ttf", + "preferred_family_name": "Cousine Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Cousine Regular Nerd Font Complete.ttf||1145144:1634564302.0": { + "family_name": "Cousine Nerd Font", + "font-family": "Cousine Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Cousine Regular Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 7, + 4, + 9, + 2, + 2, + 5, + 2, + 4, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Cousine Regular Nerd Font Complete.ttf", + "preferred_family_name": "Cousine Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/DaddyTimeMono Nerd Font Complete Mono.ttf||822552:1634564302.0": { + "family_name": "DaddyTimeMono Nerd Font Mono", + "font-family": "DaddyTimeMono Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "DaddyTimeMono Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 5, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/DaddyTimeMono Nerd Font Complete Mono.ttf", + "preferred_family_name": "DaddyTimeMono Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Book", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/DaddyTimeMono Nerd Font Complete.ttf||843892:1634564302.0": { + "family_name": "DaddyTimeMono Nerd Font", + "font-family": "DaddyTimeMono Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "DaddyTimeMono Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 5, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/DaddyTimeMono Nerd Font Complete.ttf", + "preferred_family_name": "DaddyTimeMono Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Book", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/DejaVu Sans Mono Bold Nerd Font Complete Mono.ttf||1139916:1634564302.0": { + "family_name": "DejaVuSansMono Nerd Font Mono", + "font-family": "DejaVuSansMono Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "DejaVu Sans Mono Bold Nerd Font Complete Mono", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 7, + 9, + 3, + 6, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/DejaVu Sans Mono Bold Nerd Font Complete Mono.ttf", + "preferred_family_name": "DejaVuSansMono Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/DejaVu Sans Mono Bold Nerd Font Complete.ttf||1165720:1634564302.0": { + "family_name": "DejaVuSansMono Nerd Font", + "font-family": "DejaVuSansMono Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "DejaVu Sans Mono Bold Nerd Font Complete", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 7, + 9, + 3, + 6, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/DejaVu Sans Mono Bold Nerd Font Complete.ttf", + "preferred_family_name": "DejaVuSansMono Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/DejaVu Sans Mono Bold Oblique Nerd Font Complete Mono.ttf||1066760:1634564302.0": { + "family_name": "DejaVuSansMono Nerd Font Mono", + "font-family": "DejaVuSansMono Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "DejaVu Sans Mono Bold Oblique Nerd Font Complete Mono", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 7, + 9, + 3, + 3, + 4, + 11, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/DejaVu Sans Mono Bold Oblique Nerd Font Complete Mono.ttf", + "preferred_family_name": "DejaVuSansMono Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Bold Oblique", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/DejaVu Sans Mono Bold Oblique Nerd Font Complete.ttf||1092268:1634564302.0": { + "family_name": "DejaVuSansMono Nerd Font", + "font-family": "DejaVuSansMono Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "DejaVu Sans Mono Bold Oblique Nerd Font Complete", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 7, + 9, + 3, + 3, + 4, + 11, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/DejaVu Sans Mono Bold Oblique Nerd Font Complete.ttf", + "preferred_family_name": "DejaVuSansMono Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Bold Oblique", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/DejaVu Sans Mono Nerd Font Complete Mono.ttf||1149180:1634564302.0": { + "family_name": "DejaVuSansMono Nerd Font Mono", + "font-family": "DejaVuSansMono Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "DejaVu Sans Mono Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 6, + 9, + 3, + 8, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/DejaVu Sans Mono Nerd Font Complete Mono.ttf", + "preferred_family_name": "DejaVuSansMono Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Book", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/DejaVu Sans Mono Nerd Font Complete.ttf||1175040:1634564302.0": { + "family_name": "DejaVuSansMono Nerd Font", + "font-family": "DejaVuSansMono Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "DejaVu Sans Mono Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 6, + 9, + 3, + 8, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/DejaVu Sans Mono Nerd Font Complete.ttf", + "preferred_family_name": "DejaVuSansMono Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Book", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/DejaVu Sans Mono Oblique Nerd Font Complete Mono.ttf||1065500:1634564302.0": { + "family_name": "DejaVuSansMono Nerd Font Mono", + "font-family": "DejaVuSansMono Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "DejaVu Sans Mono Oblique Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 6, + 9, + 3, + 3, + 4, + 11, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/DejaVu Sans Mono Oblique Nerd Font Complete Mono.ttf", + "preferred_family_name": "DejaVuSansMono Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Oblique", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/DejaVu Sans Mono Oblique Nerd Font Complete.ttf||1091004:1634564302.0": { + "family_name": "DejaVuSansMono Nerd Font", + "font-family": "DejaVuSansMono Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "DejaVu Sans Mono Oblique Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 6, + 9, + 3, + 3, + 4, + 11, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/DejaVu Sans Mono Oblique Nerd Font Complete.ttf", + "preferred_family_name": "DejaVuSansMono Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Oblique", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Fantasque Sans Mono Bold Italic Nerd Font Complete Mono.ttf||983244:1634564302.0": { + "family_name": "FantasqueSansMono Nerd Font Mono", + "font-family": "FantasqueSansMono Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 8, + "full_name": "Fantasque Sans Mono Bold Italic Nerd Font Complete Mono", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 9, + 2, + 2, + 4, + 3, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Fantasque Sans Mono Bold Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "FantasqueSansMono Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Fantasque Sans Mono Bold Italic Nerd Font Complete.ttf||1011544:1634564302.0": { + "family_name": "FantasqueSansMono Nerd Font", + "font-family": "FantasqueSansMono Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 8, + "full_name": "Fantasque Sans Mono Bold Italic Nerd Font Complete", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 9, + 2, + 2, + 4, + 3, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Fantasque Sans Mono Bold Italic Nerd Font Complete.ttf", + "preferred_family_name": "FantasqueSansMono Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Fantasque Sans Mono Bold Nerd Font Complete Mono.ttf||968336:1634564302.0": { + "family_name": "FantasqueSansMono Nerd Font Mono", + "font-family": "FantasqueSansMono Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 8, + "full_name": "Fantasque Sans Mono Bold Nerd Font Complete Mono", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 9, + 2, + 2, + 4, + 3, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Fantasque Sans Mono Bold Nerd Font Complete Mono.ttf", + "preferred_family_name": "FantasqueSansMono Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Fantasque Sans Mono Bold Nerd Font Complete.ttf||996640:1634564302.0": { + "family_name": "FantasqueSansMono Nerd Font", + "font-family": "FantasqueSansMono Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 8, + "full_name": "Fantasque Sans Mono Bold Nerd Font Complete", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 9, + 2, + 2, + 4, + 3, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Fantasque Sans Mono Bold Nerd Font Complete.ttf", + "preferred_family_name": "FantasqueSansMono Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Fantasque Sans Mono Italic Nerd Font Complete Mono.ttf||977564:1634564302.0": { + "family_name": "FantasqueSansMono Nerd Font Mono", + "font-family": "FantasqueSansMono Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 8, + "full_name": "Fantasque Sans Mono Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 9, + 2, + 2, + 4, + 3, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Fantasque Sans Mono Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "FantasqueSansMono Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Fantasque Sans Mono Italic Nerd Font Complete.ttf||1005864:1634564302.0": { + "family_name": "FantasqueSansMono Nerd Font", + "font-family": "FantasqueSansMono Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 8, + "full_name": "Fantasque Sans Mono Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 9, + 2, + 2, + 4, + 3, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Fantasque Sans Mono Italic Nerd Font Complete.ttf", + "preferred_family_name": "FantasqueSansMono Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Fantasque Sans Mono Regular Nerd Font Complete Mono.ttf||972172:1634564302.0": { + "family_name": "FantasqueSansMono Nerd Font Mono", + "font-family": "FantasqueSansMono Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 8, + "full_name": "Fantasque Sans Mono Regular Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 9, + 2, + 2, + 4, + 3, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Fantasque Sans Mono Regular Nerd Font Complete Mono.ttf", + "preferred_family_name": "FantasqueSansMono Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Fantasque Sans Mono Regular Nerd Font Complete.ttf||1000472:1634564302.0": { + "family_name": "FantasqueSansMono Nerd Font", + "font-family": "FantasqueSansMono Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 8, + "full_name": "Fantasque Sans Mono Regular Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 9, + 2, + 2, + 4, + 3, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Fantasque Sans Mono Regular Nerd Font Complete.ttf", + "preferred_family_name": "FantasqueSansMono Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Go Mono Bold Italic Nerd Font Complete Mono.ttf||984876:1634564302.0": { + "family_name": "GoMono Nerd Font Mono", + "font-family": "GoMono Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "600", + "fs_type": 0, + "full_name": "Go Mono Bold Italic Nerd Font Complete Mono", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 6, + 7, + 9, + 5, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Go Mono Bold Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "GoMono Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Bold Italic", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Go Mono Bold Italic Nerd Font Complete.ttf||1005392:1634564302.0": { + "family_name": "GoMono Nerd Font", + "font-family": "GoMono Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "600", + "fs_type": 0, + "full_name": "Go Mono Bold Italic Nerd Font Complete", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 6, + 7, + 9, + 5, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Go Mono Bold Italic Nerd Font Complete.ttf", + "preferred_family_name": "GoMono Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Bold Italic", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Go Mono Bold Nerd Font Complete Mono.ttf||976944:1634564302.0": { + "family_name": "GoMono Nerd Font Mono", + "font-family": "GoMono Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Go Mono Bold Nerd Font Complete Mono", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 6, + 7, + 9, + 5, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Go Mono Bold Nerd Font Complete Mono.ttf", + "preferred_family_name": "GoMono Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Go Mono Bold Nerd Font Complete.ttf||997460:1634564302.0": { + "family_name": "GoMono Nerd Font", + "font-family": "GoMono Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Go Mono Bold Nerd Font Complete", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 6, + 7, + 9, + 5, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Go Mono Bold Nerd Font Complete.ttf", + "preferred_family_name": "GoMono Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Go Mono Italic Nerd Font Complete Mono.ttf||981812:1634564302.0": { + "family_name": "GoMono Nerd Font Mono", + "font-family": "GoMono Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Go Mono Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 6, + 6, + 9, + 5, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Go Mono Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "GoMono Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Go Mono Italic Nerd Font Complete.ttf||1002332:1634564302.0": { + "family_name": "GoMono Nerd Font", + "font-family": "GoMono Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Go Mono Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 6, + 6, + 9, + 5, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Go Mono Italic Nerd Font Complete.ttf", + "preferred_family_name": "GoMono Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Go Mono Nerd Font Complete Mono.ttf||973024:1634564302.0": { + "family_name": "GoMono Nerd Font Mono", + "font-family": "GoMono Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Go Mono Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 6, + 6, + 9, + 5, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Go Mono Nerd Font Complete Mono.ttf", + "preferred_family_name": "GoMono Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Book", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Go Mono Nerd Font Complete.ttf||993540:1634564302.0": { + "family_name": "GoMono Nerd Font", + "font-family": "GoMono Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Go Mono Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 6, + 6, + 9, + 5, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Go Mono Nerd Font Complete.ttf", + "preferred_family_name": "GoMono Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Book", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/GohuFont Nerd Font Complete Mono.ttf||836928:1634564302.0": { + "family_name": "GohuFont Nerd Font Mono", + "font-family": "GohuFont Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "GohuFont Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 6, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/GohuFont Nerd Font Complete Mono.ttf", + "preferred_family_name": "GohuFont Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "14", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/GohuFont Nerd Font Complete.ttf||860720:1634564302.0": { + "family_name": "GohuFont Nerd Font", + "font-family": "GohuFont Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "GohuFont Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 6, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/GohuFont Nerd Font Complete.ttf", + "preferred_family_name": "GohuFont Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "14", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Hack Bold Italic Nerd Font Complete Mono.ttf||1694848:1634564302.0": { + "family_name": "Hack Nerd Font Mono", + "font-family": "Hack Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Hack Bold Italic Nerd Font Complete Mono", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 9, + 3, + 2, + 2, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Hack Bold Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "Hack Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Hack Bold Italic Nerd Font Complete.ttf||1792180:1634564302.0": { + "family_name": "Hack Nerd Font", + "font-family": "Hack Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Hack Bold Italic Nerd Font Complete", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 9, + 3, + 2, + 2, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Hack Bold Italic Nerd Font Complete.ttf", + "preferred_family_name": "Hack Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Hack Bold Nerd Font Complete Mono.ttf||1688128:1634564302.0": { + "family_name": "Hack Nerd Font Mono", + "font-family": "Hack Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Hack Bold Nerd Font Complete Mono", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 9, + 3, + 2, + 2, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Hack Bold Nerd Font Complete Mono.ttf", + "preferred_family_name": "Hack Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Hack Bold Nerd Font Complete.ttf||1789212:1634564302.0": { + "family_name": "Hack Nerd Font", + "font-family": "Hack Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Hack Bold Nerd Font Complete", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 9, + 3, + 2, + 2, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Hack Bold Nerd Font Complete.ttf", + "preferred_family_name": "Hack Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Hack Italic Nerd Font Complete Mono.ttf||1645952:1634564302.0": { + "family_name": "Hack Nerd Font Mono", + "font-family": "Hack Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Hack Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 9, + 3, + 2, + 2, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Hack Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "Hack Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Hack Italic Nerd Font Complete.ttf||1748544:1634564302.0": { + "family_name": "Hack Nerd Font", + "font-family": "Hack Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Hack Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 9, + 3, + 2, + 2, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Hack Italic Nerd Font Complete.ttf", + "preferred_family_name": "Hack Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Hack Regular Nerd Font Complete Mono.ttf||1639256:1634564302.0": { + "family_name": "Hack Nerd Font Mono", + "font-family": "Hack Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Hack Regular Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 9, + 3, + 2, + 2, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Hack Regular Nerd Font Complete Mono.ttf", + "preferred_family_name": "Hack Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Hack Regular Nerd Font Complete.ttf||1741792:1634564302.0": { + "family_name": "Hack Nerd Font", + "font-family": "Hack Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Hack Regular Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 9, + 3, + 2, + 2, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Hack Regular Nerd Font Complete.ttf", + "preferred_family_name": "Hack Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Heavy Data Nerd Font Complete Mono.ttf||861788:1634564302.0": { + "family_name": "HeavyData Nerd Font Mono", + "font-family": "HeavyData Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 8, + "full_name": "Heavy Data Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Heavy Data Nerd Font Complete Mono.ttf", + "preferred_family_name": "HeavyData Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "HeavyDataNerdFontCompleteM-", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Heavy Data Nerd Font Complete.ttf||862620:1634564302.0": { + "family_name": "HeavyData Nerd Font", + "font-family": "HeavyData Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 8, + "full_name": "Heavy Data Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Heavy Data Nerd Font Complete.ttf", + "preferred_family_name": "HeavyData Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "HeavyDataNerdFontComplete-", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Inconsolata LGC Bold Italic Nerd Font Complete Mono.ttf||840096:1634564302.0": { + "family_name": "InconsolataLGC Nerd Font Mono", + "font-family": "InconsolataLGC Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 8, + "full_name": "Inconsolata LGC Bold Italic Nerd Font Complete Mono", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 8, + 9, + 3, + 0, + 3, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Inconsolata LGC Bold Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "InconsolataLGC Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "BoldItalic", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Inconsolata LGC Bold Italic Nerd Font Complete.ttf||852884:1634564302.0": { + "family_name": "InconsolataLGC Nerd Font", + "font-family": "InconsolataLGC Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 8, + "full_name": "Inconsolata LGC Bold Italic Nerd Font Complete", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 8, + 9, + 3, + 0, + 3, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Inconsolata LGC Bold Italic Nerd Font Complete.ttf", + "preferred_family_name": "InconsolataLGC Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "BoldItalic", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Inconsolata LGC Bold Nerd Font Complete Mono.ttf||835144:1634564302.0": { + "family_name": "InconsolataLGC Nerd Font Mono", + "font-family": "InconsolataLGC Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 8, + "full_name": "Inconsolata LGC Bold Nerd Font Complete Mono", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 8, + 9, + 3, + 0, + 3, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Inconsolata LGC Bold Nerd Font Complete Mono.ttf", + "preferred_family_name": "InconsolataLGC Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Inconsolata LGC Bold Nerd Font Complete.ttf||847932:1634564302.0": { + "family_name": "InconsolataLGC Nerd Font", + "font-family": "InconsolataLGC Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 8, + "full_name": "Inconsolata LGC Bold Nerd Font Complete", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 8, + 9, + 3, + 0, + 3, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Inconsolata LGC Bold Nerd Font Complete.ttf", + "preferred_family_name": "InconsolataLGC Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Inconsolata LGC Italic Nerd Font Complete Mono.ttf||838392:1634564302.0": { + "family_name": "InconsolataLGC Nerd Font Mono", + "font-family": "InconsolataLGC Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "500", + "fs_type": 8, + "full_name": "Inconsolata LGC Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 6, + 9, + 3, + 0, + 3, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Inconsolata LGC Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "InconsolataLGC Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Inconsolata LGC Italic Nerd Font Complete.ttf||859148:1634564302.0": { + "family_name": "InconsolataLGC Nerd Font", + "font-family": "InconsolataLGC Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "500", + "fs_type": 8, + "full_name": "Inconsolata LGC Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 6, + 9, + 3, + 0, + 3, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Inconsolata LGC Italic Nerd Font Complete.ttf", + "preferred_family_name": "InconsolataLGC Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Inconsolata LGC Nerd Font Complete Mono.ttf||834876:1634564302.0": { + "family_name": "InconsolataLGC Nerd Font Mono", + "font-family": "InconsolataLGC Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 8, + "full_name": "Inconsolata LGC Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 6, + 9, + 3, + 0, + 3, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Inconsolata LGC Nerd Font Complete Mono.ttf", + "preferred_family_name": "InconsolataLGC Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Medium", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Inconsolata LGC Nerd Font Complete.ttf||854676:1634564302.0": { + "family_name": "InconsolataLGC Nerd Font", + "font-family": "InconsolataLGC Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 8, + "full_name": "Inconsolata LGC Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 6, + 9, + 3, + 0, + 3, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Inconsolata LGC Nerd Font Complete.ttf", + "preferred_family_name": "InconsolataLGC Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Medium", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/InconsolataGo Bold Nerd Font Complete Mono.ttf||870460:1634564302.0": { + "family_name": "InconsolataGo Nerd Font Mono", + "font-family": "InconsolataGo Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "InconsolataGo Bold Nerd Font Complete Mono", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 6, + 9, + 3, + 0, + 3, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/InconsolataGo Bold Nerd Font Complete Mono.ttf", + "preferred_family_name": "InconsolataGo Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/InconsolataGo Bold Nerd Font Complete.ttf||907804:1634564302.0": { + "family_name": "InconsolataGo Nerd Font", + "font-family": "InconsolataGo Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "InconsolataGo Bold Nerd Font Complete", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 6, + 9, + 3, + 0, + 3, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/InconsolataGo Bold Nerd Font Complete.ttf", + "preferred_family_name": "InconsolataGo Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/InconsolataGo Nerd Font Complete Mono.ttf||842264:1634564302.0": { + "family_name": "InconsolataGo Nerd Font Mono", + "font-family": "InconsolataGo Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 8, + "full_name": "InconsolataGo Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 6, + 9, + 3, + 0, + 3, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/InconsolataGo Nerd Font Complete Mono.ttf", + "preferred_family_name": "InconsolataGo Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/InconsolataGo Nerd Font Complete.ttf||866000:1634564302.0": { + "family_name": "InconsolataGo Nerd Font", + "font-family": "InconsolataGo Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 8, + "full_name": "InconsolataGo Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 6, + 9, + 3, + 0, + 3, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/InconsolataGo Nerd Font Complete.ttf", + "preferred_family_name": "InconsolataGo Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Bold Italic Nerd Font Complete Mono.ttf||1281924:1634564302.0": { + "family_name": "Iosevka Nerd Font Mono", + "font-family": "Iosevka Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Iosevka Bold Italic Nerd Font Complete Mono", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 8, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Bold Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "Iosevka Nerd Font Mono", + "preferred_subfamily_name": "Bold Italic", + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 5, + "wws_family_name": "Iosevka", + "wws_subfamily_name": "Bold Italic" + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Bold Italic Nerd Font Complete.ttf||1312396:1634564302.0": { + "family_name": "Iosevka Nerd Font", + "font-family": "Iosevka Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Iosevka Bold Italic Nerd Font Complete", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 8, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Bold Italic Nerd Font Complete.ttf", + "preferred_family_name": "Iosevka Nerd Font", + "preferred_subfamily_name": "Bold Italic", + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 5, + "wws_family_name": "Iosevka", + "wws_subfamily_name": "Bold Italic" + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Bold Nerd Font Complete Mono.ttf||1270644:1634564302.0": { + "family_name": "Iosevka Nerd Font Mono", + "font-family": "Iosevka Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Iosevka Bold Nerd Font Complete Mono", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 8, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Bold Nerd Font Complete Mono.ttf", + "preferred_family_name": "Iosevka Nerd Font Mono", + "preferred_subfamily_name": "Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": "Iosevka", + "wws_subfamily_name": "Bold" + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Bold Nerd Font Complete.ttf||1301112:1634564302.0": { + "family_name": "Iosevka Nerd Font", + "font-family": "Iosevka Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Iosevka Bold Nerd Font Complete", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 8, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Bold Nerd Font Complete.ttf", + "preferred_family_name": "Iosevka Nerd Font", + "preferred_subfamily_name": "Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": "Iosevka", + "wws_subfamily_name": "Bold" + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Bold Oblique Nerd Font Complete Mono.ttf||1281788:1634564302.0": { + "family_name": "Iosevka Nerd Font Mono", + "font-family": "Iosevka Nerd Font Mono", + "font-stretch": "normal", + "font-style": "oblique", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Iosevka Bold Oblique Nerd Font Complete Mono", + "is_bold": true, + "is_italic": true, + "is_oblique": true, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 8, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Bold Oblique Nerd Font Complete Mono.ttf", + "preferred_family_name": "Iosevka Nerd Font Mono", + "preferred_subfamily_name": "Bold Oblique", + "subfamily_name": "Regular", + "weight": 700, + "width": 5, + "wws_family_name": "Iosevka", + "wws_subfamily_name": "Bold Oblique" + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Bold Oblique Nerd Font Complete.ttf||1312260:1634564302.0": { + "family_name": "Iosevka Nerd Font", + "font-family": "Iosevka Nerd Font", + "font-stretch": "normal", + "font-style": "oblique", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Iosevka Bold Oblique Nerd Font Complete", + "is_bold": true, + "is_italic": true, + "is_oblique": true, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 8, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Bold Oblique Nerd Font Complete.ttf", + "preferred_family_name": "Iosevka Nerd Font", + "preferred_subfamily_name": "Bold Oblique", + "subfamily_name": "Regular", + "weight": 700, + "width": 5, + "wws_family_name": "Iosevka", + "wws_subfamily_name": "Bold Oblique" + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Extralight Italic Nerd Font Complete Mono.ttf||1272596:1634564302.0": { + "family_name": "Iosevka Nerd Font Mono", + "font-family": "Iosevka Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "200", + "fs_type": 0, + "full_name": "Iosevka Extralight Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 3, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Extralight Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "Iosevka Nerd Font Mono", + "preferred_subfamily_name": "Extralight Italic", + "subfamily_name": "Italic", + "weight": 200, + "width": 5, + "wws_family_name": "Iosevka", + "wws_subfamily_name": "Extralight Italic" + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Extralight Italic Nerd Font Complete.ttf||1303068:1634564302.0": { + "family_name": "Iosevka Nerd Font", + "font-family": "Iosevka Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "200", + "fs_type": 0, + "full_name": "Iosevka Extralight Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 3, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Extralight Italic Nerd Font Complete.ttf", + "preferred_family_name": "Iosevka Nerd Font", + "preferred_subfamily_name": "Extralight Italic", + "subfamily_name": "Italic", + "weight": 200, + "width": 5, + "wws_family_name": "Iosevka", + "wws_subfamily_name": "Extralight Italic" + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Extralight Nerd Font Complete Mono.ttf||1259352:1634564302.0": { + "family_name": "Iosevka Nerd Font Mono", + "font-family": "Iosevka Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Iosevka Extralight Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 3, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Extralight Nerd Font Complete Mono.ttf", + "preferred_family_name": "Iosevka Nerd Font Mono", + "preferred_subfamily_name": "Extralight", + "subfamily_name": "Regular", + "weight": 200, + "width": 5, + "wws_family_name": "Iosevka", + "wws_subfamily_name": "Extralight" + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Extralight Nerd Font Complete.ttf||1289824:1634564302.0": { + "family_name": "Iosevka Nerd Font", + "font-family": "Iosevka Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Iosevka Extralight Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 3, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Extralight Nerd Font Complete.ttf", + "preferred_family_name": "Iosevka Nerd Font", + "preferred_subfamily_name": "Extralight", + "subfamily_name": "Regular", + "weight": 200, + "width": 5, + "wws_family_name": "Iosevka", + "wws_subfamily_name": "Extralight" + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Extralight Oblique Nerd Font Complete Mono.ttf||1272584:1634564302.0": { + "family_name": "Iosevka Nerd Font Mono", + "font-family": "Iosevka Nerd Font Mono", + "font-stretch": "normal", + "font-style": "oblique", + "font-weight": "200", + "fs_type": 0, + "full_name": "Iosevka Extralight Oblique Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": true, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 3, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Extralight Oblique Nerd Font Complete Mono.ttf", + "preferred_family_name": "Iosevka Nerd Font Mono", + "preferred_subfamily_name": "Extralight Oblique", + "subfamily_name": "Regular", + "weight": 200, + "width": 5, + "wws_family_name": "Iosevka", + "wws_subfamily_name": "Extralight Oblique" + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Extralight Oblique Nerd Font Complete.ttf||1303056:1634564302.0": { + "family_name": "Iosevka Nerd Font", + "font-family": "Iosevka Nerd Font", + "font-stretch": "normal", + "font-style": "oblique", + "font-weight": "200", + "fs_type": 0, + "full_name": "Iosevka Extralight Oblique Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": true, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 3, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Extralight Oblique Nerd Font Complete.ttf", + "preferred_family_name": "Iosevka Nerd Font", + "preferred_subfamily_name": "Extralight Oblique", + "subfamily_name": "Regular", + "weight": 200, + "width": 5, + "wws_family_name": "Iosevka", + "wws_subfamily_name": "Extralight Oblique" + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Heavy Italic Nerd Font Complete Mono.ttf||1280600:1634564302.0": { + "family_name": "Iosevka Nerd Font Mono", + "font-family": "Iosevka Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "900", + "fs_type": 0, + "full_name": "Iosevka Heavy Italic Nerd Font Complete Mono", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 10, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Heavy Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "Iosevka Nerd Font Mono", + "preferred_subfamily_name": "Heavy Italic", + "subfamily_name": "Italic", + "weight": 900, + "width": 5, + "wws_family_name": "Iosevka", + "wws_subfamily_name": "Heavy Italic" + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Heavy Italic Nerd Font Complete.ttf||1311072:1634564302.0": { + "family_name": "Iosevka Nerd Font", + "font-family": "Iosevka Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "900", + "fs_type": 0, + "full_name": "Iosevka Heavy Italic Nerd Font Complete", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 10, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Heavy Italic Nerd Font Complete.ttf", + "preferred_family_name": "Iosevka Nerd Font", + "preferred_subfamily_name": "Heavy Italic", + "subfamily_name": "Italic", + "weight": 900, + "width": 5, + "wws_family_name": "Iosevka", + "wws_subfamily_name": "Heavy Italic" + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Heavy Nerd Font Complete Mono.ttf||1268364:1634564302.0": { + "family_name": "Iosevka Nerd Font Mono", + "font-family": "Iosevka Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Iosevka Heavy Nerd Font Complete Mono", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 10, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Heavy Nerd Font Complete Mono.ttf", + "preferred_family_name": "Iosevka Nerd Font Mono", + "preferred_subfamily_name": "Heavy", + "subfamily_name": "Regular", + "weight": 900, + "width": 5, + "wws_family_name": "Iosevka", + "wws_subfamily_name": "Heavy" + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Heavy Nerd Font Complete.ttf||1298832:1634564302.0": { + "family_name": "Iosevka Nerd Font", + "font-family": "Iosevka Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Iosevka Heavy Nerd Font Complete", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 10, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Heavy Nerd Font Complete.ttf", + "preferred_family_name": "Iosevka Nerd Font", + "preferred_subfamily_name": "Heavy", + "subfamily_name": "Regular", + "weight": 900, + "width": 5, + "wws_family_name": "Iosevka", + "wws_subfamily_name": "Heavy" + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Heavy Oblique Nerd Font Complete Mono.ttf||1279868:1634564302.0": { + "family_name": "Iosevka Nerd Font Mono", + "font-family": "Iosevka Nerd Font Mono", + "font-stretch": "normal", + "font-style": "oblique", + "font-weight": "900", + "fs_type": 0, + "full_name": "Iosevka Heavy Oblique Nerd Font Complete Mono", + "is_bold": true, + "is_italic": true, + "is_oblique": true, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 10, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Heavy Oblique Nerd Font Complete Mono.ttf", + "preferred_family_name": "Iosevka Nerd Font Mono", + "preferred_subfamily_name": "Heavy Oblique", + "subfamily_name": "Regular", + "weight": 900, + "width": 5, + "wws_family_name": "Iosevka", + "wws_subfamily_name": "Heavy Oblique" + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Heavy Oblique Nerd Font Complete.ttf||1310344:1634564302.0": { + "family_name": "Iosevka Nerd Font", + "font-family": "Iosevka Nerd Font", + "font-stretch": "normal", + "font-style": "oblique", + "font-weight": "900", + "fs_type": 0, + "full_name": "Iosevka Heavy Oblique Nerd Font Complete", + "is_bold": true, + "is_italic": true, + "is_oblique": true, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 10, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Heavy Oblique Nerd Font Complete.ttf", + "preferred_family_name": "Iosevka Nerd Font", + "preferred_subfamily_name": "Heavy Oblique", + "subfamily_name": "Regular", + "weight": 900, + "width": 5, + "wws_family_name": "Iosevka", + "wws_subfamily_name": "Heavy Oblique" + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Italic Nerd Font Complete Mono.ttf||1280448:1634564302.0": { + "family_name": "Iosevka Nerd Font Mono", + "font-family": "Iosevka Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Iosevka Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 5, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "Iosevka Nerd Font Mono", + "preferred_subfamily_name": "Italic", + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": "Iosevka", + "wws_subfamily_name": "Italic" + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Italic Nerd Font Complete.ttf||1310920:1634564302.0": { + "family_name": "Iosevka Nerd Font", + "font-family": "Iosevka Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Iosevka Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 5, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Italic Nerd Font Complete.ttf", + "preferred_family_name": "Iosevka Nerd Font", + "preferred_subfamily_name": "Italic", + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": "Iosevka", + "wws_subfamily_name": "Italic" + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Light Italic Nerd Font Complete Mono.ttf||1279852:1634564302.0": { + "family_name": "Iosevka Nerd Font Mono", + "font-family": "Iosevka Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "300", + "fs_type": 0, + "full_name": "Iosevka Light Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 4, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Light Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "Iosevka Nerd Font Mono", + "preferred_subfamily_name": "Light Italic", + "subfamily_name": "Italic", + "weight": 300, + "width": 5, + "wws_family_name": "Iosevka", + "wws_subfamily_name": "Light Italic" + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Light Italic Nerd Font Complete.ttf||1310324:1634564302.0": { + "family_name": "Iosevka Nerd Font", + "font-family": "Iosevka Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "300", + "fs_type": 0, + "full_name": "Iosevka Light Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 4, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Light Italic Nerd Font Complete.ttf", + "preferred_family_name": "Iosevka Nerd Font", + "preferred_subfamily_name": "Light Italic", + "subfamily_name": "Italic", + "weight": 300, + "width": 5, + "wws_family_name": "Iosevka", + "wws_subfamily_name": "Light Italic" + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Light Nerd Font Complete Mono.ttf||1265764:1634564302.0": { + "family_name": "Iosevka Nerd Font Mono", + "font-family": "Iosevka Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Iosevka Light Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 4, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Light Nerd Font Complete Mono.ttf", + "preferred_family_name": "Iosevka Nerd Font Mono", + "preferred_subfamily_name": "Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": "Iosevka", + "wws_subfamily_name": "Light" + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Light Nerd Font Complete.ttf||1296232:1634564302.0": { + "family_name": "Iosevka Nerd Font", + "font-family": "Iosevka Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Iosevka Light Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 4, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Light Nerd Font Complete.ttf", + "preferred_family_name": "Iosevka Nerd Font", + "preferred_subfamily_name": "Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": "Iosevka", + "wws_subfamily_name": "Light" + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Light Oblique Nerd Font Complete Mono.ttf||1279356:1634564302.0": { + "family_name": "Iosevka Nerd Font Mono", + "font-family": "Iosevka Nerd Font Mono", + "font-stretch": "normal", + "font-style": "oblique", + "font-weight": "300", + "fs_type": 0, + "full_name": "Iosevka Light Oblique Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": true, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 4, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Light Oblique Nerd Font Complete Mono.ttf", + "preferred_family_name": "Iosevka Nerd Font Mono", + "preferred_subfamily_name": "Light Oblique", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": "Iosevka", + "wws_subfamily_name": "Light Oblique" + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Light Oblique Nerd Font Complete.ttf||1309832:1634564302.0": { + "family_name": "Iosevka Nerd Font", + "font-family": "Iosevka Nerd Font", + "font-stretch": "normal", + "font-style": "oblique", + "font-weight": "300", + "fs_type": 0, + "full_name": "Iosevka Light Oblique Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": true, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 4, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Light Oblique Nerd Font Complete.ttf", + "preferred_family_name": "Iosevka Nerd Font", + "preferred_subfamily_name": "Light Oblique", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": "Iosevka", + "wws_subfamily_name": "Light Oblique" + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Medium Italic Nerd Font Complete Mono.ttf||1281064:1634564302.0": { + "family_name": "Iosevka Nerd Font Mono", + "font-family": "Iosevka Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "500", + "fs_type": 0, + "full_name": "Iosevka Medium Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 6, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Medium Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "Iosevka Nerd Font Mono", + "preferred_subfamily_name": "Medium Italic", + "subfamily_name": "Italic", + "weight": 500, + "width": 5, + "wws_family_name": "Iosevka", + "wws_subfamily_name": "Medium Italic" + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Medium Italic Nerd Font Complete.ttf||1311536:1634564302.0": { + "family_name": "Iosevka Nerd Font", + "font-family": "Iosevka Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "500", + "fs_type": 0, + "full_name": "Iosevka Medium Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 6, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Medium Italic Nerd Font Complete.ttf", + "preferred_family_name": "Iosevka Nerd Font", + "preferred_subfamily_name": "Medium Italic", + "subfamily_name": "Italic", + "weight": 500, + "width": 5, + "wws_family_name": "Iosevka", + "wws_subfamily_name": "Medium Italic" + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Medium Nerd Font Complete Mono.ttf||1268068:1634564302.0": { + "family_name": "Iosevka Nerd Font Mono", + "font-family": "Iosevka Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Iosevka Medium Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 6, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Medium Nerd Font Complete Mono.ttf", + "preferred_family_name": "Iosevka Nerd Font Mono", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": "Iosevka", + "wws_subfamily_name": "Medium" + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Medium Nerd Font Complete.ttf||1298540:1634564302.0": { + "family_name": "Iosevka Nerd Font", + "font-family": "Iosevka Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Iosevka Medium Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 6, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Medium Nerd Font Complete.ttf", + "preferred_family_name": "Iosevka Nerd Font", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": "Iosevka", + "wws_subfamily_name": "Medium" + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Medium Oblique Nerd Font Complete Mono.ttf||1280680:1634564302.0": { + "family_name": "Iosevka Nerd Font Mono", + "font-family": "Iosevka Nerd Font Mono", + "font-stretch": "normal", + "font-style": "oblique", + "font-weight": "500", + "fs_type": 0, + "full_name": "Iosevka Medium Oblique Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": true, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 6, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Medium Oblique Nerd Font Complete Mono.ttf", + "preferred_family_name": "Iosevka Nerd Font Mono", + "preferred_subfamily_name": "Medium Oblique", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": "Iosevka", + "wws_subfamily_name": "Medium Oblique" + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Medium Oblique Nerd Font Complete.ttf||1311152:1634564302.0": { + "family_name": "Iosevka Nerd Font", + "font-family": "Iosevka Nerd Font", + "font-stretch": "normal", + "font-style": "oblique", + "font-weight": "500", + "fs_type": 0, + "full_name": "Iosevka Medium Oblique Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": true, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 6, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Medium Oblique Nerd Font Complete.ttf", + "preferred_family_name": "Iosevka Nerd Font", + "preferred_subfamily_name": "Medium Oblique", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": "Iosevka", + "wws_subfamily_name": "Medium Oblique" + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Nerd Font Complete Mono.ttf||1268512:1634564302.0": { + "family_name": "Iosevka Nerd Font Mono", + "font-family": "Iosevka Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Iosevka Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 5, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Nerd Font Complete Mono.ttf", + "preferred_family_name": "Iosevka Nerd Font Mono", + "preferred_subfamily_name": "Regular", + "subfamily_name": "Book", + "weight": 400, + "width": 5, + "wws_family_name": "Iosevka", + "wws_subfamily_name": "Regular" + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Nerd Font Complete.ttf||1298984:1634564302.0": { + "family_name": "Iosevka Nerd Font", + "font-family": "Iosevka Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Iosevka Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 5, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Nerd Font Complete.ttf", + "preferred_family_name": "Iosevka Nerd Font", + "preferred_subfamily_name": "Regular", + "subfamily_name": "Book", + "weight": 400, + "width": 5, + "wws_family_name": "Iosevka", + "wws_subfamily_name": "Regular" + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Oblique Nerd Font Complete Mono.ttf||1280168:1634564302.0": { + "family_name": "Iosevka Nerd Font Mono", + "font-family": "Iosevka Nerd Font Mono", + "font-stretch": "normal", + "font-style": "oblique", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Iosevka Oblique Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": true, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 5, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Oblique Nerd Font Complete Mono.ttf", + "preferred_family_name": "Iosevka Nerd Font Mono", + "preferred_subfamily_name": "Oblique", + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": "Iosevka", + "wws_subfamily_name": "Oblique" + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Oblique Nerd Font Complete.ttf||1310640:1634564302.0": { + "family_name": "Iosevka Nerd Font", + "font-family": "Iosevka Nerd Font", + "font-stretch": "normal", + "font-style": "oblique", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Iosevka Oblique Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": true, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 5, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Oblique Nerd Font Complete.ttf", + "preferred_family_name": "Iosevka Nerd Font", + "preferred_subfamily_name": "Oblique", + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": "Iosevka", + "wws_subfamily_name": "Oblique" + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Term Bold Italic Nerd Font Complete Mono.ttf||1278704:1634564302.0": { + "family_name": "Iosevka Nerd Font Mono", + "font-family": "Iosevka Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Iosevka Term Bold Italic Nerd Font Complete Mono", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 8, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Term Bold Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "Iosevka Nerd Font Mono", + "preferred_subfamily_name": "Bold Italic", + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 5, + "wws_family_name": "Iosevka Term", + "wws_subfamily_name": "Bold Italic" + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Term Bold Italic Nerd Font Complete.ttf||1309144:1634564302.0": { + "family_name": "Iosevka Nerd Font", + "font-family": "Iosevka Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Iosevka Term Bold Italic Nerd Font Complete", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 8, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Term Bold Italic Nerd Font Complete.ttf", + "preferred_family_name": "Iosevka Nerd Font", + "preferred_subfamily_name": "Bold Italic", + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 5, + "wws_family_name": "Iosevka Term", + "wws_subfamily_name": "Bold Italic" + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Term Bold Nerd Font Complete Mono.ttf||1266696:1634564302.0": { + "family_name": "Iosevka Nerd Font Mono", + "font-family": "Iosevka Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Iosevka Term Bold Nerd Font Complete Mono", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 8, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Term Bold Nerd Font Complete Mono.ttf", + "preferred_family_name": "Iosevka Nerd Font Mono", + "preferred_subfamily_name": "Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": "Iosevka Term", + "wws_subfamily_name": "Bold" + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Term Bold Nerd Font Complete.ttf||1297136:1634564302.0": { + "family_name": "Iosevka Nerd Font", + "font-family": "Iosevka Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Iosevka Term Bold Nerd Font Complete", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 8, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Term Bold Nerd Font Complete.ttf", + "preferred_family_name": "Iosevka Nerd Font", + "preferred_subfamily_name": "Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": "Iosevka Term", + "wws_subfamily_name": "Bold" + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Term Bold Oblique Nerd Font Complete Mono.ttf||1278500:1634564302.0": { + "family_name": "Iosevka Nerd Font Mono", + "font-family": "Iosevka Nerd Font Mono", + "font-stretch": "normal", + "font-style": "oblique", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Iosevka Term Bold Oblique Nerd Font Complete Mono", + "is_bold": true, + "is_italic": true, + "is_oblique": true, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 8, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Term Bold Oblique Nerd Font Complete Mono.ttf", + "preferred_family_name": "Iosevka Nerd Font Mono", + "preferred_subfamily_name": "Bold Oblique", + "subfamily_name": "Regular", + "weight": 700, + "width": 5, + "wws_family_name": "Iosevka Term", + "wws_subfamily_name": "Bold Oblique" + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Term Bold Oblique Nerd Font Complete.ttf||1308940:1634564302.0": { + "family_name": "Iosevka Nerd Font", + "font-family": "Iosevka Nerd Font", + "font-stretch": "normal", + "font-style": "oblique", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Iosevka Term Bold Oblique Nerd Font Complete", + "is_bold": true, + "is_italic": true, + "is_oblique": true, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 8, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Term Bold Oblique Nerd Font Complete.ttf", + "preferred_family_name": "Iosevka Nerd Font", + "preferred_subfamily_name": "Bold Oblique", + "subfamily_name": "Regular", + "weight": 700, + "width": 5, + "wws_family_name": "Iosevka Term", + "wws_subfamily_name": "Bold Oblique" + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Term Extralight Italic Nerd Font Complete Mono.ttf||1270036:1634564302.0": { + "family_name": "Iosevka Nerd Font Mono", + "font-family": "Iosevka Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "200", + "fs_type": 0, + "full_name": "Iosevka Term Extralight Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 3, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Term Extralight Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "Iosevka Nerd Font Mono", + "preferred_subfamily_name": "Extralight Italic", + "subfamily_name": "Italic", + "weight": 200, + "width": 5, + "wws_family_name": "Iosevka Term", + "wws_subfamily_name": "Extralight Italic" + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Term Extralight Italic Nerd Font Complete.ttf||1300476:1634564302.0": { + "family_name": "Iosevka Nerd Font", + "font-family": "Iosevka Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "200", + "fs_type": 0, + "full_name": "Iosevka Term Extralight Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 3, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Term Extralight Italic Nerd Font Complete.ttf", + "preferred_family_name": "Iosevka Nerd Font", + "preferred_subfamily_name": "Extralight Italic", + "subfamily_name": "Italic", + "weight": 200, + "width": 5, + "wws_family_name": "Iosevka Term", + "wws_subfamily_name": "Extralight Italic" + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Term Extralight Nerd Font Complete Mono.ttf||1255820:1634564302.0": { + "family_name": "Iosevka Nerd Font Mono", + "font-family": "Iosevka Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Iosevka Term Extralight Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 3, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Term Extralight Nerd Font Complete Mono.ttf", + "preferred_family_name": "Iosevka Nerd Font Mono", + "preferred_subfamily_name": "Extralight", + "subfamily_name": "Regular", + "weight": 200, + "width": 5, + "wws_family_name": "Iosevka Term", + "wws_subfamily_name": "Extralight" + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Term Extralight Nerd Font Complete.ttf||1286264:1634564302.0": { + "family_name": "Iosevka Nerd Font", + "font-family": "Iosevka Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Iosevka Term Extralight Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 3, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Term Extralight Nerd Font Complete.ttf", + "preferred_family_name": "Iosevka Nerd Font", + "preferred_subfamily_name": "Extralight", + "subfamily_name": "Regular", + "weight": 200, + "width": 5, + "wws_family_name": "Iosevka Term", + "wws_subfamily_name": "Extralight" + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Term Extralight Oblique Nerd Font Complete Mono.ttf||1270072:1634564302.0": { + "family_name": "Iosevka Nerd Font Mono", + "font-family": "Iosevka Nerd Font Mono", + "font-stretch": "normal", + "font-style": "oblique", + "font-weight": "200", + "fs_type": 0, + "full_name": "Iosevka Term Extralight Oblique Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": true, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 3, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Term Extralight Oblique Nerd Font Complete Mono.ttf", + "preferred_family_name": "Iosevka Nerd Font Mono", + "preferred_subfamily_name": "Extralight Oblique", + "subfamily_name": "Regular", + "weight": 200, + "width": 5, + "wws_family_name": "Iosevka Term", + "wws_subfamily_name": "Extralight Oblique" + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Term Extralight Oblique Nerd Font Complete.ttf||1300512:1634564302.0": { + "family_name": "Iosevka Nerd Font", + "font-family": "Iosevka Nerd Font", + "font-stretch": "normal", + "font-style": "oblique", + "font-weight": "200", + "fs_type": 0, + "full_name": "Iosevka Term Extralight Oblique Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": true, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 3, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Term Extralight Oblique Nerd Font Complete.ttf", + "preferred_family_name": "Iosevka Nerd Font", + "preferred_subfamily_name": "Extralight Oblique", + "subfamily_name": "Regular", + "weight": 200, + "width": 5, + "wws_family_name": "Iosevka Term", + "wws_subfamily_name": "Extralight Oblique" + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Term Heavy Italic Nerd Font Complete Mono.ttf||1278484:1634564302.0": { + "family_name": "Iosevka Nerd Font Mono", + "font-family": "Iosevka Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "900", + "fs_type": 0, + "full_name": "Iosevka Term Heavy Italic Nerd Font Complete Mono", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 10, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Term Heavy Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "Iosevka Nerd Font Mono", + "preferred_subfamily_name": "Heavy Italic", + "subfamily_name": "Italic", + "weight": 900, + "width": 5, + "wws_family_name": "Iosevka Term", + "wws_subfamily_name": "Heavy Italic" + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Term Heavy Italic Nerd Font Complete.ttf||1308924:1634564302.0": { + "family_name": "Iosevka Nerd Font", + "font-family": "Iosevka Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "900", + "fs_type": 0, + "full_name": "Iosevka Term Heavy Italic Nerd Font Complete", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 10, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Term Heavy Italic Nerd Font Complete.ttf", + "preferred_family_name": "Iosevka Nerd Font", + "preferred_subfamily_name": "Heavy Italic", + "subfamily_name": "Italic", + "weight": 900, + "width": 5, + "wws_family_name": "Iosevka Term", + "wws_subfamily_name": "Heavy Italic" + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Term Heavy Nerd Font Complete Mono.ttf||1264464:1634564302.0": { + "family_name": "Iosevka Nerd Font Mono", + "font-family": "Iosevka Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Iosevka Term Heavy Nerd Font Complete Mono", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 10, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Term Heavy Nerd Font Complete Mono.ttf", + "preferred_family_name": "Iosevka Nerd Font Mono", + "preferred_subfamily_name": "Heavy", + "subfamily_name": "Regular", + "weight": 900, + "width": 5, + "wws_family_name": "Iosevka Term", + "wws_subfamily_name": "Heavy" + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Term Heavy Nerd Font Complete.ttf||1294904:1634564302.0": { + "family_name": "Iosevka Nerd Font", + "font-family": "Iosevka Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Iosevka Term Heavy Nerd Font Complete", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 10, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Term Heavy Nerd Font Complete.ttf", + "preferred_family_name": "Iosevka Nerd Font", + "preferred_subfamily_name": "Heavy", + "subfamily_name": "Regular", + "weight": 900, + "width": 5, + "wws_family_name": "Iosevka Term", + "wws_subfamily_name": "Heavy" + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Term Heavy Oblique Nerd Font Complete Mono.ttf||1277716:1634564302.0": { + "family_name": "Iosevka Nerd Font Mono", + "font-family": "Iosevka Nerd Font Mono", + "font-stretch": "normal", + "font-style": "oblique", + "font-weight": "900", + "fs_type": 0, + "full_name": "Iosevka Term Heavy Oblique Nerd Font Complete Mono", + "is_bold": true, + "is_italic": true, + "is_oblique": true, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 10, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Term Heavy Oblique Nerd Font Complete Mono.ttf", + "preferred_family_name": "Iosevka Nerd Font Mono", + "preferred_subfamily_name": "Heavy Oblique", + "subfamily_name": "Regular", + "weight": 900, + "width": 5, + "wws_family_name": "Iosevka Term", + "wws_subfamily_name": "Heavy Oblique" + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Term Heavy Oblique Nerd Font Complete.ttf||1308160:1634564302.0": { + "family_name": "Iosevka Nerd Font", + "font-family": "Iosevka Nerd Font", + "font-stretch": "normal", + "font-style": "oblique", + "font-weight": "900", + "fs_type": 0, + "full_name": "Iosevka Term Heavy Oblique Nerd Font Complete", + "is_bold": true, + "is_italic": true, + "is_oblique": true, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 10, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Term Heavy Oblique Nerd Font Complete.ttf", + "preferred_family_name": "Iosevka Nerd Font", + "preferred_subfamily_name": "Heavy Oblique", + "subfamily_name": "Regular", + "weight": 900, + "width": 5, + "wws_family_name": "Iosevka Term", + "wws_subfamily_name": "Heavy Oblique" + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Term Italic Nerd Font Complete Mono.ttf||1277820:1634564302.0": { + "family_name": "Iosevka Nerd Font Mono", + "font-family": "Iosevka Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Iosevka Term Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 5, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Term Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "Iosevka Nerd Font Mono", + "preferred_subfamily_name": "Italic", + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": "Iosevka Term", + "wws_subfamily_name": "Italic" + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Term Italic Nerd Font Complete.ttf||1308260:1634564302.0": { + "family_name": "Iosevka Nerd Font", + "font-family": "Iosevka Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Iosevka Term Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 5, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Term Italic Nerd Font Complete.ttf", + "preferred_family_name": "Iosevka Nerd Font", + "preferred_subfamily_name": "Italic", + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": "Iosevka Term", + "wws_subfamily_name": "Italic" + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Term Light Italic Nerd Font Complete Mono.ttf||1277284:1634564302.0": { + "family_name": "Iosevka Nerd Font Mono", + "font-family": "Iosevka Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "300", + "fs_type": 0, + "full_name": "Iosevka Term Light Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 4, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Term Light Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "Iosevka Nerd Font Mono", + "preferred_subfamily_name": "Light Italic", + "subfamily_name": "Italic", + "weight": 300, + "width": 5, + "wws_family_name": "Iosevka Term", + "wws_subfamily_name": "Light Italic" + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Term Light Italic Nerd Font Complete.ttf||1307724:1634564302.0": { + "family_name": "Iosevka Nerd Font", + "font-family": "Iosevka Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "300", + "fs_type": 0, + "full_name": "Iosevka Term Light Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 4, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Term Light Italic Nerd Font Complete.ttf", + "preferred_family_name": "Iosevka Nerd Font", + "preferred_subfamily_name": "Light Italic", + "subfamily_name": "Italic", + "weight": 300, + "width": 5, + "wws_family_name": "Iosevka Term", + "wws_subfamily_name": "Light Italic" + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Term Light Nerd Font Complete Mono.ttf||1262468:1634564302.0": { + "family_name": "Iosevka Nerd Font Mono", + "font-family": "Iosevka Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Iosevka Term Light Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 4, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Term Light Nerd Font Complete Mono.ttf", + "preferred_family_name": "Iosevka Nerd Font Mono", + "preferred_subfamily_name": "Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": "Iosevka Term", + "wws_subfamily_name": "Light" + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Term Light Nerd Font Complete.ttf||1292908:1634564302.0": { + "family_name": "Iosevka Nerd Font", + "font-family": "Iosevka Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Iosevka Term Light Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 4, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Term Light Nerd Font Complete.ttf", + "preferred_family_name": "Iosevka Nerd Font", + "preferred_subfamily_name": "Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": "Iosevka Term", + "wws_subfamily_name": "Light" + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Term Light Oblique Nerd Font Complete Mono.ttf||1276624:1634564302.0": { + "family_name": "Iosevka Nerd Font Mono", + "font-family": "Iosevka Nerd Font Mono", + "font-stretch": "normal", + "font-style": "oblique", + "font-weight": "300", + "fs_type": 0, + "full_name": "Iosevka Term Light Oblique Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": true, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 4, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Term Light Oblique Nerd Font Complete Mono.ttf", + "preferred_family_name": "Iosevka Nerd Font Mono", + "preferred_subfamily_name": "Light Oblique", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": "Iosevka Term", + "wws_subfamily_name": "Light Oblique" + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Term Light Oblique Nerd Font Complete.ttf||1307068:1634564302.0": { + "family_name": "Iosevka Nerd Font", + "font-family": "Iosevka Nerd Font", + "font-stretch": "normal", + "font-style": "oblique", + "font-weight": "300", + "fs_type": 0, + "full_name": "Iosevka Term Light Oblique Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": true, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 4, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Term Light Oblique Nerd Font Complete.ttf", + "preferred_family_name": "Iosevka Nerd Font", + "preferred_subfamily_name": "Light Oblique", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": "Iosevka Term", + "wws_subfamily_name": "Light Oblique" + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Term Medium Italic Nerd Font Complete Mono.ttf||1277748:1634564302.0": { + "family_name": "Iosevka Nerd Font Mono", + "font-family": "Iosevka Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "500", + "fs_type": 0, + "full_name": "Iosevka Term Medium Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 6, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Term Medium Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "Iosevka Nerd Font Mono", + "preferred_subfamily_name": "Medium Italic", + "subfamily_name": "Italic", + "weight": 500, + "width": 5, + "wws_family_name": "Iosevka Term", + "wws_subfamily_name": "Medium Italic" + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Term Medium Italic Nerd Font Complete.ttf||1308188:1634564302.0": { + "family_name": "Iosevka Nerd Font", + "font-family": "Iosevka Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "500", + "fs_type": 0, + "full_name": "Iosevka Term Medium Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 6, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Term Medium Italic Nerd Font Complete.ttf", + "preferred_family_name": "Iosevka Nerd Font", + "preferred_subfamily_name": "Medium Italic", + "subfamily_name": "Italic", + "weight": 500, + "width": 5, + "wws_family_name": "Iosevka Term", + "wws_subfamily_name": "Medium Italic" + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Term Medium Nerd Font Complete Mono.ttf||1263888:1634564302.0": { + "family_name": "Iosevka Nerd Font Mono", + "font-family": "Iosevka Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Iosevka Term Medium Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 6, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Term Medium Nerd Font Complete Mono.ttf", + "preferred_family_name": "Iosevka Nerd Font Mono", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": "Iosevka Term", + "wws_subfamily_name": "Medium" + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Term Medium Nerd Font Complete.ttf||1294332:1634564302.0": { + "family_name": "Iosevka Nerd Font", + "font-family": "Iosevka Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Iosevka Term Medium Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 6, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Term Medium Nerd Font Complete.ttf", + "preferred_family_name": "Iosevka Nerd Font", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": "Iosevka Term", + "wws_subfamily_name": "Medium" + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Term Medium Oblique Nerd Font Complete Mono.ttf||1277132:1634564302.0": { + "family_name": "Iosevka Nerd Font Mono", + "font-family": "Iosevka Nerd Font Mono", + "font-stretch": "normal", + "font-style": "oblique", + "font-weight": "500", + "fs_type": 0, + "full_name": "Iosevka Term Medium Oblique Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": true, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 6, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Term Medium Oblique Nerd Font Complete Mono.ttf", + "preferred_family_name": "Iosevka Nerd Font Mono", + "preferred_subfamily_name": "Medium Oblique", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": "Iosevka Term", + "wws_subfamily_name": "Medium Oblique" + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Term Medium Oblique Nerd Font Complete.ttf||1307572:1634564302.0": { + "family_name": "Iosevka Nerd Font", + "font-family": "Iosevka Nerd Font", + "font-stretch": "normal", + "font-style": "oblique", + "font-weight": "500", + "fs_type": 0, + "full_name": "Iosevka Term Medium Oblique Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": true, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 6, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Term Medium Oblique Nerd Font Complete.ttf", + "preferred_family_name": "Iosevka Nerd Font", + "preferred_subfamily_name": "Medium Oblique", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": "Iosevka Term", + "wws_subfamily_name": "Medium Oblique" + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Term Nerd Font Complete Mono.ttf||1264264:1634564302.0": { + "family_name": "Iosevka Nerd Font Mono", + "font-family": "Iosevka Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Iosevka Term Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 5, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Term Nerd Font Complete Mono.ttf", + "preferred_family_name": "Iosevka Nerd Font Mono", + "preferred_subfamily_name": "Regular", + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": "Iosevka Term", + "wws_subfamily_name": "Regular" + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Term Nerd Font Complete.ttf||1294704:1634564302.0": { + "family_name": "Iosevka Nerd Font", + "font-family": "Iosevka Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Iosevka Term Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 5, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Term Nerd Font Complete.ttf", + "preferred_family_name": "Iosevka Nerd Font", + "preferred_subfamily_name": "Regular", + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": "Iosevka Term", + "wws_subfamily_name": "Regular" + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Term Oblique Nerd Font Complete Mono.ttf||1277248:1634564302.0": { + "family_name": "Iosevka Nerd Font Mono", + "font-family": "Iosevka Nerd Font Mono", + "font-stretch": "normal", + "font-style": "oblique", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Iosevka Term Oblique Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": true, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 5, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Term Oblique Nerd Font Complete Mono.ttf", + "preferred_family_name": "Iosevka Nerd Font Mono", + "preferred_subfamily_name": "Oblique", + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": "Iosevka Term", + "wws_subfamily_name": "Oblique" + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Term Oblique Nerd Font Complete.ttf||1307688:1634564302.0": { + "family_name": "Iosevka Nerd Font", + "font-family": "Iosevka Nerd Font", + "font-stretch": "normal", + "font-style": "oblique", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Iosevka Term Oblique Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": true, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 5, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Term Oblique Nerd Font Complete.ttf", + "preferred_family_name": "Iosevka Nerd Font", + "preferred_subfamily_name": "Oblique", + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": "Iosevka Term", + "wws_subfamily_name": "Oblique" + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Term Thin Italic Nerd Font Complete Mono.ttf||1265988:1634564302.0": { + "family_name": "Iosevka Nerd Font Mono", + "font-family": "Iosevka Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "100", + "fs_type": 0, + "full_name": "Iosevka Term Thin Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 2, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Term Thin Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "Iosevka Nerd Font Mono", + "preferred_subfamily_name": "Thin Italic", + "subfamily_name": "Italic", + "weight": 100, + "width": 5, + "wws_family_name": "Iosevka Term", + "wws_subfamily_name": "Thin Italic" + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Term Thin Italic Nerd Font Complete.ttf||1296432:1634564302.0": { + "family_name": "Iosevka Nerd Font", + "font-family": "Iosevka Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "100", + "fs_type": 0, + "full_name": "Iosevka Term Thin Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 2, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Term Thin Italic Nerd Font Complete.ttf", + "preferred_family_name": "Iosevka Nerd Font", + "preferred_subfamily_name": "Thin Italic", + "subfamily_name": "Italic", + "weight": 100, + "width": 5, + "wws_family_name": "Iosevka Term", + "wws_subfamily_name": "Thin Italic" + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Term Thin Nerd Font Complete Mono.ttf||1253784:1634564302.0": { + "family_name": "Iosevka Nerd Font Mono", + "font-family": "Iosevka Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Iosevka Term Thin Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 2, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Term Thin Nerd Font Complete Mono.ttf", + "preferred_family_name": "Iosevka Nerd Font Mono", + "preferred_subfamily_name": "Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 5, + "wws_family_name": "Iosevka Term", + "wws_subfamily_name": "Thin" + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Term Thin Nerd Font Complete.ttf||1284228:1634564302.0": { + "family_name": "Iosevka Nerd Font", + "font-family": "Iosevka Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Iosevka Term Thin Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 2, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Term Thin Nerd Font Complete.ttf", + "preferred_family_name": "Iosevka Nerd Font", + "preferred_subfamily_name": "Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 5, + "wws_family_name": "Iosevka Term", + "wws_subfamily_name": "Thin" + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Term Thin Oblique Nerd Font Complete Mono.ttf||1266600:1634564302.0": { + "family_name": "Iosevka Nerd Font Mono", + "font-family": "Iosevka Nerd Font Mono", + "font-stretch": "normal", + "font-style": "oblique", + "font-weight": "100", + "fs_type": 0, + "full_name": "Iosevka Term Thin Oblique Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": true, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 2, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Term Thin Oblique Nerd Font Complete Mono.ttf", + "preferred_family_name": "Iosevka Nerd Font Mono", + "preferred_subfamily_name": "Thin Oblique", + "subfamily_name": "Regular", + "weight": 100, + "width": 5, + "wws_family_name": "Iosevka Term", + "wws_subfamily_name": "Thin Oblique" + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Term Thin Oblique Nerd Font Complete.ttf||1297040:1634564302.0": { + "family_name": "Iosevka Nerd Font", + "font-family": "Iosevka Nerd Font", + "font-stretch": "normal", + "font-style": "oblique", + "font-weight": "100", + "fs_type": 0, + "full_name": "Iosevka Term Thin Oblique Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": true, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 2, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Term Thin Oblique Nerd Font Complete.ttf", + "preferred_family_name": "Iosevka Nerd Font", + "preferred_subfamily_name": "Thin Oblique", + "subfamily_name": "Regular", + "weight": 100, + "width": 5, + "wws_family_name": "Iosevka Term", + "wws_subfamily_name": "Thin Oblique" + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Thin Italic Nerd Font Complete Mono.ttf||1270652:1634564302.0": { + "family_name": "Iosevka Nerd Font Mono", + "font-family": "Iosevka Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "100", + "fs_type": 0, + "full_name": "Iosevka Thin Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 2, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Thin Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "Iosevka Nerd Font Mono", + "preferred_subfamily_name": "Thin Italic", + "subfamily_name": "Italic", + "weight": 100, + "width": 5, + "wws_family_name": "Iosevka", + "wws_subfamily_name": "Thin Italic" + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Thin Italic Nerd Font Complete.ttf||1301128:1634564302.0": { + "family_name": "Iosevka Nerd Font", + "font-family": "Iosevka Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "100", + "fs_type": 0, + "full_name": "Iosevka Thin Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 2, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Thin Italic Nerd Font Complete.ttf", + "preferred_family_name": "Iosevka Nerd Font", + "preferred_subfamily_name": "Thin Italic", + "subfamily_name": "Italic", + "weight": 100, + "width": 5, + "wws_family_name": "Iosevka", + "wws_subfamily_name": "Thin Italic" + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Thin Nerd Font Complete Mono.ttf||1257344:1634564302.0": { + "family_name": "Iosevka Nerd Font Mono", + "font-family": "Iosevka Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Iosevka Thin Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 2, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Thin Nerd Font Complete Mono.ttf", + "preferred_family_name": "Iosevka Nerd Font Mono", + "preferred_subfamily_name": "Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 5, + "wws_family_name": "Iosevka", + "wws_subfamily_name": "Thin" + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Thin Nerd Font Complete.ttf||1287816:1634564302.0": { + "family_name": "Iosevka Nerd Font", + "font-family": "Iosevka Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Iosevka Thin Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 2, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Thin Nerd Font Complete.ttf", + "preferred_family_name": "Iosevka Nerd Font", + "preferred_subfamily_name": "Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 5, + "wws_family_name": "Iosevka", + "wws_subfamily_name": "Thin" + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Thin Oblique Nerd Font Complete Mono.ttf||1271204:1634564302.0": { + "family_name": "Iosevka Nerd Font Mono", + "font-family": "Iosevka Nerd Font Mono", + "font-stretch": "normal", + "font-style": "oblique", + "font-weight": "100", + "fs_type": 0, + "full_name": "Iosevka Thin Oblique Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": true, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 2, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Thin Oblique Nerd Font Complete Mono.ttf", + "preferred_family_name": "Iosevka Nerd Font Mono", + "preferred_subfamily_name": "Thin Oblique", + "subfamily_name": "Regular", + "weight": 100, + "width": 5, + "wws_family_name": "Iosevka", + "wws_subfamily_name": "Thin Oblique" + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Thin Oblique Nerd Font Complete.ttf||1301676:1634564302.0": { + "family_name": "Iosevka Nerd Font", + "font-family": "Iosevka Nerd Font", + "font-stretch": "normal", + "font-style": "oblique", + "font-weight": "100", + "fs_type": 0, + "full_name": "Iosevka Thin Oblique Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": true, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 2, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Iosevka Thin Oblique Nerd Font Complete.ttf", + "preferred_family_name": "Iosevka Nerd Font", + "preferred_subfamily_name": "Thin Oblique", + "subfamily_name": "Regular", + "weight": 100, + "width": 5, + "wws_family_name": "Iosevka", + "wws_subfamily_name": "Thin Oblique" + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/JetBrains Mono Bold Italic Nerd Font Complete Mono.ttf||916584:1634564302.0": { + "family_name": "JetBrainsMono Nerd Font Mono", + "font-family": "JetBrainsMono Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 4, + "full_name": "JetBrains Mono Bold Italic Nerd Font Complete Mono", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 1, + 8, + 9, + 3, + 1, + 2, + 5, + 0, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/JetBrains Mono Bold Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "JetBrainsMono Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/JetBrains Mono Bold Italic Nerd Font Complete.ttf||926260:1634564302.0": { + "family_name": "JetBrainsMono Nerd Font", + "font-family": "JetBrainsMono Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 4, + "full_name": "JetBrains Mono Bold Italic Nerd Font Complete", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 1, + 8, + 9, + 3, + 1, + 2, + 5, + 0, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/JetBrains Mono Bold Italic Nerd Font Complete.ttf", + "preferred_family_name": "JetBrainsMono Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/JetBrains Mono Bold Nerd Font Complete Mono.ttf||909052:1634564302.0": { + "family_name": "JetBrainsMono Nerd Font Mono", + "font-family": "JetBrainsMono Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 4, + "full_name": "JetBrains Mono Bold Nerd Font Complete Mono", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 1, + 8, + 9, + 3, + 1, + 2, + 5, + 0, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/JetBrains Mono Bold Nerd Font Complete Mono.ttf", + "preferred_family_name": "JetBrainsMono Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/JetBrains Mono Bold Nerd Font Complete.ttf||918020:1634564302.0": { + "family_name": "JetBrainsMono Nerd Font", + "font-family": "JetBrainsMono Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 4, + "full_name": "JetBrains Mono Bold Nerd Font Complete", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 1, + 8, + 9, + 3, + 1, + 2, + 5, + 0, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/JetBrains Mono Bold Nerd Font Complete.ttf", + "preferred_family_name": "JetBrainsMono Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/JetBrains Mono ExtBd Ita Nerd Font Complete Mono.ttf||916748:1634564302.0": { + "family_name": "JetBrainsMono Nerd Font Mono", + "font-family": "JetBrainsMono Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "800", + "fs_type": 4, + "full_name": "JetBrains Mono ExtBd Ita Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/JetBrains Mono ExtBd Ita Nerd Font Complete Mono.ttf", + "preferred_family_name": "JetBrainsMono Nerd Font Mono", + "preferred_subfamily_name": "Extra Bold Italic", + "subfamily_name": "Italic", + "weight": 800, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/JetBrains Mono ExtBd Ita Nerd Font Complete.ttf||926408:1634564302.0": { + "family_name": "JetBrainsMono Nerd Font", + "font-family": "JetBrainsMono Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "800", + "fs_type": 4, + "full_name": "JetBrains Mono ExtBd Ita Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/JetBrains Mono ExtBd Ita Nerd Font Complete.ttf", + "preferred_family_name": "JetBrainsMono Nerd Font", + "preferred_subfamily_name": "Extra Bold Italic", + "subfamily_name": "Italic", + "weight": 800, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/JetBrains Mono Extra Bold Nerd Font Complete Mono.ttf||909212:1634564302.0": { + "family_name": "JetBrainsMono Nerd Font Mono", + "font-family": "JetBrainsMono Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "800", + "fs_type": 4, + "full_name": "JetBrains Mono Extra Bold Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/JetBrains Mono Extra Bold Nerd Font Complete Mono.ttf", + "preferred_family_name": "JetBrainsMono Nerd Font Mono", + "preferred_subfamily_name": "Extra Bold", + "subfamily_name": "Regular", + "weight": 800, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/JetBrains Mono Extra Bold Nerd Font Complete.ttf||918168:1634564302.0": { + "family_name": "JetBrainsMono Nerd Font", + "font-family": "JetBrainsMono Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "800", + "fs_type": 4, + "full_name": "JetBrains Mono Extra Bold Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/JetBrains Mono Extra Bold Nerd Font Complete.ttf", + "preferred_family_name": "JetBrainsMono Nerd Font", + "preferred_subfamily_name": "Extra Bold", + "subfamily_name": "Regular", + "weight": 800, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/JetBrains Mono ExtraBold ExBd I Nerd Font Complete Mono.ttf||919148:1634564302.0": { + "family_name": "JetBrainsMonoExtraBold Nerd Font Mono", + "font-family": "JetBrainsMonoExtraBold Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "800", + "fs_type": 4, + "full_name": "JetBrains Mono ExtraBold ExBd I Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 1, + 9, + 9, + 3, + 1, + 2, + 5, + 0, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/JetBrains Mono ExtraBold ExBd I Nerd Font Complete Mono.ttf", + "preferred_family_name": "JetBrainsMonoExtraBold Nerd Font Mono", + "preferred_subfamily_name": "Extra Bold Italic", + "subfamily_name": "Italic", + "weight": 800, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/JetBrains Mono ExtraBold ExBd I Nerd Font Complete.ttf||928820:1634564302.0": { + "family_name": "JetBrainsMonoExtraBold Nerd Font", + "font-family": "JetBrainsMonoExtraBold Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "800", + "fs_type": 4, + "full_name": "JetBrains Mono ExtraBold ExBd I Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 1, + 9, + 9, + 3, + 1, + 2, + 5, + 0, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/JetBrains Mono ExtraBold ExBd I Nerd Font Complete.ttf", + "preferred_family_name": "JetBrainsMonoExtraBold Nerd Font", + "preferred_subfamily_name": "Extra Bold Italic", + "subfamily_name": "Italic", + "weight": 800, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/JetBrains Mono ExtraBold ExtBd Nerd Font Complete Mono.ttf||910572:1634564302.0": { + "family_name": "JetBrainsMonoExtraBold Nerd Font Mono", + "font-family": "JetBrainsMonoExtraBold Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "800", + "fs_type": 4, + "full_name": "JetBrains Mono ExtraBold ExtBd Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 1, + 9, + 9, + 3, + 1, + 2, + 5, + 0, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/JetBrains Mono ExtraBold ExtBd Nerd Font Complete Mono.ttf", + "preferred_family_name": "JetBrainsMonoExtraBold Nerd Font Mono", + "preferred_subfamily_name": "Extra Bold", + "subfamily_name": "Regular", + "weight": 800, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/JetBrains Mono ExtraBold ExtBd Nerd Font Complete.ttf||919544:1634564302.0": { + "family_name": "JetBrainsMonoExtraBold Nerd Font", + "font-family": "JetBrainsMonoExtraBold Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "800", + "fs_type": 4, + "full_name": "JetBrains Mono ExtraBold ExtBd Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 1, + 9, + 9, + 3, + 1, + 2, + 5, + 0, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/JetBrains Mono ExtraBold ExtBd Nerd Font Complete.ttf", + "preferred_family_name": "JetBrainsMonoExtraBold Nerd Font", + "preferred_subfamily_name": "Extra Bold", + "subfamily_name": "Regular", + "weight": 800, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/JetBrains Mono Italic Nerd Font Complete Mono.ttf||912148:1634564302.0": { + "family_name": "JetBrainsMono Nerd Font Mono", + "font-family": "JetBrainsMono Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 4, + "full_name": "JetBrains Mono Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 1, + 5, + 9, + 2, + 1, + 2, + 5, + 0, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/JetBrains Mono Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "JetBrainsMono Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/JetBrains Mono Italic Nerd Font Complete.ttf||921120:1634564302.0": { + "family_name": "JetBrainsMono Nerd Font", + "font-family": "JetBrainsMono Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 4, + "full_name": "JetBrains Mono Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 1, + 5, + 9, + 2, + 1, + 2, + 5, + 0, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/JetBrains Mono Italic Nerd Font Complete.ttf", + "preferred_family_name": "JetBrainsMono Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/JetBrains Mono Medium Italic Nerd Font Complete Mono.ttf||914040:1634564302.0": { + "family_name": "JetBrainsMono Nerd Font Mono", + "font-family": "JetBrainsMono Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "500", + "fs_type": 4, + "full_name": "JetBrains Mono Medium Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/JetBrains Mono Medium Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "JetBrainsMono Nerd Font Mono", + "preferred_subfamily_name": "Medium Italic", + "subfamily_name": "Italic", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/JetBrains Mono Medium Italic Nerd Font Complete.ttf||923700:1634564302.0": { + "family_name": "JetBrainsMono Nerd Font", + "font-family": "JetBrainsMono Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "500", + "fs_type": 4, + "full_name": "JetBrains Mono Medium Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/JetBrains Mono Medium Italic Nerd Font Complete.ttf", + "preferred_family_name": "JetBrainsMono Nerd Font", + "preferred_subfamily_name": "Medium Italic", + "subfamily_name": "Italic", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/JetBrains Mono Medium Med Ita Nerd Font Complete Mono.ttf||916312:1634564302.0": { + "family_name": "JetBrainsMonoMedium Nerd Font Mono", + "font-family": "JetBrainsMonoMedium Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "500", + "fs_type": 4, + "full_name": "JetBrains Mono Medium Med Ita Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 1, + 6, + 9, + 2, + 1, + 2, + 5, + 0, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/JetBrains Mono Medium Med Ita Nerd Font Complete Mono.ttf", + "preferred_family_name": "JetBrainsMonoMedium Nerd Font Mono", + "preferred_subfamily_name": "Medium Italic", + "subfamily_name": "Italic", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/JetBrains Mono Medium Med Ita Nerd Font Complete.ttf||925984:1634564302.0": { + "family_name": "JetBrainsMonoMedium Nerd Font", + "font-family": "JetBrainsMonoMedium Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "500", + "fs_type": 4, + "full_name": "JetBrains Mono Medium Med Ita Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 1, + 6, + 9, + 2, + 1, + 2, + 5, + 0, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/JetBrains Mono Medium Med Ita Nerd Font Complete.ttf", + "preferred_family_name": "JetBrainsMonoMedium Nerd Font", + "preferred_subfamily_name": "Medium Italic", + "subfamily_name": "Italic", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/JetBrains Mono Medium Medium Nerd Font Complete Mono.ttf||908396:1634564302.0": { + "family_name": "JetBrainsMonoMedium Nerd Font Mono", + "font-family": "JetBrainsMonoMedium Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 4, + "full_name": "JetBrains Mono Medium Medium Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 1, + 6, + 9, + 2, + 1, + 2, + 5, + 0, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/JetBrains Mono Medium Medium Nerd Font Complete Mono.ttf", + "preferred_family_name": "JetBrainsMonoMedium Nerd Font Mono", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/JetBrains Mono Medium Medium Nerd Font Complete.ttf||917364:1634564302.0": { + "family_name": "JetBrainsMonoMedium Nerd Font", + "font-family": "JetBrainsMonoMedium Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 4, + "full_name": "JetBrains Mono Medium Medium Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 1, + 6, + 9, + 2, + 1, + 2, + 5, + 0, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/JetBrains Mono Medium Medium Nerd Font Complete.ttf", + "preferred_family_name": "JetBrainsMonoMedium Nerd Font", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/JetBrains Mono Medium Nerd Font Complete Mono.ttf||907028:1634564302.0": { + "family_name": "JetBrainsMono Nerd Font Mono", + "font-family": "JetBrainsMono Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 4, + "full_name": "JetBrains Mono Medium Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/JetBrains Mono Medium Nerd Font Complete Mono.ttf", + "preferred_family_name": "JetBrainsMono Nerd Font Mono", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/JetBrains Mono Medium Nerd Font Complete.ttf||924648:1634564302.0": { + "family_name": "JetBrainsMono Nerd Font", + "font-family": "JetBrainsMono Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 4, + "full_name": "JetBrains Mono Medium Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/JetBrains Mono Medium Nerd Font Complete.ttf", + "preferred_family_name": "JetBrainsMono Nerd Font", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/JetBrains Mono Regular Nerd Font Complete Mono.ttf||908656:1634564302.0": { + "family_name": "JetBrainsMono Nerd Font Mono", + "font-family": "JetBrainsMono Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 4, + "full_name": "JetBrains Mono Regular Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 1, + 5, + 9, + 2, + 1, + 2, + 5, + 0, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/JetBrains Mono Regular Nerd Font Complete Mono.ttf", + "preferred_family_name": "JetBrainsMono Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/JetBrains Mono Regular Nerd Font Complete.ttf||917624:1634564302.0": { + "family_name": "JetBrainsMono Nerd Font", + "font-family": "JetBrainsMono Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 4, + "full_name": "JetBrains Mono Regular Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 1, + 5, + 9, + 2, + 1, + 2, + 5, + 0, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/JetBrains Mono Regular Nerd Font Complete.ttf", + "preferred_family_name": "JetBrainsMono Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Lekton Nerd Font Complete Mono.ttf||873808:1634564302.0": { + "family_name": "Lekton Nerd Font Mono", + "font-family": "Lekton Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Lekton Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 2, + "panose": [ + 2, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Lekton Nerd Font Complete Mono.ttf", + "preferred_family_name": "Lekton Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Lekton Nerd Font Complete.ttf||899016:1634564302.0": { + "family_name": "Lekton Nerd Font", + "font-family": "Lekton Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Lekton Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 2, + "panose": [ + 2, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Lekton Nerd Font Complete.ttf", + "preferred_family_name": "Lekton Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Lekton-Bold Nerd Font Complete Mono.ttf||873192:1634564302.0": { + "family_name": "Lekton Nerd Font Mono", + "font-family": "Lekton Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Lekton-Bold Nerd Font Complete Mono", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 2, + "panose": [ + 2, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Lekton-Bold Nerd Font Complete Mono.ttf", + "preferred_family_name": "Lekton Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Lekton-Bold Nerd Font Complete.ttf||898396:1634564302.0": { + "family_name": "Lekton Nerd Font", + "font-family": "Lekton Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Lekton-Bold Nerd Font Complete", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 2, + "panose": [ + 2, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Lekton-Bold Nerd Font Complete.ttf", + "preferred_family_name": "Lekton Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Lekton-Italic Nerd Font Complete Mono.ttf||794252:1634564302.0": { + "family_name": "Lekton Nerd Font Mono", + "font-family": "Lekton Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Lekton-Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 2, + "panose": [ + 2, + 0, + 5, + 6, + 3, + 0, + 0, + 9, + 0, + 3 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Lekton-Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "Lekton Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Lekton-Italic Nerd Font Complete.ttf||810328:1634564302.0": { + "family_name": "Lekton Nerd Font", + "font-family": "Lekton Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Lekton-Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 2, + "panose": [ + 2, + 0, + 5, + 6, + 3, + 0, + 0, + 9, + 0, + 3 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Lekton-Italic Nerd Font Complete.ttf", + "preferred_family_name": "Lekton Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Literation Mono Bold Italic Nerd Font Complete Mono.ttf||1077956:1634564302.0": { + "family_name": "LiterationMono Nerd Font Mono", + "font-family": "LiterationMono Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Literation Mono Bold Italic Nerd Font Complete Mono", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 7, + 7, + 9, + 2, + 2, + 5, + 9, + 4, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Literation Mono Bold Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "LiterationMono Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Literation Mono Bold Italic Nerd Font Complete.ttf||1110816:1634564302.0": { + "family_name": "LiterationMono Nerd Font", + "font-family": "LiterationMono Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Literation Mono Bold Italic Nerd Font Complete", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 7, + 7, + 9, + 2, + 2, + 5, + 9, + 4, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Literation Mono Bold Italic Nerd Font Complete.ttf", + "preferred_family_name": "LiterationMono Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Literation Mono Bold Nerd Font Complete Mono.ttf||1100896:1634564302.0": { + "family_name": "LiterationMono Nerd Font Mono", + "font-family": "LiterationMono Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Literation Mono Bold Nerd Font Complete Mono", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 7, + 7, + 9, + 2, + 2, + 5, + 2, + 4, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Literation Mono Bold Nerd Font Complete Mono.ttf", + "preferred_family_name": "LiterationMono Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Literation Mono Bold Nerd Font Complete.ttf||1133752:1634564302.0": { + "family_name": "LiterationMono Nerd Font", + "font-family": "LiterationMono Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Literation Mono Bold Nerd Font Complete", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 7, + 7, + 9, + 2, + 2, + 5, + 2, + 4, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Literation Mono Bold Nerd Font Complete.ttf", + "preferred_family_name": "LiterationMono Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Literation Mono Italic Nerd Font Complete Mono.ttf||1076208:1634564302.0": { + "family_name": "LiterationMono Nerd Font Mono", + "font-family": "LiterationMono Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Literation Mono Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 7, + 4, + 9, + 2, + 2, + 5, + 9, + 4, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Literation Mono Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "LiterationMono Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Literation Mono Italic Nerd Font Complete.ttf||1109060:1634564302.0": { + "family_name": "LiterationMono Nerd Font", + "font-family": "LiterationMono Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Literation Mono Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 7, + 4, + 9, + 2, + 2, + 5, + 9, + 4, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Literation Mono Italic Nerd Font Complete.ttf", + "preferred_family_name": "LiterationMono Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Literation Mono Nerd Font Complete Mono.ttf||1112952:1634564302.0": { + "family_name": "LiterationMono Nerd Font Mono", + "font-family": "LiterationMono Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Literation Mono Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 7, + 4, + 9, + 2, + 2, + 5, + 2, + 4, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Literation Mono Nerd Font Complete Mono.ttf", + "preferred_family_name": "LiterationMono Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Book", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Literation Mono Nerd Font Complete.ttf||1145812:1634564302.0": { + "family_name": "LiterationMono Nerd Font", + "font-family": "LiterationMono Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Literation Mono Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 7, + 4, + 9, + 2, + 2, + 5, + 2, + 4, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Literation Mono Nerd Font Complete.ttf", + "preferred_family_name": "LiterationMono Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Book", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Literation Sans Bold Italic Nerd Font Complete Mono.ttf||1230488:1634564302.0": { + "family_name": "LiterationSans Nerd Font Mono", + "font-family": "LiterationSans Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Literation Sans Bold Italic Nerd Font Complete Mono", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 7, + 4, + 2, + 2, + 2, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Literation Sans Bold Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "LiterationSans Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Literation Sans Bold Italic Nerd Font Complete.ttf||1236404:1634564302.0": { + "family_name": "LiterationSans Nerd Font", + "font-family": "LiterationSans Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Literation Sans Bold Italic Nerd Font Complete", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 7, + 4, + 2, + 2, + 2, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Literation Sans Bold Italic Nerd Font Complete.ttf", + "preferred_family_name": "LiterationSans Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Literation Sans Bold Nerd Font Complete Mono.ttf||1233884:1634564302.0": { + "family_name": "LiterationSans Nerd Font Mono", + "font-family": "LiterationSans Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Literation Sans Bold Nerd Font Complete Mono", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 7, + 4, + 2, + 2, + 2, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Literation Sans Bold Nerd Font Complete Mono.ttf", + "preferred_family_name": "LiterationSans Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Literation Sans Bold Nerd Font Complete.ttf||1239804:1634564302.0": { + "family_name": "LiterationSans Nerd Font", + "font-family": "LiterationSans Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Literation Sans Bold Nerd Font Complete", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 7, + 4, + 2, + 2, + 2, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Literation Sans Bold Nerd Font Complete.ttf", + "preferred_family_name": "LiterationSans Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Literation Sans Italic Nerd Font Complete Mono.ttf||1236588:1634564302.0": { + "family_name": "LiterationSans Nerd Font Mono", + "font-family": "LiterationSans Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Literation Sans Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 6, + 4, + 2, + 2, + 2, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Literation Sans Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "LiterationSans Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Literation Sans Italic Nerd Font Complete.ttf||1242076:1634564302.0": { + "family_name": "LiterationSans Nerd Font", + "font-family": "LiterationSans Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Literation Sans Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 6, + 4, + 2, + 2, + 2, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Literation Sans Italic Nerd Font Complete.ttf", + "preferred_family_name": "LiterationSans Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Literation Sans Nerd Font Complete Mono.ttf||1231028:1634564302.0": { + "family_name": "LiterationSans Nerd Font Mono", + "font-family": "LiterationSans Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Literation Sans Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 6, + 4, + 2, + 2, + 2, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Literation Sans Nerd Font Complete Mono.ttf", + "preferred_family_name": "LiterationSans Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Book", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Literation Sans Nerd Font Complete.ttf||1236512:1634564302.0": { + "family_name": "LiterationSans Nerd Font", + "font-family": "LiterationSans Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Literation Sans Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 6, + 4, + 2, + 2, + 2, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Literation Sans Nerd Font Complete.ttf", + "preferred_family_name": "LiterationSans Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Book", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Literation Serif Bold Italic Nerd Font Complete Mono.ttf||1191520:1634564302.0": { + "family_name": "LiterationSerif Nerd Font Mono", + "font-family": "LiterationSerif Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Literation Serif Bold Italic Nerd Font Complete Mono", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 2, + 7, + 3, + 6, + 5, + 5, + 9, + 3, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Literation Serif Bold Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "LiterationSerif Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Literation Serif Bold Italic Nerd Font Complete.ttf||1199872:1634564302.0": { + "family_name": "LiterationSerif Nerd Font", + "font-family": "LiterationSerif Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Literation Serif Bold Italic Nerd Font Complete", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 2, + 7, + 3, + 6, + 5, + 5, + 9, + 3, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Literation Serif Bold Italic Nerd Font Complete.ttf", + "preferred_family_name": "LiterationSerif Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Literation Serif Bold Nerd Font Complete Mono.ttf||1187848:1634564302.0": { + "family_name": "LiterationSerif Nerd Font Mono", + "font-family": "LiterationSerif Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Literation Serif Bold Nerd Font Complete Mono", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 2, + 8, + 3, + 7, + 5, + 5, + 2, + 3, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Literation Serif Bold Nerd Font Complete Mono.ttf", + "preferred_family_name": "LiterationSerif Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Literation Serif Bold Nerd Font Complete.ttf||1193712:1634564302.0": { + "family_name": "LiterationSerif Nerd Font", + "font-family": "LiterationSerif Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Literation Serif Bold Nerd Font Complete", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 2, + 8, + 3, + 7, + 5, + 5, + 2, + 3, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Literation Serif Bold Nerd Font Complete.ttf", + "preferred_family_name": "LiterationSerif Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Literation Serif Italic Nerd Font Complete Mono.ttf||1194464:1634564302.0": { + "family_name": "LiterationSerif Nerd Font Mono", + "font-family": "LiterationSerif Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Literation Serif Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 2, + 5, + 3, + 5, + 4, + 5, + 9, + 3, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Literation Serif Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "LiterationSerif Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Literation Serif Italic Nerd Font Complete.ttf||1202796:1634564302.0": { + "family_name": "LiterationSerif Nerd Font", + "font-family": "LiterationSerif Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Literation Serif Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 2, + 5, + 3, + 5, + 4, + 5, + 9, + 3, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Literation Serif Italic Nerd Font Complete.ttf", + "preferred_family_name": "LiterationSerif Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Literation Serif Nerd Font Complete Mono.ttf||1208472:1634564302.0": { + "family_name": "LiterationSerif Nerd Font Mono", + "font-family": "LiterationSerif Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Literation Serif Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 2, + 6, + 3, + 5, + 4, + 5, + 2, + 3, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Literation Serif Nerd Font Complete Mono.ttf", + "preferred_family_name": "LiterationSerif Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Book", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Literation Serif Nerd Font Complete.ttf||1216812:1634564302.0": { + "family_name": "LiterationSerif Nerd Font", + "font-family": "LiterationSerif Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Literation Serif Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 2, + 6, + 3, + 5, + 4, + 5, + 2, + 3, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Literation Serif Nerd Font Complete.ttf", + "preferred_family_name": "LiterationSerif Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Book", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 1c Nerd Font Complete Mono.ttf||2621380:1634564302.0": { + "family_name": "mplus Nerd Font Mono", + "font-family": "mplus Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "M+ 1c Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 5, + 3, + 2, + 2, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 1c Nerd Font Complete Mono.ttf", + "preferred_family_name": "mplus Nerd Font Mono", + "preferred_subfamily_name": "regular", + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 1c Nerd Font Complete.ttf||2640248:1634564302.0": { + "family_name": "mplus Nerd Font", + "font-family": "mplus Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "M+ 1c Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 5, + 3, + 2, + 2, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 1c Nerd Font Complete.ttf", + "preferred_family_name": "mplus Nerd Font", + "preferred_subfamily_name": "regular", + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 1c black Nerd Font Complete Mono.ttf||2638804:1634564302.0": { + "family_name": "mplus Nerd Font Mono", + "font-family": "mplus Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "M+ 1c black Nerd Font Complete Mono", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 8, + 3, + 2, + 2, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 1c black Nerd Font Complete Mono.ttf", + "preferred_family_name": "mplus Nerd Font Mono", + "preferred_subfamily_name": "black", + "subfamily_name": "Regular", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 1c black Nerd Font Complete.ttf||2656832:1634564302.0": { + "family_name": "mplus Nerd Font", + "font-family": "mplus Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "M+ 1c black Nerd Font Complete", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 8, + 3, + 2, + 2, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 1c black Nerd Font Complete.ttf", + "preferred_family_name": "mplus Nerd Font", + "preferred_subfamily_name": "black", + "subfamily_name": "Regular", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 1c bold Nerd Font Complete Mono.ttf||2629412:1634564302.0": { + "family_name": "mplus Nerd Font Mono", + "font-family": "mplus Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "M+ 1c bold Nerd Font Complete Mono", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 7, + 3, + 2, + 2, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 1c bold Nerd Font Complete Mono.ttf", + "preferred_family_name": "mplus Nerd Font Mono", + "preferred_subfamily_name": "bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 1c bold Nerd Font Complete.ttf||2648132:1634564302.0": { + "family_name": "mplus Nerd Font", + "font-family": "mplus Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "M+ 1c bold Nerd Font Complete", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 7, + 3, + 2, + 2, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 1c bold Nerd Font Complete.ttf", + "preferred_family_name": "mplus Nerd Font", + "preferred_subfamily_name": "bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 1c heavy Nerd Font Complete Mono.ttf||2637116:1634564302.0": { + "family_name": "mplus Nerd Font Mono", + "font-family": "mplus Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "M+ 1c heavy Nerd Font Complete Mono", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 8, + 3, + 2, + 2, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 1c heavy Nerd Font Complete Mono.ttf", + "preferred_family_name": "mplus Nerd Font Mono", + "preferred_subfamily_name": "heavy", + "subfamily_name": "Regular", + "weight": 800, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 1c heavy Nerd Font Complete.ttf||2655792:1634564302.0": { + "family_name": "mplus Nerd Font", + "font-family": "mplus Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "M+ 1c heavy Nerd Font Complete", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 8, + 3, + 2, + 2, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 1c heavy Nerd Font Complete.ttf", + "preferred_family_name": "mplus Nerd Font", + "preferred_subfamily_name": "heavy", + "subfamily_name": "Regular", + "weight": 800, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 1c light Nerd Font Complete Mono.ttf||2629964:1634564302.0": { + "family_name": "mplus Nerd Font Mono", + "font-family": "mplus Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "M+ 1c light Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 4, + 3, + 2, + 2, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 1c light Nerd Font Complete Mono.ttf", + "preferred_family_name": "mplus Nerd Font Mono", + "preferred_subfamily_name": "light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 1c light Nerd Font Complete.ttf||2649012:1634564302.0": { + "family_name": "mplus Nerd Font", + "font-family": "mplus Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "M+ 1c light Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 4, + 3, + 2, + 2, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 1c light Nerd Font Complete.ttf", + "preferred_family_name": "mplus Nerd Font", + "preferred_subfamily_name": "light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 1c medium Nerd Font Complete Mono.ttf||2622032:1634564302.0": { + "family_name": "mplus Nerd Font Mono", + "font-family": "mplus Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "M+ 1c medium Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 6, + 3, + 2, + 2, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 1c medium Nerd Font Complete Mono.ttf", + "preferred_family_name": "mplus Nerd Font Mono", + "preferred_subfamily_name": "medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 1c medium Nerd Font Complete.ttf||2640888:1634564302.0": { + "family_name": "mplus Nerd Font", + "font-family": "mplus Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "M+ 1c medium Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 6, + 3, + 2, + 2, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 1c medium Nerd Font Complete.ttf", + "preferred_family_name": "mplus Nerd Font", + "preferred_subfamily_name": "medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 1c thin Nerd Font Complete Mono.ttf||2636348:1634564302.0": { + "family_name": "mplus Nerd Font Mono", + "font-family": "mplus Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "M+ 1c thin Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 2, + 3, + 2, + 2, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 1c thin Nerd Font Complete Mono.ttf", + "preferred_family_name": "mplus Nerd Font Mono", + "preferred_subfamily_name": "thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 1c thin Nerd Font Complete.ttf||2655884:1634564302.0": { + "family_name": "mplus Nerd Font", + "font-family": "mplus Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "M+ 1c thin Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 2, + 3, + 2, + 2, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 1c thin Nerd Font Complete.ttf", + "preferred_family_name": "mplus Nerd Font", + "preferred_subfamily_name": "thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 1m Nerd Font Complete Mono.ttf||2494652:1634564302.0": { + "family_name": "mplus Nerd Font Mono", + "font-family": "mplus Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "M+ 1m Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 5, + 9, + 2, + 2, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 1m Nerd Font Complete Mono.ttf", + "preferred_family_name": "mplus Nerd Font Mono", + "preferred_subfamily_name": "regular", + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 1m Nerd Font Complete.ttf||2533704:1634564302.0": { + "family_name": "mplus Nerd Font", + "font-family": "mplus Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "M+ 1m Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 5, + 9, + 2, + 2, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 1m Nerd Font Complete.ttf", + "preferred_family_name": "mplus Nerd Font", + "preferred_subfamily_name": "regular", + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 1m bold Nerd Font Complete Mono.ttf||2501172:1634564302.0": { + "family_name": "mplus Nerd Font Mono", + "font-family": "mplus Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "M+ 1m bold Nerd Font Complete Mono", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 7, + 9, + 2, + 2, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 1m bold Nerd Font Complete Mono.ttf", + "preferred_family_name": "mplus Nerd Font Mono", + "preferred_subfamily_name": "bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 1m bold Nerd Font Complete.ttf||2540224:1634564302.0": { + "family_name": "mplus Nerd Font", + "font-family": "mplus Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "M+ 1m bold Nerd Font Complete", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 7, + 9, + 2, + 2, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 1m bold Nerd Font Complete.ttf", + "preferred_family_name": "mplus Nerd Font", + "preferred_subfamily_name": "bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 1m light Nerd Font Complete Mono.ttf||2502464:1634564302.0": { + "family_name": "mplus Nerd Font Mono", + "font-family": "mplus Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "M+ 1m light Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 4, + 9, + 2, + 2, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 1m light Nerd Font Complete Mono.ttf", + "preferred_family_name": "mplus Nerd Font Mono", + "preferred_subfamily_name": "light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 1m light Nerd Font Complete.ttf||2541516:1634564302.0": { + "family_name": "mplus Nerd Font", + "font-family": "mplus Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "M+ 1m light Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 4, + 9, + 2, + 2, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 1m light Nerd Font Complete.ttf", + "preferred_family_name": "mplus Nerd Font", + "preferred_subfamily_name": "light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 1m medium Nerd Font Complete Mono.ttf||2494416:1634564302.0": { + "family_name": "mplus Nerd Font Mono", + "font-family": "mplus Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "M+ 1m medium Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 6, + 9, + 2, + 2, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 1m medium Nerd Font Complete Mono.ttf", + "preferred_family_name": "mplus Nerd Font Mono", + "preferred_subfamily_name": "medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 1m medium Nerd Font Complete.ttf||2533468:1634564302.0": { + "family_name": "mplus Nerd Font", + "font-family": "mplus Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "M+ 1m medium Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 6, + 9, + 2, + 2, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 1m medium Nerd Font Complete.ttf", + "preferred_family_name": "mplus Nerd Font", + "preferred_subfamily_name": "medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 1m thin Nerd Font Complete Mono.ttf||2509408:1634564302.0": { + "family_name": "mplus Nerd Font Mono", + "font-family": "mplus Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "M+ 1m thin Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 2, + 9, + 2, + 2, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 1m thin Nerd Font Complete Mono.ttf", + "preferred_family_name": "mplus Nerd Font Mono", + "preferred_subfamily_name": "thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 1m thin Nerd Font Complete.ttf||2548464:1634564302.0": { + "family_name": "mplus Nerd Font", + "font-family": "mplus Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "M+ 1m thin Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 2, + 9, + 2, + 2, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 1m thin Nerd Font Complete.ttf", + "preferred_family_name": "mplus Nerd Font", + "preferred_subfamily_name": "thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 1mn Nerd Font Complete Mono.ttf||2492052:1634564302.0": { + "family_name": "mplus Nerd Font Mono", + "font-family": "mplus Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "M+ 1mn Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 5, + 9, + 2, + 2, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 1mn Nerd Font Complete Mono.ttf", + "preferred_family_name": "mplus Nerd Font Mono", + "preferred_subfamily_name": "regular", + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 1mn Nerd Font Complete.ttf||2531104:1634564302.0": { + "family_name": "mplus Nerd Font", + "font-family": "mplus Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "M+ 1mn Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 5, + 9, + 2, + 2, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 1mn Nerd Font Complete.ttf", + "preferred_family_name": "mplus Nerd Font", + "preferred_subfamily_name": "regular", + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 1mn bold Nerd Font Complete Mono.ttf||2500224:1634564302.0": { + "family_name": "mplus Nerd Font Mono", + "font-family": "mplus Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "M+ 1mn bold Nerd Font Complete Mono", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 7, + 9, + 2, + 2, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 1mn bold Nerd Font Complete Mono.ttf", + "preferred_family_name": "mplus Nerd Font Mono", + "preferred_subfamily_name": "bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 1mn bold Nerd Font Complete.ttf||2539276:1634564302.0": { + "family_name": "mplus Nerd Font", + "font-family": "mplus Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "M+ 1mn bold Nerd Font Complete", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 7, + 9, + 2, + 2, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 1mn bold Nerd Font Complete.ttf", + "preferred_family_name": "mplus Nerd Font", + "preferred_subfamily_name": "bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 1mn light Nerd Font Complete Mono.ttf||2499776:1634564302.0": { + "family_name": "mplus Nerd Font Mono", + "font-family": "mplus Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "M+ 1mn light Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 4, + 9, + 2, + 2, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 1mn light Nerd Font Complete Mono.ttf", + "preferred_family_name": "mplus Nerd Font Mono", + "preferred_subfamily_name": "light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 1mn light Nerd Font Complete.ttf||2538832:1634564302.0": { + "family_name": "mplus Nerd Font", + "font-family": "mplus Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "M+ 1mn light Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 4, + 9, + 2, + 2, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 1mn light Nerd Font Complete.ttf", + "preferred_family_name": "mplus Nerd Font", + "preferred_subfamily_name": "light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 1mn medium Nerd Font Complete Mono.ttf||2493192:1634564302.0": { + "family_name": "mplus Nerd Font Mono", + "font-family": "mplus Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "M+ 1mn medium Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 6, + 9, + 2, + 2, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 1mn medium Nerd Font Complete Mono.ttf", + "preferred_family_name": "mplus Nerd Font Mono", + "preferred_subfamily_name": "medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 1mn medium Nerd Font Complete.ttf||2532244:1634564302.0": { + "family_name": "mplus Nerd Font", + "font-family": "mplus Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "M+ 1mn medium Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 6, + 9, + 2, + 2, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 1mn medium Nerd Font Complete.ttf", + "preferred_family_name": "mplus Nerd Font", + "preferred_subfamily_name": "medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 1mn thin Nerd Font Complete Mono.ttf||2506728:1634564302.0": { + "family_name": "mplus Nerd Font Mono", + "font-family": "mplus Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "M+ 1mn thin Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 2, + 9, + 2, + 2, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 1mn thin Nerd Font Complete Mono.ttf", + "preferred_family_name": "mplus Nerd Font Mono", + "preferred_subfamily_name": "thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 1mn thin Nerd Font Complete.ttf||2545780:1634564302.0": { + "family_name": "mplus Nerd Font", + "font-family": "mplus Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "M+ 1mn thin Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 2, + 9, + 2, + 2, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 1mn thin Nerd Font Complete.ttf", + "preferred_family_name": "mplus Nerd Font", + "preferred_subfamily_name": "thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 1p Nerd Font Complete Mono.ttf||2624084:1634564302.0": { + "family_name": "mplus Nerd Font Mono", + "font-family": "mplus Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "M+ 1p Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 5, + 3, + 2, + 2, + 3, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 1p Nerd Font Complete Mono.ttf", + "preferred_family_name": "mplus Nerd Font Mono", + "preferred_subfamily_name": "regular", + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 1p Nerd Font Complete.ttf||2641864:1634564302.0": { + "family_name": "mplus Nerd Font", + "font-family": "mplus Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "M+ 1p Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 5, + 3, + 2, + 2, + 3, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 1p Nerd Font Complete.ttf", + "preferred_family_name": "mplus Nerd Font", + "preferred_subfamily_name": "regular", + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 1p black Nerd Font Complete Mono.ttf||2641156:1634564302.0": { + "family_name": "mplus Nerd Font Mono", + "font-family": "mplus Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "M+ 1p black Nerd Font Complete Mono", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 8, + 3, + 2, + 2, + 3, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 1p black Nerd Font Complete Mono.ttf", + "preferred_family_name": "mplus Nerd Font Mono", + "preferred_subfamily_name": "black", + "subfamily_name": "Regular", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 1p black Nerd Font Complete.ttf||2658460:1634564302.0": { + "family_name": "mplus Nerd Font", + "font-family": "mplus Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "M+ 1p black Nerd Font Complete", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 8, + 3, + 2, + 2, + 3, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 1p black Nerd Font Complete.ttf", + "preferred_family_name": "mplus Nerd Font", + "preferred_subfamily_name": "black", + "subfamily_name": "Regular", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 1p bold Nerd Font Complete Mono.ttf||2632440:1634564302.0": { + "family_name": "mplus Nerd Font Mono", + "font-family": "mplus Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "M+ 1p bold Nerd Font Complete Mono", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 7, + 3, + 2, + 2, + 3, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 1p bold Nerd Font Complete Mono.ttf", + "preferred_family_name": "mplus Nerd Font Mono", + "preferred_subfamily_name": "bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 1p bold Nerd Font Complete.ttf||2649900:1634564302.0": { + "family_name": "mplus Nerd Font", + "font-family": "mplus Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "M+ 1p bold Nerd Font Complete", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 7, + 3, + 2, + 2, + 3, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 1p bold Nerd Font Complete.ttf", + "preferred_family_name": "mplus Nerd Font", + "preferred_subfamily_name": "bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 1p heavy Nerd Font Complete Mono.ttf||2640128:1634564302.0": { + "family_name": "mplus Nerd Font Mono", + "font-family": "mplus Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "M+ 1p heavy Nerd Font Complete Mono", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 8, + 3, + 2, + 2, + 3, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 1p heavy Nerd Font Complete Mono.ttf", + "preferred_family_name": "mplus Nerd Font Mono", + "preferred_subfamily_name": "heavy", + "subfamily_name": "Regular", + "weight": 800, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 1p heavy Nerd Font Complete.ttf||2657488:1634564302.0": { + "family_name": "mplus Nerd Font", + "font-family": "mplus Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "M+ 1p heavy Nerd Font Complete", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 8, + 3, + 2, + 2, + 3, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 1p heavy Nerd Font Complete.ttf", + "preferred_family_name": "mplus Nerd Font", + "preferred_subfamily_name": "heavy", + "subfamily_name": "Regular", + "weight": 800, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 1p light Nerd Font Complete Mono.ttf||2632072:1634564302.0": { + "family_name": "mplus Nerd Font Mono", + "font-family": "mplus Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "M+ 1p light Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 4, + 2, + 2, + 2, + 3, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 1p light Nerd Font Complete Mono.ttf", + "preferred_family_name": "mplus Nerd Font Mono", + "preferred_subfamily_name": "light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 1p light Nerd Font Complete.ttf||2650212:1634564302.0": { + "family_name": "mplus Nerd Font", + "font-family": "mplus Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "M+ 1p light Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 4, + 2, + 2, + 2, + 3, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 1p light Nerd Font Complete.ttf", + "preferred_family_name": "mplus Nerd Font", + "preferred_subfamily_name": "light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 1p medium Nerd Font Complete Mono.ttf||2624676:1634564302.0": { + "family_name": "mplus Nerd Font Mono", + "font-family": "mplus Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "M+ 1p medium Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 6, + 3, + 2, + 2, + 3, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 1p medium Nerd Font Complete Mono.ttf", + "preferred_family_name": "mplus Nerd Font Mono", + "preferred_subfamily_name": "medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 1p medium Nerd Font Complete.ttf||2642272:1634564302.0": { + "family_name": "mplus Nerd Font", + "font-family": "mplus Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "M+ 1p medium Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 6, + 3, + 2, + 2, + 3, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 1p medium Nerd Font Complete.ttf", + "preferred_family_name": "mplus Nerd Font", + "preferred_subfamily_name": "medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 1p thin Nerd Font Complete Mono.ttf||2636944:1634564302.0": { + "family_name": "mplus Nerd Font Mono", + "font-family": "mplus Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "M+ 1p thin Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 2, + 2, + 2, + 2, + 3, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 1p thin Nerd Font Complete Mono.ttf", + "preferred_family_name": "mplus Nerd Font Mono", + "preferred_subfamily_name": "thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 1p thin Nerd Font Complete.ttf||2655528:1634564302.0": { + "family_name": "mplus Nerd Font", + "font-family": "mplus Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "M+ 1p thin Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 2, + 2, + 2, + 2, + 3, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 1p thin Nerd Font Complete.ttf", + "preferred_family_name": "mplus Nerd Font", + "preferred_subfamily_name": "thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 2c Nerd Font Complete Mono.ttf||2621768:1634564302.0": { + "family_name": "mplus Nerd Font Mono", + "font-family": "mplus Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "M+ 2c Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 5, + 3, + 2, + 2, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 2c Nerd Font Complete Mono.ttf", + "preferred_family_name": "mplus Nerd Font Mono", + "preferred_subfamily_name": "regular", + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 2c Nerd Font Complete.ttf||2640636:1634564302.0": { + "family_name": "mplus Nerd Font", + "font-family": "mplus Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "M+ 2c Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 5, + 3, + 2, + 2, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 2c Nerd Font Complete.ttf", + "preferred_family_name": "mplus Nerd Font", + "preferred_subfamily_name": "regular", + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 2c black Nerd Font Complete Mono.ttf||2643268:1634564302.0": { + "family_name": "mplus Nerd Font Mono", + "font-family": "mplus Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "M+ 2c black Nerd Font Complete Mono", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 8, + 3, + 2, + 2, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 2c black Nerd Font Complete Mono.ttf", + "preferred_family_name": "mplus Nerd Font Mono", + "preferred_subfamily_name": "black", + "subfamily_name": "Regular", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 2c black Nerd Font Complete.ttf||2661296:1634564302.0": { + "family_name": "mplus Nerd Font", + "font-family": "mplus Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "M+ 2c black Nerd Font Complete", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 8, + 3, + 2, + 2, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 2c black Nerd Font Complete.ttf", + "preferred_family_name": "mplus Nerd Font", + "preferred_subfamily_name": "black", + "subfamily_name": "Regular", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 2c bold Nerd Font Complete Mono.ttf||2629420:1634564302.0": { + "family_name": "mplus Nerd Font Mono", + "font-family": "mplus Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "M+ 2c bold Nerd Font Complete Mono", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 7, + 3, + 2, + 2, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 2c bold Nerd Font Complete Mono.ttf", + "preferred_family_name": "mplus Nerd Font Mono", + "preferred_subfamily_name": "bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 2c bold Nerd Font Complete.ttf||2648140:1634564302.0": { + "family_name": "mplus Nerd Font", + "font-family": "mplus Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "M+ 2c bold Nerd Font Complete", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 7, + 3, + 2, + 2, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 2c bold Nerd Font Complete.ttf", + "preferred_family_name": "mplus Nerd Font", + "preferred_subfamily_name": "bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 2c heavy Nerd Font Complete Mono.ttf||2637452:1634564302.0": { + "family_name": "mplus Nerd Font Mono", + "font-family": "mplus Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "M+ 2c heavy Nerd Font Complete Mono", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 8, + 3, + 2, + 2, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 2c heavy Nerd Font Complete Mono.ttf", + "preferred_family_name": "mplus Nerd Font Mono", + "preferred_subfamily_name": "heavy", + "subfamily_name": "Regular", + "weight": 800, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 2c heavy Nerd Font Complete.ttf||2656128:1634564302.0": { + "family_name": "mplus Nerd Font", + "font-family": "mplus Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "M+ 2c heavy Nerd Font Complete", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 8, + 3, + 2, + 2, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 2c heavy Nerd Font Complete.ttf", + "preferred_family_name": "mplus Nerd Font", + "preferred_subfamily_name": "heavy", + "subfamily_name": "Regular", + "weight": 800, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 2c light Nerd Font Complete Mono.ttf||2629804:1634564302.0": { + "family_name": "mplus Nerd Font Mono", + "font-family": "mplus Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "M+ 2c light Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 4, + 3, + 2, + 2, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 2c light Nerd Font Complete Mono.ttf", + "preferred_family_name": "mplus Nerd Font Mono", + "preferred_subfamily_name": "light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 2c light Nerd Font Complete.ttf||2648852:1634564302.0": { + "family_name": "mplus Nerd Font", + "font-family": "mplus Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "M+ 2c light Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 4, + 3, + 2, + 2, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 2c light Nerd Font Complete.ttf", + "preferred_family_name": "mplus Nerd Font", + "preferred_subfamily_name": "light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 2c medium Nerd Font Complete Mono.ttf||2621500:1634564302.0": { + "family_name": "mplus Nerd Font Mono", + "font-family": "mplus Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "M+ 2c medium Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 6, + 3, + 2, + 2, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 2c medium Nerd Font Complete Mono.ttf", + "preferred_family_name": "mplus Nerd Font Mono", + "preferred_subfamily_name": "medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 2c medium Nerd Font Complete.ttf||2640356:1634564302.0": { + "family_name": "mplus Nerd Font", + "font-family": "mplus Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "M+ 2c medium Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 6, + 3, + 2, + 2, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 2c medium Nerd Font Complete.ttf", + "preferred_family_name": "mplus Nerd Font", + "preferred_subfamily_name": "medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 2c thin Nerd Font Complete Mono.ttf||2637908:1634564302.0": { + "family_name": "mplus Nerd Font Mono", + "font-family": "mplus Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "M+ 2c thin Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 2, + 3, + 2, + 2, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 2c thin Nerd Font Complete Mono.ttf", + "preferred_family_name": "mplus Nerd Font Mono", + "preferred_subfamily_name": "thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 2c thin Nerd Font Complete.ttf||2657444:1634564302.0": { + "family_name": "mplus Nerd Font", + "font-family": "mplus Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "M+ 2c thin Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 2, + 3, + 2, + 2, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 2c thin Nerd Font Complete.ttf", + "preferred_family_name": "mplus Nerd Font", + "preferred_subfamily_name": "thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 2m Nerd Font Complete Mono.ttf||2494340:1634564302.0": { + "family_name": "mplus Nerd Font Mono", + "font-family": "mplus Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "M+ 2m Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 5, + 9, + 2, + 2, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 2m Nerd Font Complete Mono.ttf", + "preferred_family_name": "mplus Nerd Font Mono", + "preferred_subfamily_name": "regular", + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 2m Nerd Font Complete.ttf||2533392:1634564302.0": { + "family_name": "mplus Nerd Font", + "font-family": "mplus Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "M+ 2m Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 5, + 9, + 2, + 2, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 2m Nerd Font Complete.ttf", + "preferred_family_name": "mplus Nerd Font", + "preferred_subfamily_name": "regular", + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 2m bold Nerd Font Complete Mono.ttf||2500432:1634564302.0": { + "family_name": "mplus Nerd Font Mono", + "font-family": "mplus Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "M+ 2m bold Nerd Font Complete Mono", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 7, + 9, + 2, + 2, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 2m bold Nerd Font Complete Mono.ttf", + "preferred_family_name": "mplus Nerd Font Mono", + "preferred_subfamily_name": "bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 2m bold Nerd Font Complete.ttf||2539484:1634564302.0": { + "family_name": "mplus Nerd Font", + "font-family": "mplus Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "M+ 2m bold Nerd Font Complete", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 7, + 9, + 2, + 2, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 2m bold Nerd Font Complete.ttf", + "preferred_family_name": "mplus Nerd Font", + "preferred_subfamily_name": "bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 2m light Nerd Font Complete Mono.ttf||2501412:1634564302.0": { + "family_name": "mplus Nerd Font Mono", + "font-family": "mplus Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "M+ 2m light Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 4, + 9, + 2, + 2, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 2m light Nerd Font Complete Mono.ttf", + "preferred_family_name": "mplus Nerd Font Mono", + "preferred_subfamily_name": "light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 2m light Nerd Font Complete.ttf||2540464:1634564302.0": { + "family_name": "mplus Nerd Font", + "font-family": "mplus Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "M+ 2m light Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 4, + 9, + 2, + 2, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 2m light Nerd Font Complete.ttf", + "preferred_family_name": "mplus Nerd Font", + "preferred_subfamily_name": "light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 2m medium Nerd Font Complete Mono.ttf||2493156:1634564302.0": { + "family_name": "mplus Nerd Font Mono", + "font-family": "mplus Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "M+ 2m medium Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 6, + 9, + 2, + 2, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 2m medium Nerd Font Complete Mono.ttf", + "preferred_family_name": "mplus Nerd Font Mono", + "preferred_subfamily_name": "medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 2m medium Nerd Font Complete.ttf||2532208:1634564302.0": { + "family_name": "mplus Nerd Font", + "font-family": "mplus Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "M+ 2m medium Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 6, + 9, + 2, + 2, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 2m medium Nerd Font Complete.ttf", + "preferred_family_name": "mplus Nerd Font", + "preferred_subfamily_name": "medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 2m thin Nerd Font Complete Mono.ttf||2509744:1634564302.0": { + "family_name": "mplus Nerd Font Mono", + "font-family": "mplus Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "M+ 2m thin Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 2, + 9, + 2, + 2, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 2m thin Nerd Font Complete Mono.ttf", + "preferred_family_name": "mplus Nerd Font Mono", + "preferred_subfamily_name": "thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 2m thin Nerd Font Complete.ttf||2548800:1634564302.0": { + "family_name": "mplus Nerd Font", + "font-family": "mplus Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "M+ 2m thin Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 2, + 9, + 2, + 2, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 2m thin Nerd Font Complete.ttf", + "preferred_family_name": "mplus Nerd Font", + "preferred_subfamily_name": "thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 2p Nerd Font Complete Mono.ttf||2624624:1634564302.0": { + "family_name": "mplus Nerd Font Mono", + "font-family": "mplus Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "M+ 2p Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 5, + 3, + 2, + 2, + 3, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 2p Nerd Font Complete Mono.ttf", + "preferred_family_name": "mplus Nerd Font Mono", + "preferred_subfamily_name": "regular", + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 2p Nerd Font Complete.ttf||2642404:1634564302.0": { + "family_name": "mplus Nerd Font", + "font-family": "mplus Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "M+ 2p Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 5, + 3, + 2, + 2, + 3, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 2p Nerd Font Complete.ttf", + "preferred_family_name": "mplus Nerd Font", + "preferred_subfamily_name": "regular", + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 2p black Nerd Font Complete Mono.ttf||2645772:1634564302.0": { + "family_name": "mplus Nerd Font Mono", + "font-family": "mplus Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "M+ 2p black Nerd Font Complete Mono", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 8, + 3, + 2, + 2, + 3, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 2p black Nerd Font Complete Mono.ttf", + "preferred_family_name": "mplus Nerd Font Mono", + "preferred_subfamily_name": "black", + "subfamily_name": "Regular", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 2p black Nerd Font Complete.ttf||2663076:1634564302.0": { + "family_name": "mplus Nerd Font", + "font-family": "mplus Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "M+ 2p black Nerd Font Complete", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 8, + 3, + 2, + 2, + 3, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 2p black Nerd Font Complete.ttf", + "preferred_family_name": "mplus Nerd Font", + "preferred_subfamily_name": "black", + "subfamily_name": "Regular", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 2p bold Nerd Font Complete Mono.ttf||2632696:1634564302.0": { + "family_name": "mplus Nerd Font Mono", + "font-family": "mplus Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "M+ 2p bold Nerd Font Complete Mono", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 7, + 3, + 2, + 2, + 3, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 2p bold Nerd Font Complete Mono.ttf", + "preferred_family_name": "mplus Nerd Font Mono", + "preferred_subfamily_name": "bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 2p bold Nerd Font Complete.ttf||2650156:1634564302.0": { + "family_name": "mplus Nerd Font", + "font-family": "mplus Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "M+ 2p bold Nerd Font Complete", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 7, + 3, + 2, + 2, + 3, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 2p bold Nerd Font Complete.ttf", + "preferred_family_name": "mplus Nerd Font", + "preferred_subfamily_name": "bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 2p heavy Nerd Font Complete Mono.ttf||2640696:1634564302.0": { + "family_name": "mplus Nerd Font Mono", + "font-family": "mplus Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "M+ 2p heavy Nerd Font Complete Mono", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 8, + 3, + 2, + 2, + 3, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 2p heavy Nerd Font Complete Mono.ttf", + "preferred_family_name": "mplus Nerd Font Mono", + "preferred_subfamily_name": "heavy", + "subfamily_name": "Regular", + "weight": 800, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 2p heavy Nerd Font Complete.ttf||2658056:1634564302.0": { + "family_name": "mplus Nerd Font", + "font-family": "mplus Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "M+ 2p heavy Nerd Font Complete", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 8, + 3, + 2, + 2, + 3, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 2p heavy Nerd Font Complete.ttf", + "preferred_family_name": "mplus Nerd Font", + "preferred_subfamily_name": "heavy", + "subfamily_name": "Regular", + "weight": 800, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 2p light Nerd Font Complete Mono.ttf||2632016:1634564302.0": { + "family_name": "mplus Nerd Font Mono", + "font-family": "mplus Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "M+ 2p light Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 4, + 2, + 2, + 2, + 3, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 2p light Nerd Font Complete Mono.ttf", + "preferred_family_name": "mplus Nerd Font Mono", + "preferred_subfamily_name": "light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 2p light Nerd Font Complete.ttf||2650156:1634564302.0": { + "family_name": "mplus Nerd Font", + "font-family": "mplus Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "M+ 2p light Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 4, + 2, + 2, + 2, + 3, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 2p light Nerd Font Complete.ttf", + "preferred_family_name": "mplus Nerd Font", + "preferred_subfamily_name": "light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 2p medium Nerd Font Complete Mono.ttf||2624388:1634564302.0": { + "family_name": "mplus Nerd Font Mono", + "font-family": "mplus Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "M+ 2p medium Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 6, + 3, + 2, + 2, + 3, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 2p medium Nerd Font Complete Mono.ttf", + "preferred_family_name": "mplus Nerd Font Mono", + "preferred_subfamily_name": "medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 2p medium Nerd Font Complete.ttf||2641984:1634564302.0": { + "family_name": "mplus Nerd Font", + "font-family": "mplus Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "M+ 2p medium Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 6, + 3, + 2, + 2, + 3, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 2p medium Nerd Font Complete.ttf", + "preferred_family_name": "mplus Nerd Font", + "preferred_subfamily_name": "medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 2p thin Nerd Font Complete Mono.ttf||2638708:1634564302.0": { + "family_name": "mplus Nerd Font Mono", + "font-family": "mplus Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "M+ 2p thin Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 2, + 2, + 2, + 2, + 3, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 2p thin Nerd Font Complete Mono.ttf", + "preferred_family_name": "mplus Nerd Font Mono", + "preferred_subfamily_name": "thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 2p thin Nerd Font Complete.ttf||2657292:1634564302.0": { + "family_name": "mplus Nerd Font", + "font-family": "mplus Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "M+ 2p thin Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 11, + 2, + 2, + 2, + 2, + 3, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/M+ 2p thin Nerd Font Complete.ttf", + "preferred_family_name": "mplus Nerd Font", + "preferred_subfamily_name": "thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Meslo LG L Bold Italic Nerd Font Complete Mono.ttf||1249284:1634564302.0": { + "family_name": "MesloLGL Nerd Font Mono", + "font-family": "MesloLGL Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Meslo LG L Bold Italic Nerd Font Complete Mono", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 7, + 9, + 3, + 3, + 4, + 11, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Meslo LG L Bold Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "MesloLGL Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Meslo LG L Bold Italic Nerd Font Complete.ttf||1281648:1634564302.0": { + "family_name": "MesloLGL Nerd Font", + "font-family": "MesloLGL Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Meslo LG L Bold Italic Nerd Font Complete", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 7, + 9, + 3, + 3, + 4, + 11, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Meslo LG L Bold Italic Nerd Font Complete.ttf", + "preferred_family_name": "MesloLGL Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Meslo LG L Bold Nerd Font Complete Mono.ttf||1291032:1634564302.0": { + "family_name": "MesloLGL Nerd Font Mono", + "font-family": "MesloLGL Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Meslo LG L Bold Nerd Font Complete Mono", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 7, + 9, + 3, + 6, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Meslo LG L Bold Nerd Font Complete Mono.ttf", + "preferred_family_name": "MesloLGL Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Meslo LG L Bold Nerd Font Complete.ttf||1323928:1634564302.0": { + "family_name": "MesloLGL Nerd Font", + "font-family": "MesloLGL Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Meslo LG L Bold Nerd Font Complete", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 7, + 9, + 3, + 6, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Meslo LG L Bold Nerd Font Complete.ttf", + "preferred_family_name": "MesloLGL Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Meslo LG L DZ Bold Italic Nerd Font Complete Mono.ttf||1249336:1634564302.0": { + "family_name": "MesloLGLDZ Nerd Font Mono", + "font-family": "MesloLGLDZ Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Meslo LG L DZ Bold Italic Nerd Font Complete Mono", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 7, + 9, + 3, + 3, + 4, + 11, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Meslo LG L DZ Bold Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "MesloLGLDZ Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Meslo LG L DZ Bold Italic Nerd Font Complete.ttf||1281700:1634564302.0": { + "family_name": "MesloLGLDZ Nerd Font", + "font-family": "MesloLGLDZ Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Meslo LG L DZ Bold Italic Nerd Font Complete", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 7, + 9, + 3, + 3, + 4, + 11, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Meslo LG L DZ Bold Italic Nerd Font Complete.ttf", + "preferred_family_name": "MesloLGLDZ Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Meslo LG L DZ Bold Nerd Font Complete Mono.ttf||1291092:1634564302.0": { + "family_name": "MesloLGLDZ Nerd Font Mono", + "font-family": "MesloLGLDZ Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Meslo LG L DZ Bold Nerd Font Complete Mono", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 7, + 9, + 3, + 6, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Meslo LG L DZ Bold Nerd Font Complete Mono.ttf", + "preferred_family_name": "MesloLGLDZ Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Meslo LG L DZ Bold Nerd Font Complete.ttf||1323984:1634564302.0": { + "family_name": "MesloLGLDZ Nerd Font", + "font-family": "MesloLGLDZ Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Meslo LG L DZ Bold Nerd Font Complete", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 7, + 9, + 3, + 6, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Meslo LG L DZ Bold Nerd Font Complete.ttf", + "preferred_family_name": "MesloLGLDZ Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Meslo LG L DZ Italic Nerd Font Complete Mono.ttf||1240616:1634564302.0": { + "family_name": "MesloLGLDZ Nerd Font Mono", + "font-family": "MesloLGLDZ Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Meslo LG L DZ Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 6, + 9, + 3, + 3, + 4, + 11, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Meslo LG L DZ Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "MesloLGLDZ Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Meslo LG L DZ Italic Nerd Font Complete.ttf||1273232:1634564302.0": { + "family_name": "MesloLGLDZ Nerd Font", + "font-family": "MesloLGLDZ Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Meslo LG L DZ Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 6, + 9, + 3, + 3, + 4, + 11, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Meslo LG L DZ Italic Nerd Font Complete.ttf", + "preferred_family_name": "MesloLGLDZ Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Meslo LG L DZ Regular Nerd Font Complete Mono.ttf||1281592:1634564302.0": { + "family_name": "MesloLGLDZ Nerd Font Mono", + "font-family": "MesloLGLDZ Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Meslo LG L DZ Regular Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 6, + 9, + 3, + 8, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Meslo LG L DZ Regular Nerd Font Complete Mono.ttf", + "preferred_family_name": "MesloLGLDZ Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Meslo LG L DZ Regular Nerd Font Complete.ttf||1314740:1634564302.0": { + "family_name": "MesloLGLDZ Nerd Font", + "font-family": "MesloLGLDZ Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Meslo LG L DZ Regular Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 6, + 9, + 3, + 8, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Meslo LG L DZ Regular Nerd Font Complete.ttf", + "preferred_family_name": "MesloLGLDZ Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Meslo LG L Italic Nerd Font Complete Mono.ttf||1240556:1634564302.0": { + "family_name": "MesloLGL Nerd Font Mono", + "font-family": "MesloLGL Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Meslo LG L Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 6, + 9, + 3, + 3, + 4, + 11, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Meslo LG L Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "MesloLGL Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Meslo LG L Italic Nerd Font Complete.ttf||1273172:1634564302.0": { + "family_name": "MesloLGL Nerd Font", + "font-family": "MesloLGL Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Meslo LG L Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 6, + 9, + 3, + 3, + 4, + 11, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Meslo LG L Italic Nerd Font Complete.ttf", + "preferred_family_name": "MesloLGL Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Meslo LG L Regular Nerd Font Complete Mono.ttf||1281536:1634564302.0": { + "family_name": "MesloLGL Nerd Font Mono", + "font-family": "MesloLGL Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Meslo LG L Regular Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 6, + 9, + 3, + 8, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Meslo LG L Regular Nerd Font Complete Mono.ttf", + "preferred_family_name": "MesloLGL Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Meslo LG L Regular Nerd Font Complete.ttf||1314684:1634564302.0": { + "family_name": "MesloLGL Nerd Font", + "font-family": "MesloLGL Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Meslo LG L Regular Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 6, + 9, + 3, + 8, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Meslo LG L Regular Nerd Font Complete.ttf", + "preferred_family_name": "MesloLGL Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Meslo LG M Bold Italic Nerd Font Complete Mono.ttf||1249248:1634564302.0": { + "family_name": "MesloLGM Nerd Font Mono", + "font-family": "MesloLGM Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Meslo LG M Bold Italic Nerd Font Complete Mono", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 7, + 9, + 3, + 3, + 4, + 11, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Meslo LG M Bold Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "MesloLGM Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Meslo LG M Bold Italic Nerd Font Complete.ttf||1281624:1634564302.0": { + "family_name": "MesloLGM Nerd Font", + "font-family": "MesloLGM Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Meslo LG M Bold Italic Nerd Font Complete", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 7, + 9, + 3, + 3, + 4, + 11, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Meslo LG M Bold Italic Nerd Font Complete.ttf", + "preferred_family_name": "MesloLGM Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Meslo LG M Bold Nerd Font Complete Mono.ttf||1290996:1634564302.0": { + "family_name": "MesloLGM Nerd Font Mono", + "font-family": "MesloLGM Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Meslo LG M Bold Nerd Font Complete Mono", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 7, + 9, + 3, + 6, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Meslo LG M Bold Nerd Font Complete Mono.ttf", + "preferred_family_name": "MesloLGM Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Meslo LG M Bold Nerd Font Complete.ttf||1323904:1634564302.0": { + "family_name": "MesloLGM Nerd Font", + "font-family": "MesloLGM Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Meslo LG M Bold Nerd Font Complete", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 7, + 9, + 3, + 6, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Meslo LG M Bold Nerd Font Complete.ttf", + "preferred_family_name": "MesloLGM Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Meslo LG M DZ Bold Italic Nerd Font Complete Mono.ttf||1249300:1634564302.0": { + "family_name": "MesloLGMDZ Nerd Font Mono", + "font-family": "MesloLGMDZ Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Meslo LG M DZ Bold Italic Nerd Font Complete Mono", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 7, + 9, + 3, + 3, + 4, + 11, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Meslo LG M DZ Bold Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "MesloLGMDZ Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Meslo LG M DZ Bold Italic Nerd Font Complete.ttf||1281676:1634564302.0": { + "family_name": "MesloLGMDZ Nerd Font", + "font-family": "MesloLGMDZ Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Meslo LG M DZ Bold Italic Nerd Font Complete", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 7, + 9, + 3, + 3, + 4, + 11, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Meslo LG M DZ Bold Italic Nerd Font Complete.ttf", + "preferred_family_name": "MesloLGMDZ Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Meslo LG M DZ Bold Nerd Font Complete Mono.ttf||1291056:1634564302.0": { + "family_name": "MesloLGMDZ Nerd Font Mono", + "font-family": "MesloLGMDZ Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Meslo LG M DZ Bold Nerd Font Complete Mono", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 7, + 9, + 3, + 6, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Meslo LG M DZ Bold Nerd Font Complete Mono.ttf", + "preferred_family_name": "MesloLGMDZ Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Meslo LG M DZ Bold Nerd Font Complete.ttf||1323960:1634564302.0": { + "family_name": "MesloLGMDZ Nerd Font", + "font-family": "MesloLGMDZ Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Meslo LG M DZ Bold Nerd Font Complete", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 7, + 9, + 3, + 6, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Meslo LG M DZ Bold Nerd Font Complete.ttf", + "preferred_family_name": "MesloLGMDZ Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Meslo LG M DZ Italic Nerd Font Complete Mono.ttf||1240580:1634564302.0": { + "family_name": "MesloLGMDZ Nerd Font Mono", + "font-family": "MesloLGMDZ Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Meslo LG M DZ Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 6, + 9, + 3, + 3, + 4, + 11, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Meslo LG M DZ Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "MesloLGMDZ Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Meslo LG M DZ Italic Nerd Font Complete.ttf||1273208:1634564302.0": { + "family_name": "MesloLGMDZ Nerd Font", + "font-family": "MesloLGMDZ Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Meslo LG M DZ Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 6, + 9, + 3, + 3, + 4, + 11, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Meslo LG M DZ Italic Nerd Font Complete.ttf", + "preferred_family_name": "MesloLGMDZ Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Meslo LG M DZ Regular Nerd Font Complete Mono.ttf||1281556:1634564302.0": { + "family_name": "MesloLGMDZ Nerd Font Mono", + "font-family": "MesloLGMDZ Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Meslo LG M DZ Regular Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 6, + 9, + 3, + 8, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Meslo LG M DZ Regular Nerd Font Complete Mono.ttf", + "preferred_family_name": "MesloLGMDZ Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Meslo LG M DZ Regular Nerd Font Complete.ttf||1314716:1634564302.0": { + "family_name": "MesloLGMDZ Nerd Font", + "font-family": "MesloLGMDZ Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Meslo LG M DZ Regular Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 6, + 9, + 3, + 8, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Meslo LG M DZ Regular Nerd Font Complete.ttf", + "preferred_family_name": "MesloLGMDZ Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Meslo LG M Italic Nerd Font Complete Mono.ttf||1240520:1634564302.0": { + "family_name": "MesloLGM Nerd Font Mono", + "font-family": "MesloLGM Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Meslo LG M Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 6, + 9, + 3, + 3, + 4, + 11, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Meslo LG M Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "MesloLGM Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Meslo LG M Italic Nerd Font Complete.ttf||1273148:1634564302.0": { + "family_name": "MesloLGM Nerd Font", + "font-family": "MesloLGM Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Meslo LG M Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 6, + 9, + 3, + 3, + 4, + 11, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Meslo LG M Italic Nerd Font Complete.ttf", + "preferred_family_name": "MesloLGM Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Meslo LG M Regular Nerd Font Complete Mono.ttf||1281500:1634564302.0": { + "family_name": "MesloLGM Nerd Font Mono", + "font-family": "MesloLGM Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Meslo LG M Regular Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 6, + 9, + 3, + 8, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Meslo LG M Regular Nerd Font Complete Mono.ttf", + "preferred_family_name": "MesloLGM Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Meslo LG M Regular Nerd Font Complete.ttf||1314660:1634564302.0": { + "family_name": "MesloLGM Nerd Font", + "font-family": "MesloLGM Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Meslo LG M Regular Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 6, + 9, + 3, + 8, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Meslo LG M Regular Nerd Font Complete.ttf", + "preferred_family_name": "MesloLGM Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Meslo LG S Bold Italic Nerd Font Complete Mono.ttf||1249216:1634564302.0": { + "family_name": "MesloLGS Nerd Font Mono", + "font-family": "MesloLGS Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Meslo LG S Bold Italic Nerd Font Complete Mono", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 7, + 9, + 3, + 3, + 4, + 11, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Meslo LG S Bold Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "MesloLGS Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Meslo LG S Bold Italic Nerd Font Complete.ttf||1281588:1634564302.0": { + "family_name": "MesloLGS Nerd Font", + "font-family": "MesloLGS Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Meslo LG S Bold Italic Nerd Font Complete", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 7, + 9, + 3, + 3, + 4, + 11, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Meslo LG S Bold Italic Nerd Font Complete.ttf", + "preferred_family_name": "MesloLGS Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Meslo LG S Bold Nerd Font Complete Mono.ttf||1290964:1634564302.0": { + "family_name": "MesloLGS Nerd Font Mono", + "font-family": "MesloLGS Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Meslo LG S Bold Nerd Font Complete Mono", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 7, + 9, + 3, + 6, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Meslo LG S Bold Nerd Font Complete Mono.ttf", + "preferred_family_name": "MesloLGS Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Meslo LG S Bold Nerd Font Complete.ttf||1323868:1634564302.0": { + "family_name": "MesloLGS Nerd Font", + "font-family": "MesloLGS Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Meslo LG S Bold Nerd Font Complete", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 7, + 9, + 3, + 6, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Meslo LG S Bold Nerd Font Complete.ttf", + "preferred_family_name": "MesloLGS Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Meslo LG S DZ Bold Italic Nerd Font Complete Mono.ttf||1249268:1634564302.0": { + "family_name": "MesloLGSDZ Nerd Font Mono", + "font-family": "MesloLGSDZ Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Meslo LG S DZ Bold Italic Nerd Font Complete Mono", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 7, + 9, + 3, + 3, + 4, + 11, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Meslo LG S DZ Bold Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "MesloLGSDZ Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Meslo LG S DZ Bold Italic Nerd Font Complete.ttf||1281640:1634564302.0": { + "family_name": "MesloLGSDZ Nerd Font", + "font-family": "MesloLGSDZ Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Meslo LG S DZ Bold Italic Nerd Font Complete", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 7, + 9, + 3, + 3, + 4, + 11, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Meslo LG S DZ Bold Italic Nerd Font Complete.ttf", + "preferred_family_name": "MesloLGSDZ Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Meslo LG S DZ Bold Nerd Font Complete Mono.ttf||1291024:1634564302.0": { + "family_name": "MesloLGSDZ Nerd Font Mono", + "font-family": "MesloLGSDZ Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Meslo LG S DZ Bold Nerd Font Complete Mono", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 7, + 9, + 3, + 6, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Meslo LG S DZ Bold Nerd Font Complete Mono.ttf", + "preferred_family_name": "MesloLGSDZ Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Meslo LG S DZ Bold Nerd Font Complete.ttf||1323924:1634564302.0": { + "family_name": "MesloLGSDZ Nerd Font", + "font-family": "MesloLGSDZ Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Meslo LG S DZ Bold Nerd Font Complete", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 7, + 9, + 3, + 6, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Meslo LG S DZ Bold Nerd Font Complete.ttf", + "preferred_family_name": "MesloLGSDZ Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Meslo LG S DZ Italic Nerd Font Complete Mono.ttf||1240548:1634564302.0": { + "family_name": "MesloLGSDZ Nerd Font Mono", + "font-family": "MesloLGSDZ Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Meslo LG S DZ Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 6, + 9, + 3, + 3, + 4, + 11, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Meslo LG S DZ Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "MesloLGSDZ Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Meslo LG S DZ Italic Nerd Font Complete.ttf||1273172:1634564302.0": { + "family_name": "MesloLGSDZ Nerd Font", + "font-family": "MesloLGSDZ Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Meslo LG S DZ Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 6, + 9, + 3, + 3, + 4, + 11, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Meslo LG S DZ Italic Nerd Font Complete.ttf", + "preferred_family_name": "MesloLGSDZ Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Meslo LG S DZ Regular Nerd Font Complete Mono.ttf||1281524:1634564302.0": { + "family_name": "MesloLGSDZ Nerd Font Mono", + "font-family": "MesloLGSDZ Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Meslo LG S DZ Regular Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 6, + 9, + 3, + 8, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Meslo LG S DZ Regular Nerd Font Complete Mono.ttf", + "preferred_family_name": "MesloLGSDZ Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Meslo LG S DZ Regular Nerd Font Complete.ttf||1314680:1634564302.0": { + "family_name": "MesloLGSDZ Nerd Font", + "font-family": "MesloLGSDZ Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Meslo LG S DZ Regular Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 6, + 9, + 3, + 8, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Meslo LG S DZ Regular Nerd Font Complete.ttf", + "preferred_family_name": "MesloLGSDZ Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Meslo LG S Italic Nerd Font Complete Mono.ttf||1240488:1634564302.0": { + "family_name": "MesloLGS Nerd Font Mono", + "font-family": "MesloLGS Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Meslo LG S Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 6, + 9, + 3, + 3, + 4, + 11, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Meslo LG S Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "MesloLGS Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Meslo LG S Italic Nerd Font Complete.ttf||1273112:1634564302.0": { + "family_name": "MesloLGS Nerd Font", + "font-family": "MesloLGS Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Meslo LG S Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 6, + 9, + 3, + 3, + 4, + 11, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Meslo LG S Italic Nerd Font Complete.ttf", + "preferred_family_name": "MesloLGS Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Meslo LG S Regular Nerd Font Complete Mono.ttf||1281468:1634564302.0": { + "family_name": "MesloLGS Nerd Font Mono", + "font-family": "MesloLGS Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Meslo LG S Regular Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 6, + 9, + 3, + 8, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Meslo LG S Regular Nerd Font Complete Mono.ttf", + "preferred_family_name": "MesloLGS Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Meslo LG S Regular Nerd Font Complete.ttf||1314624:1634564302.0": { + "family_name": "MesloLGS Nerd Font", + "font-family": "MesloLGS Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Meslo LG S Regular Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 6, + 9, + 3, + 8, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Meslo LG S Regular Nerd Font Complete.ttf", + "preferred_family_name": "MesloLGS Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Monoid Bold Nerd Font Complete Mono.ttf||876660:1634564302.0": { + "family_name": "Monoid Nerd Font Mono", + "font-family": "Monoid Nerd Font Mono", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Monoid Bold Nerd Font Complete Mono", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 8, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Monoid Bold Nerd Font Complete Mono.ttf", + "preferred_family_name": "Monoid Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Monoid Bold Nerd Font Complete.ttf||887316:1634564302.0": { + "family_name": "Monoid Nerd Font", + "font-family": "Monoid Nerd Font", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Monoid Bold Nerd Font Complete", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 8, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Monoid Bold Nerd Font Complete.ttf", + "preferred_family_name": "Monoid Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Monoid Italic Nerd Font Complete Mono.ttf||898736:1634564302.0": { + "family_name": "Monoid Nerd Font Mono", + "font-family": "Monoid Nerd Font Mono", + "font-stretch": "semi-condensed", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Monoid Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 9, + 4, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Monoid Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "Monoid Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 400, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Monoid Italic Nerd Font Complete.ttf||909392:1634564302.0": { + "family_name": "Monoid Nerd Font", + "font-family": "Monoid Nerd Font", + "font-stretch": "semi-condensed", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Monoid Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 9, + 4, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Monoid Italic Nerd Font Complete.ttf", + "preferred_family_name": "Monoid Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 400, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Monoid Regular Nerd Font Complete Mono.ttf||886300:1634564302.0": { + "family_name": "Monoid Nerd Font Mono", + "font-family": "Monoid Nerd Font Mono", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Monoid Regular Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 9, + 4, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Monoid Regular Nerd Font Complete Mono.ttf", + "preferred_family_name": "Monoid Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Monoid Regular Nerd Font Complete.ttf||896956:1634564302.0": { + "family_name": "Monoid Nerd Font", + "font-family": "Monoid Nerd Font", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Monoid Regular Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 9, + 4, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Monoid Regular Nerd Font Complete.ttf", + "preferred_family_name": "Monoid Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Monoid Retina Nerd Font Complete Mono.ttf||884960:1634564302.0": { + "family_name": "Monoid Nerd Font Mono", + "font-family": "Monoid Nerd Font Mono", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Monoid Retina Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 3, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Monoid Retina Nerd Font Complete Mono.ttf", + "preferred_family_name": "Monoid Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Retina", + "weight": 300, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Monoid Retina Nerd Font Complete.ttf||895620:1634564302.0": { + "family_name": "Monoid Nerd Font", + "font-family": "Monoid Nerd Font", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Monoid Retina Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 3, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Monoid Retina Nerd Font Complete.ttf", + "preferred_family_name": "Monoid Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Retina", + "weight": 300, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Emoji Nerd Font Complete Mono.ttf||1266144:1634564302.0": { + "family_name": "NotoEmoji Nerd Font Mono", + "font-family": "NotoEmoji Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Emoji Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 9, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Emoji Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoEmoji Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Book", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Emoji Nerd Font Complete.ttf||1254668:1634564302.0": { + "family_name": "NotoEmoji Nerd Font", + "font-family": "NotoEmoji Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Emoji Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 9, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Emoji Nerd Font Complete.ttf", + "preferred_family_name": "NotoEmoji Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Book", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Mono Nerd Font Complete Mono.ttf||930268:1634564302.0": { + "family_name": "NotoMono Nerd Font Mono", + "font-family": "NotoMono Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Mono Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 6, + 9, + 3, + 8, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Mono Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoMono Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Book", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Mono Nerd Font Complete.ttf||950828:1634564302.0": { + "family_name": "NotoMono Nerd Font", + "font-family": "NotoMono Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Mono Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 6, + 9, + 3, + 8, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Mono Nerd Font Complete.ttf", + "preferred_family_name": "NotoMono Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Book", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Condensed Black Italic Nerd Font Complete Mono.ttf||1279988:1634564302.0": { + "family_name": "NotoSans Nerd Font Mono", + "font-family": "NotoSans Nerd Font Mono", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Condensed Black Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 6, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Condensed Black Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSans Nerd Font Mono", + "preferred_subfamily_name": "Condensed Black Italic", + "subfamily_name": "Italic", + "weight": 900, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Condensed Black Italic Nerd Font Complete.ttf||1291940:1634564302.0": { + "family_name": "NotoSans Nerd Font", + "font-family": "NotoSans Nerd Font", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Condensed Black Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 6, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Condensed Black Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSans Nerd Font", + "preferred_subfamily_name": "Condensed Black Italic", + "subfamily_name": "Italic", + "weight": 900, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Condensed Black Nerd Font Complete Mono.ttf||1261896:1634564302.0": { + "family_name": "NotoSans Nerd Font Mono", + "font-family": "NotoSans Nerd Font Mono", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Condensed Black Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Condensed Black Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSans Nerd Font Mono", + "preferred_subfamily_name": "Condensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Condensed Black Nerd Font Complete.ttf||1272360:1634564302.0": { + "family_name": "NotoSans Nerd Font", + "font-family": "NotoSans Nerd Font", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Condensed Black Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Condensed Black Nerd Font Complete.ttf", + "preferred_family_name": "NotoSans Nerd Font", + "preferred_subfamily_name": "Condensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Condensed Bold Italic Nerd Font Complete Mono.ttf||1268912:1634564302.0": { + "family_name": "NotoSans Nerd Font Mono", + "font-family": "NotoSans Nerd Font Mono", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Condensed Bold Italic Nerd Font Complete Mono", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 6, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Condensed Bold Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSans Nerd Font Mono", + "preferred_subfamily_name": "Condensed Bold Italic", + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Condensed Bold Italic Nerd Font Complete.ttf||1281884:1634564302.0": { + "family_name": "NotoSans Nerd Font", + "font-family": "NotoSans Nerd Font", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Condensed Bold Italic Nerd Font Complete", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 6, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Condensed Bold Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSans Nerd Font", + "preferred_subfamily_name": "Condensed Bold Italic", + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Condensed Bold Nerd Font Complete Mono.ttf||1251320:1634564302.0": { + "family_name": "NotoSans Nerd Font Mono", + "font-family": "NotoSans Nerd Font Mono", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Condensed Bold Nerd Font Complete Mono", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Condensed Bold Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSans Nerd Font Mono", + "preferred_subfamily_name": "Condensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Condensed Bold Nerd Font Complete.ttf||1263940:1634564302.0": { + "family_name": "NotoSans Nerd Font", + "font-family": "NotoSans Nerd Font", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Condensed Bold Nerd Font Complete", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Condensed Bold Nerd Font Complete.ttf", + "preferred_family_name": "NotoSans Nerd Font", + "preferred_subfamily_name": "Condensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Condensed ExtraBold Italic Nerd Font Complete Mono.ttf||1273028:1634564302.0": { + "family_name": "NotoSans Nerd Font Mono", + "font-family": "NotoSans Nerd Font Mono", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Condensed ExtraBold Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 6, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Condensed ExtraBold Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSans Nerd Font Mono", + "preferred_subfamily_name": "Condensed ExtraBold Italic", + "subfamily_name": "Italic", + "weight": 800, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Condensed ExtraBold Italic Nerd Font Complete.ttf||1286096:1634564302.0": { + "family_name": "NotoSans Nerd Font", + "font-family": "NotoSans Nerd Font", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Condensed ExtraBold Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 6, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Condensed ExtraBold Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSans Nerd Font", + "preferred_subfamily_name": "Condensed ExtraBold Italic", + "subfamily_name": "Italic", + "weight": 800, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Condensed ExtraBold Nerd Font Complete Mono.ttf||1250836:1634564302.0": { + "family_name": "NotoSans Nerd Font Mono", + "font-family": "NotoSans Nerd Font Mono", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Condensed ExtraBold Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Condensed ExtraBold Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSans Nerd Font Mono", + "preferred_subfamily_name": "Condensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Condensed ExtraBold Nerd Font Complete.ttf||1262592:1634564302.0": { + "family_name": "NotoSans Nerd Font", + "font-family": "NotoSans Nerd Font", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Condensed ExtraBold Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Condensed ExtraBold Nerd Font Complete.ttf", + "preferred_family_name": "NotoSans Nerd Font", + "preferred_subfamily_name": "Condensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Condensed ExtraLight Italic Nerd Font Complete Mono.ttf||1250928:1634564302.0": { + "family_name": "NotoSans Nerd Font Mono", + "font-family": "NotoSans Nerd Font Mono", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Condensed ExtraLight Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 6, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Condensed ExtraLight Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSans Nerd Font Mono", + "preferred_subfamily_name": "Condensed ExtraLight Italic", + "subfamily_name": "Italic", + "weight": 200, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Condensed ExtraLight Italic Nerd Font Complete.ttf||1263804:1634564302.0": { + "family_name": "NotoSans Nerd Font", + "font-family": "NotoSans Nerd Font", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Condensed ExtraLight Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 6, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Condensed ExtraLight Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSans Nerd Font", + "preferred_subfamily_name": "Condensed ExtraLight Italic", + "subfamily_name": "Italic", + "weight": 200, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Condensed ExtraLight Nerd Font Complete Mono.ttf||1229932:1634564302.0": { + "family_name": "NotoSans Nerd Font Mono", + "font-family": "NotoSans Nerd Font Mono", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Condensed ExtraLight Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Condensed ExtraLight Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSans Nerd Font Mono", + "preferred_subfamily_name": "Condensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Condensed ExtraLight Nerd Font Complete.ttf||1242696:1634564302.0": { + "family_name": "NotoSans Nerd Font", + "font-family": "NotoSans Nerd Font", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Condensed ExtraLight Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Condensed ExtraLight Nerd Font Complete.ttf", + "preferred_family_name": "NotoSans Nerd Font", + "preferred_subfamily_name": "Condensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Condensed Italic Nerd Font Complete Mono.ttf||1266960:1634564302.0": { + "family_name": "NotoSans Nerd Font Mono", + "font-family": "NotoSans Nerd Font Mono", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Condensed Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 6, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Condensed Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSans Nerd Font Mono", + "preferred_subfamily_name": "Condensed Italic", + "subfamily_name": "Italic", + "weight": 400, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Condensed Italic Nerd Font Complete.ttf||1279836:1634564302.0": { + "family_name": "NotoSans Nerd Font", + "font-family": "NotoSans Nerd Font", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Condensed Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 6, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Condensed Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSans Nerd Font", + "preferred_subfamily_name": "Condensed Italic", + "subfamily_name": "Italic", + "weight": 400, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Condensed Light Italic Nerd Font Complete Mono.ttf||1257132:1634564302.0": { + "family_name": "NotoSans Nerd Font Mono", + "font-family": "NotoSans Nerd Font Mono", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Condensed Light Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 6, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Condensed Light Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSans Nerd Font Mono", + "preferred_subfamily_name": "Condensed Light Italic", + "subfamily_name": "Italic", + "weight": 300, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Condensed Light Italic Nerd Font Complete.ttf||1270012:1634564302.0": { + "family_name": "NotoSans Nerd Font", + "font-family": "NotoSans Nerd Font", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Condensed Light Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 6, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Condensed Light Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSans Nerd Font", + "preferred_subfamily_name": "Condensed Light Italic", + "subfamily_name": "Italic", + "weight": 300, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Condensed Light Nerd Font Complete Mono.ttf||1239652:1634564302.0": { + "family_name": "NotoSans Nerd Font Mono", + "font-family": "NotoSans Nerd Font Mono", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Condensed Light Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Condensed Light Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSans Nerd Font Mono", + "preferred_subfamily_name": "Condensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Condensed Light Nerd Font Complete.ttf||1252432:1634564302.0": { + "family_name": "NotoSans Nerd Font", + "font-family": "NotoSans Nerd Font", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Condensed Light Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Condensed Light Nerd Font Complete.ttf", + "preferred_family_name": "NotoSans Nerd Font", + "preferred_subfamily_name": "Condensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Condensed Medium Italic Nerd Font Complete Mono.ttf||1265364:1634564302.0": { + "family_name": "NotoSans Nerd Font Mono", + "font-family": "NotoSans Nerd Font Mono", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Condensed Medium Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 6, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Condensed Medium Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSans Nerd Font Mono", + "preferred_subfamily_name": "Condensed Medium Italic", + "subfamily_name": "Italic", + "weight": 500, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Condensed Medium Italic Nerd Font Complete.ttf||1278132:1634564302.0": { + "family_name": "NotoSans Nerd Font", + "font-family": "NotoSans Nerd Font", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Condensed Medium Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 6, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Condensed Medium Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSans Nerd Font", + "preferred_subfamily_name": "Condensed Medium Italic", + "subfamily_name": "Italic", + "weight": 500, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Condensed Medium Nerd Font Complete Mono.ttf||1245584:1634564302.0": { + "family_name": "NotoSans Nerd Font Mono", + "font-family": "NotoSans Nerd Font Mono", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Condensed Medium Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Condensed Medium Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSans Nerd Font Mono", + "preferred_subfamily_name": "Condensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Condensed Medium Nerd Font Complete.ttf||1258276:1634564302.0": { + "family_name": "NotoSans Nerd Font", + "font-family": "NotoSans Nerd Font", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Condensed Medium Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Condensed Medium Nerd Font Complete.ttf", + "preferred_family_name": "NotoSans Nerd Font", + "preferred_subfamily_name": "Condensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Condensed Nerd Font Complete Mono.ttf||1247416:1634564302.0": { + "family_name": "NotoSans Nerd Font Mono", + "font-family": "NotoSans Nerd Font Mono", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Condensed Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Condensed Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSans Nerd Font Mono", + "preferred_subfamily_name": "Condensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Condensed Nerd Font Complete.ttf||1260208:1634564302.0": { + "family_name": "NotoSans Nerd Font", + "font-family": "NotoSans Nerd Font", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Condensed Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Condensed Nerd Font Complete.ttf", + "preferred_family_name": "NotoSans Nerd Font", + "preferred_subfamily_name": "Condensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Condensed SemiBold Italic Nerd Font Complete Mono.ttf||1268568:1634564302.0": { + "family_name": "NotoSans Nerd Font Mono", + "font-family": "NotoSans Nerd Font Mono", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Condensed SemiBold Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 6, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Condensed SemiBold Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSans Nerd Font Mono", + "preferred_subfamily_name": "Condensed SemiBold Italic", + "subfamily_name": "Italic", + "weight": 600, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Condensed SemiBold Italic Nerd Font Complete.ttf||1281448:1634564302.0": { + "family_name": "NotoSans Nerd Font", + "font-family": "NotoSans Nerd Font", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Condensed SemiBold Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 6, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Condensed SemiBold Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSans Nerd Font", + "preferred_subfamily_name": "Condensed SemiBold Italic", + "subfamily_name": "Italic", + "weight": 600, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Condensed SemiBold Nerd Font Complete Mono.ttf||1247520:1634564302.0": { + "family_name": "NotoSans Nerd Font Mono", + "font-family": "NotoSans Nerd Font Mono", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Condensed SemiBold Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Condensed SemiBold Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSans Nerd Font Mono", + "preferred_subfamily_name": "Condensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Condensed SemiBold Nerd Font Complete.ttf||1260308:1634564302.0": { + "family_name": "NotoSans Nerd Font", + "font-family": "NotoSans Nerd Font", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Condensed SemiBold Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Condensed SemiBold Nerd Font Complete.ttf", + "preferred_family_name": "NotoSans Nerd Font", + "preferred_subfamily_name": "Condensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Condensed Thin Italic Nerd Font Complete Mono.ttf||1250136:1634564302.0": { + "family_name": "NotoSans Nerd Font Mono", + "font-family": "NotoSans Nerd Font Mono", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Condensed Thin Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 6, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Condensed Thin Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSans Nerd Font Mono", + "preferred_subfamily_name": "Condensed Thin Italic", + "subfamily_name": "Italic", + "weight": 100, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Condensed Thin Italic Nerd Font Complete.ttf||1263024:1634564302.0": { + "family_name": "NotoSans Nerd Font", + "font-family": "NotoSans Nerd Font", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Condensed Thin Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 6, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Condensed Thin Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSans Nerd Font", + "preferred_subfamily_name": "Condensed Thin Italic", + "subfamily_name": "Italic", + "weight": 100, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Condensed Thin Nerd Font Complete Mono.ttf||1231916:1634564302.0": { + "family_name": "NotoSans Nerd Font Mono", + "font-family": "NotoSans Nerd Font Mono", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Condensed Thin Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Condensed Thin Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSans Nerd Font Mono", + "preferred_subfamily_name": "Condensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Condensed Thin Nerd Font Complete.ttf||1244704:1634564302.0": { + "family_name": "NotoSans Nerd Font", + "font-family": "NotoSans Nerd Font", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Condensed Thin Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Condensed Thin Nerd Font Complete.ttf", + "preferred_family_name": "NotoSans Nerd Font", + "preferred_subfamily_name": "Condensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Black Italic Nerd Font Complete Mono.ttf||1283316:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font Mono", + "font-family": "NotoSansDisplay Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Display Black Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 2, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Black Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font Mono", + "preferred_subfamily_name": "Black Italic", + "subfamily_name": "Italic", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Black Italic Nerd Font Complete.ttf||1290232:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font", + "font-family": "NotoSansDisplay Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Display Black Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 2, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Black Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font", + "preferred_subfamily_name": "Black Italic", + "subfamily_name": "Italic", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Black Nerd Font Complete Mono.ttf||1273232:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font Mono", + "font-family": "NotoSansDisplay Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Display Black Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Black Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font Mono", + "preferred_subfamily_name": "Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Black Nerd Font Complete.ttf||1278796:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font", + "font-family": "NotoSansDisplay Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Display Black Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Black Nerd Font Complete.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font", + "preferred_subfamily_name": "Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Bold Italic Nerd Font Complete Mono.ttf||1268052:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font Mono", + "font-family": "NotoSansDisplay Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Display Bold Italic Nerd Font Complete Mono", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 2, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Bold Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Bold Italic Nerd Font Complete.ttf||1278980:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font", + "font-family": "NotoSansDisplay Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Display Bold Italic Nerd Font Complete", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 2, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Bold Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Bold Nerd Font Complete Mono.ttf||1255700:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font Mono", + "font-family": "NotoSansDisplay Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Display Bold Nerd Font Complete Mono", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Bold Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Bold Nerd Font Complete.ttf||1262764:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font", + "font-family": "NotoSansDisplay Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Display Bold Nerd Font Complete", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Bold Nerd Font Complete.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Condensed Black Italic Nerd Font Complete Mono.ttf||1279496:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font Mono", + "font-family": "NotoSansDisplay Nerd Font Mono", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Display Condensed Black Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 6, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Condensed Black Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font Mono", + "preferred_subfamily_name": "Condensed Black Italic", + "subfamily_name": "Italic", + "weight": 900, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Condensed Black Italic Nerd Font Complete.ttf||1291916:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font", + "font-family": "NotoSansDisplay Nerd Font", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Display Condensed Black Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 6, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Condensed Black Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font", + "preferred_subfamily_name": "Condensed Black Italic", + "subfamily_name": "Italic", + "weight": 900, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Condensed Black Nerd Font Complete Mono.ttf||1260448:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font Mono", + "font-family": "NotoSansDisplay Nerd Font Mono", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Display Condensed Black Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Condensed Black Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font Mono", + "preferred_subfamily_name": "Condensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Condensed Black Nerd Font Complete.ttf||1272136:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font", + "font-family": "NotoSansDisplay Nerd Font", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Display Condensed Black Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Condensed Black Nerd Font Complete.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font", + "preferred_subfamily_name": "Condensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Condensed Bold Italic Nerd Font Complete Mono.ttf||1268608:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font Mono", + "font-family": "NotoSansDisplay Nerd Font Mono", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Display Condensed Bold Italic Nerd Font Complete Mono", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 6, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Condensed Bold Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font Mono", + "preferred_subfamily_name": "Condensed Bold Italic", + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Condensed Bold Italic Nerd Font Complete.ttf||1282280:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font", + "font-family": "NotoSansDisplay Nerd Font", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Display Condensed Bold Italic Nerd Font Complete", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 6, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Condensed Bold Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font", + "preferred_subfamily_name": "Condensed Bold Italic", + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Condensed Bold Nerd Font Complete Mono.ttf||1248652:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font Mono", + "font-family": "NotoSansDisplay Nerd Font Mono", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Display Condensed Bold Nerd Font Complete Mono", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Condensed Bold Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font Mono", + "preferred_subfamily_name": "Condensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Condensed Bold Nerd Font Complete.ttf||1261900:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font", + "font-family": "NotoSansDisplay Nerd Font", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Display Condensed Bold Nerd Font Complete", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Condensed Bold Nerd Font Complete.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font", + "preferred_subfamily_name": "Condensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Condensed ExtraBold Italic Nerd Font Complete Mono.ttf||1272540:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font Mono", + "font-family": "NotoSansDisplay Nerd Font Mono", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Display Condensed ExtraBold Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 6, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Condensed ExtraBold Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font Mono", + "preferred_subfamily_name": "Condensed ExtraBold Italic", + "subfamily_name": "Italic", + "weight": 800, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Condensed ExtraBold Italic Nerd Font Complete.ttf||1285976:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font", + "font-family": "NotoSansDisplay Nerd Font", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Display Condensed ExtraBold Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 6, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Condensed ExtraBold Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font", + "preferred_subfamily_name": "Condensed ExtraBold Italic", + "subfamily_name": "Italic", + "weight": 800, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Condensed ExtraBold Nerd Font Complete Mono.ttf||1249584:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font Mono", + "font-family": "NotoSansDisplay Nerd Font Mono", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Display Condensed ExtraBold Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Condensed ExtraBold Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font Mono", + "preferred_subfamily_name": "Condensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Condensed ExtraBold Nerd Font Complete.ttf||1262328:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font", + "font-family": "NotoSansDisplay Nerd Font", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Display Condensed ExtraBold Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Condensed ExtraBold Nerd Font Complete.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font", + "preferred_subfamily_name": "Condensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Condensed ExtraLight Italic Nerd Font Complete Mono.ttf||1250048:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font Mono", + "font-family": "NotoSansDisplay Nerd Font Mono", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Display Condensed ExtraLight Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 6, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Condensed ExtraLight Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font Mono", + "preferred_subfamily_name": "Condensed ExtraLight Italic", + "subfamily_name": "Italic", + "weight": 200, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Condensed ExtraLight Italic Nerd Font Complete.ttf||1263464:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font", + "font-family": "NotoSansDisplay Nerd Font", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Display Condensed ExtraLight Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 6, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Condensed ExtraLight Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font", + "preferred_subfamily_name": "Condensed ExtraLight Italic", + "subfamily_name": "Italic", + "weight": 200, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Condensed ExtraLight Nerd Font Complete Mono.ttf||1227604:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font Mono", + "font-family": "NotoSansDisplay Nerd Font Mono", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Display Condensed ExtraLight Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Condensed ExtraLight Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font Mono", + "preferred_subfamily_name": "Condensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Condensed ExtraLight Nerd Font Complete.ttf||1241232:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font", + "font-family": "NotoSansDisplay Nerd Font", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Display Condensed ExtraLight Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Condensed ExtraLight Nerd Font Complete.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font", + "preferred_subfamily_name": "Condensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Condensed Italic Nerd Font Complete Mono.ttf||1265620:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font Mono", + "font-family": "NotoSansDisplay Nerd Font Mono", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Display Condensed Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 6, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Condensed Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font Mono", + "preferred_subfamily_name": "Condensed Italic", + "subfamily_name": "Italic", + "weight": 400, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Condensed Italic Nerd Font Complete.ttf||1279108:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font", + "font-family": "NotoSansDisplay Nerd Font", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Display Condensed Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 6, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Condensed Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font", + "preferred_subfamily_name": "Condensed Italic", + "subfamily_name": "Italic", + "weight": 400, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Condensed Light Italic Nerd Font Complete Mono.ttf||1254936:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font Mono", + "font-family": "NotoSansDisplay Nerd Font Mono", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Display Condensed Light Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 6, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Condensed Light Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font Mono", + "preferred_subfamily_name": "Condensed Light Italic", + "subfamily_name": "Italic", + "weight": 300, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Condensed Light Italic Nerd Font Complete.ttf||1268428:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font", + "font-family": "NotoSansDisplay Nerd Font", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Display Condensed Light Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 6, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Condensed Light Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font", + "preferred_subfamily_name": "Condensed Light Italic", + "subfamily_name": "Italic", + "weight": 300, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Condensed Light Nerd Font Complete Mono.ttf||1237836:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font Mono", + "font-family": "NotoSansDisplay Nerd Font Mono", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Display Condensed Light Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Condensed Light Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font Mono", + "preferred_subfamily_name": "Condensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Condensed Light Nerd Font Complete.ttf||1251564:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font", + "font-family": "NotoSansDisplay Nerd Font", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Display Condensed Light Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Condensed Light Nerd Font Complete.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font", + "preferred_subfamily_name": "Condensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Condensed Medium Italic Nerd Font Complete Mono.ttf||1263248:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font Mono", + "font-family": "NotoSansDisplay Nerd Font Mono", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Display Condensed Medium Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 6, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Condensed Medium Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font Mono", + "preferred_subfamily_name": "Condensed Medium Italic", + "subfamily_name": "Italic", + "weight": 500, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Condensed Medium Italic Nerd Font Complete.ttf||1276796:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font", + "font-family": "NotoSansDisplay Nerd Font", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Display Condensed Medium Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 6, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Condensed Medium Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font", + "preferred_subfamily_name": "Condensed Medium Italic", + "subfamily_name": "Italic", + "weight": 500, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Condensed Medium Nerd Font Complete Mono.ttf||1243536:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font Mono", + "font-family": "NotoSansDisplay Nerd Font Mono", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Display Condensed Medium Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Condensed Medium Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font Mono", + "preferred_subfamily_name": "Condensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Condensed Medium Nerd Font Complete.ttf||1257180:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font", + "font-family": "NotoSansDisplay Nerd Font", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Display Condensed Medium Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Condensed Medium Nerd Font Complete.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font", + "preferred_subfamily_name": "Condensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Condensed Nerd Font Complete Mono.ttf||1244796:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font Mono", + "font-family": "NotoSansDisplay Nerd Font Mono", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Display Condensed Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Condensed Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font Mono", + "preferred_subfamily_name": "Condensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Condensed Nerd Font Complete.ttf||1258472:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font", + "font-family": "NotoSansDisplay Nerd Font", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Display Condensed Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Condensed Nerd Font Complete.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font", + "preferred_subfamily_name": "Condensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Condensed SemiBold Italic Nerd Font Complete Mono.ttf||1267768:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font Mono", + "font-family": "NotoSansDisplay Nerd Font Mono", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Display Condensed SemiBold Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 6, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Condensed SemiBold Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font Mono", + "preferred_subfamily_name": "Condensed SemiBold Italic", + "subfamily_name": "Italic", + "weight": 600, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Condensed SemiBold Italic Nerd Font Complete.ttf||1281348:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font", + "font-family": "NotoSansDisplay Nerd Font", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Display Condensed SemiBold Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 6, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Condensed SemiBold Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font", + "preferred_subfamily_name": "Condensed SemiBold Italic", + "subfamily_name": "Italic", + "weight": 600, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Condensed SemiBold Nerd Font Complete Mono.ttf||1244416:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font Mono", + "font-family": "NotoSansDisplay Nerd Font Mono", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Display Condensed SemiBold Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Condensed SemiBold Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font Mono", + "preferred_subfamily_name": "Condensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Condensed SemiBold Nerd Font Complete.ttf||1258088:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font", + "font-family": "NotoSansDisplay Nerd Font", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Display Condensed SemiBold Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Condensed SemiBold Nerd Font Complete.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font", + "preferred_subfamily_name": "Condensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Condensed Thin Italic Nerd Font Complete Mono.ttf||1247824:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font Mono", + "font-family": "NotoSansDisplay Nerd Font Mono", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Display Condensed Thin Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 6, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Condensed Thin Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font Mono", + "preferred_subfamily_name": "Condensed Thin Italic", + "subfamily_name": "Italic", + "weight": 100, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Condensed Thin Italic Nerd Font Complete.ttf||1261244:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font", + "font-family": "NotoSansDisplay Nerd Font", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Display Condensed Thin Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 6, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Condensed Thin Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font", + "preferred_subfamily_name": "Condensed Thin Italic", + "subfamily_name": "Italic", + "weight": 100, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Condensed Thin Nerd Font Complete Mono.ttf||1229272:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font Mono", + "font-family": "NotoSansDisplay Nerd Font Mono", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Display Condensed Thin Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Condensed Thin Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font Mono", + "preferred_subfamily_name": "Condensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Condensed Thin Nerd Font Complete.ttf||1242892:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font", + "font-family": "NotoSansDisplay Nerd Font", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Display Condensed Thin Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Condensed Thin Nerd Font Complete.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font", + "preferred_subfamily_name": "Condensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display ExtraBold Italic Nerd Font Complete Mono.ttf||1270772:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font Mono", + "font-family": "NotoSansDisplay Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Display ExtraBold Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 2, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display ExtraBold Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font Mono", + "preferred_subfamily_name": "ExtraBold Italic", + "subfamily_name": "Italic", + "weight": 800, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display ExtraBold Italic Nerd Font Complete.ttf||1279944:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font", + "font-family": "NotoSansDisplay Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Display ExtraBold Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 2, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display ExtraBold Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font", + "preferred_subfamily_name": "ExtraBold Italic", + "subfamily_name": "Italic", + "weight": 800, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display ExtraBold Nerd Font Complete Mono.ttf||1258660:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font Mono", + "font-family": "NotoSansDisplay Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Display ExtraBold Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display ExtraBold Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font Mono", + "preferred_subfamily_name": "ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display ExtraBold Nerd Font Complete.ttf||1264968:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font", + "font-family": "NotoSansDisplay Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Display ExtraBold Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display ExtraBold Nerd Font Complete.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font", + "preferred_subfamily_name": "ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display ExtraCondensed Black Italic Nerd Font Complete Mono.ttf||1279224:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font Mono", + "font-family": "NotoSansDisplay Nerd Font Mono", + "font-stretch": "extra-condensed", + "font-style": "italic", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Display ExtraCondensed Black Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 6, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display ExtraCondensed Black Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font Mono", + "preferred_subfamily_name": "ExtraCondensed Black Italic", + "subfamily_name": "Italic", + "weight": 900, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display ExtraCondensed Black Italic Nerd Font Complete.ttf||1292888:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font", + "font-family": "NotoSansDisplay Nerd Font", + "font-stretch": "extra-condensed", + "font-style": "italic", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Display ExtraCondensed Black Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 6, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display ExtraCondensed Black Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font", + "preferred_subfamily_name": "ExtraCondensed Black Italic", + "subfamily_name": "Italic", + "weight": 900, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display ExtraCondensed Black Nerd Font Complete Mono.ttf||1256964:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font Mono", + "font-family": "NotoSansDisplay Nerd Font Mono", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Display ExtraCondensed Black Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display ExtraCondensed Black Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font Mono", + "preferred_subfamily_name": "ExtraCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display ExtraCondensed Black Nerd Font Complete.ttf||1269876:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font", + "font-family": "NotoSansDisplay Nerd Font", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Display ExtraCondensed Black Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display ExtraCondensed Black Nerd Font Complete.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font", + "preferred_subfamily_name": "ExtraCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display ExtraCondensed Bold Italic Nerd Font Complete Mono.ttf||1268536:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font Mono", + "font-family": "NotoSansDisplay Nerd Font Mono", + "font-stretch": "extra-condensed", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Display ExtraCondensed Bold Italic Nerd Font Complete Mono", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 6, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display ExtraCondensed Bold Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font Mono", + "preferred_subfamily_name": "ExtraCondensed Bold Italic", + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display ExtraCondensed Bold Italic Nerd Font Complete.ttf||1282112:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font", + "font-family": "NotoSansDisplay Nerd Font", + "font-stretch": "extra-condensed", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Display ExtraCondensed Bold Italic Nerd Font Complete", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 6, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display ExtraCondensed Bold Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font", + "preferred_subfamily_name": "ExtraCondensed Bold Italic", + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display ExtraCondensed Bold Nerd Font Complete Mono.ttf||1244816:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font Mono", + "font-family": "NotoSansDisplay Nerd Font Mono", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Display ExtraCondensed Bold Nerd Font Complete Mono", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display ExtraCondensed Bold Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font Mono", + "preferred_subfamily_name": "ExtraCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display ExtraCondensed Bold Nerd Font Complete.ttf||1258416:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font", + "font-family": "NotoSansDisplay Nerd Font", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Display ExtraCondensed Bold Nerd Font Complete", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display ExtraCondensed Bold Nerd Font Complete.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font", + "preferred_subfamily_name": "ExtraCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display ExtraCondensed ExtraBold Italic Nerd Font Complete Mono.ttf||1273192:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font Mono", + "font-family": "NotoSansDisplay Nerd Font Mono", + "font-stretch": "extra-condensed", + "font-style": "italic", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Display ExtraCondensed ExtraBold Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 6, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display ExtraCondensed ExtraBold Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font Mono", + "preferred_subfamily_name": "ExtraCondensed ExtraBold Italic", + "subfamily_name": "Italic", + "weight": 800, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display ExtraCondensed ExtraBold Italic Nerd Font Complete.ttf||1286716:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font", + "font-family": "NotoSansDisplay Nerd Font", + "font-stretch": "extra-condensed", + "font-style": "italic", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Display ExtraCondensed ExtraBold Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 6, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display ExtraCondensed ExtraBold Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font", + "preferred_subfamily_name": "ExtraCondensed ExtraBold Italic", + "subfamily_name": "Italic", + "weight": 800, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display ExtraCondensed ExtraBold Nerd Font Complete Mono.ttf||1247952:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font Mono", + "font-family": "NotoSansDisplay Nerd Font Mono", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Display ExtraCondensed ExtraBold Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display ExtraCondensed ExtraBold Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font Mono", + "preferred_subfamily_name": "ExtraCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display ExtraCondensed ExtraBold Nerd Font Complete.ttf||1261500:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font", + "font-family": "NotoSansDisplay Nerd Font", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Display ExtraCondensed ExtraBold Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display ExtraCondensed ExtraBold Nerd Font Complete.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font", + "preferred_subfamily_name": "ExtraCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display ExtraCondensed ExtraLight Italic Nerd Font Complete Mono.ttf||1249112:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font Mono", + "font-family": "NotoSansDisplay Nerd Font Mono", + "font-stretch": "extra-condensed", + "font-style": "italic", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Display ExtraCondensed ExtraLight Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 6, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display ExtraCondensed ExtraLight Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font Mono", + "preferred_subfamily_name": "ExtraCondensed ExtraLight Italic", + "subfamily_name": "Italic", + "weight": 200, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display ExtraCondensed ExtraLight Italic Nerd Font Complete.ttf||1262460:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font", + "font-family": "NotoSansDisplay Nerd Font", + "font-stretch": "extra-condensed", + "font-style": "italic", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Display ExtraCondensed ExtraLight Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 6, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display ExtraCondensed ExtraLight Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font", + "preferred_subfamily_name": "ExtraCondensed ExtraLight Italic", + "subfamily_name": "Italic", + "weight": 200, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display ExtraCondensed ExtraLight Nerd Font Complete Mono.ttf||1229328:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font Mono", + "font-family": "NotoSansDisplay Nerd Font Mono", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Display ExtraCondensed ExtraLight Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display ExtraCondensed ExtraLight Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font Mono", + "preferred_subfamily_name": "ExtraCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display ExtraCondensed ExtraLight Nerd Font Complete.ttf||1242704:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font", + "font-family": "NotoSansDisplay Nerd Font", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Display ExtraCondensed ExtraLight Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display ExtraCondensed ExtraLight Nerd Font Complete.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font", + "preferred_subfamily_name": "ExtraCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display ExtraCondensed Italic Nerd Font Complete Mono.ttf||1264000:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font Mono", + "font-family": "NotoSansDisplay Nerd Font Mono", + "font-stretch": "extra-condensed", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Display ExtraCondensed Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 6, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display ExtraCondensed Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font Mono", + "preferred_subfamily_name": "ExtraCondensed Italic", + "subfamily_name": "Italic", + "weight": 400, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display ExtraCondensed Italic Nerd Font Complete.ttf||1277404:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font", + "font-family": "NotoSansDisplay Nerd Font", + "font-stretch": "extra-condensed", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Display ExtraCondensed Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 6, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display ExtraCondensed Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font", + "preferred_subfamily_name": "ExtraCondensed Italic", + "subfamily_name": "Italic", + "weight": 400, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display ExtraCondensed Light Italic Nerd Font Complete Mono.ttf||1256712:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font Mono", + "font-family": "NotoSansDisplay Nerd Font Mono", + "font-stretch": "extra-condensed", + "font-style": "italic", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Display ExtraCondensed Light Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 6, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display ExtraCondensed Light Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font Mono", + "preferred_subfamily_name": "ExtraCondensed Light Italic", + "subfamily_name": "Italic", + "weight": 300, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display ExtraCondensed Light Italic Nerd Font Complete.ttf||1270008:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font", + "font-family": "NotoSansDisplay Nerd Font", + "font-stretch": "extra-condensed", + "font-style": "italic", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Display ExtraCondensed Light Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 6, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display ExtraCondensed Light Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font", + "preferred_subfamily_name": "ExtraCondensed Light Italic", + "subfamily_name": "Italic", + "weight": 300, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display ExtraCondensed Light Nerd Font Complete Mono.ttf||1237116:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font Mono", + "font-family": "NotoSansDisplay Nerd Font Mono", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Display ExtraCondensed Light Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display ExtraCondensed Light Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font Mono", + "preferred_subfamily_name": "ExtraCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display ExtraCondensed Light Nerd Font Complete.ttf||1250500:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font", + "font-family": "NotoSansDisplay Nerd Font", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Display ExtraCondensed Light Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display ExtraCondensed Light Nerd Font Complete.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font", + "preferred_subfamily_name": "ExtraCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display ExtraCondensed Medium Italic Nerd Font Complete Mono.ttf||1265972:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font Mono", + "font-family": "NotoSansDisplay Nerd Font Mono", + "font-stretch": "extra-condensed", + "font-style": "italic", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Display ExtraCondensed Medium Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 6, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display ExtraCondensed Medium Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font Mono", + "preferred_subfamily_name": "ExtraCondensed Medium Italic", + "subfamily_name": "Italic", + "weight": 500, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display ExtraCondensed Medium Italic Nerd Font Complete.ttf||1279548:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font", + "font-family": "NotoSansDisplay Nerd Font", + "font-stretch": "extra-condensed", + "font-style": "italic", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Display ExtraCondensed Medium Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 6, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display ExtraCondensed Medium Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font", + "preferred_subfamily_name": "ExtraCondensed Medium Italic", + "subfamily_name": "Italic", + "weight": 500, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display ExtraCondensed Medium Nerd Font Complete Mono.ttf||1241140:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font Mono", + "font-family": "NotoSansDisplay Nerd Font Mono", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Display ExtraCondensed Medium Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display ExtraCondensed Medium Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font Mono", + "preferred_subfamily_name": "ExtraCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display ExtraCondensed Medium Nerd Font Complete.ttf||1254692:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font", + "font-family": "NotoSansDisplay Nerd Font", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Display ExtraCondensed Medium Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display ExtraCondensed Medium Nerd Font Complete.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font", + "preferred_subfamily_name": "ExtraCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display ExtraCondensed Nerd Font Complete Mono.ttf||1242832:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font Mono", + "font-family": "NotoSansDisplay Nerd Font Mono", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Display ExtraCondensed Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display ExtraCondensed Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font Mono", + "preferred_subfamily_name": "ExtraCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display ExtraCondensed Nerd Font Complete.ttf||1256312:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font", + "font-family": "NotoSansDisplay Nerd Font", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Display ExtraCondensed Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display ExtraCondensed Nerd Font Complete.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font", + "preferred_subfamily_name": "ExtraCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display ExtraCondensed SemiBold Italic Nerd Font Complete Mono.ttf||1265848:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font Mono", + "font-family": "NotoSansDisplay Nerd Font Mono", + "font-stretch": "extra-condensed", + "font-style": "italic", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Display ExtraCondensed SemiBold Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 6, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display ExtraCondensed SemiBold Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font Mono", + "preferred_subfamily_name": "ExtraCondensed SemiBold Italic", + "subfamily_name": "Italic", + "weight": 600, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display ExtraCondensed SemiBold Italic Nerd Font Complete.ttf||1279372:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font", + "font-family": "NotoSansDisplay Nerd Font", + "font-stretch": "extra-condensed", + "font-style": "italic", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Display ExtraCondensed SemiBold Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 6, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display ExtraCondensed SemiBold Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font", + "preferred_subfamily_name": "ExtraCondensed SemiBold Italic", + "subfamily_name": "Italic", + "weight": 600, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display ExtraCondensed SemiBold Nerd Font Complete Mono.ttf||1241904:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font Mono", + "font-family": "NotoSansDisplay Nerd Font Mono", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Display ExtraCondensed SemiBold Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display ExtraCondensed SemiBold Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font Mono", + "preferred_subfamily_name": "ExtraCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display ExtraCondensed SemiBold Nerd Font Complete.ttf||1255440:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font", + "font-family": "NotoSansDisplay Nerd Font", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Display ExtraCondensed SemiBold Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display ExtraCondensed SemiBold Nerd Font Complete.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font", + "preferred_subfamily_name": "ExtraCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display ExtraCondensed Thin Italic Nerd Font Complete Mono.ttf||1247480:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font Mono", + "font-family": "NotoSansDisplay Nerd Font Mono", + "font-stretch": "extra-condensed", + "font-style": "italic", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Display ExtraCondensed Thin Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 6, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display ExtraCondensed Thin Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font Mono", + "preferred_subfamily_name": "ExtraCondensed Thin Italic", + "subfamily_name": "Italic", + "weight": 100, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display ExtraCondensed Thin Italic Nerd Font Complete.ttf||1260876:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font", + "font-family": "NotoSansDisplay Nerd Font", + "font-stretch": "extra-condensed", + "font-style": "italic", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Display ExtraCondensed Thin Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 6, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display ExtraCondensed Thin Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font", + "preferred_subfamily_name": "ExtraCondensed Thin Italic", + "subfamily_name": "Italic", + "weight": 100, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display ExtraCondensed Thin Nerd Font Complete Mono.ttf||1227852:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font Mono", + "font-family": "NotoSansDisplay Nerd Font Mono", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Display ExtraCondensed Thin Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display ExtraCondensed Thin Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font Mono", + "preferred_subfamily_name": "ExtraCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display ExtraCondensed Thin Nerd Font Complete.ttf||1241224:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font", + "font-family": "NotoSansDisplay Nerd Font", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Display ExtraCondensed Thin Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display ExtraCondensed Thin Nerd Font Complete.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font", + "preferred_subfamily_name": "ExtraCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display ExtraLight Italic Nerd Font Complete Mono.ttf||1248960:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font Mono", + "font-family": "NotoSansDisplay Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Display ExtraLight Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 2, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display ExtraLight Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font Mono", + "preferred_subfamily_name": "ExtraLight Italic", + "subfamily_name": "Italic", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display ExtraLight Italic Nerd Font Complete.ttf||1261588:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font", + "font-family": "NotoSansDisplay Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Display ExtraLight Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 2, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display ExtraLight Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font", + "preferred_subfamily_name": "ExtraLight Italic", + "subfamily_name": "Italic", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display ExtraLight Nerd Font Complete Mono.ttf||1234940:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font Mono", + "font-family": "NotoSansDisplay Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Display ExtraLight Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display ExtraLight Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font Mono", + "preferred_subfamily_name": "ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display ExtraLight Nerd Font Complete.ttf||1244260:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font", + "font-family": "NotoSansDisplay Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Display ExtraLight Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display ExtraLight Nerd Font Complete.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font", + "preferred_subfamily_name": "ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Italic Nerd Font Complete Mono.ttf||1264704:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font Mono", + "font-family": "NotoSansDisplay Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Display Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Italic Nerd Font Complete.ttf||1277428:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font", + "font-family": "NotoSansDisplay Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Display Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Light Italic Nerd Font Complete Mono.ttf||1256312:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font Mono", + "font-family": "NotoSansDisplay Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Display Light Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 2, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Light Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font Mono", + "preferred_subfamily_name": "Light Italic", + "subfamily_name": "Italic", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Light Italic Nerd Font Complete.ttf||1268992:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font", + "font-family": "NotoSansDisplay Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Display Light Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 2, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Light Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font", + "preferred_subfamily_name": "Light Italic", + "subfamily_name": "Italic", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Light Nerd Font Complete Mono.ttf||1241288:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font Mono", + "font-family": "NotoSansDisplay Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Display Light Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Light Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font Mono", + "preferred_subfamily_name": "Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Light Nerd Font Complete.ttf||1251000:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font", + "font-family": "NotoSansDisplay Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Display Light Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Light Nerd Font Complete.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font", + "preferred_subfamily_name": "Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Medium Italic Nerd Font Complete Mono.ttf||1261212:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font Mono", + "font-family": "NotoSansDisplay Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Display Medium Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 2, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Medium Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font Mono", + "preferred_subfamily_name": "Medium Italic", + "subfamily_name": "Italic", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Medium Italic Nerd Font Complete.ttf||1273776:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font", + "font-family": "NotoSansDisplay Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Display Medium Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 2, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Medium Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font", + "preferred_subfamily_name": "Medium Italic", + "subfamily_name": "Italic", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Medium Nerd Font Complete Mono.ttf||1250212:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font Mono", + "font-family": "NotoSansDisplay Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Display Medium Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Medium Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font Mono", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Medium Nerd Font Complete.ttf||1259932:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font", + "font-family": "NotoSansDisplay Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Display Medium Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Medium Nerd Font Complete.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Regular Nerd Font Complete Mono.ttf||1252648:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font Mono", + "font-family": "NotoSansDisplay Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Display Regular Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Regular Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Regular Nerd Font Complete.ttf||1262680:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font", + "font-family": "NotoSansDisplay Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Display Regular Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Regular Nerd Font Complete.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display SemiBold Italic Nerd Font Complete Mono.ttf||1267688:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font Mono", + "font-family": "NotoSansDisplay Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Display SemiBold Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 2, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display SemiBold Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font Mono", + "preferred_subfamily_name": "SemiBold Italic", + "subfamily_name": "Italic", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display SemiBold Italic Nerd Font Complete.ttf||1279552:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font", + "font-family": "NotoSansDisplay Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Display SemiBold Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 2, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display SemiBold Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font", + "preferred_subfamily_name": "SemiBold Italic", + "subfamily_name": "Italic", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display SemiBold Nerd Font Complete Mono.ttf||1255708:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font Mono", + "font-family": "NotoSansDisplay Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Display SemiBold Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display SemiBold Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font Mono", + "preferred_subfamily_name": "SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display SemiBold Nerd Font Complete.ttf||1263420:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font", + "font-family": "NotoSansDisplay Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Display SemiBold Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display SemiBold Nerd Font Complete.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font", + "preferred_subfamily_name": "SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display SemiCondensed Black Italic Nerd Font Complete Mono.ttf||1282336:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font Mono", + "font-family": "NotoSansDisplay Nerd Font Mono", + "font-stretch": "semi-condensed", + "font-style": "italic", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Display SemiCondensed Black Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 2, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display SemiCondensed Black Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font Mono", + "preferred_subfamily_name": "SemiCondensed Black Italic", + "subfamily_name": "Italic", + "weight": 900, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display SemiCondensed Black Italic Nerd Font Complete.ttf||1292408:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font", + "font-family": "NotoSansDisplay Nerd Font", + "font-stretch": "semi-condensed", + "font-style": "italic", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Display SemiCondensed Black Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 2, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display SemiCondensed Black Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font", + "preferred_subfamily_name": "SemiCondensed Black Italic", + "subfamily_name": "Italic", + "weight": 900, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display SemiCondensed Black Nerd Font Complete Mono.ttf||1268396:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font Mono", + "font-family": "NotoSansDisplay Nerd Font Mono", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Display SemiCondensed Black Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display SemiCondensed Black Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font Mono", + "preferred_subfamily_name": "SemiCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display SemiCondensed Black Nerd Font Complete.ttf||1275800:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font", + "font-family": "NotoSansDisplay Nerd Font", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Display SemiCondensed Black Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display SemiCondensed Black Nerd Font Complete.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font", + "preferred_subfamily_name": "SemiCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display SemiCondensed Bold Italic Nerd Font Complete Mono.ttf||1270332:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font Mono", + "font-family": "NotoSansDisplay Nerd Font Mono", + "font-stretch": "semi-condensed", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Display SemiCondensed Bold Italic Nerd Font Complete Mono", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 2, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display SemiCondensed Bold Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font Mono", + "preferred_subfamily_name": "SemiCondensed Bold Italic", + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display SemiCondensed Bold Italic Nerd Font Complete.ttf||1283384:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font", + "font-family": "NotoSansDisplay Nerd Font", + "font-stretch": "semi-condensed", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Display SemiCondensed Bold Italic Nerd Font Complete", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 2, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display SemiCondensed Bold Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font", + "preferred_subfamily_name": "SemiCondensed Bold Italic", + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display SemiCondensed Bold Nerd Font Complete Mono.ttf||1253972:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font Mono", + "font-family": "NotoSansDisplay Nerd Font Mono", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Display SemiCondensed Bold Nerd Font Complete Mono", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display SemiCondensed Bold Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font Mono", + "preferred_subfamily_name": "SemiCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display SemiCondensed Bold Nerd Font Complete.ttf||1264664:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font", + "font-family": "NotoSansDisplay Nerd Font", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Display SemiCondensed Bold Nerd Font Complete", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display SemiCondensed Bold Nerd Font Complete.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font", + "preferred_subfamily_name": "SemiCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display SemiCondensed ExtraBold Italic Nerd Font Complete Mono.ttf||1273752:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font Mono", + "font-family": "NotoSansDisplay Nerd Font Mono", + "font-stretch": "semi-condensed", + "font-style": "italic", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Display SemiCondensed ExtraBold Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 2, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display SemiCondensed ExtraBold Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font Mono", + "preferred_subfamily_name": "SemiCondensed ExtraBold Italic", + "subfamily_name": "Italic", + "weight": 800, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display SemiCondensed ExtraBold Italic Nerd Font Complete.ttf||1285636:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font", + "font-family": "NotoSansDisplay Nerd Font", + "font-stretch": "semi-condensed", + "font-style": "italic", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Display SemiCondensed ExtraBold Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 2, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display SemiCondensed ExtraBold Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font", + "preferred_subfamily_name": "SemiCondensed ExtraBold Italic", + "subfamily_name": "Italic", + "weight": 800, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display SemiCondensed ExtraBold Nerd Font Complete Mono.ttf||1253032:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font Mono", + "font-family": "NotoSansDisplay Nerd Font Mono", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Display SemiCondensed ExtraBold Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display SemiCondensed ExtraBold Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font Mono", + "preferred_subfamily_name": "SemiCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display SemiCondensed ExtraBold Nerd Font Complete.ttf||1262804:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font", + "font-family": "NotoSansDisplay Nerd Font", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Display SemiCondensed ExtraBold Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display SemiCondensed ExtraBold Nerd Font Complete.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font", + "preferred_subfamily_name": "SemiCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display SemiCondensed ExtraLight Italic Nerd Font Complete Mono.ttf||1250712:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font Mono", + "font-family": "NotoSansDisplay Nerd Font Mono", + "font-stretch": "semi-condensed", + "font-style": "italic", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Display SemiCondensed ExtraLight Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 2, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display SemiCondensed ExtraLight Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font Mono", + "preferred_subfamily_name": "SemiCondensed ExtraLight Italic", + "subfamily_name": "Italic", + "weight": 200, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display SemiCondensed ExtraLight Italic Nerd Font Complete.ttf||1264204:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font", + "font-family": "NotoSansDisplay Nerd Font", + "font-stretch": "semi-condensed", + "font-style": "italic", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Display SemiCondensed ExtraLight Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 2, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display SemiCondensed ExtraLight Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font", + "preferred_subfamily_name": "SemiCondensed ExtraLight Italic", + "subfamily_name": "Italic", + "weight": 200, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display SemiCondensed ExtraLight Nerd Font Complete Mono.ttf||1230224:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font Mono", + "font-family": "NotoSansDisplay Nerd Font Mono", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Display SemiCondensed ExtraLight Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display SemiCondensed ExtraLight Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font Mono", + "preferred_subfamily_name": "SemiCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display SemiCondensed ExtraLight Nerd Font Complete.ttf||1243232:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font", + "font-family": "NotoSansDisplay Nerd Font", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Display SemiCondensed ExtraLight Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display SemiCondensed ExtraLight Nerd Font Complete.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font", + "preferred_subfamily_name": "SemiCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display SemiCondensed Italic Nerd Font Complete Mono.ttf||1267360:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font Mono", + "font-family": "NotoSansDisplay Nerd Font Mono", + "font-stretch": "semi-condensed", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Display SemiCondensed Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display SemiCondensed Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font Mono", + "preferred_subfamily_name": "SemiCondensed Italic", + "subfamily_name": "Italic", + "weight": 400, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display SemiCondensed Italic Nerd Font Complete.ttf||1281180:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font", + "font-family": "NotoSansDisplay Nerd Font", + "font-stretch": "semi-condensed", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Display SemiCondensed Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display SemiCondensed Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font", + "preferred_subfamily_name": "SemiCondensed Italic", + "subfamily_name": "Italic", + "weight": 400, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display SemiCondensed Light Italic Nerd Font Complete Mono.ttf||1261316:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font Mono", + "font-family": "NotoSansDisplay Nerd Font Mono", + "font-stretch": "semi-condensed", + "font-style": "italic", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Display SemiCondensed Light Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 2, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display SemiCondensed Light Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font Mono", + "preferred_subfamily_name": "SemiCondensed Light Italic", + "subfamily_name": "Italic", + "weight": 300, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display SemiCondensed Light Italic Nerd Font Complete.ttf||1274960:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font", + "font-family": "NotoSansDisplay Nerd Font", + "font-stretch": "semi-condensed", + "font-style": "italic", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Display SemiCondensed Light Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 2, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display SemiCondensed Light Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font", + "preferred_subfamily_name": "SemiCondensed Light Italic", + "subfamily_name": "Italic", + "weight": 300, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display SemiCondensed Light Nerd Font Complete Mono.ttf||1238764:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font Mono", + "font-family": "NotoSansDisplay Nerd Font Mono", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Display SemiCondensed Light Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display SemiCondensed Light Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font Mono", + "preferred_subfamily_name": "SemiCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display SemiCondensed Light Nerd Font Complete.ttf||1251900:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font", + "font-family": "NotoSansDisplay Nerd Font", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Display SemiCondensed Light Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display SemiCondensed Light Nerd Font Complete.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font", + "preferred_subfamily_name": "SemiCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display SemiCondensed Medium Italic Nerd Font Complete Mono.ttf||1264116:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font Mono", + "font-family": "NotoSansDisplay Nerd Font Mono", + "font-stretch": "semi-condensed", + "font-style": "italic", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Display SemiCondensed Medium Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 2, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display SemiCondensed Medium Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font Mono", + "preferred_subfamily_name": "SemiCondensed Medium Italic", + "subfamily_name": "Italic", + "weight": 500, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display SemiCondensed Medium Italic Nerd Font Complete.ttf||1277904:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font", + "font-family": "NotoSansDisplay Nerd Font", + "font-stretch": "semi-condensed", + "font-style": "italic", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Display SemiCondensed Medium Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 2, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display SemiCondensed Medium Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font", + "preferred_subfamily_name": "SemiCondensed Medium Italic", + "subfamily_name": "Italic", + "weight": 500, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display SemiCondensed Medium Nerd Font Complete Mono.ttf||1245744:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font Mono", + "font-family": "NotoSansDisplay Nerd Font Mono", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Display SemiCondensed Medium Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display SemiCondensed Medium Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font Mono", + "preferred_subfamily_name": "SemiCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display SemiCondensed Medium Nerd Font Complete.ttf||1258456:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font", + "font-family": "NotoSansDisplay Nerd Font", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Display SemiCondensed Medium Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display SemiCondensed Medium Nerd Font Complete.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font", + "preferred_subfamily_name": "SemiCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display SemiCondensed Nerd Font Complete Mono.ttf||1246580:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font Mono", + "font-family": "NotoSansDisplay Nerd Font Mono", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Display SemiCondensed Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display SemiCondensed Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font Mono", + "preferred_subfamily_name": "SemiCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display SemiCondensed Nerd Font Complete.ttf||1259852:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font", + "font-family": "NotoSansDisplay Nerd Font", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Display SemiCondensed Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display SemiCondensed Nerd Font Complete.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font", + "preferred_subfamily_name": "SemiCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display SemiCondensed SemiBold Italic Nerd Font Complete Mono.ttf||1269384:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font Mono", + "font-family": "NotoSansDisplay Nerd Font Mono", + "font-stretch": "semi-condensed", + "font-style": "italic", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Display SemiCondensed SemiBold Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 2, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display SemiCondensed SemiBold Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font Mono", + "preferred_subfamily_name": "SemiCondensed SemiBold Italic", + "subfamily_name": "Italic", + "weight": 600, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display SemiCondensed SemiBold Italic Nerd Font Complete.ttf||1283228:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font", + "font-family": "NotoSansDisplay Nerd Font", + "font-stretch": "semi-condensed", + "font-style": "italic", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Display SemiCondensed SemiBold Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 2, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display SemiCondensed SemiBold Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font", + "preferred_subfamily_name": "SemiCondensed SemiBold Italic", + "subfamily_name": "Italic", + "weight": 600, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display SemiCondensed SemiBold Nerd Font Complete Mono.ttf||1248976:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font Mono", + "font-family": "NotoSansDisplay Nerd Font Mono", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Display SemiCondensed SemiBold Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display SemiCondensed SemiBold Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font Mono", + "preferred_subfamily_name": "SemiCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display SemiCondensed SemiBold Nerd Font Complete.ttf||1260916:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font", + "font-family": "NotoSansDisplay Nerd Font", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Display SemiCondensed SemiBold Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display SemiCondensed SemiBold Nerd Font Complete.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font", + "preferred_subfamily_name": "SemiCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display SemiCondensed Thin Italic Nerd Font Complete Mono.ttf||1249084:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font Mono", + "font-family": "NotoSansDisplay Nerd Font Mono", + "font-stretch": "semi-condensed", + "font-style": "italic", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Display SemiCondensed Thin Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 2, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display SemiCondensed Thin Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font Mono", + "preferred_subfamily_name": "SemiCondensed Thin Italic", + "subfamily_name": "Italic", + "weight": 100, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display SemiCondensed Thin Italic Nerd Font Complete.ttf||1262552:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font", + "font-family": "NotoSansDisplay Nerd Font", + "font-stretch": "semi-condensed", + "font-style": "italic", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Display SemiCondensed Thin Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 2, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display SemiCondensed Thin Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font", + "preferred_subfamily_name": "SemiCondensed Thin Italic", + "subfamily_name": "Italic", + "weight": 100, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display SemiCondensed Thin Nerd Font Complete Mono.ttf||1230676:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font Mono", + "font-family": "NotoSansDisplay Nerd Font Mono", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Display SemiCondensed Thin Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display SemiCondensed Thin Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font Mono", + "preferred_subfamily_name": "SemiCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display SemiCondensed Thin Nerd Font Complete.ttf||1243740:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font", + "font-family": "NotoSansDisplay Nerd Font", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Display SemiCondensed Thin Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display SemiCondensed Thin Nerd Font Complete.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font", + "preferred_subfamily_name": "SemiCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Thin Italic Nerd Font Complete Mono.ttf||1249056:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font Mono", + "font-family": "NotoSansDisplay Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Display Thin Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 2, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Thin Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font Mono", + "preferred_subfamily_name": "Thin Italic", + "subfamily_name": "Italic", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Thin Italic Nerd Font Complete.ttf||1261484:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font", + "font-family": "NotoSansDisplay Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Display Thin Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 2, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Thin Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font", + "preferred_subfamily_name": "Thin Italic", + "subfamily_name": "Italic", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Thin Nerd Font Complete Mono.ttf||1235044:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font Mono", + "font-family": "NotoSansDisplay Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Display Thin Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Thin Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font Mono", + "preferred_subfamily_name": "Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Thin Nerd Font Complete.ttf||1243572:1634564302.0": { + "family_name": "NotoSansDisplay Nerd Font", + "font-family": "NotoSansDisplay Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Display Thin Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Display Thin Nerd Font Complete.ttf", + "preferred_family_name": "NotoSansDisplay Nerd Font", + "preferred_subfamily_name": "Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans ExtraBold Italic Nerd Font Complete Mono.ttf||1272680:1634564302.0": { + "family_name": "NotoSans Nerd Font Mono", + "font-family": "NotoSans Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans ExtraBold Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 2, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans ExtraBold Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSans Nerd Font Mono", + "preferred_subfamily_name": "ExtraBold Italic", + "subfamily_name": "Italic", + "weight": 800, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans ExtraBold Italic Nerd Font Complete.ttf||1280132:1634564302.0": { + "family_name": "NotoSans Nerd Font", + "font-family": "NotoSans Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans ExtraBold Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 2, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans ExtraBold Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSans Nerd Font", + "preferred_subfamily_name": "ExtraBold Italic", + "subfamily_name": "Italic", + "weight": 800, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans ExtraBold Nerd Font Complete Mono.ttf||1259132:1634564302.0": { + "family_name": "NotoSans Nerd Font Mono", + "font-family": "NotoSans Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans ExtraBold Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans ExtraBold Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSans Nerd Font Mono", + "preferred_subfamily_name": "ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans ExtraBold Nerd Font Complete.ttf||1264960:1634564302.0": { + "family_name": "NotoSans Nerd Font", + "font-family": "NotoSans Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans ExtraBold Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans ExtraBold Nerd Font Complete.ttf", + "preferred_family_name": "NotoSans Nerd Font", + "preferred_subfamily_name": "ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans ExtraCondensed Black Italic Nerd Font Complete Mono.ttf||1280316:1634564302.0": { + "family_name": "NotoSans Nerd Font Mono", + "font-family": "NotoSans Nerd Font Mono", + "font-stretch": "extra-condensed", + "font-style": "italic", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans ExtraCondensed Black Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 6, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans ExtraCondensed Black Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSans Nerd Font Mono", + "preferred_subfamily_name": "ExtraCondensed Black Italic", + "subfamily_name": "Italic", + "weight": 900, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans ExtraCondensed Black Italic Nerd Font Complete.ttf||1293584:1634564302.0": { + "family_name": "NotoSans Nerd Font", + "font-family": "NotoSans Nerd Font", + "font-stretch": "extra-condensed", + "font-style": "italic", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans ExtraCondensed Black Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 6, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans ExtraCondensed Black Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSans Nerd Font", + "preferred_subfamily_name": "ExtraCondensed Black Italic", + "subfamily_name": "Italic", + "weight": 900, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans ExtraCondensed Black Nerd Font Complete Mono.ttf||1258492:1634564302.0": { + "family_name": "NotoSans Nerd Font Mono", + "font-family": "NotoSans Nerd Font Mono", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans ExtraCondensed Black Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans ExtraCondensed Black Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSans Nerd Font Mono", + "preferred_subfamily_name": "ExtraCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans ExtraCondensed Black Nerd Font Complete.ttf||1270560:1634564302.0": { + "family_name": "NotoSans Nerd Font", + "font-family": "NotoSans Nerd Font", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans ExtraCondensed Black Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans ExtraCondensed Black Nerd Font Complete.ttf", + "preferred_family_name": "NotoSans Nerd Font", + "preferred_subfamily_name": "ExtraCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans ExtraCondensed Bold Italic Nerd Font Complete Mono.ttf||1267452:1634564302.0": { + "family_name": "NotoSans Nerd Font Mono", + "font-family": "NotoSans Nerd Font Mono", + "font-stretch": "extra-condensed", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans ExtraCondensed Bold Italic Nerd Font Complete Mono", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 6, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans ExtraCondensed Bold Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSans Nerd Font Mono", + "preferred_subfamily_name": "ExtraCondensed Bold Italic", + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans ExtraCondensed Bold Italic Nerd Font Complete.ttf||1280608:1634564302.0": { + "family_name": "NotoSans Nerd Font", + "font-family": "NotoSans Nerd Font", + "font-stretch": "extra-condensed", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans ExtraCondensed Bold Italic Nerd Font Complete", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 6, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans ExtraCondensed Bold Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSans Nerd Font", + "preferred_subfamily_name": "ExtraCondensed Bold Italic", + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans ExtraCondensed Bold Nerd Font Complete Mono.ttf||1246528:1634564302.0": { + "family_name": "NotoSans Nerd Font Mono", + "font-family": "NotoSans Nerd Font Mono", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans ExtraCondensed Bold Nerd Font Complete Mono", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans ExtraCondensed Bold Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSans Nerd Font Mono", + "preferred_subfamily_name": "ExtraCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans ExtraCondensed Bold Nerd Font Complete.ttf||1259432:1634564302.0": { + "family_name": "NotoSans Nerd Font", + "font-family": "NotoSans Nerd Font", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans ExtraCondensed Bold Nerd Font Complete", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans ExtraCondensed Bold Nerd Font Complete.ttf", + "preferred_family_name": "NotoSans Nerd Font", + "preferred_subfamily_name": "ExtraCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans ExtraCondensed ExtraBold Italic Nerd Font Complete Mono.ttf||1273012:1634564302.0": { + "family_name": "NotoSans Nerd Font Mono", + "font-family": "NotoSans Nerd Font Mono", + "font-stretch": "extra-condensed", + "font-style": "italic", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans ExtraCondensed ExtraBold Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 6, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans ExtraCondensed ExtraBold Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSans Nerd Font Mono", + "preferred_subfamily_name": "ExtraCondensed ExtraBold Italic", + "subfamily_name": "Italic", + "weight": 800, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans ExtraCondensed ExtraBold Italic Nerd Font Complete.ttf||1286248:1634564302.0": { + "family_name": "NotoSans Nerd Font", + "font-family": "NotoSans Nerd Font", + "font-stretch": "extra-condensed", + "font-style": "italic", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans ExtraCondensed ExtraBold Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 6, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans ExtraCondensed ExtraBold Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSans Nerd Font", + "preferred_subfamily_name": "ExtraCondensed ExtraBold Italic", + "subfamily_name": "Italic", + "weight": 800, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans ExtraCondensed ExtraBold Nerd Font Complete Mono.ttf||1248884:1634564302.0": { + "family_name": "NotoSans Nerd Font Mono", + "font-family": "NotoSans Nerd Font Mono", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans ExtraCondensed ExtraBold Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans ExtraCondensed ExtraBold Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSans Nerd Font Mono", + "preferred_subfamily_name": "ExtraCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans ExtraCondensed ExtraBold Nerd Font Complete.ttf||1261776:1634564302.0": { + "family_name": "NotoSans Nerd Font", + "font-family": "NotoSans Nerd Font", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans ExtraCondensed ExtraBold Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans ExtraCondensed ExtraBold Nerd Font Complete.ttf", + "preferred_family_name": "NotoSans Nerd Font", + "preferred_subfamily_name": "ExtraCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans ExtraCondensed ExtraLight Italic Nerd Font Complete Mono.ttf||1250016:1634564302.0": { + "family_name": "NotoSans Nerd Font Mono", + "font-family": "NotoSans Nerd Font Mono", + "font-stretch": "extra-condensed", + "font-style": "italic", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans ExtraCondensed ExtraLight Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 6, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans ExtraCondensed ExtraLight Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSans Nerd Font Mono", + "preferred_subfamily_name": "ExtraCondensed ExtraLight Italic", + "subfamily_name": "Italic", + "weight": 200, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans ExtraCondensed ExtraLight Italic Nerd Font Complete.ttf||1262808:1634564302.0": { + "family_name": "NotoSans Nerd Font", + "font-family": "NotoSans Nerd Font", + "font-stretch": "extra-condensed", + "font-style": "italic", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans ExtraCondensed ExtraLight Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 6, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans ExtraCondensed ExtraLight Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSans Nerd Font", + "preferred_subfamily_name": "ExtraCondensed ExtraLight Italic", + "subfamily_name": "Italic", + "weight": 200, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans ExtraCondensed ExtraLight Nerd Font Complete Mono.ttf||1231252:1634564302.0": { + "family_name": "NotoSans Nerd Font Mono", + "font-family": "NotoSans Nerd Font Mono", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans ExtraCondensed ExtraLight Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans ExtraCondensed ExtraLight Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSans Nerd Font Mono", + "preferred_subfamily_name": "ExtraCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans ExtraCondensed ExtraLight Nerd Font Complete.ttf||1243916:1634564302.0": { + "family_name": "NotoSans Nerd Font", + "font-family": "NotoSans Nerd Font", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans ExtraCondensed ExtraLight Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans ExtraCondensed ExtraLight Nerd Font Complete.ttf", + "preferred_family_name": "NotoSans Nerd Font", + "preferred_subfamily_name": "ExtraCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans ExtraCondensed Italic Nerd Font Complete Mono.ttf||1264640:1634564302.0": { + "family_name": "NotoSans Nerd Font Mono", + "font-family": "NotoSans Nerd Font Mono", + "font-stretch": "extra-condensed", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans ExtraCondensed Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 6, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans ExtraCondensed Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSans Nerd Font Mono", + "preferred_subfamily_name": "ExtraCondensed Italic", + "subfamily_name": "Italic", + "weight": 400, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans ExtraCondensed Italic Nerd Font Complete.ttf||1277440:1634564302.0": { + "family_name": "NotoSans Nerd Font", + "font-family": "NotoSans Nerd Font", + "font-stretch": "extra-condensed", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans ExtraCondensed Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 6, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans ExtraCondensed Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSans Nerd Font", + "preferred_subfamily_name": "ExtraCondensed Italic", + "subfamily_name": "Italic", + "weight": 400, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans ExtraCondensed Light Italic Nerd Font Complete Mono.ttf||1257052:1634564302.0": { + "family_name": "NotoSans Nerd Font Mono", + "font-family": "NotoSans Nerd Font Mono", + "font-stretch": "extra-condensed", + "font-style": "italic", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans ExtraCondensed Light Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 6, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans ExtraCondensed Light Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSans Nerd Font Mono", + "preferred_subfamily_name": "ExtraCondensed Light Italic", + "subfamily_name": "Italic", + "weight": 300, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans ExtraCondensed Light Italic Nerd Font Complete.ttf||1269824:1634564302.0": { + "family_name": "NotoSans Nerd Font", + "font-family": "NotoSans Nerd Font", + "font-stretch": "extra-condensed", + "font-style": "italic", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans ExtraCondensed Light Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 6, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans ExtraCondensed Light Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSans Nerd Font", + "preferred_subfamily_name": "ExtraCondensed Light Italic", + "subfamily_name": "Italic", + "weight": 300, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans ExtraCondensed Light Nerd Font Complete Mono.ttf||1239408:1634564302.0": { + "family_name": "NotoSans Nerd Font Mono", + "font-family": "NotoSans Nerd Font Mono", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans ExtraCondensed Light Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans ExtraCondensed Light Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSans Nerd Font Mono", + "preferred_subfamily_name": "ExtraCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans ExtraCondensed Light Nerd Font Complete.ttf||1252092:1634564302.0": { + "family_name": "NotoSans Nerd Font", + "font-family": "NotoSans Nerd Font", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans ExtraCondensed Light Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans ExtraCondensed Light Nerd Font Complete.ttf", + "preferred_family_name": "NotoSans Nerd Font", + "preferred_subfamily_name": "ExtraCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans ExtraCondensed Medium Italic Nerd Font Complete Mono.ttf||1264940:1634564302.0": { + "family_name": "NotoSans Nerd Font Mono", + "font-family": "NotoSans Nerd Font Mono", + "font-stretch": "extra-condensed", + "font-style": "italic", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans ExtraCondensed Medium Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 6, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans ExtraCondensed Medium Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSans Nerd Font Mono", + "preferred_subfamily_name": "ExtraCondensed Medium Italic", + "subfamily_name": "Italic", + "weight": 500, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans ExtraCondensed Medium Italic Nerd Font Complete.ttf||1277968:1634564302.0": { + "family_name": "NotoSans Nerd Font", + "font-family": "NotoSans Nerd Font", + "font-stretch": "extra-condensed", + "font-style": "italic", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans ExtraCondensed Medium Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 6, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans ExtraCondensed Medium Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSans Nerd Font", + "preferred_subfamily_name": "ExtraCondensed Medium Italic", + "subfamily_name": "Italic", + "weight": 500, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans ExtraCondensed Medium Nerd Font Complete Mono.ttf||1243328:1634564302.0": { + "family_name": "NotoSans Nerd Font Mono", + "font-family": "NotoSans Nerd Font Mono", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans ExtraCondensed Medium Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans ExtraCondensed Medium Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSans Nerd Font Mono", + "preferred_subfamily_name": "ExtraCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans ExtraCondensed Medium Nerd Font Complete.ttf||1256100:1634564302.0": { + "family_name": "NotoSans Nerd Font", + "font-family": "NotoSans Nerd Font", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans ExtraCondensed Medium Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans ExtraCondensed Medium Nerd Font Complete.ttf", + "preferred_family_name": "NotoSans Nerd Font", + "preferred_subfamily_name": "ExtraCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans ExtraCondensed Nerd Font Complete Mono.ttf||1244984:1634564302.0": { + "family_name": "NotoSans Nerd Font Mono", + "font-family": "NotoSans Nerd Font Mono", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans ExtraCondensed Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans ExtraCondensed Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSans Nerd Font Mono", + "preferred_subfamily_name": "ExtraCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans ExtraCondensed Nerd Font Complete.ttf||1257672:1634564302.0": { + "family_name": "NotoSans Nerd Font", + "font-family": "NotoSans Nerd Font", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans ExtraCondensed Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans ExtraCondensed Nerd Font Complete.ttf", + "preferred_family_name": "NotoSans Nerd Font", + "preferred_subfamily_name": "ExtraCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans ExtraCondensed SemiBold Italic Nerd Font Complete Mono.ttf||1264820:1634564302.0": { + "family_name": "NotoSans Nerd Font Mono", + "font-family": "NotoSans Nerd Font Mono", + "font-stretch": "extra-condensed", + "font-style": "italic", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans ExtraCondensed SemiBold Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 6, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans ExtraCondensed SemiBold Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSans Nerd Font Mono", + "preferred_subfamily_name": "ExtraCondensed SemiBold Italic", + "subfamily_name": "Italic", + "weight": 600, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans ExtraCondensed SemiBold Italic Nerd Font Complete.ttf||1277904:1634564302.0": { + "family_name": "NotoSans Nerd Font", + "font-family": "NotoSans Nerd Font", + "font-stretch": "extra-condensed", + "font-style": "italic", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans ExtraCondensed SemiBold Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 6, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans ExtraCondensed SemiBold Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSans Nerd Font", + "preferred_subfamily_name": "ExtraCondensed SemiBold Italic", + "subfamily_name": "Italic", + "weight": 600, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans ExtraCondensed SemiBold Nerd Font Complete Mono.ttf||1244144:1634564302.0": { + "family_name": "NotoSans Nerd Font Mono", + "font-family": "NotoSans Nerd Font Mono", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans ExtraCondensed SemiBold Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans ExtraCondensed SemiBold Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSans Nerd Font Mono", + "preferred_subfamily_name": "ExtraCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans ExtraCondensed SemiBold Nerd Font Complete.ttf||1256984:1634564302.0": { + "family_name": "NotoSans Nerd Font", + "font-family": "NotoSans Nerd Font", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans ExtraCondensed SemiBold Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans ExtraCondensed SemiBold Nerd Font Complete.ttf", + "preferred_family_name": "NotoSans Nerd Font", + "preferred_subfamily_name": "ExtraCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans ExtraCondensed Thin Italic Nerd Font Complete Mono.ttf||1249504:1634564302.0": { + "family_name": "NotoSans Nerd Font Mono", + "font-family": "NotoSans Nerd Font Mono", + "font-stretch": "extra-condensed", + "font-style": "italic", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans ExtraCondensed Thin Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 6, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans ExtraCondensed Thin Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSans Nerd Font Mono", + "preferred_subfamily_name": "ExtraCondensed Thin Italic", + "subfamily_name": "Italic", + "weight": 100, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans ExtraCondensed Thin Italic Nerd Font Complete.ttf||1262348:1634564302.0": { + "family_name": "NotoSans Nerd Font", + "font-family": "NotoSans Nerd Font", + "font-stretch": "extra-condensed", + "font-style": "italic", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans ExtraCondensed Thin Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 6, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans ExtraCondensed Thin Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSans Nerd Font", + "preferred_subfamily_name": "ExtraCondensed Thin Italic", + "subfamily_name": "Italic", + "weight": 100, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans ExtraCondensed Thin Nerd Font Complete Mono.ttf||1229788:1634564302.0": { + "family_name": "NotoSans Nerd Font Mono", + "font-family": "NotoSans Nerd Font Mono", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans ExtraCondensed Thin Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans ExtraCondensed Thin Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSans Nerd Font Mono", + "preferred_subfamily_name": "ExtraCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans ExtraCondensed Thin Nerd Font Complete.ttf||1242472:1634564302.0": { + "family_name": "NotoSans Nerd Font", + "font-family": "NotoSans Nerd Font", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans ExtraCondensed Thin Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans ExtraCondensed Thin Nerd Font Complete.ttf", + "preferred_family_name": "NotoSans Nerd Font", + "preferred_subfamily_name": "ExtraCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans ExtraLight Italic Nerd Font Complete Mono.ttf||1253436:1634564302.0": { + "family_name": "NotoSans Nerd Font Mono", + "font-family": "NotoSans Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans ExtraLight Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 2, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans ExtraLight Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSans Nerd Font Mono", + "preferred_subfamily_name": "ExtraLight Italic", + "subfamily_name": "Italic", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans ExtraLight Italic Nerd Font Complete.ttf||1263748:1634564302.0": { + "family_name": "NotoSans Nerd Font", + "font-family": "NotoSans Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans ExtraLight Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 2, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans ExtraLight Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSans Nerd Font", + "preferred_subfamily_name": "ExtraLight Italic", + "subfamily_name": "Italic", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans ExtraLight Nerd Font Complete Mono.ttf||1239684:1634564302.0": { + "family_name": "NotoSans Nerd Font Mono", + "font-family": "NotoSans Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans ExtraLight Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans ExtraLight Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSans Nerd Font Mono", + "preferred_subfamily_name": "ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans ExtraLight Nerd Font Complete.ttf||1246144:1634564302.0": { + "family_name": "NotoSans Nerd Font", + "font-family": "NotoSans Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans ExtraLight Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans ExtraLight Nerd Font Complete.ttf", + "preferred_family_name": "NotoSans Nerd Font", + "preferred_subfamily_name": "ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Italic Nerd Font Complete Mono.ttf||1268312:1634564302.0": { + "family_name": "NotoSans Nerd Font Mono", + "font-family": "NotoSans Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSans Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Italic Nerd Font Complete.ttf||1279024:1634564302.0": { + "family_name": "NotoSans Nerd Font", + "font-family": "NotoSans Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSans Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Light Italic Nerd Font Complete Mono.ttf||1260536:1634564302.0": { + "family_name": "NotoSans Nerd Font Mono", + "font-family": "NotoSans Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Light Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 2, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Light Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSans Nerd Font Mono", + "preferred_subfamily_name": "Light Italic", + "subfamily_name": "Italic", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Light Italic Nerd Font Complete.ttf||1270980:1634564302.0": { + "family_name": "NotoSans Nerd Font", + "font-family": "NotoSans Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Light Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 2, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Light Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSans Nerd Font", + "preferred_subfamily_name": "Light Italic", + "subfamily_name": "Italic", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Light Nerd Font Complete Mono.ttf||1245952:1634564302.0": { + "family_name": "NotoSans Nerd Font Mono", + "font-family": "NotoSans Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Light Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Light Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSans Nerd Font Mono", + "preferred_subfamily_name": "Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Light Nerd Font Complete.ttf||1252524:1634564302.0": { + "family_name": "NotoSans Nerd Font", + "font-family": "NotoSans Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Light Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Light Nerd Font Complete.ttf", + "preferred_family_name": "NotoSans Nerd Font", + "preferred_subfamily_name": "Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Medium Italic Nerd Font Complete Mono.ttf||1265036:1634564302.0": { + "family_name": "NotoSans Nerd Font Mono", + "font-family": "NotoSans Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Medium Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 2, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Medium Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSans Nerd Font Mono", + "preferred_subfamily_name": "Medium Italic", + "subfamily_name": "Italic", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Medium Italic Nerd Font Complete.ttf||1275404:1634564302.0": { + "family_name": "NotoSans Nerd Font", + "font-family": "NotoSans Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Medium Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 2, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Medium Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSans Nerd Font", + "preferred_subfamily_name": "Medium Italic", + "subfamily_name": "Italic", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Medium Nerd Font Complete Mono.ttf||1254980:1634564302.0": { + "family_name": "NotoSans Nerd Font Mono", + "font-family": "NotoSans Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Medium Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Medium Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSans Nerd Font Mono", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Medium Nerd Font Complete.ttf||1261652:1634564302.0": { + "family_name": "NotoSans Nerd Font", + "font-family": "NotoSans Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Medium Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Medium Nerd Font Complete.ttf", + "preferred_family_name": "NotoSans Nerd Font", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono Black Nerd Font Complete Mono.ttf||1257864:1634564302.0": { + "family_name": "NotoSansMono Nerd Font Mono", + "font-family": "NotoSansMono Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Mono Black Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 9, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono Black Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSansMono Nerd Font Mono", + "preferred_subfamily_name": "Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono Black Nerd Font Complete.ttf||1261916:1634564302.0": { + "family_name": "NotoSansMono Nerd Font", + "font-family": "NotoSansMono Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Mono Black Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 9, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono Black Nerd Font Complete.ttf", + "preferred_family_name": "NotoSansMono Nerd Font", + "preferred_subfamily_name": "Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono Bold Nerd Font Complete Mono.ttf||1252284:1634564302.0": { + "family_name": "NotoSansMono Nerd Font Mono", + "font-family": "NotoSansMono Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Mono Bold Nerd Font Complete Mono", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 9, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono Bold Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSansMono Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono Bold Nerd Font Complete.ttf||1256332:1634564302.0": { + "family_name": "NotoSansMono Nerd Font", + "font-family": "NotoSansMono Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Mono Bold Nerd Font Complete", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 9, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono Bold Nerd Font Complete.ttf", + "preferred_family_name": "NotoSansMono Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono Condensed Black Nerd Font Complete Mono.ttf||1246788:1634564302.0": { + "family_name": "NotoSansMono Nerd Font Mono", + "font-family": "NotoSansMono Nerd Font Mono", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Mono Condensed Black Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 9, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono Condensed Black Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSansMono Nerd Font Mono", + "preferred_subfamily_name": "Condensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono Condensed Black Nerd Font Complete.ttf||1251884:1634564302.0": { + "family_name": "NotoSansMono Nerd Font", + "font-family": "NotoSansMono Nerd Font", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Mono Condensed Black Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 9, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono Condensed Black Nerd Font Complete.ttf", + "preferred_family_name": "NotoSansMono Nerd Font", + "preferred_subfamily_name": "Condensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono Condensed Bold Nerd Font Complete Mono.ttf||1243356:1634564302.0": { + "family_name": "NotoSansMono Nerd Font Mono", + "font-family": "NotoSansMono Nerd Font Mono", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Mono Condensed Bold Nerd Font Complete Mono", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 9, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono Condensed Bold Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSansMono Nerd Font Mono", + "preferred_subfamily_name": "Condensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono Condensed Bold Nerd Font Complete.ttf||1248440:1634564302.0": { + "family_name": "NotoSansMono Nerd Font", + "font-family": "NotoSansMono Nerd Font", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Mono Condensed Bold Nerd Font Complete", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 9, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono Condensed Bold Nerd Font Complete.ttf", + "preferred_family_name": "NotoSansMono Nerd Font", + "preferred_subfamily_name": "Condensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono Condensed ExtraBold Nerd Font Complete Mono.ttf||1243204:1634564302.0": { + "family_name": "NotoSansMono Nerd Font Mono", + "font-family": "NotoSansMono Nerd Font Mono", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Mono Condensed ExtraBold Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 9, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono Condensed ExtraBold Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSansMono Nerd Font Mono", + "preferred_subfamily_name": "Condensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono Condensed ExtraBold Nerd Font Complete.ttf||1248316:1634564302.0": { + "family_name": "NotoSansMono Nerd Font", + "font-family": "NotoSansMono Nerd Font", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Mono Condensed ExtraBold Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 9, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono Condensed ExtraBold Nerd Font Complete.ttf", + "preferred_family_name": "NotoSansMono Nerd Font", + "preferred_subfamily_name": "Condensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono Condensed ExtraLight Nerd Font Complete Mono.ttf||1226856:1634564302.0": { + "family_name": "NotoSansMono Nerd Font Mono", + "font-family": "NotoSansMono Nerd Font Mono", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Mono Condensed ExtraLight Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 9, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono Condensed ExtraLight Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSansMono Nerd Font Mono", + "preferred_subfamily_name": "Condensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono Condensed ExtraLight Nerd Font Complete.ttf||1231960:1634564302.0": { + "family_name": "NotoSansMono Nerd Font", + "font-family": "NotoSansMono Nerd Font", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Mono Condensed ExtraLight Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 9, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono Condensed ExtraLight Nerd Font Complete.ttf", + "preferred_family_name": "NotoSansMono Nerd Font", + "preferred_subfamily_name": "Condensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono Condensed Light Nerd Font Complete Mono.ttf||1233492:1634564302.0": { + "family_name": "NotoSansMono Nerd Font Mono", + "font-family": "NotoSansMono Nerd Font Mono", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Mono Condensed Light Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 9, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono Condensed Light Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSansMono Nerd Font Mono", + "preferred_subfamily_name": "Condensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono Condensed Light Nerd Font Complete.ttf||1238588:1634564302.0": { + "family_name": "NotoSansMono Nerd Font", + "font-family": "NotoSansMono Nerd Font", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Mono Condensed Light Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 9, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono Condensed Light Nerd Font Complete.ttf", + "preferred_family_name": "NotoSansMono Nerd Font", + "preferred_subfamily_name": "Condensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono Condensed Medium Nerd Font Complete Mono.ttf||1240680:1634564302.0": { + "family_name": "NotoSansMono Nerd Font Mono", + "font-family": "NotoSansMono Nerd Font Mono", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Mono Condensed Medium Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 9, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono Condensed Medium Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSansMono Nerd Font Mono", + "preferred_subfamily_name": "Condensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono Condensed Medium Nerd Font Complete.ttf||1245788:1634564302.0": { + "family_name": "NotoSansMono Nerd Font", + "font-family": "NotoSansMono Nerd Font", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Mono Condensed Medium Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 9, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono Condensed Medium Nerd Font Complete.ttf", + "preferred_family_name": "NotoSansMono Nerd Font", + "preferred_subfamily_name": "Condensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono Condensed Nerd Font Complete Mono.ttf||1240068:1634564302.0": { + "family_name": "NotoSansMono Nerd Font Mono", + "font-family": "NotoSansMono Nerd Font Mono", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Mono Condensed Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 9, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono Condensed Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSansMono Nerd Font Mono", + "preferred_subfamily_name": "Condensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono Condensed Nerd Font Complete.ttf||1245172:1634564302.0": { + "family_name": "NotoSansMono Nerd Font", + "font-family": "NotoSansMono Nerd Font", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Mono Condensed Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 9, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono Condensed Nerd Font Complete.ttf", + "preferred_family_name": "NotoSansMono Nerd Font", + "preferred_subfamily_name": "Condensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono Condensed SemiBold Nerd Font Complete Mono.ttf||1243724:1634564302.0": { + "family_name": "NotoSansMono Nerd Font Mono", + "font-family": "NotoSansMono Nerd Font Mono", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Mono Condensed SemiBold Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 9, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono Condensed SemiBold Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSansMono Nerd Font Mono", + "preferred_subfamily_name": "Condensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono Condensed SemiBold Nerd Font Complete.ttf||1248820:1634564302.0": { + "family_name": "NotoSansMono Nerd Font", + "font-family": "NotoSansMono Nerd Font", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Mono Condensed SemiBold Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 9, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono Condensed SemiBold Nerd Font Complete.ttf", + "preferred_family_name": "NotoSansMono Nerd Font", + "preferred_subfamily_name": "Condensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono Condensed Thin Nerd Font Complete Mono.ttf||1230836:1634564302.0": { + "family_name": "NotoSansMono Nerd Font Mono", + "font-family": "NotoSansMono Nerd Font Mono", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Mono Condensed Thin Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 9, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono Condensed Thin Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSansMono Nerd Font Mono", + "preferred_subfamily_name": "Condensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono Condensed Thin Nerd Font Complete.ttf||1235940:1634564302.0": { + "family_name": "NotoSansMono Nerd Font", + "font-family": "NotoSansMono Nerd Font", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Mono Condensed Thin Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 9, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono Condensed Thin Nerd Font Complete.ttf", + "preferred_family_name": "NotoSansMono Nerd Font", + "preferred_subfamily_name": "Condensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono ExtraBold Nerd Font Complete Mono.ttf||1251356:1634564302.0": { + "family_name": "NotoSansMono Nerd Font Mono", + "font-family": "NotoSansMono Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Mono ExtraBold Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 9, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono ExtraBold Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSansMono Nerd Font Mono", + "preferred_subfamily_name": "ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono ExtraBold Nerd Font Complete.ttf||1255416:1634564302.0": { + "family_name": "NotoSansMono Nerd Font", + "font-family": "NotoSansMono Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Mono ExtraBold Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 9, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono ExtraBold Nerd Font Complete.ttf", + "preferred_family_name": "NotoSansMono Nerd Font", + "preferred_subfamily_name": "ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono ExtraCondensed Black Nerd Font Complete Mono.ttf||1245456:1634564302.0": { + "family_name": "NotoSansMono Nerd Font Mono", + "font-family": "NotoSansMono Nerd Font Mono", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Mono ExtraCondensed Black Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 9, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono ExtraCondensed Black Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSansMono Nerd Font Mono", + "preferred_subfamily_name": "ExtraCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono ExtraCondensed Black Nerd Font Complete.ttf||1251564:1634564302.0": { + "family_name": "NotoSansMono Nerd Font", + "font-family": "NotoSansMono Nerd Font", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Mono ExtraCondensed Black Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 9, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono ExtraCondensed Black Nerd Font Complete.ttf", + "preferred_family_name": "NotoSansMono Nerd Font", + "preferred_subfamily_name": "ExtraCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono ExtraCondensed Bold Nerd Font Complete Mono.ttf||1243084:1634564302.0": { + "family_name": "NotoSansMono Nerd Font Mono", + "font-family": "NotoSansMono Nerd Font Mono", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Mono ExtraCondensed Bold Nerd Font Complete Mono", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 9, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono ExtraCondensed Bold Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSansMono Nerd Font Mono", + "preferred_subfamily_name": "ExtraCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono ExtraCondensed Bold Nerd Font Complete.ttf||1249180:1634564302.0": { + "family_name": "NotoSansMono Nerd Font", + "font-family": "NotoSansMono Nerd Font", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Mono ExtraCondensed Bold Nerd Font Complete", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 9, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono ExtraCondensed Bold Nerd Font Complete.ttf", + "preferred_family_name": "NotoSansMono Nerd Font", + "preferred_subfamily_name": "ExtraCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono ExtraCondensed ExtraBold Nerd Font Complete Mono.ttf||1244304:1634564302.0": { + "family_name": "NotoSansMono Nerd Font Mono", + "font-family": "NotoSansMono Nerd Font Mono", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Mono ExtraCondensed ExtraBold Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 9, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono ExtraCondensed ExtraBold Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSansMono Nerd Font Mono", + "preferred_subfamily_name": "ExtraCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono ExtraCondensed ExtraBold Nerd Font Complete.ttf||1250404:1634564302.0": { + "family_name": "NotoSansMono Nerd Font", + "font-family": "NotoSansMono Nerd Font", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Mono ExtraCondensed ExtraBold Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 9, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono ExtraCondensed ExtraBold Nerd Font Complete.ttf", + "preferred_family_name": "NotoSansMono Nerd Font", + "preferred_subfamily_name": "ExtraCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono ExtraCondensed ExtraLight Nerd Font Complete Mono.ttf||1226248:1634564302.0": { + "family_name": "NotoSansMono Nerd Font Mono", + "font-family": "NotoSansMono Nerd Font Mono", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Mono ExtraCondensed ExtraLight Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 9, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono ExtraCondensed ExtraLight Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSansMono Nerd Font Mono", + "preferred_subfamily_name": "ExtraCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono ExtraCondensed ExtraLight Nerd Font Complete.ttf||1232352:1634564302.0": { + "family_name": "NotoSansMono Nerd Font", + "font-family": "NotoSansMono Nerd Font", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Mono ExtraCondensed ExtraLight Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 9, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono ExtraCondensed ExtraLight Nerd Font Complete.ttf", + "preferred_family_name": "NotoSansMono Nerd Font", + "preferred_subfamily_name": "ExtraCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono ExtraCondensed Light Nerd Font Complete Mono.ttf||1230540:1634564302.0": { + "family_name": "NotoSansMono Nerd Font Mono", + "font-family": "NotoSansMono Nerd Font Mono", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Mono ExtraCondensed Light Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 9, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono ExtraCondensed Light Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSansMono Nerd Font Mono", + "preferred_subfamily_name": "ExtraCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono ExtraCondensed Light Nerd Font Complete.ttf||1236644:1634564302.0": { + "family_name": "NotoSansMono Nerd Font", + "font-family": "NotoSansMono Nerd Font", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Mono ExtraCondensed Light Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 9, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono ExtraCondensed Light Nerd Font Complete.ttf", + "preferred_family_name": "NotoSansMono Nerd Font", + "preferred_subfamily_name": "ExtraCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono ExtraCondensed Medium Nerd Font Complete Mono.ttf||1238348:1634564302.0": { + "family_name": "NotoSansMono Nerd Font Mono", + "font-family": "NotoSansMono Nerd Font Mono", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Mono ExtraCondensed Medium Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 9, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono ExtraCondensed Medium Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSansMono Nerd Font Mono", + "preferred_subfamily_name": "ExtraCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono ExtraCondensed Medium Nerd Font Complete.ttf||1244440:1634564302.0": { + "family_name": "NotoSansMono Nerd Font", + "font-family": "NotoSansMono Nerd Font", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Mono ExtraCondensed Medium Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 9, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono ExtraCondensed Medium Nerd Font Complete.ttf", + "preferred_family_name": "NotoSansMono Nerd Font", + "preferred_subfamily_name": "ExtraCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono ExtraCondensed Nerd Font Complete Mono.ttf||1238032:1634564302.0": { + "family_name": "NotoSansMono Nerd Font Mono", + "font-family": "NotoSansMono Nerd Font Mono", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Mono ExtraCondensed Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 9, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono ExtraCondensed Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSansMono Nerd Font Mono", + "preferred_subfamily_name": "ExtraCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono ExtraCondensed Nerd Font Complete.ttf||1244156:1634564302.0": { + "family_name": "NotoSansMono Nerd Font", + "font-family": "NotoSansMono Nerd Font", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Mono ExtraCondensed Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 9, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono ExtraCondensed Nerd Font Complete.ttf", + "preferred_family_name": "NotoSansMono Nerd Font", + "preferred_subfamily_name": "ExtraCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono ExtraCondensed SemiBold Nerd Font Complete Mono.ttf||1238356:1634564302.0": { + "family_name": "NotoSansMono Nerd Font Mono", + "font-family": "NotoSansMono Nerd Font Mono", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Mono ExtraCondensed SemiBold Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 9, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono ExtraCondensed SemiBold Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSansMono Nerd Font Mono", + "preferred_subfamily_name": "ExtraCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono ExtraCondensed SemiBold Nerd Font Complete.ttf||1244444:1634564302.0": { + "family_name": "NotoSansMono Nerd Font", + "font-family": "NotoSansMono Nerd Font", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Mono ExtraCondensed SemiBold Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 9, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono ExtraCondensed SemiBold Nerd Font Complete.ttf", + "preferred_family_name": "NotoSansMono Nerd Font", + "preferred_subfamily_name": "ExtraCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono ExtraCondensed Thin Nerd Font Complete Mono.ttf||1228676:1634564302.0": { + "family_name": "NotoSansMono Nerd Font Mono", + "font-family": "NotoSansMono Nerd Font Mono", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Mono ExtraCondensed Thin Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 9, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono ExtraCondensed Thin Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSansMono Nerd Font Mono", + "preferred_subfamily_name": "ExtraCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono ExtraCondensed Thin Nerd Font Complete.ttf||1234780:1634564302.0": { + "family_name": "NotoSansMono Nerd Font", + "font-family": "NotoSansMono Nerd Font", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Mono ExtraCondensed Thin Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 9, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono ExtraCondensed Thin Nerd Font Complete.ttf", + "preferred_family_name": "NotoSansMono Nerd Font", + "preferred_subfamily_name": "ExtraCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono ExtraLight Nerd Font Complete Mono.ttf||1230188:1634564302.0": { + "family_name": "NotoSansMono Nerd Font Mono", + "font-family": "NotoSansMono Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Mono ExtraLight Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 9, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono ExtraLight Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSansMono Nerd Font Mono", + "preferred_subfamily_name": "ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono ExtraLight Nerd Font Complete.ttf||1234240:1634564302.0": { + "family_name": "NotoSansMono Nerd Font", + "font-family": "NotoSansMono Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Mono ExtraLight Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 9, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono ExtraLight Nerd Font Complete.ttf", + "preferred_family_name": "NotoSansMono Nerd Font", + "preferred_subfamily_name": "ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono Light Nerd Font Complete Mono.ttf||1234984:1634564302.0": { + "family_name": "NotoSansMono Nerd Font Mono", + "font-family": "NotoSansMono Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Mono Light Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 9, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono Light Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSansMono Nerd Font Mono", + "preferred_subfamily_name": "Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono Light Nerd Font Complete.ttf||1239028:1634564302.0": { + "family_name": "NotoSansMono Nerd Font", + "font-family": "NotoSansMono Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Mono Light Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 9, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono Light Nerd Font Complete.ttf", + "preferred_family_name": "NotoSansMono Nerd Font", + "preferred_subfamily_name": "Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono Medium Nerd Font Complete Mono.ttf||1242432:1634564302.0": { + "family_name": "NotoSansMono Nerd Font Mono", + "font-family": "NotoSansMono Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Mono Medium Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 9, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono Medium Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSansMono Nerd Font Mono", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono Medium Nerd Font Complete.ttf||1246492:1634564302.0": { + "family_name": "NotoSansMono Nerd Font", + "font-family": "NotoSansMono Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Mono Medium Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 9, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono Medium Nerd Font Complete.ttf", + "preferred_family_name": "NotoSansMono Nerd Font", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono Regular Nerd Font Complete Mono.ttf||1241316:1634564302.0": { + "family_name": "NotoSansMono Nerd Font Mono", + "font-family": "NotoSansMono Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Mono Regular Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 9, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono Regular Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSansMono Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono Regular Nerd Font Complete.ttf||1245352:1634564302.0": { + "family_name": "NotoSansMono Nerd Font", + "font-family": "NotoSansMono Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Mono Regular Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 9, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono Regular Nerd Font Complete.ttf", + "preferred_family_name": "NotoSansMono Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono SemiBold Nerd Font Complete Mono.ttf||1245680:1634564302.0": { + "family_name": "NotoSansMono Nerd Font Mono", + "font-family": "NotoSansMono Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Mono SemiBold Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 9, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono SemiBold Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSansMono Nerd Font Mono", + "preferred_subfamily_name": "SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono SemiBold Nerd Font Complete.ttf||1249724:1634564302.0": { + "family_name": "NotoSansMono Nerd Font", + "font-family": "NotoSansMono Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Mono SemiBold Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 9, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono SemiBold Nerd Font Complete.ttf", + "preferred_family_name": "NotoSansMono Nerd Font", + "preferred_subfamily_name": "SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono SemiCondensed Black Nerd Font Complete Mono.ttf||1254316:1634564302.0": { + "family_name": "NotoSansMono Nerd Font Mono", + "font-family": "NotoSansMono Nerd Font Mono", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Mono SemiCondensed Black Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 9, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono SemiCondensed Black Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSansMono Nerd Font Mono", + "preferred_subfamily_name": "SemiCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono SemiCondensed Black Nerd Font Complete.ttf||1258944:1634564302.0": { + "family_name": "NotoSansMono Nerd Font", + "font-family": "NotoSansMono Nerd Font", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Mono SemiCondensed Black Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 9, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono SemiCondensed Black Nerd Font Complete.ttf", + "preferred_family_name": "NotoSansMono Nerd Font", + "preferred_subfamily_name": "SemiCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono SemiCondensed Bold Nerd Font Complete Mono.ttf||1243440:1634564302.0": { + "family_name": "NotoSansMono Nerd Font Mono", + "font-family": "NotoSansMono Nerd Font Mono", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Mono SemiCondensed Bold Nerd Font Complete Mono", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 9, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono SemiCondensed Bold Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSansMono Nerd Font Mono", + "preferred_subfamily_name": "SemiCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono SemiCondensed Bold Nerd Font Complete.ttf||1248048:1634564302.0": { + "family_name": "NotoSansMono Nerd Font", + "font-family": "NotoSansMono Nerd Font", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Mono SemiCondensed Bold Nerd Font Complete", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 9, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono SemiCondensed Bold Nerd Font Complete.ttf", + "preferred_family_name": "NotoSansMono Nerd Font", + "preferred_subfamily_name": "SemiCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono SemiCondensed ExtraBold Nerd Font Complete Mono.ttf||1243304:1634564302.0": { + "family_name": "NotoSansMono Nerd Font Mono", + "font-family": "NotoSansMono Nerd Font Mono", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Mono SemiCondensed ExtraBold Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 9, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono SemiCondensed ExtraBold Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSansMono Nerd Font Mono", + "preferred_subfamily_name": "SemiCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono SemiCondensed ExtraBold Nerd Font Complete.ttf||1247932:1634564302.0": { + "family_name": "NotoSansMono Nerd Font", + "font-family": "NotoSansMono Nerd Font", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Mono SemiCondensed ExtraBold Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 9, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono SemiCondensed ExtraBold Nerd Font Complete.ttf", + "preferred_family_name": "NotoSansMono Nerd Font", + "preferred_subfamily_name": "SemiCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono SemiCondensed ExtraLight Nerd Font Complete Mono.ttf||1229124:1634564302.0": { + "family_name": "NotoSansMono Nerd Font Mono", + "font-family": "NotoSansMono Nerd Font Mono", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Mono SemiCondensed ExtraLight Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 9, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono SemiCondensed ExtraLight Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSansMono Nerd Font Mono", + "preferred_subfamily_name": "SemiCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono SemiCondensed ExtraLight Nerd Font Complete.ttf||1233744:1634564302.0": { + "family_name": "NotoSansMono Nerd Font", + "font-family": "NotoSansMono Nerd Font", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Mono SemiCondensed ExtraLight Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 9, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono SemiCondensed ExtraLight Nerd Font Complete.ttf", + "preferred_family_name": "NotoSansMono Nerd Font", + "preferred_subfamily_name": "SemiCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono SemiCondensed Light Nerd Font Complete Mono.ttf||1234640:1634564302.0": { + "family_name": "NotoSansMono Nerd Font Mono", + "font-family": "NotoSansMono Nerd Font Mono", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Mono SemiCondensed Light Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 9, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono SemiCondensed Light Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSansMono Nerd Font Mono", + "preferred_subfamily_name": "SemiCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono SemiCondensed Light Nerd Font Complete.ttf||1239244:1634564302.0": { + "family_name": "NotoSansMono Nerd Font", + "font-family": "NotoSansMono Nerd Font", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Mono SemiCondensed Light Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 9, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono SemiCondensed Light Nerd Font Complete.ttf", + "preferred_family_name": "NotoSansMono Nerd Font", + "preferred_subfamily_name": "SemiCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono SemiCondensed Medium Nerd Font Complete Mono.ttf||1240932:1634564302.0": { + "family_name": "NotoSansMono Nerd Font Mono", + "font-family": "NotoSansMono Nerd Font Mono", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Mono SemiCondensed Medium Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 9, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono SemiCondensed Medium Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSansMono Nerd Font Mono", + "preferred_subfamily_name": "SemiCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono SemiCondensed Medium Nerd Font Complete.ttf||1245544:1634564302.0": { + "family_name": "NotoSansMono Nerd Font", + "font-family": "NotoSansMono Nerd Font", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Mono SemiCondensed Medium Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 9, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono SemiCondensed Medium Nerd Font Complete.ttf", + "preferred_family_name": "NotoSansMono Nerd Font", + "preferred_subfamily_name": "SemiCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono SemiCondensed Nerd Font Complete Mono.ttf||1238820:1634564302.0": { + "family_name": "NotoSansMono Nerd Font Mono", + "font-family": "NotoSansMono Nerd Font Mono", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Mono SemiCondensed Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 9, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono SemiCondensed Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSansMono Nerd Font Mono", + "preferred_subfamily_name": "SemiCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono SemiCondensed Nerd Font Complete.ttf||1243424:1634564302.0": { + "family_name": "NotoSansMono Nerd Font", + "font-family": "NotoSansMono Nerd Font", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Mono SemiCondensed Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 9, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono SemiCondensed Nerd Font Complete.ttf", + "preferred_family_name": "NotoSansMono Nerd Font", + "preferred_subfamily_name": "SemiCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono SemiCondensed SemiBold Nerd Font Complete Mono.ttf||1242584:1634564302.0": { + "family_name": "NotoSansMono Nerd Font Mono", + "font-family": "NotoSansMono Nerd Font Mono", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Mono SemiCondensed SemiBold Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 9, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono SemiCondensed SemiBold Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSansMono Nerd Font Mono", + "preferred_subfamily_name": "SemiCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono SemiCondensed SemiBold Nerd Font Complete.ttf||1247204:1634564302.0": { + "family_name": "NotoSansMono Nerd Font", + "font-family": "NotoSansMono Nerd Font", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Mono SemiCondensed SemiBold Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 9, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono SemiCondensed SemiBold Nerd Font Complete.ttf", + "preferred_family_name": "NotoSansMono Nerd Font", + "preferred_subfamily_name": "SemiCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono SemiCondensed Thin Nerd Font Complete Mono.ttf||1230152:1634564302.0": { + "family_name": "NotoSansMono Nerd Font Mono", + "font-family": "NotoSansMono Nerd Font Mono", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Mono SemiCondensed Thin Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 9, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono SemiCondensed Thin Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSansMono Nerd Font Mono", + "preferred_subfamily_name": "SemiCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono SemiCondensed Thin Nerd Font Complete.ttf||1234764:1634564302.0": { + "family_name": "NotoSansMono Nerd Font", + "font-family": "NotoSansMono Nerd Font", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Mono SemiCondensed Thin Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 9, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono SemiCondensed Thin Nerd Font Complete.ttf", + "preferred_family_name": "NotoSansMono Nerd Font", + "preferred_subfamily_name": "SemiCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono Thin Nerd Font Complete Mono.ttf||1233016:1634564302.0": { + "family_name": "NotoSansMono Nerd Font Mono", + "font-family": "NotoSansMono Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Mono Thin Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 9, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono Thin Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSansMono Nerd Font Mono", + "preferred_subfamily_name": "Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono Thin Nerd Font Complete.ttf||1237060:1634564302.0": { + "family_name": "NotoSansMono Nerd Font", + "font-family": "NotoSansMono Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Mono Thin Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 9, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Mono Thin Nerd Font Complete.ttf", + "preferred_family_name": "NotoSansMono Nerd Font", + "preferred_subfamily_name": "Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Regular Nerd Font Complete Mono.ttf||1257540:1634564302.0": { + "family_name": "NotoSans Nerd Font Mono", + "font-family": "NotoSans Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Regular Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Regular Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSans Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Regular Nerd Font Complete.ttf||1264412:1634564302.0": { + "family_name": "NotoSans Nerd Font", + "font-family": "NotoSans Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Regular Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Regular Nerd Font Complete.ttf", + "preferred_family_name": "NotoSans Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans SemiBold Italic Nerd Font Complete Mono.ttf||1269756:1634564302.0": { + "family_name": "NotoSans Nerd Font Mono", + "font-family": "NotoSans Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans SemiBold Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 2, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans SemiBold Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSans Nerd Font Mono", + "preferred_subfamily_name": "SemiBold Italic", + "subfamily_name": "Italic", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans SemiBold Italic Nerd Font Complete.ttf||1279844:1634564302.0": { + "family_name": "NotoSans Nerd Font", + "font-family": "NotoSans Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans SemiBold Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 2, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans SemiBold Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSans Nerd Font", + "preferred_subfamily_name": "SemiBold Italic", + "subfamily_name": "Italic", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans SemiBold Nerd Font Complete Mono.ttf||1258648:1634564302.0": { + "family_name": "NotoSans Nerd Font Mono", + "font-family": "NotoSans Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans SemiBold Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans SemiBold Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSans Nerd Font Mono", + "preferred_subfamily_name": "SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans SemiBold Nerd Font Complete.ttf||1265084:1634564302.0": { + "family_name": "NotoSans Nerd Font", + "font-family": "NotoSans Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans SemiBold Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans SemiBold Nerd Font Complete.ttf", + "preferred_family_name": "NotoSans Nerd Font", + "preferred_subfamily_name": "SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans SemiCondensed Black Italic Nerd Font Complete Mono.ttf||1283876:1634564302.0": { + "family_name": "NotoSans Nerd Font Mono", + "font-family": "NotoSans Nerd Font Mono", + "font-stretch": "semi-condensed", + "font-style": "italic", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans SemiCondensed Black Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 2, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans SemiCondensed Black Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSans Nerd Font Mono", + "preferred_subfamily_name": "SemiCondensed Black Italic", + "subfamily_name": "Italic", + "weight": 900, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans SemiCondensed Black Italic Nerd Font Complete.ttf||1292376:1634564302.0": { + "family_name": "NotoSans Nerd Font", + "font-family": "NotoSans Nerd Font", + "font-stretch": "semi-condensed", + "font-style": "italic", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans SemiCondensed Black Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 2, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans SemiCondensed Black Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSans Nerd Font", + "preferred_subfamily_name": "SemiCondensed Black Italic", + "subfamily_name": "Italic", + "weight": 900, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans SemiCondensed Black Nerd Font Complete Mono.ttf||1268352:1634564302.0": { + "family_name": "NotoSans Nerd Font Mono", + "font-family": "NotoSans Nerd Font Mono", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans SemiCondensed Black Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans SemiCondensed Black Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSans Nerd Font Mono", + "preferred_subfamily_name": "SemiCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans SemiCondensed Black Nerd Font Complete.ttf||1275116:1634564302.0": { + "family_name": "NotoSans Nerd Font", + "font-family": "NotoSans Nerd Font", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans SemiCondensed Black Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans SemiCondensed Black Nerd Font Complete.ttf", + "preferred_family_name": "NotoSans Nerd Font", + "preferred_subfamily_name": "SemiCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans SemiCondensed Bold Italic Nerd Font Complete Mono.ttf||1270396:1634564302.0": { + "family_name": "NotoSans Nerd Font Mono", + "font-family": "NotoSans Nerd Font Mono", + "font-stretch": "semi-condensed", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans SemiCondensed Bold Italic Nerd Font Complete Mono", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 2, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans SemiCondensed Bold Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSans Nerd Font Mono", + "preferred_subfamily_name": "SemiCondensed Bold Italic", + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans SemiCondensed Bold Italic Nerd Font Complete.ttf||1283036:1634564302.0": { + "family_name": "NotoSans Nerd Font", + "font-family": "NotoSans Nerd Font", + "font-stretch": "semi-condensed", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans SemiCondensed Bold Italic Nerd Font Complete", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 2, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans SemiCondensed Bold Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSans Nerd Font", + "preferred_subfamily_name": "SemiCondensed Bold Italic", + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans SemiCondensed Bold Nerd Font Complete Mono.ttf||1255784:1634564302.0": { + "family_name": "NotoSans Nerd Font Mono", + "font-family": "NotoSans Nerd Font Mono", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans SemiCondensed Bold Nerd Font Complete Mono", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans SemiCondensed Bold Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSans Nerd Font Mono", + "preferred_subfamily_name": "SemiCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans SemiCondensed Bold Nerd Font Complete.ttf||1265620:1634564302.0": { + "family_name": "NotoSans Nerd Font", + "font-family": "NotoSans Nerd Font", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans SemiCondensed Bold Nerd Font Complete", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans SemiCondensed Bold Nerd Font Complete.ttf", + "preferred_family_name": "NotoSans Nerd Font", + "preferred_subfamily_name": "SemiCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans SemiCondensed ExtraBold Italic Nerd Font Complete Mono.ttf||1275160:1634564302.0": { + "family_name": "NotoSans Nerd Font Mono", + "font-family": "NotoSans Nerd Font Mono", + "font-stretch": "semi-condensed", + "font-style": "italic", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans SemiCondensed ExtraBold Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 2, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans SemiCondensed ExtraBold Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSans Nerd Font Mono", + "preferred_subfamily_name": "SemiCondensed ExtraBold Italic", + "subfamily_name": "Italic", + "weight": 800, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans SemiCondensed ExtraBold Italic Nerd Font Complete.ttf||1285920:1634564302.0": { + "family_name": "NotoSans Nerd Font", + "font-family": "NotoSans Nerd Font", + "font-stretch": "semi-condensed", + "font-style": "italic", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans SemiCondensed ExtraBold Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 2, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans SemiCondensed ExtraBold Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSans Nerd Font", + "preferred_subfamily_name": "SemiCondensed ExtraBold Italic", + "subfamily_name": "Italic", + "weight": 800, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans SemiCondensed ExtraBold Nerd Font Complete Mono.ttf||1255496:1634564302.0": { + "family_name": "NotoSans Nerd Font Mono", + "font-family": "NotoSans Nerd Font Mono", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans SemiCondensed ExtraBold Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans SemiCondensed ExtraBold Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSans Nerd Font Mono", + "preferred_subfamily_name": "SemiCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans SemiCondensed ExtraBold Nerd Font Complete.ttf||1263020:1634564302.0": { + "family_name": "NotoSans Nerd Font", + "font-family": "NotoSans Nerd Font", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans SemiCondensed ExtraBold Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans SemiCondensed ExtraBold Nerd Font Complete.ttf", + "preferred_family_name": "NotoSans Nerd Font", + "preferred_subfamily_name": "SemiCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans SemiCondensed ExtraLight Italic Nerd Font Complete Mono.ttf||1251976:1634564302.0": { + "family_name": "NotoSans Nerd Font Mono", + "font-family": "NotoSans Nerd Font Mono", + "font-stretch": "semi-condensed", + "font-style": "italic", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans SemiCondensed ExtraLight Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 2, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans SemiCondensed ExtraLight Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSans Nerd Font Mono", + "preferred_subfamily_name": "SemiCondensed ExtraLight Italic", + "subfamily_name": "Italic", + "weight": 200, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans SemiCondensed ExtraLight Italic Nerd Font Complete.ttf||1264812:1634564302.0": { + "family_name": "NotoSans Nerd Font", + "font-family": "NotoSans Nerd Font", + "font-stretch": "semi-condensed", + "font-style": "italic", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans SemiCondensed ExtraLight Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 2, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans SemiCondensed ExtraLight Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSans Nerd Font", + "preferred_subfamily_name": "SemiCondensed ExtraLight Italic", + "subfamily_name": "Italic", + "weight": 200, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans SemiCondensed ExtraLight Nerd Font Complete Mono.ttf||1233308:1634564302.0": { + "family_name": "NotoSans Nerd Font Mono", + "font-family": "NotoSans Nerd Font Mono", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans SemiCondensed ExtraLight Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans SemiCondensed ExtraLight Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSans Nerd Font Mono", + "preferred_subfamily_name": "SemiCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans SemiCondensed ExtraLight Nerd Font Complete.ttf||1244804:1634564302.0": { + "family_name": "NotoSans Nerd Font", + "font-family": "NotoSans Nerd Font", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans SemiCondensed ExtraLight Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans SemiCondensed ExtraLight Nerd Font Complete.ttf", + "preferred_family_name": "NotoSans Nerd Font", + "preferred_subfamily_name": "SemiCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans SemiCondensed Italic Nerd Font Complete Mono.ttf||1268664:1634564302.0": { + "family_name": "NotoSans Nerd Font Mono", + "font-family": "NotoSans Nerd Font Mono", + "font-stretch": "semi-condensed", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans SemiCondensed Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans SemiCondensed Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSans Nerd Font Mono", + "preferred_subfamily_name": "SemiCondensed Italic", + "subfamily_name": "Italic", + "weight": 400, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans SemiCondensed Italic Nerd Font Complete.ttf||1281552:1634564302.0": { + "family_name": "NotoSans Nerd Font", + "font-family": "NotoSans Nerd Font", + "font-stretch": "semi-condensed", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans SemiCondensed Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans SemiCondensed Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSans Nerd Font", + "preferred_subfamily_name": "SemiCondensed Italic", + "subfamily_name": "Italic", + "weight": 400, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans SemiCondensed Light Italic Nerd Font Complete Mono.ttf||1263452:1634564302.0": { + "family_name": "NotoSans Nerd Font Mono", + "font-family": "NotoSans Nerd Font Mono", + "font-stretch": "semi-condensed", + "font-style": "italic", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans SemiCondensed Light Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 2, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans SemiCondensed Light Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSans Nerd Font Mono", + "preferred_subfamily_name": "SemiCondensed Light Italic", + "subfamily_name": "Italic", + "weight": 300, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans SemiCondensed Light Italic Nerd Font Complete.ttf||1276280:1634564302.0": { + "family_name": "NotoSans Nerd Font", + "font-family": "NotoSans Nerd Font", + "font-stretch": "semi-condensed", + "font-style": "italic", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans SemiCondensed Light Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 2, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans SemiCondensed Light Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSans Nerd Font", + "preferred_subfamily_name": "SemiCondensed Light Italic", + "subfamily_name": "Italic", + "weight": 300, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans SemiCondensed Light Nerd Font Complete Mono.ttf||1242308:1634564302.0": { + "family_name": "NotoSans Nerd Font Mono", + "font-family": "NotoSans Nerd Font Mono", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans SemiCondensed Light Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans SemiCondensed Light Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSans Nerd Font Mono", + "preferred_subfamily_name": "SemiCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans SemiCondensed Light Nerd Font Complete.ttf||1253892:1634564302.0": { + "family_name": "NotoSans Nerd Font", + "font-family": "NotoSans Nerd Font", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans SemiCondensed Light Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans SemiCondensed Light Nerd Font Complete.ttf", + "preferred_family_name": "NotoSans Nerd Font", + "preferred_subfamily_name": "SemiCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans SemiCondensed Medium Italic Nerd Font Complete Mono.ttf||1265728:1634564302.0": { + "family_name": "NotoSans Nerd Font Mono", + "font-family": "NotoSans Nerd Font Mono", + "font-stretch": "semi-condensed", + "font-style": "italic", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans SemiCondensed Medium Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 2, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans SemiCondensed Medium Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSans Nerd Font Mono", + "preferred_subfamily_name": "SemiCondensed Medium Italic", + "subfamily_name": "Italic", + "weight": 500, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans SemiCondensed Medium Italic Nerd Font Complete.ttf||1278628:1634564302.0": { + "family_name": "NotoSans Nerd Font", + "font-family": "NotoSans Nerd Font", + "font-stretch": "semi-condensed", + "font-style": "italic", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans SemiCondensed Medium Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 2, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans SemiCondensed Medium Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSans Nerd Font", + "preferred_subfamily_name": "SemiCondensed Medium Italic", + "subfamily_name": "Italic", + "weight": 500, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans SemiCondensed Medium Nerd Font Complete Mono.ttf||1248516:1634564302.0": { + "family_name": "NotoSans Nerd Font Mono", + "font-family": "NotoSans Nerd Font Mono", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans SemiCondensed Medium Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans SemiCondensed Medium Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSans Nerd Font Mono", + "preferred_subfamily_name": "SemiCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans SemiCondensed Medium Nerd Font Complete.ttf||1259868:1634564302.0": { + "family_name": "NotoSans Nerd Font", + "font-family": "NotoSans Nerd Font", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans SemiCondensed Medium Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans SemiCondensed Medium Nerd Font Complete.ttf", + "preferred_family_name": "NotoSans Nerd Font", + "preferred_subfamily_name": "SemiCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans SemiCondensed Nerd Font Complete Mono.ttf||1249484:1634564302.0": { + "family_name": "NotoSans Nerd Font Mono", + "font-family": "NotoSans Nerd Font Mono", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans SemiCondensed Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans SemiCondensed Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSans Nerd Font Mono", + "preferred_subfamily_name": "SemiCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans SemiCondensed Nerd Font Complete.ttf||1261220:1634564302.0": { + "family_name": "NotoSans Nerd Font", + "font-family": "NotoSans Nerd Font", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans SemiCondensed Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans SemiCondensed Nerd Font Complete.ttf", + "preferred_family_name": "NotoSans Nerd Font", + "preferred_subfamily_name": "SemiCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans SemiCondensed SemiBold Italic Nerd Font Complete Mono.ttf||1270308:1634564302.0": { + "family_name": "NotoSans Nerd Font Mono", + "font-family": "NotoSans Nerd Font Mono", + "font-stretch": "semi-condensed", + "font-style": "italic", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans SemiCondensed SemiBold Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 2, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans SemiCondensed SemiBold Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSans Nerd Font Mono", + "preferred_subfamily_name": "SemiCondensed SemiBold Italic", + "subfamily_name": "Italic", + "weight": 600, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans SemiCondensed SemiBold Italic Nerd Font Complete.ttf||1283112:1634564302.0": { + "family_name": "NotoSans Nerd Font", + "font-family": "NotoSans Nerd Font", + "font-stretch": "semi-condensed", + "font-style": "italic", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans SemiCondensed SemiBold Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 2, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans SemiCondensed SemiBold Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSans Nerd Font", + "preferred_subfamily_name": "SemiCondensed SemiBold Italic", + "subfamily_name": "Italic", + "weight": 600, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans SemiCondensed SemiBold Nerd Font Complete Mono.ttf||1252000:1634564302.0": { + "family_name": "NotoSans Nerd Font Mono", + "font-family": "NotoSans Nerd Font Mono", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans SemiCondensed SemiBold Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans SemiCondensed SemiBold Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSans Nerd Font Mono", + "preferred_subfamily_name": "SemiCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans SemiCondensed SemiBold Nerd Font Complete.ttf||1262344:1634564302.0": { + "family_name": "NotoSans Nerd Font", + "font-family": "NotoSans Nerd Font", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans SemiCondensed SemiBold Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans SemiCondensed SemiBold Nerd Font Complete.ttf", + "preferred_family_name": "NotoSans Nerd Font", + "preferred_subfamily_name": "SemiCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans SemiCondensed Thin Italic Nerd Font Complete Mono.ttf||1251664:1634564302.0": { + "family_name": "NotoSans Nerd Font Mono", + "font-family": "NotoSans Nerd Font Mono", + "font-stretch": "semi-condensed", + "font-style": "italic", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans SemiCondensed Thin Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 2, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans SemiCondensed Thin Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSans Nerd Font Mono", + "preferred_subfamily_name": "SemiCondensed Thin Italic", + "subfamily_name": "Italic", + "weight": 100, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans SemiCondensed Thin Italic Nerd Font Complete.ttf||1264500:1634564302.0": { + "family_name": "NotoSans Nerd Font", + "font-family": "NotoSans Nerd Font", + "font-stretch": "semi-condensed", + "font-style": "italic", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans SemiCondensed Thin Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 2, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans SemiCondensed Thin Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSans Nerd Font", + "preferred_subfamily_name": "SemiCondensed Thin Italic", + "subfamily_name": "Italic", + "weight": 100, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans SemiCondensed Thin Nerd Font Complete Mono.ttf||1234028:1634564302.0": { + "family_name": "NotoSans Nerd Font Mono", + "font-family": "NotoSans Nerd Font Mono", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans SemiCondensed Thin Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans SemiCondensed Thin Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSans Nerd Font Mono", + "preferred_subfamily_name": "SemiCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans SemiCondensed Thin Nerd Font Complete.ttf||1245452:1634564302.0": { + "family_name": "NotoSans Nerd Font", + "font-family": "NotoSans Nerd Font", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans SemiCondensed Thin Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans SemiCondensed Thin Nerd Font Complete.ttf", + "preferred_family_name": "NotoSans Nerd Font", + "preferred_subfamily_name": "SemiCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Thin Italic Nerd Font Complete Mono.ttf||1253380:1634564302.0": { + "family_name": "NotoSans Nerd Font Mono", + "font-family": "NotoSans Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Thin Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 2, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Thin Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSans Nerd Font Mono", + "preferred_subfamily_name": "Thin Italic", + "subfamily_name": "Italic", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Thin Italic Nerd Font Complete.ttf||1263464:1634564302.0": { + "family_name": "NotoSans Nerd Font", + "font-family": "NotoSans Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Thin Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 2, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Thin Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSans Nerd Font", + "preferred_subfamily_name": "Thin Italic", + "subfamily_name": "Italic", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Thin Nerd Font Complete Mono.ttf||1239284:1634564302.0": { + "family_name": "NotoSans Nerd Font Mono", + "font-family": "NotoSans Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Thin Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Thin Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSans Nerd Font Mono", + "preferred_subfamily_name": "Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Thin Nerd Font Complete.ttf||1245700:1634564302.0": { + "family_name": "NotoSans Nerd Font", + "font-family": "NotoSans Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Thin Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Sans Thin Nerd Font Complete.ttf", + "preferred_family_name": "NotoSans Nerd Font", + "preferred_subfamily_name": "Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Black Italic Nerd Font Complete Mono.ttf||1426924:1634564302.0": { + "family_name": "NotoSerif Nerd Font Mono", + "font-family": "NotoSerif Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Serif Black Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 10, + 2, + 6, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Black Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerif Nerd Font Mono", + "preferred_subfamily_name": "Black Italic", + "subfamily_name": "Italic", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Black Italic Nerd Font Complete.ttf||1431820:1634564302.0": { + "family_name": "NotoSerif Nerd Font", + "font-family": "NotoSerif Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Serif Black Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 10, + 2, + 6, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Black Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerif Nerd Font", + "preferred_subfamily_name": "Black Italic", + "subfamily_name": "Italic", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Black Nerd Font Complete Mono.ttf||1415700:1634564302.0": { + "family_name": "NotoSerif Nerd Font Mono", + "font-family": "NotoSerif Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Serif Black Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 10, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Black Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerif Nerd Font Mono", + "preferred_subfamily_name": "Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Black Nerd Font Complete.ttf||1420388:1634564302.0": { + "family_name": "NotoSerif Nerd Font", + "font-family": "NotoSerif Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Serif Black Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 10, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Black Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerif Nerd Font", + "preferred_subfamily_name": "Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Bold Italic Nerd Font Complete Mono.ttf||1407664:1634564302.0": { + "family_name": "NotoSerif Nerd Font Mono", + "font-family": "NotoSerif Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Serif Bold Italic Nerd Font Complete Mono", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 8, + 2, + 6, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Bold Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerif Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Bold Italic Nerd Font Complete.ttf||1412620:1634564302.0": { + "family_name": "NotoSerif Nerd Font", + "font-family": "NotoSerif Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Serif Bold Italic Nerd Font Complete", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 8, + 2, + 6, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Bold Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerif Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Bold Nerd Font Complete Mono.ttf||1371912:1634564302.0": { + "family_name": "NotoSerif Nerd Font Mono", + "font-family": "NotoSerif Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Serif Bold Nerd Font Complete Mono", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 8, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Bold Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerif Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Bold Nerd Font Complete.ttf||1376668:1634564302.0": { + "family_name": "NotoSerif Nerd Font", + "font-family": "NotoSerif Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Serif Bold Nerd Font Complete", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 8, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Bold Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerif Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Condensed Black Italic Nerd Font Complete Mono.ttf||1411652:1634564302.0": { + "family_name": "NotoSerif Nerd Font Mono", + "font-family": "NotoSerif Nerd Font Mono", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Serif Condensed Black Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 10, + 6, + 6, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Condensed Black Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerif Nerd Font Mono", + "preferred_subfamily_name": "Condensed Black Italic", + "subfamily_name": "Italic", + "weight": 900, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Condensed Black Italic Nerd Font Complete.ttf||1418660:1634564302.0": { + "family_name": "NotoSerif Nerd Font", + "font-family": "NotoSerif Nerd Font", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Serif Condensed Black Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 10, + 6, + 6, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Condensed Black Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerif Nerd Font", + "preferred_subfamily_name": "Condensed Black Italic", + "subfamily_name": "Italic", + "weight": 900, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Condensed Black Nerd Font Complete Mono.ttf||1382320:1634564302.0": { + "family_name": "NotoSerif Nerd Font Mono", + "font-family": "NotoSerif Nerd Font Mono", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Serif Condensed Black Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 10, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Condensed Black Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerif Nerd Font Mono", + "preferred_subfamily_name": "Condensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Condensed Black Nerd Font Complete.ttf||1388896:1634564302.0": { + "family_name": "NotoSerif Nerd Font", + "font-family": "NotoSerif Nerd Font", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Serif Condensed Black Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 10, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Condensed Black Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerif Nerd Font", + "preferred_subfamily_name": "Condensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Condensed Bold Italic Nerd Font Complete Mono.ttf||1407516:1634564302.0": { + "family_name": "NotoSerif Nerd Font Mono", + "font-family": "NotoSerif Nerd Font Mono", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Serif Condensed Bold Italic Nerd Font Complete Mono", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 8, + 6, + 6, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Condensed Bold Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerif Nerd Font Mono", + "preferred_subfamily_name": "Condensed Bold Italic", + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Condensed Bold Italic Nerd Font Complete.ttf||1415212:1634564302.0": { + "family_name": "NotoSerif Nerd Font", + "font-family": "NotoSerif Nerd Font", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Serif Condensed Bold Italic Nerd Font Complete", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 8, + 6, + 6, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Condensed Bold Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerif Nerd Font", + "preferred_subfamily_name": "Condensed Bold Italic", + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Condensed Bold Nerd Font Complete Mono.ttf||1379640:1634564302.0": { + "family_name": "NotoSerif Nerd Font Mono", + "font-family": "NotoSerif Nerd Font Mono", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Serif Condensed Bold Nerd Font Complete Mono", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 8, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Condensed Bold Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerif Nerd Font Mono", + "preferred_subfamily_name": "Condensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Condensed Bold Nerd Font Complete.ttf||1387056:1634564302.0": { + "family_name": "NotoSerif Nerd Font", + "font-family": "NotoSerif Nerd Font", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Serif Condensed Bold Nerd Font Complete", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 8, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Condensed Bold Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerif Nerd Font", + "preferred_subfamily_name": "Condensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Condensed ExtraBold Italic Nerd Font Complete Mono.ttf||1412304:1634564302.0": { + "family_name": "NotoSerif Nerd Font Mono", + "font-family": "NotoSerif Nerd Font Mono", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Serif Condensed ExtraBold Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 9, + 6, + 6, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Condensed ExtraBold Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerif Nerd Font Mono", + "preferred_subfamily_name": "Condensed ExtraBold Italic", + "subfamily_name": "Italic", + "weight": 800, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Condensed ExtraBold Italic Nerd Font Complete.ttf||1419684:1634564302.0": { + "family_name": "NotoSerif Nerd Font", + "font-family": "NotoSerif Nerd Font", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Serif Condensed ExtraBold Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 9, + 6, + 6, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Condensed ExtraBold Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerif Nerd Font", + "preferred_subfamily_name": "Condensed ExtraBold Italic", + "subfamily_name": "Italic", + "weight": 800, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Condensed ExtraBold Nerd Font Complete Mono.ttf||1381464:1634564302.0": { + "family_name": "NotoSerif Nerd Font Mono", + "font-family": "NotoSerif Nerd Font Mono", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Serif Condensed ExtraBold Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 9, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Condensed ExtraBold Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerif Nerd Font Mono", + "preferred_subfamily_name": "Condensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Condensed ExtraBold Nerd Font Complete.ttf||1388356:1634564302.0": { + "family_name": "NotoSerif Nerd Font", + "font-family": "NotoSerif Nerd Font", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Serif Condensed ExtraBold Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 9, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Condensed ExtraBold Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerif Nerd Font", + "preferred_subfamily_name": "Condensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Condensed ExtraLight Italic Nerd Font Complete Mono.ttf||1373652:1634564302.0": { + "family_name": "NotoSerif Nerd Font Mono", + "font-family": "NotoSerif Nerd Font Mono", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Serif Condensed ExtraLight Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 3, + 6, + 6, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Condensed ExtraLight Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerif Nerd Font Mono", + "preferred_subfamily_name": "Condensed ExtraLight Italic", + "subfamily_name": "Italic", + "weight": 200, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Condensed ExtraLight Italic Nerd Font Complete.ttf||1385084:1634564302.0": { + "family_name": "NotoSerif Nerd Font", + "font-family": "NotoSerif Nerd Font", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Serif Condensed ExtraLight Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 3, + 6, + 6, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Condensed ExtraLight Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerif Nerd Font", + "preferred_subfamily_name": "Condensed ExtraLight Italic", + "subfamily_name": "Italic", + "weight": 200, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Condensed ExtraLight Nerd Font Complete Mono.ttf||1352156:1634564302.0": { + "family_name": "NotoSerif Nerd Font Mono", + "font-family": "NotoSerif Nerd Font Mono", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Serif Condensed ExtraLight Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 3, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Condensed ExtraLight Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerif Nerd Font Mono", + "preferred_subfamily_name": "Condensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Condensed ExtraLight Nerd Font Complete.ttf||1363680:1634564302.0": { + "family_name": "NotoSerif Nerd Font", + "font-family": "NotoSerif Nerd Font", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Serif Condensed ExtraLight Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 3, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Condensed ExtraLight Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerif Nerd Font", + "preferred_subfamily_name": "Condensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Condensed Italic Nerd Font Complete Mono.ttf||1384488:1634564302.0": { + "family_name": "NotoSerif Nerd Font Mono", + "font-family": "NotoSerif Nerd Font Mono", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif Condensed Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 5, + 6, + 6, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Condensed Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerif Nerd Font Mono", + "preferred_subfamily_name": "Condensed Italic", + "subfamily_name": "Italic", + "weight": 400, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Condensed Italic Nerd Font Complete.ttf||1394304:1634564302.0": { + "family_name": "NotoSerif Nerd Font", + "font-family": "NotoSerif Nerd Font", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif Condensed Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 5, + 6, + 6, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Condensed Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerif Nerd Font", + "preferred_subfamily_name": "Condensed Italic", + "subfamily_name": "Italic", + "weight": 400, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Condensed Light Italic Nerd Font Complete Mono.ttf||1378252:1634564302.0": { + "family_name": "NotoSerif Nerd Font Mono", + "font-family": "NotoSerif Nerd Font Mono", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Serif Condensed Light Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 4, + 6, + 6, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Condensed Light Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerif Nerd Font Mono", + "preferred_subfamily_name": "Condensed Light Italic", + "subfamily_name": "Italic", + "weight": 300, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Condensed Light Italic Nerd Font Complete.ttf||1388808:1634564302.0": { + "family_name": "NotoSerif Nerd Font", + "font-family": "NotoSerif Nerd Font", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Serif Condensed Light Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 4, + 6, + 6, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Condensed Light Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerif Nerd Font", + "preferred_subfamily_name": "Condensed Light Italic", + "subfamily_name": "Italic", + "weight": 300, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Condensed Light Nerd Font Complete Mono.ttf||1347328:1634564302.0": { + "family_name": "NotoSerif Nerd Font Mono", + "font-family": "NotoSerif Nerd Font Mono", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Serif Condensed Light Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 4, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Condensed Light Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerif Nerd Font Mono", + "preferred_subfamily_name": "Condensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Condensed Light Nerd Font Complete.ttf||1357752:1634564302.0": { + "family_name": "NotoSerif Nerd Font", + "font-family": "NotoSerif Nerd Font", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Serif Condensed Light Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 4, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Condensed Light Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerif Nerd Font", + "preferred_subfamily_name": "Condensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Condensed Medium Italic Nerd Font Complete Mono.ttf||1391900:1634564302.0": { + "family_name": "NotoSerif Nerd Font Mono", + "font-family": "NotoSerif Nerd Font Mono", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Serif Condensed Medium Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 6, + 6, + 6, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Condensed Medium Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerif Nerd Font Mono", + "preferred_subfamily_name": "Condensed Medium Italic", + "subfamily_name": "Italic", + "weight": 500, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Condensed Medium Italic Nerd Font Complete.ttf||1400636:1634564302.0": { + "family_name": "NotoSerif Nerd Font", + "font-family": "NotoSerif Nerd Font", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Serif Condensed Medium Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 6, + 6, + 6, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Condensed Medium Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerif Nerd Font", + "preferred_subfamily_name": "Condensed Medium Italic", + "subfamily_name": "Italic", + "weight": 500, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Condensed Medium Nerd Font Complete Mono.ttf||1358544:1634564302.0": { + "family_name": "NotoSerif Nerd Font Mono", + "font-family": "NotoSerif Nerd Font Mono", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Serif Condensed Medium Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 6, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Condensed Medium Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerif Nerd Font Mono", + "preferred_subfamily_name": "Condensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Condensed Medium Nerd Font Complete.ttf||1367640:1634564302.0": { + "family_name": "NotoSerif Nerd Font", + "font-family": "NotoSerif Nerd Font", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Serif Condensed Medium Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 6, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Condensed Medium Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerif Nerd Font", + "preferred_subfamily_name": "Condensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Condensed Nerd Font Complete Mono.ttf||1356840:1634564302.0": { + "family_name": "NotoSerif Nerd Font Mono", + "font-family": "NotoSerif Nerd Font Mono", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif Condensed Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 5, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Condensed Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerif Nerd Font Mono", + "preferred_subfamily_name": "Condensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Condensed Nerd Font Complete.ttf||1366680:1634564302.0": { + "family_name": "NotoSerif Nerd Font", + "font-family": "NotoSerif Nerd Font", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif Condensed Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 5, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Condensed Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerif Nerd Font", + "preferred_subfamily_name": "Condensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Condensed SemiBold Italic Nerd Font Complete Mono.ttf||1406668:1634564302.0": { + "family_name": "NotoSerif Nerd Font Mono", + "font-family": "NotoSerif Nerd Font Mono", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Serif Condensed SemiBold Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 7, + 6, + 6, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Condensed SemiBold Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerif Nerd Font Mono", + "preferred_subfamily_name": "Condensed SemiBold Italic", + "subfamily_name": "Italic", + "weight": 600, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Condensed SemiBold Italic Nerd Font Complete.ttf||1414552:1634564302.0": { + "family_name": "NotoSerif Nerd Font", + "font-family": "NotoSerif Nerd Font", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Serif Condensed SemiBold Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 7, + 6, + 6, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Condensed SemiBold Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerif Nerd Font", + "preferred_subfamily_name": "Condensed SemiBold Italic", + "subfamily_name": "Italic", + "weight": 600, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Condensed SemiBold Nerd Font Complete Mono.ttf||1371616:1634564302.0": { + "family_name": "NotoSerif Nerd Font Mono", + "font-family": "NotoSerif Nerd Font Mono", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Serif Condensed SemiBold Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 7, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Condensed SemiBold Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerif Nerd Font Mono", + "preferred_subfamily_name": "Condensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Condensed SemiBold Nerd Font Complete.ttf||1379256:1634564302.0": { + "family_name": "NotoSerif Nerd Font", + "font-family": "NotoSerif Nerd Font", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Serif Condensed SemiBold Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 7, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Condensed SemiBold Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerif Nerd Font", + "preferred_subfamily_name": "Condensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Condensed Thin Italic Nerd Font Complete Mono.ttf||1378444:1634564302.0": { + "family_name": "NotoSerif Nerd Font Mono", + "font-family": "NotoSerif Nerd Font Mono", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Serif Condensed Thin Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 2, + 6, + 6, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Condensed Thin Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerif Nerd Font Mono", + "preferred_subfamily_name": "Condensed Thin Italic", + "subfamily_name": "Italic", + "weight": 100, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Condensed Thin Italic Nerd Font Complete.ttf||1390260:1634564302.0": { + "family_name": "NotoSerif Nerd Font", + "font-family": "NotoSerif Nerd Font", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Serif Condensed Thin Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 2, + 6, + 6, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Condensed Thin Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerif Nerd Font", + "preferred_subfamily_name": "Condensed Thin Italic", + "subfamily_name": "Italic", + "weight": 100, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Condensed Thin Nerd Font Complete Mono.ttf||1368772:1634564302.0": { + "family_name": "NotoSerif Nerd Font Mono", + "font-family": "NotoSerif Nerd Font Mono", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Serif Condensed Thin Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 2, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Condensed Thin Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerif Nerd Font Mono", + "preferred_subfamily_name": "Condensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Condensed Thin Nerd Font Complete.ttf||1380736:1634564302.0": { + "family_name": "NotoSerif Nerd Font", + "font-family": "NotoSerif Nerd Font", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Serif Condensed Thin Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 2, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Condensed Thin Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerif Nerd Font", + "preferred_subfamily_name": "Condensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display Black Italic Nerd Font Complete Mono.ttf||1364360:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font Mono", + "font-family": "NotoSerifDisplay Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Serif Display Black Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 10, + 2, + 8, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display Black Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font Mono", + "preferred_subfamily_name": "Black Italic", + "subfamily_name": "Italic", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display Black Italic Nerd Font Complete.ttf||1369212:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font", + "font-family": "NotoSerifDisplay Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Serif Display Black Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 10, + 2, + 8, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display Black Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font", + "preferred_subfamily_name": "Black Italic", + "subfamily_name": "Italic", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display Black Nerd Font Complete Mono.ttf||1372012:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font Mono", + "font-family": "NotoSerifDisplay Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Serif Display Black Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 10, + 2, + 8, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display Black Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font Mono", + "preferred_subfamily_name": "Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display Black Nerd Font Complete.ttf||1376696:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font", + "font-family": "NotoSerifDisplay Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Serif Display Black Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 10, + 2, + 8, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display Black Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font", + "preferred_subfamily_name": "Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display Bold Italic Nerd Font Complete Mono.ttf||1348944:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font Mono", + "font-family": "NotoSerifDisplay Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Serif Display Bold Italic Nerd Font Complete Mono", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 8, + 2, + 8, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display Bold Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display Bold Italic Nerd Font Complete.ttf||1353976:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font", + "font-family": "NotoSerifDisplay Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Serif Display Bold Italic Nerd Font Complete", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 8, + 2, + 8, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display Bold Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display Bold Nerd Font Complete Mono.ttf||1332480:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font Mono", + "font-family": "NotoSerifDisplay Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Serif Display Bold Nerd Font Complete Mono", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 8, + 2, + 8, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display Bold Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display Bold Nerd Font Complete.ttf||1337232:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font", + "font-family": "NotoSerifDisplay Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Serif Display Bold Nerd Font Complete", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 8, + 2, + 8, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display Bold Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display Condensed Black Italic Nerd Font Complete Mono.ttf||1354088:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font Mono", + "font-family": "NotoSerifDisplay Nerd Font Mono", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Serif Display Condensed Black Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 10, + 6, + 8, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display Condensed Black Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font Mono", + "preferred_subfamily_name": "Condensed Black Italic", + "subfamily_name": "Italic", + "weight": 900, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display Condensed Black Italic Nerd Font Complete.ttf||1361144:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font", + "font-family": "NotoSerifDisplay Nerd Font", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Serif Display Condensed Black Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 10, + 6, + 8, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display Condensed Black Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font", + "preferred_subfamily_name": "Condensed Black Italic", + "subfamily_name": "Italic", + "weight": 900, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display Condensed Black Nerd Font Complete Mono.ttf||1337068:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font Mono", + "font-family": "NotoSerifDisplay Nerd Font Mono", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Serif Display Condensed Black Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 10, + 6, + 8, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display Condensed Black Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font Mono", + "preferred_subfamily_name": "Condensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display Condensed Black Nerd Font Complete.ttf||1343656:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font", + "font-family": "NotoSerifDisplay Nerd Font", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Serif Display Condensed Black Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 10, + 6, + 8, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display Condensed Black Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font", + "preferred_subfamily_name": "Condensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display Condensed Bold Italic Nerd Font Complete Mono.ttf||1352672:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font Mono", + "font-family": "NotoSerifDisplay Nerd Font Mono", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Serif Display Condensed Bold Italic Nerd Font Complete Mono", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 8, + 6, + 8, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display Condensed Bold Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font Mono", + "preferred_subfamily_name": "Condensed Bold Italic", + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display Condensed Bold Italic Nerd Font Complete.ttf||1360352:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font", + "font-family": "NotoSerifDisplay Nerd Font", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Serif Display Condensed Bold Italic Nerd Font Complete", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 8, + 6, + 8, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display Condensed Bold Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font", + "preferred_subfamily_name": "Condensed Bold Italic", + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display Condensed Bold Nerd Font Complete Mono.ttf||1337768:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font Mono", + "font-family": "NotoSerifDisplay Nerd Font Mono", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Serif Display Condensed Bold Nerd Font Complete Mono", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 8, + 6, + 8, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display Condensed Bold Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font Mono", + "preferred_subfamily_name": "Condensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display Condensed Bold Nerd Font Complete.ttf||1345180:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font", + "font-family": "NotoSerifDisplay Nerd Font", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Serif Display Condensed Bold Nerd Font Complete", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 8, + 6, + 8, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display Condensed Bold Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font", + "preferred_subfamily_name": "Condensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display Condensed ExtraBold Italic Nerd Font Complete Mono.ttf||1352108:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font Mono", + "font-family": "NotoSerifDisplay Nerd Font Mono", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Serif Display Condensed ExtraBold Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 9, + 6, + 8, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display Condensed ExtraBold Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font Mono", + "preferred_subfamily_name": "Condensed ExtraBold Italic", + "subfamily_name": "Italic", + "weight": 800, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display Condensed ExtraBold Italic Nerd Font Complete.ttf||1359452:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font", + "font-family": "NotoSerifDisplay Nerd Font", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Serif Display Condensed ExtraBold Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 9, + 6, + 8, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display Condensed ExtraBold Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font", + "preferred_subfamily_name": "Condensed ExtraBold Italic", + "subfamily_name": "Italic", + "weight": 800, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display Condensed ExtraBold Nerd Font Complete Mono.ttf||1342684:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font Mono", + "font-family": "NotoSerifDisplay Nerd Font Mono", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Serif Display Condensed ExtraBold Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 9, + 6, + 8, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display Condensed ExtraBold Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font Mono", + "preferred_subfamily_name": "Condensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display Condensed ExtraBold Nerd Font Complete.ttf||1349576:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font", + "font-family": "NotoSerifDisplay Nerd Font", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Serif Display Condensed ExtraBold Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 9, + 6, + 8, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display Condensed ExtraBold Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font", + "preferred_subfamily_name": "Condensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display Condensed ExtraLight Italic Nerd Font Complete Mono.ttf||1348660:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font Mono", + "font-family": "NotoSerifDisplay Nerd Font Mono", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Serif Display Condensed ExtraLight Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 3, + 6, + 8, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display Condensed ExtraLight Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font Mono", + "preferred_subfamily_name": "Condensed ExtraLight Italic", + "subfamily_name": "Italic", + "weight": 200, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display Condensed ExtraLight Italic Nerd Font Complete.ttf||1360080:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font", + "font-family": "NotoSerifDisplay Nerd Font", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Serif Display Condensed ExtraLight Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 3, + 6, + 8, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display Condensed ExtraLight Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font", + "preferred_subfamily_name": "Condensed ExtraLight Italic", + "subfamily_name": "Italic", + "weight": 200, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display Condensed ExtraLight Nerd Font Complete Mono.ttf||1345008:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font Mono", + "font-family": "NotoSerifDisplay Nerd Font Mono", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Serif Display Condensed ExtraLight Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 3, + 6, + 8, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display Condensed ExtraLight Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font Mono", + "preferred_subfamily_name": "Condensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display Condensed ExtraLight Nerd Font Complete.ttf||1356524:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font", + "font-family": "NotoSerifDisplay Nerd Font", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Serif Display Condensed ExtraLight Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 3, + 6, + 8, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display Condensed ExtraLight Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font", + "preferred_subfamily_name": "Condensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display Condensed Italic Nerd Font Complete Mono.ttf||1346552:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font Mono", + "font-family": "NotoSerifDisplay Nerd Font Mono", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif Display Condensed Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 5, + 6, + 8, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display Condensed Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font Mono", + "preferred_subfamily_name": "Condensed Italic", + "subfamily_name": "Italic", + "weight": 400, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display Condensed Italic Nerd Font Complete.ttf||1356492:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font", + "font-family": "NotoSerifDisplay Nerd Font", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif Display Condensed Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 5, + 6, + 8, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display Condensed Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font", + "preferred_subfamily_name": "Condensed Italic", + "subfamily_name": "Italic", + "weight": 400, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display Condensed Light Italic Nerd Font Complete Mono.ttf||1349180:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font Mono", + "font-family": "NotoSerifDisplay Nerd Font Mono", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Serif Display Condensed Light Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 4, + 6, + 8, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display Condensed Light Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font Mono", + "preferred_subfamily_name": "Condensed Light Italic", + "subfamily_name": "Italic", + "weight": 300, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display Condensed Light Italic Nerd Font Complete.ttf||1359712:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font", + "font-family": "NotoSerifDisplay Nerd Font", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Serif Display Condensed Light Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 4, + 6, + 8, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display Condensed Light Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font", + "preferred_subfamily_name": "Condensed Light Italic", + "subfamily_name": "Italic", + "weight": 300, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display Condensed Light Nerd Font Complete Mono.ttf||1343092:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font Mono", + "font-family": "NotoSerifDisplay Nerd Font Mono", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Serif Display Condensed Light Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 4, + 6, + 8, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display Condensed Light Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font Mono", + "preferred_subfamily_name": "Condensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display Condensed Light Nerd Font Complete.ttf||1353568:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font", + "font-family": "NotoSerifDisplay Nerd Font", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Serif Display Condensed Light Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 4, + 6, + 8, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display Condensed Light Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font", + "preferred_subfamily_name": "Condensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display Condensed Medium Italic Nerd Font Complete Mono.ttf||1349632:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font Mono", + "font-family": "NotoSerifDisplay Nerd Font Mono", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Serif Display Condensed Medium Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 6, + 6, + 8, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display Condensed Medium Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font Mono", + "preferred_subfamily_name": "Condensed Medium Italic", + "subfamily_name": "Italic", + "weight": 500, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display Condensed Medium Italic Nerd Font Complete.ttf||1358424:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font", + "font-family": "NotoSerifDisplay Nerd Font", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Serif Display Condensed Medium Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 6, + 6, + 8, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display Condensed Medium Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font", + "preferred_subfamily_name": "Condensed Medium Italic", + "subfamily_name": "Italic", + "weight": 500, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display Condensed Medium Nerd Font Complete Mono.ttf||1333276:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font Mono", + "font-family": "NotoSerifDisplay Nerd Font Mono", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Serif Display Condensed Medium Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 6, + 6, + 8, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display Condensed Medium Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font Mono", + "preferred_subfamily_name": "Condensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display Condensed Medium Nerd Font Complete.ttf||1342348:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font", + "font-family": "NotoSerifDisplay Nerd Font", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Serif Display Condensed Medium Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 6, + 6, + 8, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display Condensed Medium Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font", + "preferred_subfamily_name": "Condensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display Condensed Nerd Font Complete Mono.ttf||1332532:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font Mono", + "font-family": "NotoSerifDisplay Nerd Font Mono", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif Display Condensed Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 5, + 6, + 8, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display Condensed Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font Mono", + "preferred_subfamily_name": "Condensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display Condensed Nerd Font Complete.ttf||1342352:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font", + "font-family": "NotoSerifDisplay Nerd Font", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif Display Condensed Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 5, + 6, + 8, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display Condensed Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font", + "preferred_subfamily_name": "Condensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display Condensed SemiBold Italic Nerd Font Complete Mono.ttf||1350172:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font Mono", + "font-family": "NotoSerifDisplay Nerd Font Mono", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Serif Display Condensed SemiBold Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 7, + 6, + 8, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display Condensed SemiBold Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font Mono", + "preferred_subfamily_name": "Condensed SemiBold Italic", + "subfamily_name": "Italic", + "weight": 600, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display Condensed SemiBold Italic Nerd Font Complete.ttf||1358044:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font", + "font-family": "NotoSerifDisplay Nerd Font", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Serif Display Condensed SemiBold Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 7, + 6, + 8, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display Condensed SemiBold Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font", + "preferred_subfamily_name": "Condensed SemiBold Italic", + "subfamily_name": "Italic", + "weight": 600, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display Condensed SemiBold Nerd Font Complete Mono.ttf||1343956:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font Mono", + "font-family": "NotoSerifDisplay Nerd Font Mono", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Serif Display Condensed SemiBold Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 7, + 6, + 8, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display Condensed SemiBold Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font Mono", + "preferred_subfamily_name": "Condensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display Condensed SemiBold Nerd Font Complete.ttf||1351608:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font", + "font-family": "NotoSerifDisplay Nerd Font", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Serif Display Condensed SemiBold Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 7, + 6, + 8, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display Condensed SemiBold Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font", + "preferred_subfamily_name": "Condensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display Condensed Thin Italic Nerd Font Complete Mono.ttf||1342736:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font Mono", + "font-family": "NotoSerifDisplay Nerd Font Mono", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Serif Display Condensed Thin Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 2, + 6, + 8, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display Condensed Thin Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font Mono", + "preferred_subfamily_name": "Condensed Thin Italic", + "subfamily_name": "Italic", + "weight": 100, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display Condensed Thin Italic Nerd Font Complete.ttf||1354560:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font", + "font-family": "NotoSerifDisplay Nerd Font", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Serif Display Condensed Thin Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 2, + 6, + 8, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display Condensed Thin Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font", + "preferred_subfamily_name": "Condensed Thin Italic", + "subfamily_name": "Italic", + "weight": 100, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display Condensed Thin Nerd Font Complete Mono.ttf||1339432:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font Mono", + "font-family": "NotoSerifDisplay Nerd Font Mono", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Serif Display Condensed Thin Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 2, + 6, + 8, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display Condensed Thin Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font Mono", + "preferred_subfamily_name": "Condensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display Condensed Thin Nerd Font Complete.ttf||1351388:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font", + "font-family": "NotoSerifDisplay Nerd Font", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Serif Display Condensed Thin Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 2, + 6, + 8, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display Condensed Thin Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font", + "preferred_subfamily_name": "Condensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display ExtraBold Italic Nerd Font Complete Mono.ttf||1354596:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font Mono", + "font-family": "NotoSerifDisplay Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Serif Display ExtraBold Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 9, + 2, + 8, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display ExtraBold Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font Mono", + "preferred_subfamily_name": "ExtraBold Italic", + "subfamily_name": "Italic", + "weight": 800, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display ExtraBold Italic Nerd Font Complete.ttf||1359412:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font", + "font-family": "NotoSerifDisplay Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Serif Display ExtraBold Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 9, + 2, + 8, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display ExtraBold Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font", + "preferred_subfamily_name": "ExtraBold Italic", + "subfamily_name": "Italic", + "weight": 800, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display ExtraBold Nerd Font Complete Mono.ttf||1334364:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font Mono", + "font-family": "NotoSerifDisplay Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Serif Display ExtraBold Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 9, + 2, + 8, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display ExtraBold Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font Mono", + "preferred_subfamily_name": "ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display ExtraBold Nerd Font Complete.ttf||1339124:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font", + "font-family": "NotoSerifDisplay Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Serif Display ExtraBold Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 9, + 2, + 8, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display ExtraBold Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font", + "preferred_subfamily_name": "ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display ExtraCondensed Black Italic Nerd Font Complete Mono.ttf||1348276:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font Mono", + "font-family": "NotoSerifDisplay Nerd Font Mono", + "font-stretch": "extra-condensed", + "font-style": "italic", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Serif Display ExtraCondensed Black Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 10, + 6, + 8, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display ExtraCondensed Black Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font Mono", + "preferred_subfamily_name": "ExtraCondensed Black Italic", + "subfamily_name": "Italic", + "weight": 900, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display ExtraCondensed Black Italic Nerd Font Complete.ttf||1358660:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font", + "font-family": "NotoSerifDisplay Nerd Font", + "font-stretch": "extra-condensed", + "font-style": "italic", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Serif Display ExtraCondensed Black Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 10, + 6, + 8, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display ExtraCondensed Black Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font", + "preferred_subfamily_name": "ExtraCondensed Black Italic", + "subfamily_name": "Italic", + "weight": 900, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display ExtraCondensed Black Nerd Font Complete Mono.ttf||1335900:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font Mono", + "font-family": "NotoSerifDisplay Nerd Font Mono", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Serif Display ExtraCondensed Black Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 10, + 6, + 8, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display ExtraCondensed Black Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font Mono", + "preferred_subfamily_name": "ExtraCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display ExtraCondensed Black Nerd Font Complete.ttf||1345536:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font", + "font-family": "NotoSerifDisplay Nerd Font", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Serif Display ExtraCondensed Black Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 10, + 6, + 8, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display ExtraCondensed Black Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font", + "preferred_subfamily_name": "ExtraCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display ExtraCondensed Bold Italic Nerd Font Complete Mono.ttf||1344220:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font Mono", + "font-family": "NotoSerifDisplay Nerd Font Mono", + "font-stretch": "extra-condensed", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Serif Display ExtraCondensed Bold Italic Nerd Font Complete Mono", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 8, + 6, + 8, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display ExtraCondensed Bold Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font Mono", + "preferred_subfamily_name": "ExtraCondensed Bold Italic", + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display ExtraCondensed Bold Italic Nerd Font Complete.ttf||1355752:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font", + "font-family": "NotoSerifDisplay Nerd Font", + "font-stretch": "extra-condensed", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Serif Display ExtraCondensed Bold Italic Nerd Font Complete", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 8, + 6, + 8, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display ExtraCondensed Bold Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font", + "preferred_subfamily_name": "ExtraCondensed Bold Italic", + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display ExtraCondensed Bold Nerd Font Complete Mono.ttf||1338744:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font Mono", + "font-family": "NotoSerifDisplay Nerd Font Mono", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Serif Display ExtraCondensed Bold Nerd Font Complete Mono", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 8, + 6, + 8, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display ExtraCondensed Bold Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font Mono", + "preferred_subfamily_name": "ExtraCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display ExtraCondensed Bold Nerd Font Complete.ttf||1349648:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font", + "font-family": "NotoSerifDisplay Nerd Font", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Serif Display ExtraCondensed Bold Nerd Font Complete", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 8, + 6, + 8, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display ExtraCondensed Bold Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font", + "preferred_subfamily_name": "ExtraCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display ExtraCondensed ExtraBold Italic Nerd Font Complete Mono.ttf||1348036:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font Mono", + "font-family": "NotoSerifDisplay Nerd Font Mono", + "font-stretch": "extra-condensed", + "font-style": "italic", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Serif Display ExtraCondensed ExtraBold Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 9, + 6, + 8, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display ExtraCondensed ExtraBold Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font Mono", + "preferred_subfamily_name": "ExtraCondensed ExtraBold Italic", + "subfamily_name": "Italic", + "weight": 800, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display ExtraCondensed ExtraBold Italic Nerd Font Complete.ttf||1358636:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font", + "font-family": "NotoSerifDisplay Nerd Font", + "font-stretch": "extra-condensed", + "font-style": "italic", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Serif Display ExtraCondensed ExtraBold Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 9, + 6, + 8, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display ExtraCondensed ExtraBold Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font", + "preferred_subfamily_name": "ExtraCondensed ExtraBold Italic", + "subfamily_name": "Italic", + "weight": 800, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display ExtraCondensed ExtraBold Nerd Font Complete Mono.ttf||1337372:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font Mono", + "font-family": "NotoSerifDisplay Nerd Font Mono", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Serif Display ExtraCondensed ExtraBold Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 9, + 6, + 8, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display ExtraCondensed ExtraBold Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font Mono", + "preferred_subfamily_name": "ExtraCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display ExtraCondensed ExtraBold Nerd Font Complete.ttf||1347512:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font", + "font-family": "NotoSerifDisplay Nerd Font", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Serif Display ExtraCondensed ExtraBold Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 9, + 6, + 8, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display ExtraCondensed ExtraBold Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font", + "preferred_subfamily_name": "ExtraCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display ExtraCondensed ExtraLight Italic Nerd Font Complete Mono.ttf||1342208:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font Mono", + "font-family": "NotoSerifDisplay Nerd Font Mono", + "font-stretch": "extra-condensed", + "font-style": "italic", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Serif Display ExtraCondensed ExtraLight Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 3, + 6, + 8, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display ExtraCondensed ExtraLight Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font Mono", + "preferred_subfamily_name": "ExtraCondensed ExtraLight Italic", + "subfamily_name": "Italic", + "weight": 200, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display ExtraCondensed ExtraLight Italic Nerd Font Complete.ttf||1355748:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font", + "font-family": "NotoSerifDisplay Nerd Font", + "font-stretch": "extra-condensed", + "font-style": "italic", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Serif Display ExtraCondensed ExtraLight Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 3, + 6, + 8, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display ExtraCondensed ExtraLight Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font", + "preferred_subfamily_name": "ExtraCondensed ExtraLight Italic", + "subfamily_name": "Italic", + "weight": 200, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display ExtraCondensed ExtraLight Nerd Font Complete Mono.ttf||1334752:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font Mono", + "font-family": "NotoSerifDisplay Nerd Font Mono", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Serif Display ExtraCondensed ExtraLight Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 3, + 6, + 8, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display ExtraCondensed ExtraLight Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font Mono", + "preferred_subfamily_name": "ExtraCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display ExtraCondensed ExtraLight Nerd Font Complete.ttf||1348648:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font", + "font-family": "NotoSerifDisplay Nerd Font", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Serif Display ExtraCondensed ExtraLight Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 3, + 6, + 8, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display ExtraCondensed ExtraLight Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font", + "preferred_subfamily_name": "ExtraCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display ExtraCondensed Italic Nerd Font Complete Mono.ttf||1343384:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font Mono", + "font-family": "NotoSerifDisplay Nerd Font Mono", + "font-stretch": "extra-condensed", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif Display ExtraCondensed Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 5, + 6, + 8, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display ExtraCondensed Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font Mono", + "preferred_subfamily_name": "ExtraCondensed Italic", + "subfamily_name": "Italic", + "weight": 400, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display ExtraCondensed Italic Nerd Font Complete.ttf||1356120:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font", + "font-family": "NotoSerifDisplay Nerd Font", + "font-stretch": "extra-condensed", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif Display ExtraCondensed Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 5, + 6, + 8, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display ExtraCondensed Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font", + "preferred_subfamily_name": "ExtraCondensed Italic", + "subfamily_name": "Italic", + "weight": 400, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display ExtraCondensed Light Italic Nerd Font Complete Mono.ttf||1343096:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font Mono", + "font-family": "NotoSerifDisplay Nerd Font Mono", + "font-stretch": "extra-condensed", + "font-style": "italic", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Serif Display ExtraCondensed Light Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 4, + 6, + 8, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display ExtraCondensed Light Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font Mono", + "preferred_subfamily_name": "ExtraCondensed Light Italic", + "subfamily_name": "Italic", + "weight": 300, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display ExtraCondensed Light Italic Nerd Font Complete.ttf||1356324:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font", + "font-family": "NotoSerifDisplay Nerd Font", + "font-stretch": "extra-condensed", + "font-style": "italic", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Serif Display ExtraCondensed Light Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 4, + 6, + 8, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display ExtraCondensed Light Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font", + "preferred_subfamily_name": "ExtraCondensed Light Italic", + "subfamily_name": "Italic", + "weight": 300, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display ExtraCondensed Light Nerd Font Complete Mono.ttf||1331384:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font Mono", + "font-family": "NotoSerifDisplay Nerd Font Mono", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Serif Display ExtraCondensed Light Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 4, + 6, + 8, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display ExtraCondensed Light Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font Mono", + "preferred_subfamily_name": "ExtraCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display ExtraCondensed Light Nerd Font Complete.ttf||1344776:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font", + "font-family": "NotoSerifDisplay Nerd Font", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Serif Display ExtraCondensed Light Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 4, + 6, + 8, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display ExtraCondensed Light Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font", + "preferred_subfamily_name": "ExtraCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display ExtraCondensed Medium Italic Nerd Font Complete Mono.ttf||1340340:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font Mono", + "font-family": "NotoSerifDisplay Nerd Font Mono", + "font-stretch": "extra-condensed", + "font-style": "italic", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Serif Display ExtraCondensed Medium Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 6, + 6, + 8, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display ExtraCondensed Medium Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font Mono", + "preferred_subfamily_name": "ExtraCondensed Medium Italic", + "subfamily_name": "Italic", + "weight": 500, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display ExtraCondensed Medium Italic Nerd Font Complete.ttf||1352848:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font", + "font-family": "NotoSerifDisplay Nerd Font", + "font-stretch": "extra-condensed", + "font-style": "italic", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Serif Display ExtraCondensed Medium Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 6, + 6, + 8, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display ExtraCondensed Medium Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font", + "preferred_subfamily_name": "ExtraCondensed Medium Italic", + "subfamily_name": "Italic", + "weight": 500, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display ExtraCondensed Medium Nerd Font Complete Mono.ttf||1330580:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font Mono", + "font-family": "NotoSerifDisplay Nerd Font Mono", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Serif Display ExtraCondensed Medium Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 6, + 6, + 8, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display ExtraCondensed Medium Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font Mono", + "preferred_subfamily_name": "ExtraCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display ExtraCondensed Medium Nerd Font Complete.ttf||1343012:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font", + "font-family": "NotoSerifDisplay Nerd Font", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Serif Display ExtraCondensed Medium Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 6, + 6, + 8, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display ExtraCondensed Medium Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font", + "preferred_subfamily_name": "ExtraCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display ExtraCondensed Nerd Font Complete Mono.ttf||1336864:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font Mono", + "font-family": "NotoSerifDisplay Nerd Font Mono", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif Display ExtraCondensed Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 5, + 6, + 8, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display ExtraCondensed Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font Mono", + "preferred_subfamily_name": "ExtraCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display ExtraCondensed Nerd Font Complete.ttf||1349620:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font", + "font-family": "NotoSerifDisplay Nerd Font", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif Display ExtraCondensed Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 5, + 6, + 8, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display ExtraCondensed Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font", + "preferred_subfamily_name": "ExtraCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display ExtraCondensed SemiBold Italic Nerd Font Complete Mono.ttf||1340924:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font Mono", + "font-family": "NotoSerifDisplay Nerd Font Mono", + "font-stretch": "extra-condensed", + "font-style": "italic", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Serif Display ExtraCondensed SemiBold Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 7, + 6, + 8, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display ExtraCondensed SemiBold Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font Mono", + "preferred_subfamily_name": "ExtraCondensed SemiBold Italic", + "subfamily_name": "Italic", + "weight": 600, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display ExtraCondensed SemiBold Italic Nerd Font Complete.ttf||1352912:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font", + "font-family": "NotoSerifDisplay Nerd Font", + "font-stretch": "extra-condensed", + "font-style": "italic", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Serif Display ExtraCondensed SemiBold Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 7, + 6, + 8, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display ExtraCondensed SemiBold Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font", + "preferred_subfamily_name": "ExtraCondensed SemiBold Italic", + "subfamily_name": "Italic", + "weight": 600, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display ExtraCondensed SemiBold Nerd Font Complete Mono.ttf||1334044:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font Mono", + "font-family": "NotoSerifDisplay Nerd Font Mono", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Serif Display ExtraCondensed SemiBold Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 7, + 6, + 8, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display ExtraCondensed SemiBold Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font Mono", + "preferred_subfamily_name": "ExtraCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display ExtraCondensed SemiBold Nerd Font Complete.ttf||1345796:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font", + "font-family": "NotoSerifDisplay Nerd Font", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Serif Display ExtraCondensed SemiBold Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 7, + 6, + 8, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display ExtraCondensed SemiBold Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font", + "preferred_subfamily_name": "ExtraCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display ExtraCondensed Thin Italic Nerd Font Complete Mono.ttf||1338084:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font Mono", + "font-family": "NotoSerifDisplay Nerd Font Mono", + "font-stretch": "extra-condensed", + "font-style": "italic", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Serif Display ExtraCondensed Thin Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 2, + 6, + 8, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display ExtraCondensed Thin Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font Mono", + "preferred_subfamily_name": "ExtraCondensed Thin Italic", + "subfamily_name": "Italic", + "weight": 100, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display ExtraCondensed Thin Italic Nerd Font Complete.ttf||1351872:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font", + "font-family": "NotoSerifDisplay Nerd Font", + "font-stretch": "extra-condensed", + "font-style": "italic", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Serif Display ExtraCondensed Thin Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 2, + 6, + 8, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display ExtraCondensed Thin Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font", + "preferred_subfamily_name": "ExtraCondensed Thin Italic", + "subfamily_name": "Italic", + "weight": 100, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display ExtraCondensed Thin Nerd Font Complete Mono.ttf||1332640:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font Mono", + "font-family": "NotoSerifDisplay Nerd Font Mono", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Serif Display ExtraCondensed Thin Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 2, + 6, + 8, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display ExtraCondensed Thin Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font Mono", + "preferred_subfamily_name": "ExtraCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display ExtraCondensed Thin Nerd Font Complete.ttf||1346820:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font", + "font-family": "NotoSerifDisplay Nerd Font", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Serif Display ExtraCondensed Thin Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 2, + 6, + 8, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display ExtraCondensed Thin Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font", + "preferred_subfamily_name": "ExtraCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display ExtraLight Italic Nerd Font Complete Mono.ttf||1351972:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font Mono", + "font-family": "NotoSerifDisplay Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Serif Display ExtraLight Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 3, + 2, + 8, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display ExtraLight Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font Mono", + "preferred_subfamily_name": "ExtraLight Italic", + "subfamily_name": "Italic", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display ExtraLight Italic Nerd Font Complete.ttf||1357936:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font", + "font-family": "NotoSerifDisplay Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Serif Display ExtraLight Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 3, + 2, + 8, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display ExtraLight Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font", + "preferred_subfamily_name": "ExtraLight Italic", + "subfamily_name": "Italic", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display ExtraLight Nerd Font Complete Mono.ttf||1339960:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font Mono", + "font-family": "NotoSerifDisplay Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Serif Display ExtraLight Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 3, + 2, + 8, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display ExtraLight Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font Mono", + "preferred_subfamily_name": "ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display ExtraLight Nerd Font Complete.ttf||1345136:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font", + "font-family": "NotoSerifDisplay Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Serif Display ExtraLight Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 3, + 2, + 8, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display ExtraLight Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font", + "preferred_subfamily_name": "ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display Italic Nerd Font Complete Mono.ttf||1348144:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font Mono", + "font-family": "NotoSerifDisplay Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif Display Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 5, + 2, + 8, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display Italic Nerd Font Complete.ttf||1353264:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font", + "font-family": "NotoSerifDisplay Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif Display Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 5, + 2, + 8, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display Light Italic Nerd Font Complete Mono.ttf||1348500:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font Mono", + "font-family": "NotoSerifDisplay Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Serif Display Light Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 4, + 2, + 8, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display Light Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font Mono", + "preferred_subfamily_name": "Light Italic", + "subfamily_name": "Italic", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display Light Italic Nerd Font Complete.ttf||1354008:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font", + "font-family": "NotoSerifDisplay Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Serif Display Light Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 4, + 2, + 8, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display Light Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font", + "preferred_subfamily_name": "Light Italic", + "subfamily_name": "Italic", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display Light Nerd Font Complete Mono.ttf||1332064:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font Mono", + "font-family": "NotoSerifDisplay Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Serif Display Light Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 4, + 2, + 8, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display Light Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font Mono", + "preferred_subfamily_name": "Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display Light Nerd Font Complete.ttf||1337108:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font", + "font-family": "NotoSerifDisplay Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Serif Display Light Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 4, + 2, + 8, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display Light Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font", + "preferred_subfamily_name": "Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display Medium Italic Nerd Font Complete Mono.ttf||1352372:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font Mono", + "font-family": "NotoSerifDisplay Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Serif Display Medium Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 6, + 2, + 8, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display Medium Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font Mono", + "preferred_subfamily_name": "Medium Italic", + "subfamily_name": "Italic", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display Medium Italic Nerd Font Complete.ttf||1357468:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font", + "font-family": "NotoSerifDisplay Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Serif Display Medium Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 6, + 2, + 8, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display Medium Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font", + "preferred_subfamily_name": "Medium Italic", + "subfamily_name": "Italic", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display Medium Nerd Font Complete Mono.ttf||1332268:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font Mono", + "font-family": "NotoSerifDisplay Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Serif Display Medium Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 6, + 2, + 8, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display Medium Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font Mono", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display Medium Nerd Font Complete.ttf||1337120:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font", + "font-family": "NotoSerifDisplay Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Serif Display Medium Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 6, + 2, + 8, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display Medium Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display Regular Nerd Font Complete Mono.ttf||1325484:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font Mono", + "font-family": "NotoSerifDisplay Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif Display Regular Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 5, + 2, + 8, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display Regular Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display Regular Nerd Font Complete.ttf||1330404:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font", + "font-family": "NotoSerifDisplay Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif Display Regular Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 5, + 2, + 8, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display Regular Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display SemiBold Italic Nerd Font Complete Mono.ttf||1348808:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font Mono", + "font-family": "NotoSerifDisplay Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Serif Display SemiBold Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 7, + 2, + 8, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display SemiBold Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font Mono", + "preferred_subfamily_name": "SemiBold Italic", + "subfamily_name": "Italic", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display SemiBold Italic Nerd Font Complete.ttf||1353820:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font", + "font-family": "NotoSerifDisplay Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Serif Display SemiBold Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 7, + 2, + 8, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display SemiBold Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font", + "preferred_subfamily_name": "SemiBold Italic", + "subfamily_name": "Italic", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display SemiBold Nerd Font Complete Mono.ttf||1330068:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font Mono", + "font-family": "NotoSerifDisplay Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Serif Display SemiBold Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 7, + 2, + 8, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display SemiBold Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font Mono", + "preferred_subfamily_name": "SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display SemiBold Nerd Font Complete.ttf||1334876:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font", + "font-family": "NotoSerifDisplay Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Serif Display SemiBold Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 7, + 2, + 8, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display SemiBold Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font", + "preferred_subfamily_name": "SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display SemiCondensed Black Italic Nerd Font Complete Mono.ttf||1362504:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font Mono", + "font-family": "NotoSerifDisplay Nerd Font Mono", + "font-stretch": "semi-condensed", + "font-style": "italic", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Serif Display SemiCondensed Black Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 10, + 2, + 8, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display SemiCondensed Black Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font Mono", + "preferred_subfamily_name": "SemiCondensed Black Italic", + "subfamily_name": "Italic", + "weight": 900, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display SemiCondensed Black Italic Nerd Font Complete.ttf||1368328:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font", + "font-family": "NotoSerifDisplay Nerd Font", + "font-stretch": "semi-condensed", + "font-style": "italic", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Serif Display SemiCondensed Black Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 10, + 2, + 8, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display SemiCondensed Black Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font", + "preferred_subfamily_name": "SemiCondensed Black Italic", + "subfamily_name": "Italic", + "weight": 900, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display SemiCondensed Black Nerd Font Complete Mono.ttf||1371920:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font Mono", + "font-family": "NotoSerifDisplay Nerd Font Mono", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Serif Display SemiCondensed Black Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 10, + 2, + 8, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display SemiCondensed Black Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font Mono", + "preferred_subfamily_name": "SemiCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display SemiCondensed Black Nerd Font Complete.ttf||1377380:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font", + "font-family": "NotoSerifDisplay Nerd Font", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Serif Display SemiCondensed Black Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 10, + 2, + 8, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display SemiCondensed Black Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font", + "preferred_subfamily_name": "SemiCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display SemiCondensed Bold Italic Nerd Font Complete Mono.ttf||1351952:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font Mono", + "font-family": "NotoSerifDisplay Nerd Font Mono", + "font-stretch": "semi-condensed", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Serif Display SemiCondensed Bold Italic Nerd Font Complete Mono", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 8, + 2, + 8, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display SemiCondensed Bold Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font Mono", + "preferred_subfamily_name": "SemiCondensed Bold Italic", + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display SemiCondensed Bold Italic Nerd Font Complete.ttf||1358144:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font", + "font-family": "NotoSerifDisplay Nerd Font", + "font-stretch": "semi-condensed", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Serif Display SemiCondensed Bold Italic Nerd Font Complete", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 8, + 2, + 8, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display SemiCondensed Bold Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font", + "preferred_subfamily_name": "SemiCondensed Bold Italic", + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display SemiCondensed Bold Nerd Font Complete Mono.ttf||1335088:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font Mono", + "font-family": "NotoSerifDisplay Nerd Font Mono", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Serif Display SemiCondensed Bold Nerd Font Complete Mono", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 8, + 2, + 8, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display SemiCondensed Bold Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font Mono", + "preferred_subfamily_name": "SemiCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display SemiCondensed Bold Nerd Font Complete.ttf||1341012:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font", + "font-family": "NotoSerifDisplay Nerd Font", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Serif Display SemiCondensed Bold Nerd Font Complete", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 8, + 2, + 8, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display SemiCondensed Bold Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font", + "preferred_subfamily_name": "SemiCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display SemiCondensed ExtraBold Italic Nerd Font Complete Mono.ttf||1353640:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font Mono", + "font-family": "NotoSerifDisplay Nerd Font Mono", + "font-stretch": "semi-condensed", + "font-style": "italic", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Serif Display SemiCondensed ExtraBold Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 9, + 2, + 8, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display SemiCondensed ExtraBold Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font Mono", + "preferred_subfamily_name": "SemiCondensed ExtraBold Italic", + "subfamily_name": "Italic", + "weight": 800, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display SemiCondensed ExtraBold Italic Nerd Font Complete.ttf||1359480:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font", + "font-family": "NotoSerifDisplay Nerd Font", + "font-stretch": "semi-condensed", + "font-style": "italic", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Serif Display SemiCondensed ExtraBold Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 9, + 2, + 8, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display SemiCondensed ExtraBold Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font", + "preferred_subfamily_name": "SemiCondensed ExtraBold Italic", + "subfamily_name": "Italic", + "weight": 800, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display SemiCondensed ExtraBold Nerd Font Complete Mono.ttf||1340572:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font Mono", + "font-family": "NotoSerifDisplay Nerd Font Mono", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Serif Display SemiCondensed ExtraBold Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 9, + 2, + 8, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display SemiCondensed ExtraBold Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font Mono", + "preferred_subfamily_name": "SemiCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display SemiCondensed ExtraBold Nerd Font Complete.ttf||1346184:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font", + "font-family": "NotoSerifDisplay Nerd Font", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Serif Display SemiCondensed ExtraBold Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 9, + 2, + 8, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display SemiCondensed ExtraBold Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font", + "preferred_subfamily_name": "SemiCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display SemiCondensed ExtraLight Italic Nerd Font Complete Mono.ttf||1353516:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font Mono", + "font-family": "NotoSerifDisplay Nerd Font Mono", + "font-stretch": "semi-condensed", + "font-style": "italic", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Serif Display SemiCondensed ExtraLight Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 3, + 2, + 8, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display SemiCondensed ExtraLight Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font Mono", + "preferred_subfamily_name": "SemiCondensed ExtraLight Italic", + "subfamily_name": "Italic", + "weight": 200, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display SemiCondensed ExtraLight Italic Nerd Font Complete.ttf||1361044:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font", + "font-family": "NotoSerifDisplay Nerd Font", + "font-stretch": "semi-condensed", + "font-style": "italic", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Serif Display SemiCondensed ExtraLight Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 3, + 2, + 8, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display SemiCondensed ExtraLight Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font", + "preferred_subfamily_name": "SemiCondensed ExtraLight Italic", + "subfamily_name": "Italic", + "weight": 200, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display SemiCondensed ExtraLight Nerd Font Complete Mono.ttf||1345152:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font Mono", + "font-family": "NotoSerifDisplay Nerd Font Mono", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Serif Display SemiCondensed ExtraLight Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 3, + 2, + 8, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display SemiCondensed ExtraLight Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font Mono", + "preferred_subfamily_name": "SemiCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display SemiCondensed ExtraLight Nerd Font Complete.ttf||1352132:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font", + "font-family": "NotoSerifDisplay Nerd Font", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Serif Display SemiCondensed ExtraLight Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 3, + 2, + 8, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display SemiCondensed ExtraLight Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font", + "preferred_subfamily_name": "SemiCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display SemiCondensed Italic Nerd Font Complete Mono.ttf||1351732:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font Mono", + "font-family": "NotoSerifDisplay Nerd Font Mono", + "font-stretch": "semi-condensed", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif Display SemiCondensed Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 5, + 2, + 8, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display SemiCondensed Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font Mono", + "preferred_subfamily_name": "SemiCondensed Italic", + "subfamily_name": "Italic", + "weight": 400, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display SemiCondensed Italic Nerd Font Complete.ttf||1358328:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font", + "font-family": "NotoSerifDisplay Nerd Font", + "font-stretch": "semi-condensed", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif Display SemiCondensed Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 5, + 2, + 8, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display SemiCondensed Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font", + "preferred_subfamily_name": "SemiCondensed Italic", + "subfamily_name": "Italic", + "weight": 400, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display SemiCondensed Light Italic Nerd Font Complete Mono.ttf||1354136:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font Mono", + "font-family": "NotoSerifDisplay Nerd Font Mono", + "font-stretch": "semi-condensed", + "font-style": "italic", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Serif Display SemiCondensed Light Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 4, + 2, + 8, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display SemiCondensed Light Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font Mono", + "preferred_subfamily_name": "SemiCondensed Light Italic", + "subfamily_name": "Italic", + "weight": 300, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display SemiCondensed Light Italic Nerd Font Complete.ttf||1361212:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font", + "font-family": "NotoSerifDisplay Nerd Font", + "font-stretch": "semi-condensed", + "font-style": "italic", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Serif Display SemiCondensed Light Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 4, + 2, + 8, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display SemiCondensed Light Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font", + "preferred_subfamily_name": "SemiCondensed Light Italic", + "subfamily_name": "Italic", + "weight": 300, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display SemiCondensed Light Nerd Font Complete Mono.ttf||1342500:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font Mono", + "font-family": "NotoSerifDisplay Nerd Font Mono", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Serif Display SemiCondensed Light Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 4, + 2, + 8, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display SemiCondensed Light Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font Mono", + "preferred_subfamily_name": "SemiCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display SemiCondensed Light Nerd Font Complete.ttf||1349152:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font", + "font-family": "NotoSerifDisplay Nerd Font", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Serif Display SemiCondensed Light Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 4, + 2, + 8, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display SemiCondensed Light Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font", + "preferred_subfamily_name": "SemiCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display SemiCondensed Medium Italic Nerd Font Complete Mono.ttf||1352268:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font Mono", + "font-family": "NotoSerifDisplay Nerd Font Mono", + "font-stretch": "semi-condensed", + "font-style": "italic", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Serif Display SemiCondensed Medium Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 6, + 2, + 8, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display SemiCondensed Medium Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font Mono", + "preferred_subfamily_name": "SemiCondensed Medium Italic", + "subfamily_name": "Italic", + "weight": 500, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display SemiCondensed Medium Italic Nerd Font Complete.ttf||1358772:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font", + "font-family": "NotoSerifDisplay Nerd Font", + "font-stretch": "semi-condensed", + "font-style": "italic", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Serif Display SemiCondensed Medium Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 6, + 2, + 8, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display SemiCondensed Medium Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font", + "preferred_subfamily_name": "SemiCondensed Medium Italic", + "subfamily_name": "Italic", + "weight": 500, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display SemiCondensed Medium Nerd Font Complete Mono.ttf||1339256:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font Mono", + "font-family": "NotoSerifDisplay Nerd Font Mono", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Serif Display SemiCondensed Medium Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 6, + 2, + 8, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display SemiCondensed Medium Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font Mono", + "preferred_subfamily_name": "SemiCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display SemiCondensed Medium Nerd Font Complete.ttf||1345504:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font", + "font-family": "NotoSerifDisplay Nerd Font", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Serif Display SemiCondensed Medium Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 6, + 2, + 8, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display SemiCondensed Medium Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font", + "preferred_subfamily_name": "SemiCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display SemiCondensed Nerd Font Complete Mono.ttf||1339888:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font Mono", + "font-family": "NotoSerifDisplay Nerd Font Mono", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif Display SemiCondensed Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 5, + 2, + 8, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display SemiCondensed Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font Mono", + "preferred_subfamily_name": "SemiCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display SemiCondensed Nerd Font Complete.ttf||1346196:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font", + "font-family": "NotoSerifDisplay Nerd Font", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif Display SemiCondensed Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 5, + 2, + 8, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display SemiCondensed Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font", + "preferred_subfamily_name": "SemiCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display SemiCondensed SemiBold Italic Nerd Font Complete Mono.ttf||1351424:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font Mono", + "font-family": "NotoSerifDisplay Nerd Font Mono", + "font-stretch": "semi-condensed", + "font-style": "italic", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Serif Display SemiCondensed SemiBold Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 7, + 2, + 8, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display SemiCondensed SemiBold Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font Mono", + "preferred_subfamily_name": "SemiCondensed SemiBold Italic", + "subfamily_name": "Italic", + "weight": 600, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display SemiCondensed SemiBold Italic Nerd Font Complete.ttf||1357716:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font", + "font-family": "NotoSerifDisplay Nerd Font", + "font-stretch": "semi-condensed", + "font-style": "italic", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Serif Display SemiCondensed SemiBold Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 7, + 2, + 8, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display SemiCondensed SemiBold Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font", + "preferred_subfamily_name": "SemiCondensed SemiBold Italic", + "subfamily_name": "Italic", + "weight": 600, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display SemiCondensed SemiBold Nerd Font Complete Mono.ttf||1338660:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font Mono", + "font-family": "NotoSerifDisplay Nerd Font Mono", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Serif Display SemiCondensed SemiBold Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 7, + 2, + 8, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display SemiCondensed SemiBold Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font Mono", + "preferred_subfamily_name": "SemiCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display SemiCondensed SemiBold Nerd Font Complete.ttf||1344752:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font", + "font-family": "NotoSerifDisplay Nerd Font", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Serif Display SemiCondensed SemiBold Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 7, + 2, + 8, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display SemiCondensed SemiBold Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font", + "preferred_subfamily_name": "SemiCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display SemiCondensed Thin Italic Nerd Font Complete Mono.ttf||1348732:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font Mono", + "font-family": "NotoSerifDisplay Nerd Font Mono", + "font-stretch": "semi-condensed", + "font-style": "italic", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Serif Display SemiCondensed Thin Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 2, + 2, + 8, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display SemiCondensed Thin Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font Mono", + "preferred_subfamily_name": "SemiCondensed Thin Italic", + "subfamily_name": "Italic", + "weight": 100, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display SemiCondensed Thin Italic Nerd Font Complete.ttf||1356496:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font", + "font-family": "NotoSerifDisplay Nerd Font", + "font-stretch": "semi-condensed", + "font-style": "italic", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Serif Display SemiCondensed Thin Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 2, + 2, + 8, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display SemiCondensed Thin Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font", + "preferred_subfamily_name": "SemiCondensed Thin Italic", + "subfamily_name": "Italic", + "weight": 100, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display SemiCondensed Thin Nerd Font Complete Mono.ttf||1344752:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font Mono", + "font-family": "NotoSerifDisplay Nerd Font Mono", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Serif Display SemiCondensed Thin Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 2, + 2, + 8, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display SemiCondensed Thin Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font Mono", + "preferred_subfamily_name": "SemiCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display SemiCondensed Thin Nerd Font Complete.ttf||1352172:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font", + "font-family": "NotoSerifDisplay Nerd Font", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Serif Display SemiCondensed Thin Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 2, + 2, + 8, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display SemiCondensed Thin Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font", + "preferred_subfamily_name": "SemiCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display Thin Nerd Font Complete Mono.ttf||1340020:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font Mono", + "font-family": "NotoSerifDisplay Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Serif Display Thin Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 2, + 2, + 8, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display Thin Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font Mono", + "preferred_subfamily_name": "Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display Thin Nerd Font Complete.ttf||1345396:1634564302.0": { + "family_name": "NotoSerifDisplay Nerd Font", + "font-family": "NotoSerifDisplay Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Serif Display Thin Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 2, + 2, + 8, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Display Thin Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerifDisplay Nerd Font", + "preferred_subfamily_name": "Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif ExtraBold Italic Nerd Font Complete Mono.ttf||1414608:1634564302.0": { + "family_name": "NotoSerif Nerd Font Mono", + "font-family": "NotoSerif Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Serif ExtraBold Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 9, + 2, + 6, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif ExtraBold Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerif Nerd Font Mono", + "preferred_subfamily_name": "ExtraBold Italic", + "subfamily_name": "Italic", + "weight": 800, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif ExtraBold Italic Nerd Font Complete.ttf||1419404:1634564302.0": { + "family_name": "NotoSerif Nerd Font", + "font-family": "NotoSerif Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Serif ExtraBold Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 9, + 2, + 6, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif ExtraBold Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerif Nerd Font", + "preferred_subfamily_name": "ExtraBold Italic", + "subfamily_name": "Italic", + "weight": 800, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif ExtraBold Nerd Font Complete Mono.ttf||1386960:1634564302.0": { + "family_name": "NotoSerif Nerd Font Mono", + "font-family": "NotoSerif Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Serif ExtraBold Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 9, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif ExtraBold Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerif Nerd Font Mono", + "preferred_subfamily_name": "ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif ExtraBold Nerd Font Complete.ttf||1391708:1634564302.0": { + "family_name": "NotoSerif Nerd Font", + "font-family": "NotoSerif Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Serif ExtraBold Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 9, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif ExtraBold Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerif Nerd Font", + "preferred_subfamily_name": "ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif ExtraCondensed Black Italic Nerd Font Complete Mono.ttf||1408296:1634564302.0": { + "family_name": "NotoSerif Nerd Font Mono", + "font-family": "NotoSerif Nerd Font Mono", + "font-stretch": "extra-condensed", + "font-style": "italic", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Serif ExtraCondensed Black Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 10, + 6, + 6, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif ExtraCondensed Black Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerif Nerd Font Mono", + "preferred_subfamily_name": "ExtraCondensed Black Italic", + "subfamily_name": "Italic", + "weight": 900, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif ExtraCondensed Black Italic Nerd Font Complete.ttf||1418636:1634564302.0": { + "family_name": "NotoSerif Nerd Font", + "font-family": "NotoSerif Nerd Font", + "font-stretch": "extra-condensed", + "font-style": "italic", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Serif ExtraCondensed Black Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 10, + 6, + 6, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif ExtraCondensed Black Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerif Nerd Font", + "preferred_subfamily_name": "ExtraCondensed Black Italic", + "subfamily_name": "Italic", + "weight": 900, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif ExtraCondensed Black Nerd Font Complete Mono.ttf||1379672:1634564302.0": { + "family_name": "NotoSerif Nerd Font Mono", + "font-family": "NotoSerif Nerd Font Mono", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Serif ExtraCondensed Black Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 10, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif ExtraCondensed Black Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerif Nerd Font Mono", + "preferred_subfamily_name": "ExtraCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif ExtraCondensed Black Nerd Font Complete.ttf||1389308:1634564302.0": { + "family_name": "NotoSerif Nerd Font", + "font-family": "NotoSerif Nerd Font", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Serif ExtraCondensed Black Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 10, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif ExtraCondensed Black Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerif Nerd Font", + "preferred_subfamily_name": "ExtraCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif ExtraCondensed Bold Italic Nerd Font Complete Mono.ttf||1405512:1634564302.0": { + "family_name": "NotoSerif Nerd Font Mono", + "font-family": "NotoSerif Nerd Font Mono", + "font-stretch": "extra-condensed", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Serif ExtraCondensed Bold Italic Nerd Font Complete Mono", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 8, + 6, + 6, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif ExtraCondensed Bold Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerif Nerd Font Mono", + "preferred_subfamily_name": "ExtraCondensed Bold Italic", + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif ExtraCondensed Bold Italic Nerd Font Complete.ttf||1416944:1634564302.0": { + "family_name": "NotoSerif Nerd Font", + "font-family": "NotoSerif Nerd Font", + "font-stretch": "extra-condensed", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Serif ExtraCondensed Bold Italic Nerd Font Complete", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 8, + 6, + 6, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif ExtraCondensed Bold Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerif Nerd Font", + "preferred_subfamily_name": "ExtraCondensed Bold Italic", + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif ExtraCondensed Bold Nerd Font Complete Mono.ttf||1374568:1634564302.0": { + "family_name": "NotoSerif Nerd Font Mono", + "font-family": "NotoSerif Nerd Font Mono", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Serif ExtraCondensed Bold Nerd Font Complete Mono", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 8, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif ExtraCondensed Bold Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerif Nerd Font Mono", + "preferred_subfamily_name": "ExtraCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif ExtraCondensed Bold Nerd Font Complete.ttf||1385424:1634564302.0": { + "family_name": "NotoSerif Nerd Font", + "font-family": "NotoSerif Nerd Font", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Serif ExtraCondensed Bold Nerd Font Complete", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 8, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif ExtraCondensed Bold Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerif Nerd Font", + "preferred_subfamily_name": "ExtraCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif ExtraCondensed ExtraBold Italic Nerd Font Complete Mono.ttf||1406068:1634564302.0": { + "family_name": "NotoSerif Nerd Font Mono", + "font-family": "NotoSerif Nerd Font Mono", + "font-stretch": "extra-condensed", + "font-style": "italic", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Serif ExtraCondensed ExtraBold Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 9, + 6, + 6, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif ExtraCondensed ExtraBold Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerif Nerd Font Mono", + "preferred_subfamily_name": "ExtraCondensed ExtraBold Italic", + "subfamily_name": "Italic", + "weight": 800, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif ExtraCondensed ExtraBold Italic Nerd Font Complete.ttf||1416588:1634564302.0": { + "family_name": "NotoSerif Nerd Font", + "font-family": "NotoSerif Nerd Font", + "font-stretch": "extra-condensed", + "font-style": "italic", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Serif ExtraCondensed ExtraBold Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 9, + 6, + 6, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif ExtraCondensed ExtraBold Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerif Nerd Font", + "preferred_subfamily_name": "ExtraCondensed ExtraBold Italic", + "subfamily_name": "Italic", + "weight": 800, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif ExtraCondensed ExtraBold Nerd Font Complete Mono.ttf||1379332:1634564302.0": { + "family_name": "NotoSerif Nerd Font Mono", + "font-family": "NotoSerif Nerd Font Mono", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Serif ExtraCondensed ExtraBold Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 9, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif ExtraCondensed ExtraBold Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerif Nerd Font Mono", + "preferred_subfamily_name": "ExtraCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif ExtraCondensed ExtraBold Nerd Font Complete.ttf||1389488:1634564302.0": { + "family_name": "NotoSerif Nerd Font", + "font-family": "NotoSerif Nerd Font", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Serif ExtraCondensed ExtraBold Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 9, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif ExtraCondensed ExtraBold Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerif Nerd Font", + "preferred_subfamily_name": "ExtraCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif ExtraCondensed ExtraLight Italic Nerd Font Complete Mono.ttf||1374204:1634564302.0": { + "family_name": "NotoSerif Nerd Font Mono", + "font-family": "NotoSerif Nerd Font Mono", + "font-stretch": "extra-condensed", + "font-style": "italic", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Serif ExtraCondensed ExtraLight Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 3, + 6, + 6, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif ExtraCondensed ExtraLight Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerif Nerd Font Mono", + "preferred_subfamily_name": "ExtraCondensed ExtraLight Italic", + "subfamily_name": "Italic", + "weight": 200, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif ExtraCondensed ExtraLight Italic Nerd Font Complete.ttf||1387708:1634564302.0": { + "family_name": "NotoSerif Nerd Font", + "font-family": "NotoSerif Nerd Font", + "font-stretch": "extra-condensed", + "font-style": "italic", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Serif ExtraCondensed ExtraLight Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 3, + 6, + 6, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif ExtraCondensed ExtraLight Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerif Nerd Font", + "preferred_subfamily_name": "ExtraCondensed ExtraLight Italic", + "subfamily_name": "Italic", + "weight": 200, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif ExtraCondensed ExtraLight Nerd Font Complete Mono.ttf||1347628:1634564302.0": { + "family_name": "NotoSerif Nerd Font Mono", + "font-family": "NotoSerif Nerd Font Mono", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Serif ExtraCondensed ExtraLight Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 3, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif ExtraCondensed ExtraLight Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerif Nerd Font Mono", + "preferred_subfamily_name": "ExtraCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif ExtraCondensed ExtraLight Nerd Font Complete.ttf||1361512:1634564302.0": { + "family_name": "NotoSerif Nerd Font", + "font-family": "NotoSerif Nerd Font", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Serif ExtraCondensed ExtraLight Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 3, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif ExtraCondensed ExtraLight Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerif Nerd Font", + "preferred_subfamily_name": "ExtraCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif ExtraCondensed Italic Nerd Font Complete Mono.ttf||1381852:1634564302.0": { + "family_name": "NotoSerif Nerd Font Mono", + "font-family": "NotoSerif Nerd Font Mono", + "font-stretch": "extra-condensed", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif ExtraCondensed Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 5, + 6, + 6, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif ExtraCondensed Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerif Nerd Font Mono", + "preferred_subfamily_name": "ExtraCondensed Italic", + "subfamily_name": "Italic", + "weight": 400, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif ExtraCondensed Italic Nerd Font Complete.ttf||1394672:1634564302.0": { + "family_name": "NotoSerif Nerd Font", + "font-family": "NotoSerif Nerd Font", + "font-stretch": "extra-condensed", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif ExtraCondensed Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 5, + 6, + 6, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif ExtraCondensed Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerif Nerd Font", + "preferred_subfamily_name": "ExtraCondensed Italic", + "subfamily_name": "Italic", + "weight": 400, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif ExtraCondensed Light Italic Nerd Font Complete Mono.ttf||1372316:1634564302.0": { + "family_name": "NotoSerif Nerd Font Mono", + "font-family": "NotoSerif Nerd Font Mono", + "font-stretch": "extra-condensed", + "font-style": "italic", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Serif ExtraCondensed Light Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 4, + 6, + 6, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif ExtraCondensed Light Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerif Nerd Font Mono", + "preferred_subfamily_name": "ExtraCondensed Light Italic", + "subfamily_name": "Italic", + "weight": 300, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif ExtraCondensed Light Italic Nerd Font Complete.ttf||1385528:1634564302.0": { + "family_name": "NotoSerif Nerd Font", + "font-family": "NotoSerif Nerd Font", + "font-stretch": "extra-condensed", + "font-style": "italic", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Serif ExtraCondensed Light Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 4, + 6, + 6, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif ExtraCondensed Light Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerif Nerd Font", + "preferred_subfamily_name": "ExtraCondensed Light Italic", + "subfamily_name": "Italic", + "weight": 300, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif ExtraCondensed Light Nerd Font Complete Mono.ttf||1340688:1634564302.0": { + "family_name": "NotoSerif Nerd Font Mono", + "font-family": "NotoSerif Nerd Font Mono", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Serif ExtraCondensed Light Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 4, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif ExtraCondensed Light Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerif Nerd Font Mono", + "preferred_subfamily_name": "ExtraCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif ExtraCondensed Light Nerd Font Complete.ttf||1354088:1634564302.0": { + "family_name": "NotoSerif Nerd Font", + "font-family": "NotoSerif Nerd Font", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Serif ExtraCondensed Light Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 4, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif ExtraCondensed Light Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerif Nerd Font", + "preferred_subfamily_name": "ExtraCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif ExtraCondensed Medium Italic Nerd Font Complete Mono.ttf||1387956:1634564302.0": { + "family_name": "NotoSerif Nerd Font Mono", + "font-family": "NotoSerif Nerd Font Mono", + "font-stretch": "extra-condensed", + "font-style": "italic", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Serif ExtraCondensed Medium Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 6, + 6, + 6, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif ExtraCondensed Medium Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerif Nerd Font Mono", + "preferred_subfamily_name": "ExtraCondensed Medium Italic", + "subfamily_name": "Italic", + "weight": 500, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif ExtraCondensed Medium Italic Nerd Font Complete.ttf||1400396:1634564302.0": { + "family_name": "NotoSerif Nerd Font", + "font-family": "NotoSerif Nerd Font", + "font-stretch": "extra-condensed", + "font-style": "italic", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Serif ExtraCondensed Medium Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 6, + 6, + 6, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif ExtraCondensed Medium Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerif Nerd Font", + "preferred_subfamily_name": "ExtraCondensed Medium Italic", + "subfamily_name": "Italic", + "weight": 500, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif ExtraCondensed Medium Nerd Font Complete Mono.ttf||1361836:1634564302.0": { + "family_name": "NotoSerif Nerd Font Mono", + "font-family": "NotoSerif Nerd Font Mono", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Serif ExtraCondensed Medium Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 6, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif ExtraCondensed Medium Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerif Nerd Font Mono", + "preferred_subfamily_name": "ExtraCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif ExtraCondensed Medium Nerd Font Complete.ttf||1374256:1634564302.0": { + "family_name": "NotoSerif Nerd Font", + "font-family": "NotoSerif Nerd Font", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Serif ExtraCondensed Medium Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 6, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif ExtraCondensed Medium Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerif Nerd Font", + "preferred_subfamily_name": "ExtraCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif ExtraCondensed Nerd Font Complete Mono.ttf||1349552:1634564302.0": { + "family_name": "NotoSerif Nerd Font Mono", + "font-family": "NotoSerif Nerd Font Mono", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif ExtraCondensed Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 5, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif ExtraCondensed Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerif Nerd Font Mono", + "preferred_subfamily_name": "ExtraCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif ExtraCondensed Nerd Font Complete.ttf||1362300:1634564302.0": { + "family_name": "NotoSerif Nerd Font", + "font-family": "NotoSerif Nerd Font", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif ExtraCondensed Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 5, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif ExtraCondensed Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerif Nerd Font", + "preferred_subfamily_name": "ExtraCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif ExtraCondensed SemiBold Italic Nerd Font Complete Mono.ttf||1402440:1634564302.0": { + "family_name": "NotoSerif Nerd Font Mono", + "font-family": "NotoSerif Nerd Font Mono", + "font-stretch": "extra-condensed", + "font-style": "italic", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Serif ExtraCondensed SemiBold Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 7, + 6, + 6, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif ExtraCondensed SemiBold Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerif Nerd Font Mono", + "preferred_subfamily_name": "ExtraCondensed SemiBold Italic", + "subfamily_name": "Italic", + "weight": 600, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif ExtraCondensed SemiBold Italic Nerd Font Complete.ttf||1414396:1634564302.0": { + "family_name": "NotoSerif Nerd Font", + "font-family": "NotoSerif Nerd Font", + "font-stretch": "extra-condensed", + "font-style": "italic", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Serif ExtraCondensed SemiBold Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 7, + 6, + 6, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif ExtraCondensed SemiBold Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerif Nerd Font", + "preferred_subfamily_name": "ExtraCondensed SemiBold Italic", + "subfamily_name": "Italic", + "weight": 600, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif ExtraCondensed SemiBold Nerd Font Complete Mono.ttf||1371104:1634564302.0": { + "family_name": "NotoSerif Nerd Font Mono", + "font-family": "NotoSerif Nerd Font Mono", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Serif ExtraCondensed SemiBold Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 7, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif ExtraCondensed SemiBold Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerif Nerd Font Mono", + "preferred_subfamily_name": "ExtraCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif ExtraCondensed SemiBold Nerd Font Complete.ttf||1382844:1634564302.0": { + "family_name": "NotoSerif Nerd Font", + "font-family": "NotoSerif Nerd Font", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Serif ExtraCondensed SemiBold Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 7, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif ExtraCondensed SemiBold Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerif Nerd Font", + "preferred_subfamily_name": "ExtraCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif ExtraCondensed Thin Italic Nerd Font Complete Mono.ttf||1383172:1634564302.0": { + "family_name": "NotoSerif Nerd Font Mono", + "font-family": "NotoSerif Nerd Font Mono", + "font-stretch": "extra-condensed", + "font-style": "italic", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Serif ExtraCondensed Thin Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 2, + 6, + 6, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif ExtraCondensed Thin Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerif Nerd Font Mono", + "preferred_subfamily_name": "ExtraCondensed Thin Italic", + "subfamily_name": "Italic", + "weight": 100, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif ExtraCondensed Thin Italic Nerd Font Complete.ttf||1396956:1634564302.0": { + "family_name": "NotoSerif Nerd Font", + "font-family": "NotoSerif Nerd Font", + "font-stretch": "extra-condensed", + "font-style": "italic", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Serif ExtraCondensed Thin Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 2, + 6, + 6, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif ExtraCondensed Thin Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerif Nerd Font", + "preferred_subfamily_name": "ExtraCondensed Thin Italic", + "subfamily_name": "Italic", + "weight": 100, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif ExtraCondensed Thin Nerd Font Complete Mono.ttf||1365368:1634564302.0": { + "family_name": "NotoSerif Nerd Font Mono", + "font-family": "NotoSerif Nerd Font Mono", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Serif ExtraCondensed Thin Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 2, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif ExtraCondensed Thin Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerif Nerd Font Mono", + "preferred_subfamily_name": "ExtraCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif ExtraCondensed Thin Nerd Font Complete.ttf||1379544:1634564302.0": { + "family_name": "NotoSerif Nerd Font", + "font-family": "NotoSerif Nerd Font", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Serif ExtraCondensed Thin Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 2, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif ExtraCondensed Thin Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerif Nerd Font", + "preferred_subfamily_name": "ExtraCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif ExtraLight Italic Nerd Font Complete Mono.ttf||1371920:1634564302.0": { + "family_name": "NotoSerif Nerd Font Mono", + "font-family": "NotoSerif Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Serif ExtraLight Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 3, + 2, + 6, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif ExtraLight Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerif Nerd Font Mono", + "preferred_subfamily_name": "ExtraLight Italic", + "subfamily_name": "Italic", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif ExtraLight Italic Nerd Font Complete.ttf||1377912:1634564302.0": { + "family_name": "NotoSerif Nerd Font", + "font-family": "NotoSerif Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Serif ExtraLight Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 3, + 2, + 6, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif ExtraLight Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerif Nerd Font", + "preferred_subfamily_name": "ExtraLight Italic", + "subfamily_name": "Italic", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif ExtraLight Nerd Font Complete Mono.ttf||1351104:1634564302.0": { + "family_name": "NotoSerif Nerd Font Mono", + "font-family": "NotoSerif Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Serif ExtraLight Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 3, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif ExtraLight Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerif Nerd Font Mono", + "preferred_subfamily_name": "ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif ExtraLight Nerd Font Complete.ttf||1356252:1634564302.0": { + "family_name": "NotoSerif Nerd Font", + "font-family": "NotoSerif Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Serif ExtraLight Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 3, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif ExtraLight Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerif Nerd Font", + "preferred_subfamily_name": "ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Italic Nerd Font Complete Mono.ttf||1392752:1634564302.0": { + "family_name": "NotoSerif Nerd Font Mono", + "font-family": "NotoSerif Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 5, + 2, + 6, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerif Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Italic Nerd Font Complete.ttf||1397880:1634564302.0": { + "family_name": "NotoSerif Nerd Font", + "font-family": "NotoSerif Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 5, + 2, + 6, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerif Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Light Italic Nerd Font Complete Mono.ttf||1378256:1634564302.0": { + "family_name": "NotoSerif Nerd Font Mono", + "font-family": "NotoSerif Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Serif Light Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 4, + 2, + 6, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Light Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerif Nerd Font Mono", + "preferred_subfamily_name": "Light Italic", + "subfamily_name": "Italic", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Light Italic Nerd Font Complete.ttf||1383772:1634564302.0": { + "family_name": "NotoSerif Nerd Font", + "font-family": "NotoSerif Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Serif Light Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 4, + 2, + 6, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Light Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerif Nerd Font", + "preferred_subfamily_name": "Light Italic", + "subfamily_name": "Italic", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Light Nerd Font Complete Mono.ttf||1363956:1634564302.0": { + "family_name": "NotoSerif Nerd Font Mono", + "font-family": "NotoSerif Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Serif Light Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 4, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Light Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerif Nerd Font Mono", + "preferred_subfamily_name": "Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Light Nerd Font Complete.ttf||1369000:1634564302.0": { + "family_name": "NotoSerif Nerd Font", + "font-family": "NotoSerif Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Serif Light Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 4, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Light Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerif Nerd Font", + "preferred_subfamily_name": "Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Medium Italic Nerd Font Complete Mono.ttf||1412032:1634564302.0": { + "family_name": "NotoSerif Nerd Font Mono", + "font-family": "NotoSerif Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Serif Medium Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 6, + 2, + 6, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Medium Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerif Nerd Font Mono", + "preferred_subfamily_name": "Medium Italic", + "subfamily_name": "Italic", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Medium Italic Nerd Font Complete.ttf||1417108:1634564302.0": { + "family_name": "NotoSerif Nerd Font", + "font-family": "NotoSerif Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Serif Medium Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 6, + 2, + 6, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Medium Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerif Nerd Font", + "preferred_subfamily_name": "Medium Italic", + "subfamily_name": "Italic", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Medium Nerd Font Complete Mono.ttf||1371688:1634564302.0": { + "family_name": "NotoSerif Nerd Font Mono", + "font-family": "NotoSerif Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Serif Medium Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 6, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Medium Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerif Nerd Font Mono", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Medium Nerd Font Complete.ttf||1376544:1634564302.0": { + "family_name": "NotoSerif Nerd Font", + "font-family": "NotoSerif Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Serif Medium Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 6, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Medium Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerif Nerd Font", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Regular Nerd Font Complete Mono.ttf||1351860:1634564302.0": { + "family_name": "NotoSerif Nerd Font Mono", + "font-family": "NotoSerif Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif Regular Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 5, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Regular Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerif Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Regular Nerd Font Complete.ttf||1356780:1634564302.0": { + "family_name": "NotoSerif Nerd Font", + "font-family": "NotoSerif Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif Regular Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 5, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Regular Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerif Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif SemiBold Italic Nerd Font Complete Mono.ttf||1411204:1634564302.0": { + "family_name": "NotoSerif Nerd Font Mono", + "font-family": "NotoSerif Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Serif SemiBold Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 7, + 2, + 6, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif SemiBold Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerif Nerd Font Mono", + "preferred_subfamily_name": "SemiBold Italic", + "subfamily_name": "Italic", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif SemiBold Italic Nerd Font Complete.ttf||1416232:1634564302.0": { + "family_name": "NotoSerif Nerd Font", + "font-family": "NotoSerif Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Serif SemiBold Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 7, + 2, + 6, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif SemiBold Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerif Nerd Font", + "preferred_subfamily_name": "SemiBold Italic", + "subfamily_name": "Italic", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif SemiBold Nerd Font Complete Mono.ttf||1371676:1634564302.0": { + "family_name": "NotoSerif Nerd Font Mono", + "font-family": "NotoSerif Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Serif SemiBold Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 7, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif SemiBold Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerif Nerd Font Mono", + "preferred_subfamily_name": "SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif SemiBold Nerd Font Complete.ttf||1376472:1634564302.0": { + "family_name": "NotoSerif Nerd Font", + "font-family": "NotoSerif Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Serif SemiBold Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 7, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif SemiBold Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerif Nerd Font", + "preferred_subfamily_name": "SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif SemiCondensed Black Italic Nerd Font Complete Mono.ttf||1424836:1634564302.0": { + "family_name": "NotoSerif Nerd Font Mono", + "font-family": "NotoSerif Nerd Font Mono", + "font-stretch": "semi-condensed", + "font-style": "italic", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Serif SemiCondensed Black Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 10, + 2, + 6, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif SemiCondensed Black Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerif Nerd Font Mono", + "preferred_subfamily_name": "SemiCondensed Black Italic", + "subfamily_name": "Italic", + "weight": 900, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif SemiCondensed Black Italic Nerd Font Complete.ttf||1430668:1634564302.0": { + "family_name": "NotoSerif Nerd Font", + "font-family": "NotoSerif Nerd Font", + "font-stretch": "semi-condensed", + "font-style": "italic", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Serif SemiCondensed Black Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 10, + 2, + 6, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif SemiCondensed Black Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerif Nerd Font", + "preferred_subfamily_name": "SemiCondensed Black Italic", + "subfamily_name": "Italic", + "weight": 900, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif SemiCondensed Black Nerd Font Complete Mono.ttf||1414480:1634564302.0": { + "family_name": "NotoSerif Nerd Font Mono", + "font-family": "NotoSerif Nerd Font Mono", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Serif SemiCondensed Black Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 10, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif SemiCondensed Black Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerif Nerd Font Mono", + "preferred_subfamily_name": "SemiCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif SemiCondensed Black Nerd Font Complete.ttf||1419944:1634564302.0": { + "family_name": "NotoSerif Nerd Font", + "font-family": "NotoSerif Nerd Font", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Serif SemiCondensed Black Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 10, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif SemiCondensed Black Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerif Nerd Font", + "preferred_subfamily_name": "SemiCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif SemiCondensed Bold Italic Nerd Font Complete Mono.ttf||1408256:1634564302.0": { + "family_name": "NotoSerif Nerd Font Mono", + "font-family": "NotoSerif Nerd Font Mono", + "font-stretch": "semi-condensed", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Serif SemiCondensed Bold Italic Nerd Font Complete Mono", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 8, + 2, + 6, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif SemiCondensed Bold Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerif Nerd Font Mono", + "preferred_subfamily_name": "SemiCondensed Bold Italic", + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif SemiCondensed Bold Italic Nerd Font Complete.ttf||1414400:1634564302.0": { + "family_name": "NotoSerif Nerd Font", + "font-family": "NotoSerif Nerd Font", + "font-stretch": "semi-condensed", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Serif SemiCondensed Bold Italic Nerd Font Complete", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 8, + 2, + 6, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif SemiCondensed Bold Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerif Nerd Font", + "preferred_subfamily_name": "SemiCondensed Bold Italic", + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif SemiCondensed Bold Nerd Font Complete Mono.ttf||1375880:1634564302.0": { + "family_name": "NotoSerif Nerd Font Mono", + "font-family": "NotoSerif Nerd Font Mono", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Serif SemiCondensed Bold Nerd Font Complete Mono", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 8, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif SemiCondensed Bold Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerif Nerd Font Mono", + "preferred_subfamily_name": "SemiCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif SemiCondensed Bold Nerd Font Complete.ttf||1381776:1634564302.0": { + "family_name": "NotoSerif Nerd Font", + "font-family": "NotoSerif Nerd Font", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Serif SemiCondensed Bold Nerd Font Complete", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 8, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif SemiCondensed Bold Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerif Nerd Font", + "preferred_subfamily_name": "SemiCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif SemiCondensed ExtraBold Italic Nerd Font Complete Mono.ttf||1413864:1634564302.0": { + "family_name": "NotoSerif Nerd Font Mono", + "font-family": "NotoSerif Nerd Font Mono", + "font-stretch": "semi-condensed", + "font-style": "italic", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Serif SemiCondensed ExtraBold Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 9, + 2, + 6, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif SemiCondensed ExtraBold Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerif Nerd Font Mono", + "preferred_subfamily_name": "SemiCondensed ExtraBold Italic", + "subfamily_name": "Italic", + "weight": 800, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif SemiCondensed ExtraBold Italic Nerd Font Complete.ttf||1419664:1634564302.0": { + "family_name": "NotoSerif Nerd Font", + "font-family": "NotoSerif Nerd Font", + "font-stretch": "semi-condensed", + "font-style": "italic", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Serif SemiCondensed ExtraBold Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 9, + 2, + 6, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif SemiCondensed ExtraBold Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerif Nerd Font", + "preferred_subfamily_name": "SemiCondensed ExtraBold Italic", + "subfamily_name": "Italic", + "weight": 800, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif SemiCondensed ExtraBold Nerd Font Complete Mono.ttf||1384888:1634564302.0": { + "family_name": "NotoSerif Nerd Font Mono", + "font-family": "NotoSerif Nerd Font Mono", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Serif SemiCondensed ExtraBold Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 9, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif SemiCondensed ExtraBold Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerif Nerd Font Mono", + "preferred_subfamily_name": "SemiCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif SemiCondensed ExtraBold Nerd Font Complete.ttf||1390508:1634564302.0": { + "family_name": "NotoSerif Nerd Font", + "font-family": "NotoSerif Nerd Font", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Serif SemiCondensed ExtraBold Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 9, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif SemiCondensed ExtraBold Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerif Nerd Font", + "preferred_subfamily_name": "SemiCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif SemiCondensed ExtraLight Italic Nerd Font Complete Mono.ttf||1373616:1634564302.0": { + "family_name": "NotoSerif Nerd Font Mono", + "font-family": "NotoSerif Nerd Font Mono", + "font-stretch": "semi-condensed", + "font-style": "italic", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Serif SemiCondensed ExtraLight Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 3, + 2, + 6, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif SemiCondensed ExtraLight Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerif Nerd Font Mono", + "preferred_subfamily_name": "SemiCondensed ExtraLight Italic", + "subfamily_name": "Italic", + "weight": 200, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif SemiCondensed ExtraLight Italic Nerd Font Complete.ttf||1381164:1634564302.0": { + "family_name": "NotoSerif Nerd Font", + "font-family": "NotoSerif Nerd Font", + "font-stretch": "semi-condensed", + "font-style": "italic", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Serif SemiCondensed ExtraLight Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 3, + 2, + 6, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif SemiCondensed ExtraLight Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerif Nerd Font", + "preferred_subfamily_name": "SemiCondensed ExtraLight Italic", + "subfamily_name": "Italic", + "weight": 200, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif SemiCondensed ExtraLight Nerd Font Complete Mono.ttf||1351568:1634564302.0": { + "family_name": "NotoSerif Nerd Font Mono", + "font-family": "NotoSerif Nerd Font Mono", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Serif SemiCondensed ExtraLight Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 3, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif SemiCondensed ExtraLight Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerif Nerd Font Mono", + "preferred_subfamily_name": "SemiCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif SemiCondensed ExtraLight Nerd Font Complete.ttf||1358544:1634564302.0": { + "family_name": "NotoSerif Nerd Font", + "font-family": "NotoSerif Nerd Font", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Serif SemiCondensed ExtraLight Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 3, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif SemiCondensed ExtraLight Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerif Nerd Font", + "preferred_subfamily_name": "SemiCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif SemiCondensed Italic Nerd Font Complete Mono.ttf||1392960:1634564302.0": { + "family_name": "NotoSerif Nerd Font Mono", + "font-family": "NotoSerif Nerd Font Mono", + "font-stretch": "semi-condensed", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif SemiCondensed Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 5, + 2, + 6, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif SemiCondensed Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerif Nerd Font Mono", + "preferred_subfamily_name": "SemiCondensed Italic", + "subfamily_name": "Italic", + "weight": 400, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif SemiCondensed Italic Nerd Font Complete.ttf||1399520:1634564302.0": { + "family_name": "NotoSerif Nerd Font", + "font-family": "NotoSerif Nerd Font", + "font-stretch": "semi-condensed", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif SemiCondensed Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 5, + 2, + 6, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif SemiCondensed Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerif Nerd Font", + "preferred_subfamily_name": "SemiCondensed Italic", + "subfamily_name": "Italic", + "weight": 400, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif SemiCondensed Light Italic Nerd Font Complete Mono.ttf||1381876:1634564302.0": { + "family_name": "NotoSerif Nerd Font Mono", + "font-family": "NotoSerif Nerd Font Mono", + "font-stretch": "semi-condensed", + "font-style": "italic", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Serif SemiCondensed Light Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 4, + 2, + 6, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif SemiCondensed Light Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerif Nerd Font Mono", + "preferred_subfamily_name": "SemiCondensed Light Italic", + "subfamily_name": "Italic", + "weight": 300, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif SemiCondensed Light Italic Nerd Font Complete.ttf||1388852:1634564302.0": { + "family_name": "NotoSerif Nerd Font", + "font-family": "NotoSerif Nerd Font", + "font-stretch": "semi-condensed", + "font-style": "italic", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Serif SemiCondensed Light Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 4, + 2, + 6, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif SemiCondensed Light Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerif Nerd Font", + "preferred_subfamily_name": "SemiCondensed Light Italic", + "subfamily_name": "Italic", + "weight": 300, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif SemiCondensed Light Nerd Font Complete Mono.ttf||1363756:1634564302.0": { + "family_name": "NotoSerif Nerd Font Mono", + "font-family": "NotoSerif Nerd Font Mono", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Serif SemiCondensed Light Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 4, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif SemiCondensed Light Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerif Nerd Font Mono", + "preferred_subfamily_name": "SemiCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif SemiCondensed Light Nerd Font Complete.ttf||1370392:1634564302.0": { + "family_name": "NotoSerif Nerd Font", + "font-family": "NotoSerif Nerd Font", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Serif SemiCondensed Light Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 4, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif SemiCondensed Light Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerif Nerd Font", + "preferred_subfamily_name": "SemiCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif SemiCondensed Medium Italic Nerd Font Complete Mono.ttf||1393992:1634564302.0": { + "family_name": "NotoSerif Nerd Font Mono", + "font-family": "NotoSerif Nerd Font Mono", + "font-stretch": "semi-condensed", + "font-style": "italic", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Serif SemiCondensed Medium Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 6, + 2, + 6, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif SemiCondensed Medium Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerif Nerd Font Mono", + "preferred_subfamily_name": "SemiCondensed Medium Italic", + "subfamily_name": "Italic", + "weight": 500, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif SemiCondensed Medium Italic Nerd Font Complete.ttf||1400392:1634564302.0": { + "family_name": "NotoSerif Nerd Font", + "font-family": "NotoSerif Nerd Font", + "font-stretch": "semi-condensed", + "font-style": "italic", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Serif SemiCondensed Medium Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 6, + 2, + 6, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif SemiCondensed Medium Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerif Nerd Font", + "preferred_subfamily_name": "SemiCondensed Medium Italic", + "subfamily_name": "Italic", + "weight": 500, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif SemiCondensed Medium Nerd Font Complete Mono.ttf||1377188:1634564302.0": { + "family_name": "NotoSerif Nerd Font Mono", + "font-family": "NotoSerif Nerd Font Mono", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Serif SemiCondensed Medium Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 6, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif SemiCondensed Medium Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerif Nerd Font Mono", + "preferred_subfamily_name": "SemiCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif SemiCondensed Medium Nerd Font Complete.ttf||1383412:1634564302.0": { + "family_name": "NotoSerif Nerd Font", + "font-family": "NotoSerif Nerd Font", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Serif SemiCondensed Medium Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 6, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif SemiCondensed Medium Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerif Nerd Font", + "preferred_subfamily_name": "SemiCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif SemiCondensed Nerd Font Complete Mono.ttf||1358092:1634564302.0": { + "family_name": "NotoSerif Nerd Font Mono", + "font-family": "NotoSerif Nerd Font Mono", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif SemiCondensed Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 5, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif SemiCondensed Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerif Nerd Font Mono", + "preferred_subfamily_name": "SemiCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif SemiCondensed Nerd Font Complete.ttf||1364420:1634564302.0": { + "family_name": "NotoSerif Nerd Font", + "font-family": "NotoSerif Nerd Font", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif SemiCondensed Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 5, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif SemiCondensed Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerif Nerd Font", + "preferred_subfamily_name": "SemiCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif SemiCondensed SemiBold Italic Nerd Font Complete Mono.ttf||1410704:1634564302.0": { + "family_name": "NotoSerif Nerd Font Mono", + "font-family": "NotoSerif Nerd Font Mono", + "font-stretch": "semi-condensed", + "font-style": "italic", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Serif SemiCondensed SemiBold Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 7, + 2, + 6, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif SemiCondensed SemiBold Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerif Nerd Font Mono", + "preferred_subfamily_name": "SemiCondensed SemiBold Italic", + "subfamily_name": "Italic", + "weight": 600, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif SemiCondensed SemiBold Italic Nerd Font Complete.ttf||1417056:1634564302.0": { + "family_name": "NotoSerif Nerd Font", + "font-family": "NotoSerif Nerd Font", + "font-stretch": "semi-condensed", + "font-style": "italic", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Serif SemiCondensed SemiBold Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 7, + 2, + 6, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif SemiCondensed SemiBold Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerif Nerd Font", + "preferred_subfamily_name": "SemiCondensed SemiBold Italic", + "subfamily_name": "Italic", + "weight": 600, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif SemiCondensed SemiBold Nerd Font Complete Mono.ttf||1377016:1634564302.0": { + "family_name": "NotoSerif Nerd Font Mono", + "font-family": "NotoSerif Nerd Font Mono", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Serif SemiCondensed SemiBold Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 7, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif SemiCondensed SemiBold Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerif Nerd Font Mono", + "preferred_subfamily_name": "SemiCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif SemiCondensed SemiBold Nerd Font Complete.ttf||1383100:1634564302.0": { + "family_name": "NotoSerif Nerd Font", + "font-family": "NotoSerif Nerd Font", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Serif SemiCondensed SemiBold Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 7, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif SemiCondensed SemiBold Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerif Nerd Font", + "preferred_subfamily_name": "SemiCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif SemiCondensed Thin Italic Nerd Font Complete Mono.ttf||1379976:1634564302.0": { + "family_name": "NotoSerif Nerd Font Mono", + "font-family": "NotoSerif Nerd Font Mono", + "font-stretch": "semi-condensed", + "font-style": "italic", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Serif SemiCondensed Thin Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 2, + 2, + 6, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif SemiCondensed Thin Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerif Nerd Font Mono", + "preferred_subfamily_name": "SemiCondensed Thin Italic", + "subfamily_name": "Italic", + "weight": 100, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif SemiCondensed Thin Italic Nerd Font Complete.ttf||1387760:1634564302.0": { + "family_name": "NotoSerif Nerd Font", + "font-family": "NotoSerif Nerd Font", + "font-stretch": "semi-condensed", + "font-style": "italic", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Serif SemiCondensed Thin Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 2, + 2, + 6, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif SemiCondensed Thin Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerif Nerd Font", + "preferred_subfamily_name": "SemiCondensed Thin Italic", + "subfamily_name": "Italic", + "weight": 100, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif SemiCondensed Thin Nerd Font Complete Mono.ttf||1372484:1634564302.0": { + "family_name": "NotoSerif Nerd Font Mono", + "font-family": "NotoSerif Nerd Font Mono", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Serif SemiCondensed Thin Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 2, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif SemiCondensed Thin Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerif Nerd Font Mono", + "preferred_subfamily_name": "SemiCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif SemiCondensed Thin Nerd Font Complete.ttf||1379888:1634564302.0": { + "family_name": "NotoSerif Nerd Font", + "font-family": "NotoSerif Nerd Font", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Serif SemiCondensed Thin Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 2, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif SemiCondensed Thin Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerif Nerd Font", + "preferred_subfamily_name": "SemiCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Thin Italic Nerd Font Complete Mono.ttf||1386788:1634564302.0": { + "family_name": "NotoSerif Nerd Font Mono", + "font-family": "NotoSerif Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Serif Thin Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 2, + 2, + 6, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Thin Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerif Nerd Font Mono", + "preferred_subfamily_name": "Thin Italic", + "subfamily_name": "Italic", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Thin Italic Nerd Font Complete.ttf||1393092:1634564302.0": { + "family_name": "NotoSerif Nerd Font", + "font-family": "NotoSerif Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Serif Thin Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 2, + 2, + 6, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Thin Italic Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerif Nerd Font", + "preferred_subfamily_name": "Thin Italic", + "subfamily_name": "Italic", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Thin Nerd Font Complete Mono.ttf||1379060:1634564302.0": { + "family_name": "NotoSerif Nerd Font Mono", + "font-family": "NotoSerif Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Serif Thin Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 2, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Thin Nerd Font Complete Mono.ttf", + "preferred_family_name": "NotoSerif Nerd Font Mono", + "preferred_subfamily_name": "Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Thin Nerd Font Complete.ttf||1384440:1634564302.0": { + "family_name": "NotoSerif Nerd Font", + "font-family": "NotoSerif Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Serif Thin Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 2, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Noto Serif Thin Nerd Font Complete.ttf", + "preferred_family_name": "NotoSerif Nerd Font", + "preferred_subfamily_name": "Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/ProFont IIx Nerd Font Complete Mono.ttf||817148:1634564302.0": { + "family_name": "ProFontIIx Nerd Font Mono", + "font-family": "ProFontIIx Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "ProFont IIx Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 1, + "panose": [ + 0, + 0, + 4, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/ProFont IIx Nerd Font Complete Mono.ttf", + "preferred_family_name": "ProFontIIx Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Book", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/ProFont IIx Nerd Font Complete.ttf||827356:1634564302.0": { + "family_name": "ProFontIIx Nerd Font", + "font-family": "ProFontIIx Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "ProFont IIx Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 1, + "panose": [ + 0, + 0, + 4, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/ProFont IIx Nerd Font Complete.ttf", + "preferred_family_name": "ProFontIIx Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Book", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/ProFontWindows Nerd Font Complete Mono.ttf||817648:1634564302.0": { + "family_name": "ProFontWindows Nerd Font Mono", + "font-family": "ProFontWindows Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "ProFontWindows Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 0, + 4, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/ProFontWindows Nerd Font Complete Mono.ttf", + "preferred_family_name": "ProFontWindows Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Book", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/ProFontWindows Nerd Font Complete.ttf||835492:1634564302.0": { + "family_name": "ProFontWindows Nerd Font", + "font-family": "ProFontWindows Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "ProFontWindows Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 1, + "panose": [ + 2, + 0, + 4, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/ProFontWindows Nerd Font Complete.ttf", + "preferred_family_name": "ProFontWindows Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Book", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/ProggyCleanTT CE Nerd Font Complete Mono.ttf||842468:1634564302.0": { + "family_name": "ProggyCleanTTCE Nerd Font Mono", + "font-family": "ProggyCleanTTCE Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "ProggyCleanTT CE Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 1, + "panose": [ + 0, + 0, + 4, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/ProggyCleanTT CE Nerd Font Complete Mono.ttf", + "preferred_family_name": "ProggyCleanTTCE Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Book", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/ProggyCleanTT CE Nerd Font Complete.ttf||878720:1634564302.0": { + "family_name": "ProggyCleanTTCE Nerd Font", + "font-family": "ProggyCleanTTCE Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "ProggyCleanTT CE Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 1, + "panose": [ + 0, + 0, + 4, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/ProggyCleanTT CE Nerd Font Complete.ttf", + "preferred_family_name": "ProggyCleanTTCE Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Book", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/ProggyCleanTT Nerd Font Complete Mono.ttf||838628:1634564302.0": { + "family_name": "ProggyCleanTT Nerd Font Mono", + "font-family": "ProggyCleanTT Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "ProggyCleanTT Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 1, + "panose": [ + 0, + 0, + 4, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/ProggyCleanTT Nerd Font Complete Mono.ttf", + "preferred_family_name": "ProggyCleanTT Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Book", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/ProggyCleanTT Nerd Font Complete.ttf||874880:1634564302.0": { + "family_name": "ProggyCleanTT Nerd Font", + "font-family": "ProggyCleanTT Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "ProggyCleanTT Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 1, + "panose": [ + 0, + 0, + 4, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/ProggyCleanTT Nerd Font Complete.ttf", + "preferred_family_name": "ProggyCleanTT Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Book", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/ProggyCleanTTSZ Nerd Font Complete Mono.ttf||838680:1634564302.0": { + "family_name": "ProggyCleanTTSZ Nerd Font Mono", + "font-family": "ProggyCleanTTSZ Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "ProggyCleanTTSZ Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 1, + "panose": [ + 0, + 0, + 4, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/ProggyCleanTTSZ Nerd Font Complete Mono.ttf", + "preferred_family_name": "ProggyCleanTTSZ Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Book", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/ProggyCleanTTSZ Nerd Font Complete.ttf||874932:1634564302.0": { + "family_name": "ProggyCleanTTSZ Nerd Font", + "font-family": "ProggyCleanTTSZ Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "ProggyCleanTTSZ Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 1, + "panose": [ + 0, + 0, + 4, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/ProggyCleanTTSZ Nerd Font Complete.ttf", + "preferred_family_name": "ProggyCleanTTSZ Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Book", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Roboto Mono Bold Italic Nerd Font Complete Mono.ttf||943148:1634564302.0": { + "family_name": "RobotoMono Nerd Font Mono", + "font-family": "RobotoMono Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Roboto Mono Bold Italic Nerd Font Complete Mono", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Roboto Mono Bold Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "RobotoMono Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Roboto Mono Bold Italic Nerd Font Complete.ttf||964172:1634564302.0": { + "family_name": "RobotoMono Nerd Font", + "font-family": "RobotoMono Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Roboto Mono Bold Italic Nerd Font Complete", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Roboto Mono Bold Italic Nerd Font Complete.ttf", + "preferred_family_name": "RobotoMono Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Roboto Mono Bold Nerd Font Complete Mono.ttf||935936:1634564302.0": { + "family_name": "RobotoMono Nerd Font Mono", + "font-family": "RobotoMono Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Roboto Mono Bold Nerd Font Complete Mono", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Roboto Mono Bold Nerd Font Complete Mono.ttf", + "preferred_family_name": "RobotoMono Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Roboto Mono Bold Nerd Font Complete.ttf||956088:1634564302.0": { + "family_name": "RobotoMono Nerd Font", + "font-family": "RobotoMono Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Roboto Mono Bold Nerd Font Complete", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Roboto Mono Bold Nerd Font Complete.ttf", + "preferred_family_name": "RobotoMono Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Roboto Mono Italic Nerd Font Complete Mono.ttf||941124:1634564302.0": { + "family_name": "RobotoMono Nerd Font Mono", + "font-family": "RobotoMono Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Roboto Mono Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Roboto Mono Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "RobotoMono Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Roboto Mono Italic Nerd Font Complete.ttf||962304:1634564302.0": { + "family_name": "RobotoMono Nerd Font", + "font-family": "RobotoMono Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Roboto Mono Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Roboto Mono Italic Nerd Font Complete.ttf", + "preferred_family_name": "RobotoMono Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Roboto Mono Light Italic Nerd Font Complete Mono.ttf||947904:1634564302.0": { + "family_name": "RobotoMono Nerd Font Mono", + "font-family": "RobotoMono Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "300", + "fs_type": 0, + "full_name": "Roboto Mono Light Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Roboto Mono Light Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "RobotoMono Nerd Font Mono", + "preferred_subfamily_name": "Light Italic", + "subfamily_name": "Italic", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Roboto Mono Light Italic Nerd Font Complete.ttf||969092:1634564302.0": { + "family_name": "RobotoMono Nerd Font", + "font-family": "RobotoMono Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "300", + "fs_type": 0, + "full_name": "Roboto Mono Light Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Roboto Mono Light Italic Nerd Font Complete.ttf", + "preferred_family_name": "RobotoMono Nerd Font", + "preferred_subfamily_name": "Light Italic", + "subfamily_name": "Italic", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Roboto Mono Light Nerd Font Complete Mono.ttf||940184:1634564302.0": { + "family_name": "RobotoMono Nerd Font Mono", + "font-family": "RobotoMono Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Roboto Mono Light Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Roboto Mono Light Nerd Font Complete Mono.ttf", + "preferred_family_name": "RobotoMono Nerd Font Mono", + "preferred_subfamily_name": "Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Roboto Mono Light Nerd Font Complete.ttf||960508:1634564302.0": { + "family_name": "RobotoMono Nerd Font", + "font-family": "RobotoMono Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Roboto Mono Light Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Roboto Mono Light Nerd Font Complete.ttf", + "preferred_family_name": "RobotoMono Nerd Font", + "preferred_subfamily_name": "Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Roboto Mono Medium Italic Nerd Font Complete Mono.ttf||943900:1634564302.0": { + "family_name": "RobotoMono Nerd Font Mono", + "font-family": "RobotoMono Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "500", + "fs_type": 0, + "full_name": "Roboto Mono Medium Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Roboto Mono Medium Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "RobotoMono Nerd Font Mono", + "preferred_subfamily_name": "Medium Italic", + "subfamily_name": "Italic", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Roboto Mono Medium Italic Nerd Font Complete.ttf||964928:1634564302.0": { + "family_name": "RobotoMono Nerd Font", + "font-family": "RobotoMono Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "500", + "fs_type": 0, + "full_name": "Roboto Mono Medium Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Roboto Mono Medium Italic Nerd Font Complete.ttf", + "preferred_family_name": "RobotoMono Nerd Font", + "preferred_subfamily_name": "Medium Italic", + "subfamily_name": "Italic", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Roboto Mono Medium Nerd Font Complete Mono.ttf||935836:1634564302.0": { + "family_name": "RobotoMono Nerd Font Mono", + "font-family": "RobotoMono Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Roboto Mono Medium Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Roboto Mono Medium Nerd Font Complete Mono.ttf", + "preferred_family_name": "RobotoMono Nerd Font Mono", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Roboto Mono Medium Nerd Font Complete.ttf||955988:1634564302.0": { + "family_name": "RobotoMono Nerd Font", + "font-family": "RobotoMono Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Roboto Mono Medium Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Roboto Mono Medium Nerd Font Complete.ttf", + "preferred_family_name": "RobotoMono Nerd Font", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Roboto Mono Nerd Font Complete Mono.ttf||935784:1634564302.0": { + "family_name": "RobotoMono Nerd Font Mono", + "font-family": "RobotoMono Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Roboto Mono Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Roboto Mono Nerd Font Complete Mono.ttf", + "preferred_family_name": "RobotoMono Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Roboto Mono Nerd Font Complete.ttf||956100:1634564302.0": { + "family_name": "RobotoMono Nerd Font", + "font-family": "RobotoMono Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Roboto Mono Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Roboto Mono Nerd Font Complete.ttf", + "preferred_family_name": "RobotoMono Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Roboto Mono Thin Italic Nerd Font Complete Mono.ttf||941844:1634564302.0": { + "family_name": "RobotoMono Nerd Font Mono", + "font-family": "RobotoMono Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "250", + "fs_type": 0, + "full_name": "Roboto Mono Thin Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Roboto Mono Thin Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "RobotoMono Nerd Font Mono", + "preferred_subfamily_name": "Thin Italic", + "subfamily_name": "Italic", + "weight": 250, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Roboto Mono Thin Italic Nerd Font Complete.ttf||963024:1634564302.0": { + "family_name": "RobotoMono Nerd Font", + "font-family": "RobotoMono Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "250", + "fs_type": 0, + "full_name": "Roboto Mono Thin Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Roboto Mono Thin Italic Nerd Font Complete.ttf", + "preferred_family_name": "RobotoMono Nerd Font", + "preferred_subfamily_name": "Thin Italic", + "subfamily_name": "Italic", + "weight": 250, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Roboto Mono Thin Nerd Font Complete Mono.ttf||939380:1634564302.0": { + "family_name": "RobotoMono Nerd Font Mono", + "font-family": "RobotoMono Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "250", + "fs_type": 0, + "full_name": "Roboto Mono Thin Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Roboto Mono Thin Nerd Font Complete Mono.ttf", + "preferred_family_name": "RobotoMono Nerd Font Mono", + "preferred_subfamily_name": "Thin", + "subfamily_name": "Regular", + "weight": 250, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Roboto Mono Thin Nerd Font Complete.ttf||959692:1634564302.0": { + "family_name": "RobotoMono Nerd Font", + "font-family": "RobotoMono Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "250", + "fs_type": 0, + "full_name": "Roboto Mono Thin Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Roboto Mono Thin Nerd Font Complete.ttf", + "preferred_family_name": "RobotoMono Nerd Font", + "preferred_subfamily_name": "Thin", + "subfamily_name": "Regular", + "weight": 250, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Sauce Code Pro Black Italic Nerd Font Complete Mono.ttf||925748:1634564302.0": { + "family_name": "SauceCodePro Nerd Font Mono", + "font-family": "SauceCodePro Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "900", + "fs_type": 0, + "full_name": "Sauce Code Pro Black Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 8, + 9, + 3, + 4, + 3, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Sauce Code Pro Black Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "SauceCodePro Nerd Font Mono", + "preferred_subfamily_name": "Black Italic", + "subfamily_name": "Italic", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Sauce Code Pro Black Italic Nerd Font Complete.ttf||934716:1634564302.0": { + "family_name": "SauceCodePro Nerd Font", + "font-family": "SauceCodePro Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "900", + "fs_type": 0, + "full_name": "Sauce Code Pro Black Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 8, + 9, + 3, + 4, + 3, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Sauce Code Pro Black Italic Nerd Font Complete.ttf", + "preferred_family_name": "SauceCodePro Nerd Font", + "preferred_subfamily_name": "Black Italic", + "subfamily_name": "Italic", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Sauce Code Pro Black Nerd Font Complete Mono.ttf||959812:1634564302.0": { + "family_name": "SauceCodePro Nerd Font Mono", + "font-family": "SauceCodePro Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Sauce Code Pro Black Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 8, + 9, + 3, + 4, + 3, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Sauce Code Pro Black Nerd Font Complete Mono.ttf", + "preferred_family_name": "SauceCodePro Nerd Font Mono", + "preferred_subfamily_name": "Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Sauce Code Pro Black Nerd Font Complete.ttf||968784:1634564302.0": { + "family_name": "SauceCodePro Nerd Font", + "font-family": "SauceCodePro Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Sauce Code Pro Black Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 8, + 9, + 3, + 4, + 3, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Sauce Code Pro Black Nerd Font Complete.ttf", + "preferred_family_name": "SauceCodePro Nerd Font", + "preferred_subfamily_name": "Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Sauce Code Pro Bold Italic Nerd Font Complete Mono.ttf||925792:1634564302.0": { + "family_name": "SauceCodePro Nerd Font Mono", + "font-family": "SauceCodePro Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Sauce Code Pro Bold Italic Nerd Font Complete Mono", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 7, + 9, + 3, + 4, + 3, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Sauce Code Pro Bold Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "SauceCodePro Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Sauce Code Pro Bold Italic Nerd Font Complete.ttf||934760:1634564302.0": { + "family_name": "SauceCodePro Nerd Font", + "font-family": "SauceCodePro Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Sauce Code Pro Bold Italic Nerd Font Complete", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 7, + 9, + 3, + 4, + 3, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Sauce Code Pro Bold Italic Nerd Font Complete.ttf", + "preferred_family_name": "SauceCodePro Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Sauce Code Pro Bold Nerd Font Complete Mono.ttf||959628:1634564302.0": { + "family_name": "SauceCodePro Nerd Font Mono", + "font-family": "SauceCodePro Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Sauce Code Pro Bold Nerd Font Complete Mono", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 7, + 9, + 3, + 4, + 3, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Sauce Code Pro Bold Nerd Font Complete Mono.ttf", + "preferred_family_name": "SauceCodePro Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Sauce Code Pro Bold Nerd Font Complete.ttf||968596:1634564302.0": { + "family_name": "SauceCodePro Nerd Font", + "font-family": "SauceCodePro Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Sauce Code Pro Bold Nerd Font Complete", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 7, + 9, + 3, + 4, + 3, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Sauce Code Pro Bold Nerd Font Complete.ttf", + "preferred_family_name": "SauceCodePro Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Sauce Code Pro ExtraLight Italic Nerd Font Complete Mono.ttf||927812:1634564302.0": { + "family_name": "SauceCodePro Nerd Font Mono", + "font-family": "SauceCodePro Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "200", + "fs_type": 0, + "full_name": "Sauce Code Pro ExtraLight Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 3, + 9, + 3, + 4, + 3, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Sauce Code Pro ExtraLight Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "SauceCodePro Nerd Font Mono", + "preferred_subfamily_name": "ExtraLight Italic", + "subfamily_name": "Italic", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Sauce Code Pro ExtraLight Italic Nerd Font Complete.ttf||936780:1634564302.0": { + "family_name": "SauceCodePro Nerd Font", + "font-family": "SauceCodePro Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "200", + "fs_type": 0, + "full_name": "Sauce Code Pro ExtraLight Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 3, + 9, + 3, + 4, + 3, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Sauce Code Pro ExtraLight Italic Nerd Font Complete.ttf", + "preferred_family_name": "SauceCodePro Nerd Font", + "preferred_subfamily_name": "ExtraLight Italic", + "subfamily_name": "Italic", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Sauce Code Pro ExtraLight Nerd Font Complete Mono.ttf||961828:1634564302.0": { + "family_name": "SauceCodePro Nerd Font Mono", + "font-family": "SauceCodePro Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Sauce Code Pro ExtraLight Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 3, + 9, + 3, + 4, + 3, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Sauce Code Pro ExtraLight Nerd Font Complete Mono.ttf", + "preferred_family_name": "SauceCodePro Nerd Font Mono", + "preferred_subfamily_name": "ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Sauce Code Pro ExtraLight Nerd Font Complete.ttf||970796:1634564302.0": { + "family_name": "SauceCodePro Nerd Font", + "font-family": "SauceCodePro Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Sauce Code Pro ExtraLight Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 3, + 9, + 3, + 4, + 3, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Sauce Code Pro ExtraLight Nerd Font Complete.ttf", + "preferred_family_name": "SauceCodePro Nerd Font", + "preferred_subfamily_name": "ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Sauce Code Pro Italic Nerd Font Complete Mono.ttf||931812:1634564302.0": { + "family_name": "SauceCodePro Nerd Font Mono", + "font-family": "SauceCodePro Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Sauce Code Pro Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 5, + 9, + 3, + 4, + 3, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Sauce Code Pro Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "SauceCodePro Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Sauce Code Pro Italic Nerd Font Complete.ttf||937032:1634564302.0": { + "family_name": "SauceCodePro Nerd Font", + "font-family": "SauceCodePro Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Sauce Code Pro Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 5, + 9, + 3, + 4, + 3, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Sauce Code Pro Italic Nerd Font Complete.ttf", + "preferred_family_name": "SauceCodePro Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Sauce Code Pro Light Italic Nerd Font Complete Mono.ttf||927484:1634564302.0": { + "family_name": "SauceCodePro Nerd Font Mono", + "font-family": "SauceCodePro Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "300", + "fs_type": 0, + "full_name": "Sauce Code Pro Light Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 4, + 9, + 3, + 4, + 3, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Sauce Code Pro Light Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "SauceCodePro Nerd Font Mono", + "preferred_subfamily_name": "Light Italic", + "subfamily_name": "Italic", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Sauce Code Pro Light Italic Nerd Font Complete.ttf||936452:1634564302.0": { + "family_name": "SauceCodePro Nerd Font", + "font-family": "SauceCodePro Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "300", + "fs_type": 0, + "full_name": "Sauce Code Pro Light Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 4, + 9, + 3, + 4, + 3, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Sauce Code Pro Light Italic Nerd Font Complete.ttf", + "preferred_family_name": "SauceCodePro Nerd Font", + "preferred_subfamily_name": "Light Italic", + "subfamily_name": "Italic", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Sauce Code Pro Light Nerd Font Complete Mono.ttf||961188:1634564302.0": { + "family_name": "SauceCodePro Nerd Font Mono", + "font-family": "SauceCodePro Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Sauce Code Pro Light Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 4, + 9, + 3, + 4, + 3, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Sauce Code Pro Light Nerd Font Complete Mono.ttf", + "preferred_family_name": "SauceCodePro Nerd Font Mono", + "preferred_subfamily_name": "Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Sauce Code Pro Light Nerd Font Complete.ttf||970160:1634564302.0": { + "family_name": "SauceCodePro Nerd Font", + "font-family": "SauceCodePro Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Sauce Code Pro Light Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 4, + 9, + 3, + 4, + 3, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Sauce Code Pro Light Nerd Font Complete.ttf", + "preferred_family_name": "SauceCodePro Nerd Font", + "preferred_subfamily_name": "Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Sauce Code Pro Medium Italic Nerd Font Complete Mono.ttf||926532:1634564302.0": { + "family_name": "SauceCodePro Nerd Font Mono", + "font-family": "SauceCodePro Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "500", + "fs_type": 0, + "full_name": "Sauce Code Pro Medium Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 5, + 9, + 3, + 4, + 3, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Sauce Code Pro Medium Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "SauceCodePro Nerd Font Mono", + "preferred_subfamily_name": "Medium Italic", + "subfamily_name": "Italic", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Sauce Code Pro Medium Italic Nerd Font Complete.ttf||935500:1634564302.0": { + "family_name": "SauceCodePro Nerd Font", + "font-family": "SauceCodePro Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "500", + "fs_type": 0, + "full_name": "Sauce Code Pro Medium Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 5, + 9, + 3, + 4, + 3, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Sauce Code Pro Medium Italic Nerd Font Complete.ttf", + "preferred_family_name": "SauceCodePro Nerd Font", + "preferred_subfamily_name": "Medium Italic", + "subfamily_name": "Italic", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Sauce Code Pro Medium Nerd Font Complete Mono.ttf||960012:1634564302.0": { + "family_name": "SauceCodePro Nerd Font Mono", + "font-family": "SauceCodePro Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Sauce Code Pro Medium Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 5, + 9, + 3, + 4, + 3, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Sauce Code Pro Medium Nerd Font Complete Mono.ttf", + "preferred_family_name": "SauceCodePro Nerd Font Mono", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Sauce Code Pro Medium Nerd Font Complete.ttf||968980:1634564302.0": { + "family_name": "SauceCodePro Nerd Font", + "font-family": "SauceCodePro Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Sauce Code Pro Medium Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 5, + 9, + 3, + 4, + 3, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Sauce Code Pro Medium Nerd Font Complete.ttf", + "preferred_family_name": "SauceCodePro Nerd Font", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Sauce Code Pro Nerd Font Complete Mono.ttf||960812:1634564302.0": { + "family_name": "SauceCodePro Nerd Font Mono", + "font-family": "SauceCodePro Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Sauce Code Pro Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 5, + 9, + 3, + 4, + 3, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Sauce Code Pro Nerd Font Complete Mono.ttf", + "preferred_family_name": "SauceCodePro Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Sauce Code Pro Nerd Font Complete.ttf||969780:1634564302.0": { + "family_name": "SauceCodePro Nerd Font", + "font-family": "SauceCodePro Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Sauce Code Pro Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 5, + 9, + 3, + 4, + 3, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Sauce Code Pro Nerd Font Complete.ttf", + "preferred_family_name": "SauceCodePro Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Sauce Code Pro Semibold Italic Nerd Font Complete Mono.ttf||926084:1634564302.0": { + "family_name": "SauceCodePro Nerd Font Mono", + "font-family": "SauceCodePro Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "600", + "fs_type": 0, + "full_name": "Sauce Code Pro Semibold Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 6, + 9, + 3, + 4, + 3, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Sauce Code Pro Semibold Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "SauceCodePro Nerd Font Mono", + "preferred_subfamily_name": "Semibold Italic", + "subfamily_name": "Italic", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Sauce Code Pro Semibold Italic Nerd Font Complete.ttf||935052:1634564302.0": { + "family_name": "SauceCodePro Nerd Font", + "font-family": "SauceCodePro Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "600", + "fs_type": 0, + "full_name": "Sauce Code Pro Semibold Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 6, + 9, + 3, + 4, + 3, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Sauce Code Pro Semibold Italic Nerd Font Complete.ttf", + "preferred_family_name": "SauceCodePro Nerd Font", + "preferred_subfamily_name": "Semibold Italic", + "subfamily_name": "Italic", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Sauce Code Pro Semibold Nerd Font Complete Mono.ttf||959952:1634564302.0": { + "family_name": "SauceCodePro Nerd Font Mono", + "font-family": "SauceCodePro Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Sauce Code Pro Semibold Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 6, + 9, + 3, + 4, + 3, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Sauce Code Pro Semibold Nerd Font Complete Mono.ttf", + "preferred_family_name": "SauceCodePro Nerd Font Mono", + "preferred_subfamily_name": "Semibold", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Sauce Code Pro Semibold Nerd Font Complete.ttf||968920:1634564302.0": { + "family_name": "SauceCodePro Nerd Font", + "font-family": "SauceCodePro Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Sauce Code Pro Semibold Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 6, + 9, + 3, + 4, + 3, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Sauce Code Pro Semibold Nerd Font Complete.ttf", + "preferred_family_name": "SauceCodePro Nerd Font", + "preferred_subfamily_name": "Semibold", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Shure Tech Mono Nerd Font Complete Mono.ttf||807404:1634564302.0": { + "family_name": "ShureTechMono Nerd Font Mono", + "font-family": "ShureTechMono Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Shure Tech Mono Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 5, + 9, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Shure Tech Mono Nerd Font Complete Mono.ttf", + "preferred_family_name": "ShureTechMono Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Shure Tech Mono Nerd Font Complete.ttf||820164:1634564302.0": { + "family_name": "ShureTechMono Nerd Font", + "font-family": "ShureTechMono Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Shure Tech Mono Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 5, + 9, + 5, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Shure Tech Mono Nerd Font Complete.ttf", + "preferred_family_name": "ShureTechMono Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Space Mono Bold Italic Nerd Font Complete Mono.ttf||868220:1634564302.0": { + "family_name": "SpaceMono Nerd Font Mono", + "font-family": "SpaceMono Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Space Mono Bold Italic Nerd Font Complete Mono", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 8, + 9, + 4, + 0, + 0, + 9, + 0, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Space Mono Bold Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "SpaceMono Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Space Mono Bold Italic Nerd Font Complete.ttf||876692:1634564302.0": { + "family_name": "SpaceMono Nerd Font", + "font-family": "SpaceMono Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Space Mono Bold Italic Nerd Font Complete", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 8, + 9, + 4, + 0, + 0, + 9, + 0, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Space Mono Bold Italic Nerd Font Complete.ttf", + "preferred_family_name": "SpaceMono Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Space Mono Bold Nerd Font Complete Mono.ttf||859756:1634564302.0": { + "family_name": "SpaceMono Nerd Font Mono", + "font-family": "SpaceMono Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Space Mono Bold Nerd Font Complete Mono", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 8, + 9, + 3, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Space Mono Bold Nerd Font Complete Mono.ttf", + "preferred_family_name": "SpaceMono Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Space Mono Bold Nerd Font Complete.ttf||868228:1634564302.0": { + "family_name": "SpaceMono Nerd Font", + "font-family": "SpaceMono Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Space Mono Bold Nerd Font Complete", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 8, + 9, + 3, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Space Mono Bold Nerd Font Complete.ttf", + "preferred_family_name": "SpaceMono Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Space Mono Italic Nerd Font Complete Mono.ttf||876280:1634564302.0": { + "family_name": "SpaceMono Nerd Font Mono", + "font-family": "SpaceMono Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Space Mono Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 5, + 9, + 9, + 0, + 0, + 9, + 0, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Space Mono Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "SpaceMono Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Space Mono Italic Nerd Font Complete.ttf||884752:1634564302.0": { + "family_name": "SpaceMono Nerd Font", + "font-family": "SpaceMono Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Space Mono Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 5, + 9, + 9, + 0, + 0, + 9, + 0, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Space Mono Italic Nerd Font Complete.ttf", + "preferred_family_name": "SpaceMono Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Space Mono Nerd Font Complete Mono.ttf||863988:1634564302.0": { + "family_name": "SpaceMono Nerd Font Mono", + "font-family": "SpaceMono Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Space Mono Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 5, + 9, + 4, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Space Mono Nerd Font Complete Mono.ttf", + "preferred_family_name": "SpaceMono Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Space Mono Nerd Font Complete.ttf||872460:1634564302.0": { + "family_name": "SpaceMono Nerd Font", + "font-family": "SpaceMono Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Space Mono Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 5, + 9, + 4, + 0, + 0, + 2, + 0, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Space Mono Nerd Font Complete.ttf", + "preferred_family_name": "SpaceMono Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Terminess (TTF) Bold Italic Nerd Font Complete Mono.ttf||863392:1634564302.0": { + "family_name": "TerminessTTF Nerd Font Mono", + "font-family": "TerminessTTF Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Terminess (TTF) Bold Italic Nerd Font Complete Mono", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 8, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Terminess (TTF) Bold Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "TerminessTTF Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Terminess (TTF) Bold Italic Nerd Font Complete.ttf||879152:1634564302.0": { + "family_name": "TerminessTTF Nerd Font", + "font-family": "TerminessTTF Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Terminess (TTF) Bold Italic Nerd Font Complete", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 8, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Terminess (TTF) Bold Italic Nerd Font Complete.ttf", + "preferred_family_name": "TerminessTTF Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Terminess (TTF) Bold Nerd Font Complete Mono.ttf||849328:1634564302.0": { + "family_name": "TerminessTTF Nerd Font Mono", + "font-family": "TerminessTTF Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Terminess (TTF) Bold Nerd Font Complete Mono", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 8, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Terminess (TTF) Bold Nerd Font Complete Mono.ttf", + "preferred_family_name": "TerminessTTF Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Terminess (TTF) Bold Nerd Font Complete.ttf||865076:1634564302.0": { + "family_name": "TerminessTTF Nerd Font", + "font-family": "TerminessTTF Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Terminess (TTF) Bold Nerd Font Complete", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 8, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Terminess (TTF) Bold Nerd Font Complete.ttf", + "preferred_family_name": "TerminessTTF Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Terminess (TTF) Italic Nerd Font Complete Mono.ttf||862040:1634564302.0": { + "family_name": "TerminessTTF Nerd Font Mono", + "font-family": "TerminessTTF Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "500", + "fs_type": 0, + "full_name": "Terminess (TTF) Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 6, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Terminess (TTF) Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "TerminessTTF Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Terminess (TTF) Italic Nerd Font Complete.ttf||877784:1634564302.0": { + "family_name": "TerminessTTF Nerd Font", + "font-family": "TerminessTTF Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "500", + "fs_type": 0, + "full_name": "Terminess (TTF) Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 6, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Terminess (TTF) Italic Nerd Font Complete.ttf", + "preferred_family_name": "TerminessTTF Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Terminess (TTF) Nerd Font Complete Mono.ttf||848728:1634564302.0": { + "family_name": "TerminessTTF Nerd Font Mono", + "font-family": "TerminessTTF Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Terminess (TTF) Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 6, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Terminess (TTF) Nerd Font Complete Mono.ttf", + "preferred_family_name": "TerminessTTF Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Medium", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Terminess (TTF) Nerd Font Complete.ttf||864472:1634564302.0": { + "family_name": "TerminessTTF Nerd Font", + "font-family": "TerminessTTF Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Terminess (TTF) Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 6, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Terminess (TTF) Nerd Font Complete.ttf", + "preferred_family_name": "TerminessTTF Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Medium", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Tinos Bold Italic Nerd Font Complete Mono.ttf||1253736:1634564302.0": { + "family_name": "Tinos Nerd Font Mono", + "font-family": "Tinos Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 8, + "full_name": "Tinos Bold Italic Nerd Font Complete Mono", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 2, + 7, + 3, + 6, + 5, + 5, + 9, + 3, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Tinos Bold Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "Tinos Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Tinos Bold Italic Nerd Font Complete.ttf||1262048:1634564302.0": { + "family_name": "Tinos Nerd Font", + "font-family": "Tinos Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 8, + "full_name": "Tinos Bold Italic Nerd Font Complete", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 2, + 7, + 3, + 6, + 5, + 5, + 9, + 3, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Tinos Bold Italic Nerd Font Complete.ttf", + "preferred_family_name": "Tinos Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Tinos Bold Nerd Font Complete Mono.ttf||1250412:1634564302.0": { + "family_name": "Tinos Nerd Font Mono", + "font-family": "Tinos Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 8, + "full_name": "Tinos Bold Nerd Font Complete Mono", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 2, + 8, + 3, + 7, + 5, + 5, + 2, + 3, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Tinos Bold Nerd Font Complete Mono.ttf", + "preferred_family_name": "Tinos Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Tinos Bold Nerd Font Complete.ttf||1256240:1634564302.0": { + "family_name": "Tinos Nerd Font", + "font-family": "Tinos Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 8, + "full_name": "Tinos Bold Nerd Font Complete", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 2, + 8, + 3, + 7, + 5, + 5, + 2, + 3, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Tinos Bold Nerd Font Complete.ttf", + "preferred_family_name": "Tinos Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Tinos Italic Nerd Font Complete Mono.ttf||1252784:1634564302.0": { + "family_name": "Tinos Nerd Font Mono", + "font-family": "Tinos Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 8, + "full_name": "Tinos Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 2, + 5, + 3, + 5, + 4, + 5, + 9, + 3, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Tinos Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "Tinos Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Tinos Italic Nerd Font Complete.ttf||1261084:1634564302.0": { + "family_name": "Tinos Nerd Font", + "font-family": "Tinos Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 8, + "full_name": "Tinos Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 2, + 5, + 3, + 5, + 4, + 5, + 9, + 3, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Tinos Italic Nerd Font Complete.ttf", + "preferred_family_name": "Tinos Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Tinos Nerd Font Complete Mono.ttf||1270968:1634564302.0": { + "family_name": "Tinos Nerd Font Mono", + "font-family": "Tinos Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 8, + "full_name": "Tinos Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 2, + 6, + 3, + 5, + 4, + 5, + 2, + 3, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Tinos Nerd Font Complete Mono.ttf", + "preferred_family_name": "Tinos Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Book", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Tinos Nerd Font Complete.ttf||1279280:1634564302.0": { + "family_name": "Tinos Nerd Font", + "font-family": "Tinos Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 8, + "full_name": "Tinos Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 2, + 6, + 3, + 5, + 4, + 5, + 2, + 3, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Tinos Nerd Font Complete.ttf", + "preferred_family_name": "Tinos Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Book", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Ubuntu Bold Italic Nerd Font Complete Mono.ttf||1035336:1634564302.0": { + "family_name": "Ubuntu Nerd Font Mono", + "font-family": "Ubuntu Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Ubuntu Bold Italic Nerd Font Complete Mono", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 8, + 4, + 3, + 6, + 2, + 10, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Ubuntu Bold Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "Ubuntu Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Ubuntu Bold Italic Nerd Font Complete.ttf||1037292:1634564302.0": { + "family_name": "Ubuntu Nerd Font", + "font-family": "Ubuntu Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Ubuntu Bold Italic Nerd Font Complete", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 8, + 4, + 3, + 6, + 2, + 10, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Ubuntu Bold Italic Nerd Font Complete.ttf", + "preferred_family_name": "Ubuntu Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Ubuntu Bold Nerd Font Complete Mono.ttf||1022000:1634564302.0": { + "family_name": "Ubuntu Nerd Font Mono", + "font-family": "Ubuntu Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Ubuntu Bold Nerd Font Complete Mono", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 8, + 4, + 3, + 6, + 2, + 3, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Ubuntu Bold Nerd Font Complete Mono.ttf", + "preferred_family_name": "Ubuntu Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Ubuntu Bold Nerd Font Complete.ttf||1023720:1634564302.0": { + "family_name": "Ubuntu Nerd Font", + "font-family": "Ubuntu Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Ubuntu Bold Nerd Font Complete", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 8, + 4, + 3, + 6, + 2, + 3, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Ubuntu Bold Nerd Font Complete.ttf", + "preferred_family_name": "Ubuntu Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Ubuntu Condensed Nerd Font Complete Mono.ttf||1035208:1634564302.0": { + "family_name": "UbuntuCondensed Nerd Font Mono", + "font-family": "UbuntuCondensed Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Ubuntu Condensed Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 5, + 6, + 3, + 6, + 2, + 3, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Ubuntu Condensed Nerd Font Complete Mono.ttf", + "preferred_family_name": "UbuntuCondensed Nerd Font Mono", + "preferred_subfamily_name": "Regular", + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Ubuntu Condensed Nerd Font Complete.ttf||1044084:1634564302.0": { + "family_name": "UbuntuCondensed Nerd Font", + "font-family": "UbuntuCondensed Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Ubuntu Condensed Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 5, + 6, + 3, + 6, + 2, + 3, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Ubuntu Condensed Nerd Font Complete.ttf", + "preferred_family_name": "UbuntuCondensed Nerd Font", + "preferred_subfamily_name": "Regular", + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Ubuntu Italic Nerd Font Complete Mono.ttf||1077108:1634564302.0": { + "family_name": "Ubuntu Nerd Font Mono", + "font-family": "Ubuntu Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Ubuntu Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 5, + 4, + 3, + 6, + 2, + 10, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Ubuntu Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "Ubuntu Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Ubuntu Italic Nerd Font Complete.ttf||1079496:1634564302.0": { + "family_name": "Ubuntu Nerd Font", + "font-family": "Ubuntu Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Ubuntu Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 5, + 4, + 3, + 6, + 2, + 10, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Ubuntu Italic Nerd Font Complete.ttf", + "preferred_family_name": "Ubuntu Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Ubuntu Light Italic Nerd Font Complete Mono.ttf||1097420:1634564302.0": { + "family_name": "Ubuntu Nerd Font Mono", + "font-family": "Ubuntu Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "300", + "fs_type": 0, + "full_name": "Ubuntu Light Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 3, + 4, + 3, + 6, + 2, + 10, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Ubuntu Light Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "Ubuntu Nerd Font Mono", + "preferred_subfamily_name": "Light Italic", + "subfamily_name": "Italic", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Ubuntu Light Italic Nerd Font Complete.ttf||1100044:1634564302.0": { + "family_name": "Ubuntu Nerd Font", + "font-family": "Ubuntu Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "300", + "fs_type": 0, + "full_name": "Ubuntu Light Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 3, + 4, + 3, + 6, + 2, + 10, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Ubuntu Light Italic Nerd Font Complete.ttf", + "preferred_family_name": "Ubuntu Nerd Font", + "preferred_subfamily_name": "Light Italic", + "subfamily_name": "Italic", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Ubuntu Light Nerd Font Complete Mono.ttf||1111820:1634564302.0": { + "family_name": "Ubuntu Nerd Font Mono", + "font-family": "Ubuntu Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Ubuntu Light Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 3, + 4, + 3, + 6, + 2, + 3, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Ubuntu Light Nerd Font Complete Mono.ttf", + "preferred_family_name": "Ubuntu Nerd Font Mono", + "preferred_subfamily_name": "Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Ubuntu Light Nerd Font Complete.ttf||1113740:1634564302.0": { + "family_name": "Ubuntu Nerd Font", + "font-family": "Ubuntu Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Ubuntu Light Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 3, + 4, + 3, + 6, + 2, + 3, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Ubuntu Light Nerd Font Complete.ttf", + "preferred_family_name": "Ubuntu Nerd Font", + "preferred_subfamily_name": "Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Ubuntu Medium Italic Nerd Font Complete Mono.ttf||1060408:1634564302.0": { + "family_name": "Ubuntu Nerd Font Mono", + "font-family": "Ubuntu Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "500", + "fs_type": 0, + "full_name": "Ubuntu Medium Italic Nerd Font Complete Mono", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 5, + 4, + 3, + 6, + 2, + 10, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Ubuntu Medium Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "Ubuntu Nerd Font Mono", + "preferred_subfamily_name": "Medium Italic", + "subfamily_name": "Bold Italic", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Ubuntu Medium Italic Nerd Font Complete.ttf||1062560:1634564302.0": { + "family_name": "Ubuntu Nerd Font", + "font-family": "Ubuntu Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "500", + "fs_type": 0, + "full_name": "Ubuntu Medium Italic Nerd Font Complete", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 5, + 4, + 3, + 6, + 2, + 10, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Ubuntu Medium Italic Nerd Font Complete.ttf", + "preferred_family_name": "Ubuntu Nerd Font", + "preferred_subfamily_name": "Medium Italic", + "subfamily_name": "Bold Italic", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Ubuntu Medium Nerd Font Complete Mono.ttf||1035104:1634564302.0": { + "family_name": "Ubuntu Nerd Font Mono", + "font-family": "Ubuntu Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Ubuntu Medium Nerd Font Complete Mono", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 6, + 4, + 3, + 6, + 2, + 3, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Ubuntu Medium Nerd Font Complete Mono.ttf", + "preferred_family_name": "Ubuntu Nerd Font Mono", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Bold", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Ubuntu Medium Nerd Font Complete.ttf||1036912:1634564302.0": { + "family_name": "Ubuntu Nerd Font", + "font-family": "Ubuntu Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Ubuntu Medium Nerd Font Complete", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 6, + 4, + 3, + 6, + 2, + 3, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Ubuntu Medium Nerd Font Complete.ttf", + "preferred_family_name": "Ubuntu Nerd Font", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Bold", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Ubuntu Mono Bold Italic Nerd Font Complete Mono.ttf||959312:1634564302.0": { + "family_name": "UbuntuMono Nerd Font Mono", + "font-family": "UbuntuMono Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Ubuntu Mono Bold Italic Nerd Font Complete Mono", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 8, + 9, + 3, + 6, + 2, + 10, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Ubuntu Mono Bold Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "UbuntuMono Nerd Font Mono", + "preferred_subfamily_name": "Bold Italic", + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Ubuntu Mono Bold Italic Nerd Font Complete.ttf||975060:1634564302.0": { + "family_name": "UbuntuMono Nerd Font", + "font-family": "UbuntuMono Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Ubuntu Mono Bold Italic Nerd Font Complete", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 8, + 9, + 3, + 6, + 2, + 10, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Ubuntu Mono Bold Italic Nerd Font Complete.ttf", + "preferred_family_name": "UbuntuMono Nerd Font", + "preferred_subfamily_name": "Bold Italic", + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Ubuntu Mono Bold Nerd Font Complete Mono.ttf||934436:1634564302.0": { + "family_name": "UbuntuMono Nerd Font Mono", + "font-family": "UbuntuMono Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Ubuntu Mono Bold Nerd Font Complete Mono", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 8, + 9, + 3, + 6, + 2, + 3, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Ubuntu Mono Bold Nerd Font Complete Mono.ttf", + "preferred_family_name": "UbuntuMono Nerd Font Mono", + "preferred_subfamily_name": "Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Ubuntu Mono Bold Nerd Font Complete.ttf||950184:1634564302.0": { + "family_name": "UbuntuMono Nerd Font", + "font-family": "UbuntuMono Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Ubuntu Mono Bold Nerd Font Complete", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 8, + 9, + 3, + 6, + 2, + 3, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Ubuntu Mono Bold Nerd Font Complete.ttf", + "preferred_family_name": "UbuntuMono Nerd Font", + "preferred_subfamily_name": "Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Ubuntu Mono Italic Nerd Font Complete Mono.ttf||955348:1634564302.0": { + "family_name": "UbuntuMono Nerd Font Mono", + "font-family": "UbuntuMono Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Ubuntu Mono Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 5, + 9, + 3, + 6, + 2, + 10, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Ubuntu Mono Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "UbuntuMono Nerd Font Mono", + "preferred_subfamily_name": "Italic", + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Ubuntu Mono Italic Nerd Font Complete.ttf||971096:1634564302.0": { + "family_name": "UbuntuMono Nerd Font", + "font-family": "UbuntuMono Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Ubuntu Mono Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 5, + 9, + 3, + 6, + 2, + 10, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Ubuntu Mono Italic Nerd Font Complete.ttf", + "preferred_family_name": "UbuntuMono Nerd Font", + "preferred_subfamily_name": "Italic", + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Ubuntu Mono Nerd Font Complete Mono.ttf||948792:1634564302.0": { + "family_name": "UbuntuMono Nerd Font Mono", + "font-family": "UbuntuMono Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Ubuntu Mono Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 5, + 9, + 3, + 6, + 2, + 3, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Ubuntu Mono Nerd Font Complete Mono.ttf", + "preferred_family_name": "UbuntuMono Nerd Font Mono", + "preferred_subfamily_name": "Regular", + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Ubuntu Mono Nerd Font Complete.ttf||964540:1634564302.0": { + "family_name": "UbuntuMono Nerd Font", + "font-family": "UbuntuMono Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Ubuntu Mono Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 5, + 9, + 3, + 6, + 2, + 3, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Ubuntu Mono Nerd Font Complete.ttf", + "preferred_family_name": "UbuntuMono Nerd Font", + "preferred_subfamily_name": "Regular", + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Ubuntu Nerd Font Complete Mono.ttf||1048976:1634564302.0": { + "family_name": "Ubuntu Nerd Font Mono", + "font-family": "Ubuntu Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Ubuntu Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 5, + 4, + 3, + 6, + 2, + 3, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Ubuntu Nerd Font Complete Mono.ttf", + "preferred_family_name": "Ubuntu Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Book", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Ubuntu Nerd Font Complete.ttf||1050820:1634564302.0": { + "family_name": "Ubuntu Nerd Font", + "font-family": "Ubuntu Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Ubuntu Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 5, + 4, + 3, + 6, + 2, + 3, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Ubuntu Nerd Font Complete.ttf", + "preferred_family_name": "Ubuntu Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Book", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Victor Mono Bold Italic Nerd Font Complete Mono.ttf||947028:1634564302.0": { + "family_name": "VictorMono Nerd Font Mono", + "font-family": "VictorMono Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 8, + "full_name": "Victor Mono Bold Italic Nerd Font Complete Mono", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 8, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Victor Mono Bold Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "VictorMono Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Victor Mono Bold Italic Nerd Font Complete.ttf||970508:1634564302.0": { + "family_name": "VictorMono Nerd Font", + "font-family": "VictorMono Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 8, + "full_name": "Victor Mono Bold Italic Nerd Font Complete", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 8, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Victor Mono Bold Italic Nerd Font Complete.ttf", + "preferred_family_name": "VictorMono Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Victor Mono Bold Nerd Font Complete Mono.ttf||918424:1634564302.0": { + "family_name": "VictorMono Nerd Font Mono", + "font-family": "VictorMono Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 8, + "full_name": "Victor Mono Bold Nerd Font Complete Mono", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 8, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Victor Mono Bold Nerd Font Complete Mono.ttf", + "preferred_family_name": "VictorMono Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Victor Mono Bold Nerd Font Complete.ttf||941836:1634564302.0": { + "family_name": "VictorMono Nerd Font", + "font-family": "VictorMono Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 8, + "full_name": "Victor Mono Bold Nerd Font Complete", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 8, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Victor Mono Bold Nerd Font Complete.ttf", + "preferred_family_name": "VictorMono Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Victor Mono Bold Oblique Nerd Font Complete Mono.ttf||923516:1634564302.0": { + "family_name": "VictorMono Nerd Font Mono", + "font-family": "VictorMono Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 8, + "full_name": "Victor Mono Bold Oblique Nerd Font Complete Mono", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 8, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Victor Mono Bold Oblique Nerd Font Complete Mono.ttf", + "preferred_family_name": "VictorMono Nerd Font Mono", + "preferred_subfamily_name": "Bold Oblique", + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Victor Mono Bold Oblique Nerd Font Complete.ttf||946928:1634564302.0": { + "family_name": "VictorMono Nerd Font", + "font-family": "VictorMono Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 8, + "full_name": "Victor Mono Bold Oblique Nerd Font Complete", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 8, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Victor Mono Bold Oblique Nerd Font Complete.ttf", + "preferred_family_name": "VictorMono Nerd Font", + "preferred_subfamily_name": "Bold Oblique", + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Victor Mono ExtraLight Italic Nerd Font Complete Mono.ttf||937816:1634564302.0": { + "family_name": "VictorMono Nerd Font Mono", + "font-family": "VictorMono Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "200", + "fs_type": 8, + "full_name": "Victor Mono ExtraLight Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 3, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Victor Mono ExtraLight Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "VictorMono Nerd Font Mono", + "preferred_subfamily_name": "ExtraLight Italic", + "subfamily_name": "Italic", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Victor Mono ExtraLight Italic Nerd Font Complete.ttf||961404:1634564302.0": { + "family_name": "VictorMono Nerd Font", + "font-family": "VictorMono Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "200", + "fs_type": 8, + "full_name": "Victor Mono ExtraLight Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 3, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Victor Mono ExtraLight Italic Nerd Font Complete.ttf", + "preferred_family_name": "VictorMono Nerd Font", + "preferred_subfamily_name": "ExtraLight Italic", + "subfamily_name": "Italic", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Victor Mono ExtraLight Nerd Font Complete Mono.ttf||911460:1634564302.0": { + "family_name": "VictorMono Nerd Font Mono", + "font-family": "VictorMono Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "200", + "fs_type": 8, + "full_name": "Victor Mono ExtraLight Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 3, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Victor Mono ExtraLight Nerd Font Complete Mono.ttf", + "preferred_family_name": "VictorMono Nerd Font Mono", + "preferred_subfamily_name": "ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Victor Mono ExtraLight Nerd Font Complete.ttf||934872:1634564302.0": { + "family_name": "VictorMono Nerd Font", + "font-family": "VictorMono Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "200", + "fs_type": 8, + "full_name": "Victor Mono ExtraLight Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 3, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Victor Mono ExtraLight Nerd Font Complete.ttf", + "preferred_family_name": "VictorMono Nerd Font", + "preferred_subfamily_name": "ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Victor Mono ExtraLight Oblique Nerd Font Complete Mono.ttf||916444:1634564302.0": { + "family_name": "VictorMono Nerd Font Mono", + "font-family": "VictorMono Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "200", + "fs_type": 8, + "full_name": "Victor Mono ExtraLight Oblique Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 3, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Victor Mono ExtraLight Oblique Nerd Font Complete Mono.ttf", + "preferred_family_name": "VictorMono Nerd Font Mono", + "preferred_subfamily_name": "ExtraLight Oblique", + "subfamily_name": "Italic", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Victor Mono ExtraLight Oblique Nerd Font Complete.ttf||939856:1634564302.0": { + "family_name": "VictorMono Nerd Font", + "font-family": "VictorMono Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "200", + "fs_type": 8, + "full_name": "Victor Mono ExtraLight Oblique Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 3, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Victor Mono ExtraLight Oblique Nerd Font Complete.ttf", + "preferred_family_name": "VictorMono Nerd Font", + "preferred_subfamily_name": "ExtraLight Oblique", + "subfamily_name": "Italic", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Victor Mono Italic Nerd Font Complete Mono.ttf||938432:1634564302.0": { + "family_name": "VictorMono Nerd Font Mono", + "font-family": "VictorMono Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 8, + "full_name": "Victor Mono Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 5, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Victor Mono Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "VictorMono Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Victor Mono Italic Nerd Font Complete.ttf||962028:1634564302.0": { + "family_name": "VictorMono Nerd Font", + "font-family": "VictorMono Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 8, + "full_name": "Victor Mono Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 5, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Victor Mono Italic Nerd Font Complete.ttf", + "preferred_family_name": "VictorMono Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Victor Mono Light Italic Nerd Font Complete Mono.ttf||938012:1634564302.0": { + "family_name": "VictorMono Nerd Font Mono", + "font-family": "VictorMono Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "300", + "fs_type": 8, + "full_name": "Victor Mono Light Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 4, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Victor Mono Light Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "VictorMono Nerd Font Mono", + "preferred_subfamily_name": "Light Italic", + "subfamily_name": "Italic", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Victor Mono Light Italic Nerd Font Complete.ttf||961604:1634564302.0": { + "family_name": "VictorMono Nerd Font", + "font-family": "VictorMono Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "300", + "fs_type": 8, + "full_name": "Victor Mono Light Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 4, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Victor Mono Light Italic Nerd Font Complete.ttf", + "preferred_family_name": "VictorMono Nerd Font", + "preferred_subfamily_name": "Light Italic", + "subfamily_name": "Italic", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Victor Mono Light Nerd Font Complete Mono.ttf||912136:1634564302.0": { + "family_name": "VictorMono Nerd Font Mono", + "font-family": "VictorMono Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 8, + "full_name": "Victor Mono Light Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 4, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Victor Mono Light Nerd Font Complete Mono.ttf", + "preferred_family_name": "VictorMono Nerd Font Mono", + "preferred_subfamily_name": "Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Victor Mono Light Nerd Font Complete.ttf||935552:1634564302.0": { + "family_name": "VictorMono Nerd Font", + "font-family": "VictorMono Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 8, + "full_name": "Victor Mono Light Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 4, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Victor Mono Light Nerd Font Complete.ttf", + "preferred_family_name": "VictorMono Nerd Font", + "preferred_subfamily_name": "Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Victor Mono Light Oblique Nerd Font Complete Mono.ttf||916864:1634564302.0": { + "family_name": "VictorMono Nerd Font Mono", + "font-family": "VictorMono Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "300", + "fs_type": 8, + "full_name": "Victor Mono Light Oblique Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 4, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Victor Mono Light Oblique Nerd Font Complete Mono.ttf", + "preferred_family_name": "VictorMono Nerd Font Mono", + "preferred_subfamily_name": "Light Oblique", + "subfamily_name": "Italic", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Victor Mono Light Oblique Nerd Font Complete.ttf||940276:1634564302.0": { + "family_name": "VictorMono Nerd Font", + "font-family": "VictorMono Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "300", + "fs_type": 8, + "full_name": "Victor Mono Light Oblique Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 4, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Victor Mono Light Oblique Nerd Font Complete.ttf", + "preferred_family_name": "VictorMono Nerd Font", + "preferred_subfamily_name": "Light Oblique", + "subfamily_name": "Italic", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Victor Mono Medium Italic Nerd Font Complete Mono.ttf||943400:1634564302.0": { + "family_name": "VictorMono Nerd Font Mono", + "font-family": "VictorMono Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "500", + "fs_type": 8, + "full_name": "Victor Mono Medium Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 6, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Victor Mono Medium Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "VictorMono Nerd Font Mono", + "preferred_subfamily_name": "Medium Italic", + "subfamily_name": "Italic", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Victor Mono Medium Italic Nerd Font Complete.ttf||966992:1634564302.0": { + "family_name": "VictorMono Nerd Font", + "font-family": "VictorMono Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "500", + "fs_type": 8, + "full_name": "Victor Mono Medium Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 6, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Victor Mono Medium Italic Nerd Font Complete.ttf", + "preferred_family_name": "VictorMono Nerd Font", + "preferred_subfamily_name": "Medium Italic", + "subfamily_name": "Italic", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Victor Mono Medium Nerd Font Complete Mono.ttf||916280:1634564302.0": { + "family_name": "VictorMono Nerd Font Mono", + "font-family": "VictorMono Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 8, + "full_name": "Victor Mono Medium Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 6, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Victor Mono Medium Nerd Font Complete Mono.ttf", + "preferred_family_name": "VictorMono Nerd Font Mono", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Victor Mono Medium Nerd Font Complete.ttf||939692:1634564302.0": { + "family_name": "VictorMono Nerd Font", + "font-family": "VictorMono Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 8, + "full_name": "Victor Mono Medium Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 6, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Victor Mono Medium Nerd Font Complete.ttf", + "preferred_family_name": "VictorMono Nerd Font", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Victor Mono Medium Oblique Nerd Font Complete Mono.ttf||920288:1634564302.0": { + "family_name": "VictorMono Nerd Font Mono", + "font-family": "VictorMono Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "500", + "fs_type": 8, + "full_name": "Victor Mono Medium Oblique Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 6, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Victor Mono Medium Oblique Nerd Font Complete Mono.ttf", + "preferred_family_name": "VictorMono Nerd Font Mono", + "preferred_subfamily_name": "Medium Oblique", + "subfamily_name": "Italic", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Victor Mono Medium Oblique Nerd Font Complete.ttf||943700:1634564302.0": { + "family_name": "VictorMono Nerd Font", + "font-family": "VictorMono Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "500", + "fs_type": 8, + "full_name": "Victor Mono Medium Oblique Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 6, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Victor Mono Medium Oblique Nerd Font Complete.ttf", + "preferred_family_name": "VictorMono Nerd Font", + "preferred_subfamily_name": "Medium Oblique", + "subfamily_name": "Italic", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Victor Mono Oblique Nerd Font Complete Mono.ttf||917348:1634564302.0": { + "family_name": "VictorMono Nerd Font Mono", + "font-family": "VictorMono Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 8, + "full_name": "Victor Mono Oblique Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 5, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Victor Mono Oblique Nerd Font Complete Mono.ttf", + "preferred_family_name": "VictorMono Nerd Font Mono", + "preferred_subfamily_name": "Oblique", + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Victor Mono Oblique Nerd Font Complete.ttf||940764:1634564302.0": { + "family_name": "VictorMono Nerd Font", + "font-family": "VictorMono Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 8, + "full_name": "Victor Mono Oblique Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 5, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Victor Mono Oblique Nerd Font Complete.ttf", + "preferred_family_name": "VictorMono Nerd Font", + "preferred_subfamily_name": "Oblique", + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Victor Mono Regular Nerd Font Complete Mono.ttf||912928:1634564302.0": { + "family_name": "VictorMono Nerd Font Mono", + "font-family": "VictorMono Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 8, + "full_name": "Victor Mono Regular Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 5, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Victor Mono Regular Nerd Font Complete Mono.ttf", + "preferred_family_name": "VictorMono Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Victor Mono Regular Nerd Font Complete.ttf||936340:1634564302.0": { + "family_name": "VictorMono Nerd Font", + "font-family": "VictorMono Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 8, + "full_name": "Victor Mono Regular Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 5, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Victor Mono Regular Nerd Font Complete.ttf", + "preferred_family_name": "VictorMono Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Victor Mono SemiBold Italic Nerd Font Complete Mono.ttf||943360:1634564302.0": { + "family_name": "VictorMono Nerd Font Mono", + "font-family": "VictorMono Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "600", + "fs_type": 8, + "full_name": "Victor Mono SemiBold Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 7, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Victor Mono SemiBold Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "VictorMono Nerd Font Mono", + "preferred_subfamily_name": "SemiBold Italic", + "subfamily_name": "Italic", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Victor Mono SemiBold Italic Nerd Font Complete.ttf||966840:1634564302.0": { + "family_name": "VictorMono Nerd Font", + "font-family": "VictorMono Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "600", + "fs_type": 8, + "full_name": "Victor Mono SemiBold Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 7, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Victor Mono SemiBold Italic Nerd Font Complete.ttf", + "preferred_family_name": "VictorMono Nerd Font", + "preferred_subfamily_name": "SemiBold Italic", + "subfamily_name": "Italic", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Victor Mono SemiBold Nerd Font Complete Mono.ttf||916836:1634564302.0": { + "family_name": "VictorMono Nerd Font Mono", + "font-family": "VictorMono Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 8, + "full_name": "Victor Mono SemiBold Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 7, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Victor Mono SemiBold Nerd Font Complete Mono.ttf", + "preferred_family_name": "VictorMono Nerd Font Mono", + "preferred_subfamily_name": "SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Victor Mono SemiBold Nerd Font Complete.ttf||940248:1634564302.0": { + "family_name": "VictorMono Nerd Font", + "font-family": "VictorMono Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 8, + "full_name": "Victor Mono SemiBold Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 7, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Victor Mono SemiBold Nerd Font Complete.ttf", + "preferred_family_name": "VictorMono Nerd Font", + "preferred_subfamily_name": "SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Victor Mono SemiBold Oblique Nerd Font Complete Mono.ttf||920392:1634564302.0": { + "family_name": "VictorMono Nerd Font Mono", + "font-family": "VictorMono Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "600", + "fs_type": 8, + "full_name": "Victor Mono SemiBold Oblique Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 7, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Victor Mono SemiBold Oblique Nerd Font Complete Mono.ttf", + "preferred_family_name": "VictorMono Nerd Font Mono", + "preferred_subfamily_name": "SemiBold Oblique", + "subfamily_name": "Italic", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Victor Mono SemiBold Oblique Nerd Font Complete.ttf||943804:1634564302.0": { + "family_name": "VictorMono Nerd Font", + "font-family": "VictorMono Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "600", + "fs_type": 8, + "full_name": "Victor Mono SemiBold Oblique Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 7, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Victor Mono SemiBold Oblique Nerd Font Complete.ttf", + "preferred_family_name": "VictorMono Nerd Font", + "preferred_subfamily_name": "SemiBold Oblique", + "subfamily_name": "Italic", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Victor Mono Thin Italic Nerd Font Complete Mono.ttf||938708:1634564302.0": { + "family_name": "VictorMono Nerd Font Mono", + "font-family": "VictorMono Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "100", + "fs_type": 8, + "full_name": "Victor Mono Thin Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 2, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Victor Mono Thin Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "VictorMono Nerd Font Mono", + "preferred_subfamily_name": "Thin Italic", + "subfamily_name": "Italic", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Victor Mono Thin Italic Nerd Font Complete.ttf||962092:1634564302.0": { + "family_name": "VictorMono Nerd Font", + "font-family": "VictorMono Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "100", + "fs_type": 8, + "full_name": "Victor Mono Thin Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 2, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Victor Mono Thin Italic Nerd Font Complete.ttf", + "preferred_family_name": "VictorMono Nerd Font", + "preferred_subfamily_name": "Thin Italic", + "subfamily_name": "Italic", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Victor Mono Thin Nerd Font Complete Mono.ttf||911712:1634564302.0": { + "family_name": "VictorMono Nerd Font Mono", + "font-family": "VictorMono Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "100", + "fs_type": 8, + "full_name": "Victor Mono Thin Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 2, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Victor Mono Thin Nerd Font Complete Mono.ttf", + "preferred_family_name": "VictorMono Nerd Font Mono", + "preferred_subfamily_name": "Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Victor Mono Thin Nerd Font Complete.ttf||935124:1634564302.0": { + "family_name": "VictorMono Nerd Font", + "font-family": "VictorMono Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "100", + "fs_type": 8, + "full_name": "Victor Mono Thin Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 2, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Victor Mono Thin Nerd Font Complete.ttf", + "preferred_family_name": "VictorMono Nerd Font", + "preferred_subfamily_name": "Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Victor Mono Thin Oblique Nerd Font Complete Mono.ttf||916804:1634564302.0": { + "family_name": "VictorMono Nerd Font Mono", + "font-family": "VictorMono Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "100", + "fs_type": 8, + "full_name": "Victor Mono Thin Oblique Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 2, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Victor Mono Thin Oblique Nerd Font Complete Mono.ttf", + "preferred_family_name": "VictorMono Nerd Font Mono", + "preferred_subfamily_name": "Thin Oblique", + "subfamily_name": "Italic", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/Victor Mono Thin Oblique Nerd Font Complete.ttf||940216:1634564302.0": { + "family_name": "VictorMono Nerd Font", + "font-family": "VictorMono Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "100", + "fs_type": 8, + "full_name": "Victor Mono Thin Oblique Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 2, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/Victor Mono Thin Oblique Nerd Font Complete.ttf", + "preferred_family_name": "VictorMono Nerd Font", + "preferred_subfamily_name": "Thin Oblique", + "subfamily_name": "Italic", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/agave regular Nerd Font Complete Mono.ttf||932268:1634564302.0": { + "family_name": "agave Nerd Font Mono", + "font-family": "agave Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "agave regular Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 9, + 2, + 4, + 4, + 3, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/agave regular Nerd Font Complete Mono.ttf", + "preferred_family_name": "agave Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "r", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/agave regular Nerd Font Complete.ttf||961644:1634564302.0": { + "family_name": "agave Nerd Font", + "font-family": "agave Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "agave regular Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 9, + 2, + 4, + 4, + 3, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/agave regular Nerd Font Complete.ttf", + "preferred_family_name": "agave Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "r", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/iM Writing Duo S Bold Italic Nerd Font Complete Mono.ttf||884800:1634564302.0": { + "family_name": "iMWritingDuoS Nerd Font Mono", + "font-family": "iMWritingDuoS Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 8, + "full_name": "iM Writing Duo S Bold Italic Nerd Font Complete Mono", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 8, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/iM Writing Duo S Bold Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "iMWritingDuoS Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/iM Writing Duo S Bold Italic Nerd Font Complete.ttf||889592:1634564302.0": { + "family_name": "iMWritingDuoS Nerd Font", + "font-family": "iMWritingDuoS Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 8, + "full_name": "iM Writing Duo S Bold Italic Nerd Font Complete", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 8, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/iM Writing Duo S Bold Italic Nerd Font Complete.ttf", + "preferred_family_name": "iMWritingDuoS Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/iM Writing Duo S Bold Nerd Font Complete Mono.ttf||900568:1634564302.0": { + "family_name": "iMWritingDuoS Nerd Font Mono", + "font-family": "iMWritingDuoS Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 8, + "full_name": "iM Writing Duo S Bold Nerd Font Complete Mono", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 8, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/iM Writing Duo S Bold Nerd Font Complete Mono.ttf", + "preferred_family_name": "iMWritingDuoS Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/iM Writing Duo S Bold Nerd Font Complete.ttf||906032:1634564302.0": { + "family_name": "iMWritingDuoS Nerd Font", + "font-family": "iMWritingDuoS Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 8, + "full_name": "iM Writing Duo S Bold Nerd Font Complete", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 8, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/iM Writing Duo S Bold Nerd Font Complete.ttf", + "preferred_family_name": "iMWritingDuoS Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/iM Writing Duo S Italic Nerd Font Complete Mono.ttf||885416:1634564302.0": { + "family_name": "iMWritingDuoS Nerd Font Mono", + "font-family": "iMWritingDuoS Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 8, + "full_name": "iM Writing Duo S Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 5, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/iM Writing Duo S Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "iMWritingDuoS Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/iM Writing Duo S Italic Nerd Font Complete.ttf||890224:1634564302.0": { + "family_name": "iMWritingDuoS Nerd Font", + "font-family": "iMWritingDuoS Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 8, + "full_name": "iM Writing Duo S Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 5, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/iM Writing Duo S Italic Nerd Font Complete.ttf", + "preferred_family_name": "iMWritingDuoS Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/iM Writing Duo S Regular Nerd Font Complete Mono.ttf||899964:1634564302.0": { + "family_name": "iMWritingDuoS Nerd Font Mono", + "font-family": "iMWritingDuoS Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 8, + "full_name": "iM Writing Duo S Regular Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 5, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/iM Writing Duo S Regular Nerd Font Complete Mono.ttf", + "preferred_family_name": "iMWritingDuoS Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/iM Writing Duo S Regular Nerd Font Complete.ttf||905432:1634564302.0": { + "family_name": "iMWritingDuoS Nerd Font", + "font-family": "iMWritingDuoS Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 8, + "full_name": "iM Writing Duo S Regular Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 5, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/iM Writing Duo S Regular Nerd Font Complete.ttf", + "preferred_family_name": "iMWritingDuoS Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/iM Writing Mono S Bold Italic Nerd Font Complete Mono.ttf||869784:1634564302.0": { + "family_name": "iMWritingMonoS Nerd Font Mono", + "font-family": "iMWritingMonoS Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 8, + "full_name": "iM Writing Mono S Bold Italic Nerd Font Complete Mono", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 8, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/iM Writing Mono S Bold Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "iMWritingMonoS Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/iM Writing Mono S Bold Italic Nerd Font Complete.ttf||887724:1634564302.0": { + "family_name": "iMWritingMonoS Nerd Font", + "font-family": "iMWritingMonoS Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 8, + "full_name": "iM Writing Mono S Bold Italic Nerd Font Complete", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 8, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/iM Writing Mono S Bold Italic Nerd Font Complete.ttf", + "preferred_family_name": "iMWritingMonoS Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/iM Writing Mono S Bold Nerd Font Complete Mono.ttf||863696:1634564302.0": { + "family_name": "iMWritingMonoS Nerd Font Mono", + "font-family": "iMWritingMonoS Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 8, + "full_name": "iM Writing Mono S Bold Nerd Font Complete Mono", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 8, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/iM Writing Mono S Bold Nerd Font Complete Mono.ttf", + "preferred_family_name": "iMWritingMonoS Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/iM Writing Mono S Bold Nerd Font Complete.ttf||880512:1634564302.0": { + "family_name": "iMWritingMonoS Nerd Font", + "font-family": "iMWritingMonoS Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 8, + "full_name": "iM Writing Mono S Bold Nerd Font Complete", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 8, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/iM Writing Mono S Bold Nerd Font Complete.ttf", + "preferred_family_name": "iMWritingMonoS Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/iM Writing Mono S Italic Nerd Font Complete Mono.ttf||870588:1634564302.0": { + "family_name": "iMWritingMonoS Nerd Font Mono", + "font-family": "iMWritingMonoS Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 8, + "full_name": "iM Writing Mono S Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 5, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/iM Writing Mono S Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "iMWritingMonoS Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/iM Writing Mono S Italic Nerd Font Complete.ttf||888528:1634564302.0": { + "family_name": "iMWritingMonoS Nerd Font", + "font-family": "iMWritingMonoS Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 8, + "full_name": "iM Writing Mono S Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 5, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/iM Writing Mono S Italic Nerd Font Complete.ttf", + "preferred_family_name": "iMWritingMonoS Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/iM Writing Mono S Regular Nerd Font Complete Mono.ttf||873720:1634564302.0": { + "family_name": "iMWritingMonoS Nerd Font Mono", + "font-family": "iMWritingMonoS Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 8, + "full_name": "iM Writing Mono S Regular Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 5, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/iM Writing Mono S Regular Nerd Font Complete Mono.ttf", + "preferred_family_name": "iMWritingMonoS Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/iM Writing Mono S Regular Nerd Font Complete.ttf||881496:1634564302.0": { + "family_name": "iMWritingMonoS Nerd Font", + "font-family": "iMWritingMonoS Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 8, + "full_name": "iM Writing Mono S Regular Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 5, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/iM Writing Mono S Regular Nerd Font Complete.ttf", + "preferred_family_name": "iMWritingMonoS Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/iM Writing Quattro S Bold Italic Nerd Font Complete Mono.ttf||884048:1634564302.0": { + "family_name": "iMWritingQuattroS Nerd Font Mono", + "font-family": "iMWritingQuattroS Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 8, + "full_name": "iM Writing Quattro S Bold Italic Nerd Font Complete Mono", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 5, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/iM Writing Quattro S Bold Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "iMWritingQuattroS Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Bold Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/iM Writing Quattro S Bold Italic Nerd Font Complete.ttf||888840:1634564302.0": { + "family_name": "iMWritingQuattroS Nerd Font", + "font-family": "iMWritingQuattroS Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 8, + "full_name": "iM Writing Quattro S Bold Italic Nerd Font Complete", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 5, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/iM Writing Quattro S Bold Italic Nerd Font Complete.ttf", + "preferred_family_name": "iMWritingQuattroS Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Bold Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/iM Writing Quattro S Bold Nerd Font Complete Mono.ttf||899584:1634564302.0": { + "family_name": "iMWritingQuattroS Nerd Font Mono", + "font-family": "iMWritingQuattroS Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 8, + "full_name": "iM Writing Quattro S Bold Nerd Font Complete Mono", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 5, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/iM Writing Quattro S Bold Nerd Font Complete Mono.ttf", + "preferred_family_name": "iMWritingQuattroS Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/iM Writing Quattro S Bold Nerd Font Complete.ttf||905052:1634564302.0": { + "family_name": "iMWritingQuattroS Nerd Font", + "font-family": "iMWritingQuattroS Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 8, + "full_name": "iM Writing Quattro S Bold Nerd Font Complete", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 5, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/iM Writing Quattro S Bold Nerd Font Complete.ttf", + "preferred_family_name": "iMWritingQuattroS Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/iM Writing Quattro S Italic Nerd Font Complete Mono.ttf||884640:1634564302.0": { + "family_name": "iMWritingQuattroS Nerd Font Mono", + "font-family": "iMWritingQuattroS Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 8, + "full_name": "iM Writing Quattro S Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 5, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/iM Writing Quattro S Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "iMWritingQuattroS Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/iM Writing Quattro S Italic Nerd Font Complete.ttf||889448:1634564302.0": { + "family_name": "iMWritingQuattroS Nerd Font", + "font-family": "iMWritingQuattroS Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 8, + "full_name": "iM Writing Quattro S Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 5, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/iM Writing Quattro S Italic Nerd Font Complete.ttf", + "preferred_family_name": "iMWritingQuattroS Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/iM Writing Quattro S Regular Nerd Font Complete Mono.ttf||898992:1634564302.0": { + "family_name": "iMWritingQuattroS Nerd Font Mono", + "font-family": "iMWritingQuattroS Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 8, + "full_name": "iM Writing Quattro S Regular Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 5, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/iM Writing Quattro S Regular Nerd Font Complete Mono.ttf", + "preferred_family_name": "iMWritingQuattroS Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/iM Writing Quattro S Regular Nerd Font Complete.ttf||904464:1634564302.0": { + "family_name": "iMWritingQuattroS Nerd Font", + "font-family": "iMWritingQuattroS Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 8, + "full_name": "iM Writing Quattro S Regular Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 5, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/iM Writing Quattro S Regular Nerd Font Complete.ttf", + "preferred_family_name": "iMWritingQuattroS Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/monofur Nerd Font Complete Mono.ttf||967268:1634564302.0": { + "family_name": "Monofur Nerd Font Mono", + "font-family": "Monofur Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "monofur Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 15, + 4, + 9, + 2, + 2, + 3, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/monofur Nerd Font Complete Mono.ttf", + "preferred_family_name": "Monofur Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Book", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/monofur Nerd Font Complete.ttf||998152:1634564302.0": { + "family_name": "Monofur Nerd Font", + "font-family": "Monofur Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "monofur Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 15, + 4, + 9, + 2, + 2, + 3, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/monofur Nerd Font Complete.ttf", + "preferred_family_name": "Monofur Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Book", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/monofur bold Nerd Font Complete Mono.ttf||960692:1634564302.0": { + "family_name": "Monofurbold Nerd Font Mono", + "font-family": "Monofurbold Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "monofur bold Nerd Font Complete Mono", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 15, + 4, + 9, + 2, + 2, + 3, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/monofur bold Nerd Font Complete Mono.ttf", + "preferred_family_name": "Monofurbold Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": " bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/monofur bold Nerd Font Complete.ttf||989932:1634564302.0": { + "family_name": "Monofurbold Nerd Font", + "font-family": "Monofurbold Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "monofur bold Nerd Font Complete", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 15, + 4, + 9, + 2, + 2, + 3, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/monofur bold Nerd Font Complete.ttf", + "preferred_family_name": "Monofurbold Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": " bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/monofur italic Nerd Font Complete Mono.ttf||979992:1634564302.0": { + "family_name": "Monofuritalic Nerd Font Mono", + "font-family": "Monofuritalic Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "monofur italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 15, + 4, + 0, + 2, + 2, + 3, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/monofur italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "Monofuritalic Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": " italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/monofur italic Nerd Font Complete.ttf||1010880:1634564302.0": { + "family_name": "Monofuritalic Nerd Font", + "font-family": "Monofuritalic Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "monofur italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 15, + 4, + 0, + 2, + 2, + 3, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/monofur italic Nerd Font Complete.ttf", + "preferred_family_name": "Monofuritalic Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": " italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/mononoki Bold Italic Nerd Font Complete Mono.ttf||866948:1634564302.0": { + "family_name": "mononoki Nerd Font Mono", + "font-family": "mononoki Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 8, + "full_name": "mononoki Bold Italic Nerd Font Complete Mono", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 8, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/mononoki Bold Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "mononoki Nerd Font Mono", + "preferred_subfamily_name": "BoldItalic", + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/mononoki Bold Italic Nerd Font Complete.ttf||888060:1634564302.0": { + "family_name": "mononoki Nerd Font", + "font-family": "mononoki Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 8, + "full_name": "mononoki Bold Italic Nerd Font Complete", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 8, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/mononoki Bold Italic Nerd Font Complete.ttf", + "preferred_family_name": "mononoki Nerd Font", + "preferred_subfamily_name": "BoldItalic", + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/mononoki Bold Nerd Font Complete Mono.ttf||858780:1634564302.0": { + "family_name": "mononoki Nerd Font Mono", + "font-family": "mononoki Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 8, + "full_name": "mononoki Bold Nerd Font Complete Mono", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 8, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/mononoki Bold Nerd Font Complete Mono.ttf", + "preferred_family_name": "mononoki Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/mononoki Bold Nerd Font Complete.ttf||873584:1634564302.0": { + "family_name": "mononoki Nerd Font", + "font-family": "mononoki Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 8, + "full_name": "mononoki Bold Nerd Font Complete", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 8, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/mononoki Bold Nerd Font Complete.ttf", + "preferred_family_name": "mononoki Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/mononoki Italic Nerd Font Complete Mono.ttf||860728:1634564302.0": { + "family_name": "mononoki Nerd Font Mono", + "font-family": "mononoki Nerd Font Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 8, + "full_name": "mononoki Italic Nerd Font Complete Mono", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 5, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/mononoki Italic Nerd Font Complete Mono.ttf", + "preferred_family_name": "mononoki Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/mononoki Italic Nerd Font Complete.ttf||875532:1634564302.0": { + "family_name": "mononoki Nerd Font", + "font-family": "mononoki Nerd Font", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 8, + "full_name": "mononoki Italic Nerd Font Complete", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 5, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/mononoki Italic Nerd Font Complete.ttf", + "preferred_family_name": "mononoki Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/mononoki-Regular Nerd Font Complete Mono.ttf||854900:1634564302.0": { + "family_name": "mononoki Nerd Font Mono", + "font-family": "mononoki Nerd Font Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 8, + "full_name": "mononoki-Regular Nerd Font Complete Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 5, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/mononoki-Regular Nerd Font Complete Mono.ttf", + "preferred_family_name": "mononoki Nerd Font Mono", + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/nerd-fonts-complete/TTF/mononoki-Regular Nerd Font Complete.ttf||876828:1634564302.0": { + "family_name": "mononoki Nerd Font", + "font-family": "mononoki Nerd Font", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 8, + "full_name": "mononoki-Regular Nerd Font Complete", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 0, + 0, + 5, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/nerd-fonts-complete/TTF/mononoki-Regular Nerd Font Complete.ttf", + "preferred_family_name": "mononoki Nerd Font", + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoColorEmoji.ttf||9867108:1635795694.0": { + "family_name": "Noto Color Emoji", + "font-family": "Noto Color Emoji", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Color Emoji", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 6, + 9, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/noto/NotoColorEmoji.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoKufiArabic-Black.ttf||217280:1655828711.0": { + "family_name": "Noto Kufi Arabic Black", + "font-family": "Noto Kufi Arabic Black", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Kufi Arabic Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 4, + 3, + 8, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoKufiArabic-Black.ttf", + "preferred_family_name": "Noto Kufi Arabic", + "preferred_subfamily_name": "Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoKufiArabic-Bold.ttf||203640:1655828711.0": { + "family_name": "Noto Kufi Arabic", + "font-family": "Noto Kufi Arabic", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Kufi Arabic Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 4, + 3, + 8, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoKufiArabic-Bold.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoKufiArabic-ExtraBold.ttf||226180:1655828711.0": { + "family_name": "Noto Kufi Arabic ExtraBold", + "font-family": "Noto Kufi Arabic ExtraBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Kufi Arabic ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 4, + 3, + 8, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoKufiArabic-ExtraBold.ttf", + "preferred_family_name": "Noto Kufi Arabic", + "preferred_subfamily_name": "ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoKufiArabic-ExtraLight.ttf||198028:1655828711.0": { + "family_name": "Noto Kufi Arabic ExtraLight", + "font-family": "Noto Kufi Arabic ExtraLight", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Kufi Arabic ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 4, + 3, + 8, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoKufiArabic-ExtraLight.ttf", + "preferred_family_name": "Noto Kufi Arabic", + "preferred_subfamily_name": "ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoKufiArabic-Light.ttf||200916:1655828711.0": { + "family_name": "Noto Kufi Arabic Light", + "font-family": "Noto Kufi Arabic Light", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Kufi Arabic Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 4, + 3, + 8, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoKufiArabic-Light.ttf", + "preferred_family_name": "Noto Kufi Arabic", + "preferred_subfamily_name": "Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoKufiArabic-Medium.ttf||201592:1655828711.0": { + "family_name": "Noto Kufi Arabic Medium", + "font-family": "Noto Kufi Arabic Medium", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Kufi Arabic Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 4, + 3, + 8, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoKufiArabic-Medium.ttf", + "preferred_family_name": "Noto Kufi Arabic", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoKufiArabic-Regular.ttf||198872:1655828711.0": { + "family_name": "Noto Kufi Arabic", + "font-family": "Noto Kufi Arabic", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Kufi Arabic Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 4, + 3, + 8, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoKufiArabic-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoKufiArabic-SemiBold.ttf||204296:1655828711.0": { + "family_name": "Noto Kufi Arabic SemiBold", + "font-family": "Noto Kufi Arabic SemiBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Kufi Arabic SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 4, + 3, + 8, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoKufiArabic-SemiBold.ttf", + "preferred_family_name": "Noto Kufi Arabic", + "preferred_subfamily_name": "SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoKufiArabic-Thin.ttf||196840:1655828711.0": { + "family_name": "Noto Kufi Arabic Thin", + "font-family": "Noto Kufi Arabic Thin", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Kufi Arabic Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 4, + 3, + 8, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoKufiArabic-Thin.ttf", + "preferred_family_name": "Noto Kufi Arabic", + "preferred_subfamily_name": "Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedLao-Black.ttf||56460:1655828711.0": { + "family_name": "Noto Looped Lao Black", + "font-family": "Noto Looped Lao Black", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Looped Lao Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedLao-Black.ttf", + "preferred_family_name": "Noto Looped Lao", + "preferred_subfamily_name": "Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedLao-Bold.ttf||55360:1655828711.0": { + "family_name": "Noto Looped Lao Bold", + "font-family": "Noto Looped Lao Bold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Looped Lao Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedLao-Bold.ttf", + "preferred_family_name": "Noto Looped Lao", + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedLao-Condensed.ttf||54056:1655828711.0": { + "family_name": "Noto Looped Lao Condensed", + "font-family": "Noto Looped Lao Condensed", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Looped Lao Condensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedLao-Condensed.ttf", + "preferred_family_name": "Noto Looped Lao", + "preferred_subfamily_name": "Condensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedLao-CondensedBlack.ttf||55196:1655828711.0": { + "family_name": "Noto Looped Lao Cond Blk", + "font-family": "Noto Looped Lao Cond Blk", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Looped Lao Condensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedLao-CondensedBlack.ttf", + "preferred_family_name": "Noto Looped Lao", + "preferred_subfamily_name": "Condensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedLao-CondensedBold.ttf||54448:1655828711.0": { + "family_name": "Noto Looped Lao Cond Bold", + "font-family": "Noto Looped Lao Cond Bold", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Looped Lao Condensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedLao-CondensedBold.ttf", + "preferred_family_name": "Noto Looped Lao", + "preferred_subfamily_name": "Condensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedLao-CondensedExtraBold.ttf||55368:1655828711.0": { + "family_name": "Noto Looped Lao Cond ExBd", + "font-family": "Noto Looped Lao Cond ExBd", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Looped Lao Condensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedLao-CondensedExtraBold.ttf", + "preferred_family_name": "Noto Looped Lao", + "preferred_subfamily_name": "Condensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedLao-CondensedExtraLight.ttf||54060:1655828711.0": { + "family_name": "Noto Looped Lao Cond ExLt", + "font-family": "Noto Looped Lao Cond ExLt", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Looped Lao Condensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedLao-CondensedExtraLight.ttf", + "preferred_family_name": "Noto Looped Lao", + "preferred_subfamily_name": "Condensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedLao-CondensedLight.ttf||52876:1655828711.0": { + "family_name": "Noto Looped Lao Cond Lt", + "font-family": "Noto Looped Lao Cond Lt", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Looped Lao Condensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedLao-CondensedLight.ttf", + "preferred_family_name": "Noto Looped Lao", + "preferred_subfamily_name": "Condensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedLao-CondensedMedium.ttf||54296:1655828711.0": { + "family_name": "Noto Looped Lao Cond Med", + "font-family": "Noto Looped Lao Cond Med", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Looped Lao Condensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedLao-CondensedMedium.ttf", + "preferred_family_name": "Noto Looped Lao", + "preferred_subfamily_name": "Condensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedLao-CondensedSemiBold.ttf||55416:1655828711.0": { + "family_name": "Noto Looped Lao Cond SmBd", + "font-family": "Noto Looped Lao Cond SmBd", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Looped Lao Condensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedLao-CondensedSemiBold.ttf", + "preferred_family_name": "Noto Looped Lao", + "preferred_subfamily_name": "Condensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedLao-CondensedThin.ttf||51556:1655828711.0": { + "family_name": "Noto Looped Lao Cond Thin", + "font-family": "Noto Looped Lao Cond Thin", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Looped Lao Condensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedLao-CondensedThin.ttf", + "preferred_family_name": "Noto Looped Lao", + "preferred_subfamily_name": "Condensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedLao-ExtraBold.ttf||56044:1655828711.0": { + "family_name": "Noto Looped Lao ExtraBold", + "font-family": "Noto Looped Lao ExtraBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Looped Lao ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedLao-ExtraBold.ttf", + "preferred_family_name": "Noto Looped Lao", + "preferred_subfamily_name": "ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedLao-ExtraCondensed.ttf||53532:1655828711.0": { + "family_name": "Noto Looped Lao ExtraCond", + "font-family": "Noto Looped Lao ExtraCond", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Looped Lao ExtraCondensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedLao-ExtraCondensed.ttf", + "preferred_family_name": "Noto Looped Lao", + "preferred_subfamily_name": "ExtraCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedLao-ExtraCondensedBlack.ttf||54328:1655828711.0": { + "family_name": "Noto Looped Lao ExCd Blk", + "font-family": "Noto Looped Lao ExCd Blk", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Looped Lao ExtraCondensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedLao-ExtraCondensedBlack.ttf", + "preferred_family_name": "Noto Looped Lao", + "preferred_subfamily_name": "ExtraCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedLao-ExtraCondensedBold.ttf||54248:1655828711.0": { + "family_name": "Noto Looped Lao ExCd Bold", + "font-family": "Noto Looped Lao ExCd Bold", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Looped Lao ExtraCondensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedLao-ExtraCondensedBold.ttf", + "preferred_family_name": "Noto Looped Lao", + "preferred_subfamily_name": "ExtraCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedLao-ExtraCondensedExtraBold.ttf||54860:1655828711.0": { + "family_name": "Noto Looped Lao ExCd ExBd", + "font-family": "Noto Looped Lao ExCd ExBd", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Looped Lao ExtraCondensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedLao-ExtraCondensedExtraBold.ttf", + "preferred_family_name": "Noto Looped Lao", + "preferred_subfamily_name": "ExtraCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedLao-ExtraCondensedExtraLight.ttf||53460:1655828711.0": { + "family_name": "Noto Looped Lao ExCd ExLt", + "font-family": "Noto Looped Lao ExCd ExLt", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Looped Lao ExtraCondensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedLao-ExtraCondensedExtraLight.ttf", + "preferred_family_name": "Noto Looped Lao", + "preferred_subfamily_name": "ExtraCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedLao-ExtraCondensedLight.ttf||52688:1655828711.0": { + "family_name": "Noto Looped Lao ExCd Lt", + "font-family": "Noto Looped Lao ExCd Lt", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Looped Lao ExtraCondensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedLao-ExtraCondensedLight.ttf", + "preferred_family_name": "Noto Looped Lao", + "preferred_subfamily_name": "ExtraCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedLao-ExtraCondensedMedium.ttf||54232:1655828711.0": { + "family_name": "Noto Looped Lao ExCd Med", + "font-family": "Noto Looped Lao ExCd Med", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Looped Lao ExtraCondensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedLao-ExtraCondensedMedium.ttf", + "preferred_family_name": "Noto Looped Lao", + "preferred_subfamily_name": "ExtraCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedLao-ExtraCondensedSemiBold.ttf||54924:1655828711.0": { + "family_name": "Noto Looped Lao ExCd SmBd", + "font-family": "Noto Looped Lao ExCd SmBd", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Looped Lao ExtraCondensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedLao-ExtraCondensedSemiBold.ttf", + "preferred_family_name": "Noto Looped Lao", + "preferred_subfamily_name": "ExtraCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedLao-ExtraCondensedThin.ttf||51756:1655828711.0": { + "family_name": "Noto Looped Lao ExCd Thin", + "font-family": "Noto Looped Lao ExCd Thin", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Looped Lao ExtraCondensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedLao-ExtraCondensedThin.ttf", + "preferred_family_name": "Noto Looped Lao", + "preferred_subfamily_name": "ExtraCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedLao-ExtraLight.ttf||56840:1655828711.0": { + "family_name": "Noto Looped Lao ExtLight", + "font-family": "Noto Looped Lao ExtLight", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Looped Lao ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedLao-ExtraLight.ttf", + "preferred_family_name": "Noto Looped Lao", + "preferred_subfamily_name": "ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedLao-Light.ttf||53200:1655828711.0": { + "family_name": "Noto Looped Lao Light", + "font-family": "Noto Looped Lao Light", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Looped Lao Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedLao-Light.ttf", + "preferred_family_name": "Noto Looped Lao", + "preferred_subfamily_name": "Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedLao-Medium.ttf||55632:1655828711.0": { + "family_name": "Noto Looped Lao Medium", + "font-family": "Noto Looped Lao Medium", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Looped Lao Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedLao-Medium.ttf", + "preferred_family_name": "Noto Looped Lao", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedLao-Regular.ttf||55484:1655828711.0": { + "family_name": "Noto Looped Lao Regular", + "font-family": "Noto Looped Lao Regular", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Looped Lao Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedLao-Regular.ttf", + "preferred_family_name": "Noto Looped Lao", + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedLao-SemiBold.ttf||54784:1655828711.0": { + "family_name": "Noto Looped Lao SemiBold", + "font-family": "Noto Looped Lao SemiBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Looped Lao SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedLao-SemiBold.ttf", + "preferred_family_name": "Noto Looped Lao", + "preferred_subfamily_name": "SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedLao-SemiCondensed.ttf||55708:1655828711.0": { + "family_name": "Noto Looped Lao SemiCond", + "font-family": "Noto Looped Lao SemiCond", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Looped Lao SemiCondensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedLao-SemiCondensed.ttf", + "preferred_family_name": "Noto Looped Lao", + "preferred_subfamily_name": "SemiCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedLao-SemiCondensedBlack.ttf||55608:1655828711.0": { + "family_name": "Noto Looped Lao SmCd Blk", + "font-family": "Noto Looped Lao SmCd Blk", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Looped Lao SemiCondensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedLao-SemiCondensedBlack.ttf", + "preferred_family_name": "Noto Looped Lao", + "preferred_subfamily_name": "SemiCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedLao-SemiCondensedBold.ttf||54760:1655828711.0": { + "family_name": "Noto Looped Lao SmCd Bold", + "font-family": "Noto Looped Lao SmCd Bold", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Looped Lao SemiCondensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedLao-SemiCondensedBold.ttf", + "preferred_family_name": "Noto Looped Lao", + "preferred_subfamily_name": "SemiCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedLao-SemiCondensedExtraBold.ttf||55576:1655828711.0": { + "family_name": "Noto Looped Lao SmCd ExBd", + "font-family": "Noto Looped Lao SmCd ExBd", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Looped Lao SemiCondensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedLao-SemiCondensedExtraBold.ttf", + "preferred_family_name": "Noto Looped Lao", + "preferred_subfamily_name": "SemiCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedLao-SemiCondensedExtraLight.ttf||54908:1655828711.0": { + "family_name": "Noto Looped Lao SmCd ExtLt", + "font-family": "Noto Looped Lao SmCd ExtLt", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Looped Lao SemiCondensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedLao-SemiCondensedExtraLight.ttf", + "preferred_family_name": "Noto Looped Lao", + "preferred_subfamily_name": "SemiCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedLao-SemiCondensedLight.ttf||52932:1655828711.0": { + "family_name": "Noto Looped Lao SmCd Lt", + "font-family": "Noto Looped Lao SmCd Lt", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Looped Lao SemiCondensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedLao-SemiCondensedLight.ttf", + "preferred_family_name": "Noto Looped Lao", + "preferred_subfamily_name": "SemiCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedLao-SemiCondensedMedium.ttf||54960:1655828711.0": { + "family_name": "Noto Looped Lao SmCd Med", + "font-family": "Noto Looped Lao SmCd Med", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Looped Lao SemiCondensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedLao-SemiCondensedMedium.ttf", + "preferred_family_name": "Noto Looped Lao", + "preferred_subfamily_name": "SemiCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedLao-SemiCondensedSemiBold.ttf||54800:1655828711.0": { + "family_name": "Noto Looped Lao SmCd SmBd", + "font-family": "Noto Looped Lao SmCd SmBd", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Looped Lao SemiCondensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedLao-SemiCondensedSemiBold.ttf", + "preferred_family_name": "Noto Looped Lao", + "preferred_subfamily_name": "SemiCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedLao-SemiCondensedThin.ttf||52868:1655828711.0": { + "family_name": "Noto Looped Lao SmCd Thin", + "font-family": "Noto Looped Lao SmCd Thin", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Looped Lao SemiCondensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedLao-SemiCondensedThin.ttf", + "preferred_family_name": "Noto Looped Lao", + "preferred_subfamily_name": "SemiCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedLao-Thin.ttf||52772:1655828711.0": { + "family_name": "Noto Looped Lao Thin", + "font-family": "Noto Looped Lao Thin", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Looped Lao Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedLao-Thin.ttf", + "preferred_family_name": "Noto Looped Lao", + "preferred_subfamily_name": "Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedLaoUI-Black.ttf||44788:1655828711.0": { + "family_name": "Noto Looped Lao UI Black", + "font-family": "Noto Looped Lao UI Black", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Looped Lao UI Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedLaoUI-Black.ttf", + "preferred_family_name": "Noto Looped Lao UI", + "preferred_subfamily_name": "Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedLaoUI-Bold.ttf||43900:1655828711.0": { + "family_name": "Noto Looped Lao UI Bold", + "font-family": "Noto Looped Lao UI Bold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Looped Lao UI Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedLaoUI-Bold.ttf", + "preferred_family_name": "Noto Looped Lao UI", + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedLaoUI-Condensed.ttf||42620:1655828711.0": { + "family_name": "Noto Looped Lao UI Condensed", + "font-family": "Noto Looped Lao UI Condensed", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Looped Lao UI Condensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedLaoUI-Condensed.ttf", + "preferred_family_name": "Noto Looped Lao UI", + "preferred_subfamily_name": "Condensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedLaoUI-CondensedBlack.ttf||44328:1655828711.0": { + "family_name": "Noto Looped Lao UI Cond Blk", + "font-family": "Noto Looped Lao UI Cond Blk", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Looped Lao UI Condensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedLaoUI-CondensedBlack.ttf", + "preferred_family_name": "Noto Looped Lao UI", + "preferred_subfamily_name": "Condensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedLaoUI-CondensedBold.ttf||43076:1655828711.0": { + "family_name": "Noto Looped Lao UI Cond Bold", + "font-family": "Noto Looped Lao UI Cond Bold", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Looped Lao UI Condensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedLaoUI-CondensedBold.ttf", + "preferred_family_name": "Noto Looped Lao UI", + "preferred_subfamily_name": "Condensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedLaoUI-CondensedExtraBold.ttf||43596:1655828711.0": { + "family_name": "Noto Looped Lao UI Cond ExBd", + "font-family": "Noto Looped Lao UI Cond ExBd", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Looped Lao UI Condensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedLaoUI-CondensedExtraBold.ttf", + "preferred_family_name": "Noto Looped Lao UI", + "preferred_subfamily_name": "Condensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedLaoUI-CondensedExtraLight.ttf||41452:1655828711.0": { + "family_name": "Noto Looped Lao UI Cond ExLt", + "font-family": "Noto Looped Lao UI Cond ExLt", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Looped Lao UI Condensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedLaoUI-CondensedExtraLight.ttf", + "preferred_family_name": "Noto Looped Lao UI", + "preferred_subfamily_name": "Condensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedLaoUI-CondensedLight.ttf||42328:1655828711.0": { + "family_name": "Noto Looped Lao UI Cond Lt", + "font-family": "Noto Looped Lao UI Cond Lt", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Looped Lao UI Condensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedLaoUI-CondensedLight.ttf", + "preferred_family_name": "Noto Looped Lao UI", + "preferred_subfamily_name": "Condensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedLaoUI-CondensedMedium.ttf||43296:1655828711.0": { + "family_name": "Noto Looped Lao UI Cond Med", + "font-family": "Noto Looped Lao UI Cond Med", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Looped Lao UI Condensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedLaoUI-CondensedMedium.ttf", + "preferred_family_name": "Noto Looped Lao UI", + "preferred_subfamily_name": "Condensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedLaoUI-CondensedSemiBold.ttf||43312:1655828711.0": { + "family_name": "Noto Looped Lao UI Cond SmBd", + "font-family": "Noto Looped Lao UI Cond SmBd", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Looped Lao UI Condensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedLaoUI-CondensedSemiBold.ttf", + "preferred_family_name": "Noto Looped Lao UI", + "preferred_subfamily_name": "Condensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedLaoUI-CondensedThin.ttf||40572:1655828711.0": { + "family_name": "Noto Looped Lao UI Cond Thin", + "font-family": "Noto Looped Lao UI Cond Thin", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Looped Lao UI Condensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedLaoUI-CondensedThin.ttf", + "preferred_family_name": "Noto Looped Lao UI", + "preferred_subfamily_name": "Condensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedLaoUI-ExtraBold.ttf||44436:1655828711.0": { + "family_name": "Noto Looped Lao UI ExtraBold", + "font-family": "Noto Looped Lao UI ExtraBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Looped Lao UI ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedLaoUI-ExtraBold.ttf", + "preferred_family_name": "Noto Looped Lao UI", + "preferred_subfamily_name": "ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedLaoUI-ExtraCondensed.ttf||42356:1655828711.0": { + "family_name": "Noto Looped Lao UI ExtraCond", + "font-family": "Noto Looped Lao UI ExtraCond", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Looped Lao UI ExtraCondensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedLaoUI-ExtraCondensed.ttf", + "preferred_family_name": "Noto Looped Lao UI", + "preferred_subfamily_name": "ExtraCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedLaoUI-ExtraCondensedBlack.ttf||44184:1655828711.0": { + "family_name": "Noto Looped Lao UI ExCd Blk", + "font-family": "Noto Looped Lao UI ExCd Blk", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Looped Lao UI ExtraCondensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedLaoUI-ExtraCondensedBlack.ttf", + "preferred_family_name": "Noto Looped Lao UI", + "preferred_subfamily_name": "ExtraCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedLaoUI-ExtraCondensedBold.ttf||43592:1655828711.0": { + "family_name": "Noto Looped Lao UI ExCd Bold", + "font-family": "Noto Looped Lao UI ExCd Bold", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Looped Lao UI ExtraCondensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedLaoUI-ExtraCondensedBold.ttf", + "preferred_family_name": "Noto Looped Lao UI", + "preferred_subfamily_name": "ExtraCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedLaoUI-ExtraCondensedExtraBold.ttf||43820:1655828711.0": { + "family_name": "Noto Looped Lao UI ExCd ExBd", + "font-family": "Noto Looped Lao UI ExCd ExBd", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Looped Lao UI ExtraCondensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedLaoUI-ExtraCondensedExtraBold.ttf", + "preferred_family_name": "Noto Looped Lao UI", + "preferred_subfamily_name": "ExtraCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedLaoUI-ExtraCondensedExtraLight.ttf||41128:1655828711.0": { + "family_name": "Noto Looped Lao UI ExCd ExLt", + "font-family": "Noto Looped Lao UI ExCd ExLt", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Looped Lao UI ExtraCondensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedLaoUI-ExtraCondensedExtraLight.ttf", + "preferred_family_name": "Noto Looped Lao UI", + "preferred_subfamily_name": "ExtraCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedLaoUI-ExtraCondensedLight.ttf||42692:1655828711.0": { + "family_name": "Noto Looped Lao UI ExCd Lt", + "font-family": "Noto Looped Lao UI ExCd Lt", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Looped Lao UI ExtraCondensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedLaoUI-ExtraCondensedLight.ttf", + "preferred_family_name": "Noto Looped Lao UI", + "preferred_subfamily_name": "ExtraCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedLaoUI-ExtraCondensedMedium.ttf||42888:1655828711.0": { + "family_name": "Noto Looped Lao UI ExCd Med", + "font-family": "Noto Looped Lao UI ExCd Med", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Looped Lao UI ExtraCondensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedLaoUI-ExtraCondensedMedium.ttf", + "preferred_family_name": "Noto Looped Lao UI", + "preferred_subfamily_name": "ExtraCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedLaoUI-ExtraCondensedSemiBold.ttf||42880:1655828711.0": { + "family_name": "Noto Looped Lao UI ExCd SmBd", + "font-family": "Noto Looped Lao UI ExCd SmBd", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Looped Lao UI ExtraCondensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedLaoUI-ExtraCondensedSemiBold.ttf", + "preferred_family_name": "Noto Looped Lao UI", + "preferred_subfamily_name": "ExtraCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedLaoUI-ExtraCondensedThin.ttf||40720:1655828711.0": { + "family_name": "Noto Looped Lao UI ExCd Thin", + "font-family": "Noto Looped Lao UI ExCd Thin", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Looped Lao UI ExtraCondensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedLaoUI-ExtraCondensedThin.ttf", + "preferred_family_name": "Noto Looped Lao UI", + "preferred_subfamily_name": "ExtraCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedLaoUI-ExtraLight.ttf||41860:1655828711.0": { + "family_name": "Noto Looped Lao UI ExtLight", + "font-family": "Noto Looped Lao UI ExtLight", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Looped Lao UI ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedLaoUI-ExtraLight.ttf", + "preferred_family_name": "Noto Looped Lao UI", + "preferred_subfamily_name": "ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedLaoUI-Light.ttf||42692:1655828711.0": { + "family_name": "Noto Looped Lao UI Light", + "font-family": "Noto Looped Lao UI Light", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Looped Lao UI Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedLaoUI-Light.ttf", + "preferred_family_name": "Noto Looped Lao UI", + "preferred_subfamily_name": "Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedLaoUI-Medium.ttf||43580:1655828711.0": { + "family_name": "Noto Looped Lao UI Medium", + "font-family": "Noto Looped Lao UI Medium", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Looped Lao UI Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedLaoUI-Medium.ttf", + "preferred_family_name": "Noto Looped Lao UI", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedLaoUI-Regular.ttf||42948:1655828711.0": { + "family_name": "Noto Looped Lao UI Regular", + "font-family": "Noto Looped Lao UI Regular", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Looped Lao UI Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedLaoUI-Regular.ttf", + "preferred_family_name": "Noto Looped Lao UI", + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedLaoUI-SemiBold.ttf||44552:1655828711.0": { + "family_name": "Noto Looped Lao UI SemiBold", + "font-family": "Noto Looped Lao UI SemiBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Looped Lao UI SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedLaoUI-SemiBold.ttf", + "preferred_family_name": "Noto Looped Lao UI", + "preferred_subfamily_name": "SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedLaoUI-SemiCondensed.ttf||42720:1655828711.0": { + "family_name": "Noto Looped Lao UI SemiCond", + "font-family": "Noto Looped Lao UI SemiCond", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Looped Lao UI SemiCondensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedLaoUI-SemiCondensed.ttf", + "preferred_family_name": "Noto Looped Lao UI", + "preferred_subfamily_name": "SemiCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedLaoUI-SemiCondensedBlack.ttf||44840:1655828711.0": { + "family_name": "Noto Looped Lao UI SmCd Blk", + "font-family": "Noto Looped Lao UI SmCd Blk", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Looped Lao UI SemiCondensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedLaoUI-SemiCondensedBlack.ttf", + "preferred_family_name": "Noto Looped Lao UI", + "preferred_subfamily_name": "SemiCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedLaoUI-SemiCondensedBold.ttf||43488:1655828711.0": { + "family_name": "Noto Looped Lao UI SmCd Bold", + "font-family": "Noto Looped Lao UI SmCd Bold", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Looped Lao UI SemiCondensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedLaoUI-SemiCondensedBold.ttf", + "preferred_family_name": "Noto Looped Lao UI", + "preferred_subfamily_name": "SemiCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedLaoUI-SemiCondensedExtraBold.ttf||43968:1655828711.0": { + "family_name": "Noto Looped Lao UI SmCd ExBd", + "font-family": "Noto Looped Lao UI SmCd ExBd", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Looped Lao UI SemiCondensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedLaoUI-SemiCondensedExtraBold.ttf", + "preferred_family_name": "Noto Looped Lao UI", + "preferred_subfamily_name": "SemiCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedLaoUI-SemiCondensedExtraLight.ttf||42028:1655828711.0": { + "family_name": "Noto Looped Lao UI SmCd ExtLt", + "font-family": "Noto Looped Lao UI SmCd ExtLt", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Looped Lao UI SemiCondensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedLaoUI-SemiCondensedExtraLight.ttf", + "preferred_family_name": "Noto Looped Lao UI", + "preferred_subfamily_name": "SemiCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedLaoUI-SemiCondensedLight.ttf||42224:1655828711.0": { + "family_name": "Noto Looped Lao UI SmCd Lt", + "font-family": "Noto Looped Lao UI SmCd Lt", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Looped Lao UI SemiCondensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedLaoUI-SemiCondensedLight.ttf", + "preferred_family_name": "Noto Looped Lao UI", + "preferred_subfamily_name": "SemiCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedLaoUI-SemiCondensedMedium.ttf||43228:1655828711.0": { + "family_name": "Noto Looped Lao UI SmCd Med", + "font-family": "Noto Looped Lao UI SmCd Med", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Looped Lao UI SemiCondensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedLaoUI-SemiCondensedMedium.ttf", + "preferred_family_name": "Noto Looped Lao UI", + "preferred_subfamily_name": "SemiCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedLaoUI-SemiCondensedSemiBold.ttf||44292:1655828711.0": { + "family_name": "Noto Looped Lao UI SmCd SmBd", + "font-family": "Noto Looped Lao UI SmCd SmBd", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Looped Lao UI SemiCondensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedLaoUI-SemiCondensedSemiBold.ttf", + "preferred_family_name": "Noto Looped Lao UI", + "preferred_subfamily_name": "SemiCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedLaoUI-SemiCondensedThin.ttf||41560:1655828711.0": { + "family_name": "Noto Looped Lao UI SmCd Thin", + "font-family": "Noto Looped Lao UI SmCd Thin", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Looped Lao UI SemiCondensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedLaoUI-SemiCondensedThin.ttf", + "preferred_family_name": "Noto Looped Lao UI", + "preferred_subfamily_name": "SemiCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedLaoUI-Thin.ttf||41748:1655828711.0": { + "family_name": "Noto Looped Lao UI Thin", + "font-family": "Noto Looped Lao UI Thin", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Looped Lao UI Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedLaoUI-Thin.ttf", + "preferred_family_name": "Noto Looped Lao UI", + "preferred_subfamily_name": "Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedThai-Black.ttf||70376:1655828711.0": { + "family_name": "Noto Looped Thai Black", + "font-family": "Noto Looped Thai Black", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Looped Thai Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedThai-Black.ttf", + "preferred_family_name": "Noto Looped Thai", + "preferred_subfamily_name": "Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedThai-Bold.ttf||71532:1655828711.0": { + "family_name": "Noto Looped Thai Bold", + "font-family": "Noto Looped Thai Bold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Looped Thai Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedThai-Bold.ttf", + "preferred_family_name": "Noto Looped Thai", + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedThai-Condensed.ttf||67892:1655828711.0": { + "family_name": "Noto Looped Thai Condensed", + "font-family": "Noto Looped Thai Condensed", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Looped Thai Condensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedThai-Condensed.ttf", + "preferred_family_name": "Noto Looped Thai", + "preferred_subfamily_name": "Condensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedThai-CondensedBlack.ttf||68964:1655828711.0": { + "family_name": "Noto Looped Thai Cond Blk", + "font-family": "Noto Looped Thai Cond Blk", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Looped Thai Condensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedThai-CondensedBlack.ttf", + "preferred_family_name": "Noto Looped Thai", + "preferred_subfamily_name": "Condensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedThai-CondensedBold.ttf||69604:1655828711.0": { + "family_name": "Noto Looped Thai Cond Bold", + "font-family": "Noto Looped Thai Cond Bold", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Looped Thai Condensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedThai-CondensedBold.ttf", + "preferred_family_name": "Noto Looped Thai", + "preferred_subfamily_name": "Condensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedThai-CondensedExtraBold.ttf||67516:1655828711.0": { + "family_name": "Noto Looped Thai Cond ExBd", + "font-family": "Noto Looped Thai Cond ExBd", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Looped Thai Condensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedThai-CondensedExtraBold.ttf", + "preferred_family_name": "Noto Looped Thai", + "preferred_subfamily_name": "Condensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedThai-CondensedExtraLight.ttf||68328:1655828711.0": { + "family_name": "Noto Looped Thai Cond ExLt", + "font-family": "Noto Looped Thai Cond ExLt", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Looped Thai Condensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedThai-CondensedExtraLight.ttf", + "preferred_family_name": "Noto Looped Thai", + "preferred_subfamily_name": "Condensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedThai-CondensedLight.ttf||65488:1655828711.0": { + "family_name": "Noto Looped Thai Cond Lt", + "font-family": "Noto Looped Thai Cond Lt", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Looped Thai Condensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedThai-CondensedLight.ttf", + "preferred_family_name": "Noto Looped Thai", + "preferred_subfamily_name": "Condensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedThai-CondensedMedium.ttf||68608:1655828711.0": { + "family_name": "Noto Looped Thai Cond Med", + "font-family": "Noto Looped Thai Cond Med", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Looped Thai Condensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedThai-CondensedMedium.ttf", + "preferred_family_name": "Noto Looped Thai", + "preferred_subfamily_name": "Condensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedThai-CondensedSemiBold.ttf||69184:1655828711.0": { + "family_name": "Noto Looped Thai Cond SmBd", + "font-family": "Noto Looped Thai Cond SmBd", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Looped Thai Condensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedThai-CondensedSemiBold.ttf", + "preferred_family_name": "Noto Looped Thai", + "preferred_subfamily_name": "Condensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedThai-CondensedThin.ttf||62536:1655828711.0": { + "family_name": "Noto Looped Thai Cond Thin", + "font-family": "Noto Looped Thai Cond Thin", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Looped Thai Condensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedThai-CondensedThin.ttf", + "preferred_family_name": "Noto Looped Thai", + "preferred_subfamily_name": "Condensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedThai-ExtraBold.ttf||69076:1655828711.0": { + "family_name": "Noto Looped Thai ExtraBold", + "font-family": "Noto Looped Thai ExtraBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Looped Thai Extrabold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedThai-ExtraBold.ttf", + "preferred_family_name": "Noto Looped Thai", + "preferred_subfamily_name": "Extrabold", + "subfamily_name": "Regular", + "weight": 800, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedThai-ExtraCondensed.ttf||67216:1655828711.0": { + "family_name": "Noto Looped Thai ExtraCond", + "font-family": "Noto Looped Thai ExtraCond", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Looped Thai ExtraCondensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedThai-ExtraCondensed.ttf", + "preferred_family_name": "Noto Looped Thai", + "preferred_subfamily_name": "ExtraCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedThai-ExtraCondensedBlack.ttf||68276:1655828711.0": { + "family_name": "Noto Looped Thai ExCd Blk", + "font-family": "Noto Looped Thai ExCd Blk", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Looped Thai ExtraCondensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedThai-ExtraCondensedBlack.ttf", + "preferred_family_name": "Noto Looped Thai", + "preferred_subfamily_name": "ExtraCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedThai-ExtraCondensedBold.ttf||69128:1655828711.0": { + "family_name": "Noto Looped Thai ExCd Bold", + "font-family": "Noto Looped Thai ExCd Bold", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Looped Thai ExtraCondensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedThai-ExtraCondensedBold.ttf", + "preferred_family_name": "Noto Looped Thai", + "preferred_subfamily_name": "ExtraCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedThai-ExtraCondensedExtraBold.ttf||68020:1655828711.0": { + "family_name": "Noto Looped Thai ExCd ExBd", + "font-family": "Noto Looped Thai ExCd ExBd", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Looped Thai ExtraCondensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedThai-ExtraCondensedExtraBold.ttf", + "preferred_family_name": "Noto Looped Thai", + "preferred_subfamily_name": "ExtraCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedThai-ExtraCondensedExtraLight.ttf||67328:1655828711.0": { + "family_name": "Noto Looped Thai ExCd ExLt", + "font-family": "Noto Looped Thai ExCd ExLt", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Looped Thai ExtraCondensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedThai-ExtraCondensedExtraLight.ttf", + "preferred_family_name": "Noto Looped Thai", + "preferred_subfamily_name": "ExtraCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedThai-ExtraCondensedLight.ttf||64888:1655828711.0": { + "family_name": "Noto Looped Thai ExCd Lt", + "font-family": "Noto Looped Thai ExCd Lt", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Looped Thai ExtraCondensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedThai-ExtraCondensedLight.ttf", + "preferred_family_name": "Noto Looped Thai", + "preferred_subfamily_name": "ExtraCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedThai-ExtraCondensedMedium.ttf||68864:1655828711.0": { + "family_name": "Noto Looped Thai ExCd Med", + "font-family": "Noto Looped Thai ExCd Med", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Looped Thai ExtraCondensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedThai-ExtraCondensedMedium.ttf", + "preferred_family_name": "Noto Looped Thai", + "preferred_subfamily_name": "ExtraCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedThai-ExtraCondensedSemiBold.ttf||69176:1655828711.0": { + "family_name": "Noto Looped Thai ExCd SmBd", + "font-family": "Noto Looped Thai ExCd SmBd", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Looped Thai ExtraCondensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedThai-ExtraCondensedSemiBold.ttf", + "preferred_family_name": "Noto Looped Thai", + "preferred_subfamily_name": "ExtraCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedThai-ExtraCondensedThin.ttf||61924:1655828711.0": { + "family_name": "Noto Looped Thai ExCd Thin", + "font-family": "Noto Looped Thai ExCd Thin", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Looped Thai ExtraCondensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedThai-ExtraCondensedThin.ttf", + "preferred_family_name": "Noto Looped Thai", + "preferred_subfamily_name": "ExtraCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedThai-ExtraLight.ttf||74332:1655828711.0": { + "family_name": "Noto Looped Thai ExtLight", + "font-family": "Noto Looped Thai ExtLight", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Looped Thai ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedThai-ExtraLight.ttf", + "preferred_family_name": "Noto Looped Thai", + "preferred_subfamily_name": "ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedThai-Light.ttf||66112:1655828711.0": { + "family_name": "Noto Looped Thai Light", + "font-family": "Noto Looped Thai Light", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Looped Thai Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedThai-Light.ttf", + "preferred_family_name": "Noto Looped Thai", + "preferred_subfamily_name": "Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedThai-Medium.ttf||68456:1655828711.0": { + "family_name": "Noto Looped Thai Medium", + "font-family": "Noto Looped Thai Medium", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Looped Thai Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedThai-Medium.ttf", + "preferred_family_name": "Noto Looped Thai", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedThai-Regular.ttf||66500:1655828711.0": { + "family_name": "Noto Looped Thai Regular", + "font-family": "Noto Looped Thai Regular", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Looped Thai Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedThai-Regular.ttf", + "preferred_family_name": "Noto Looped Thai", + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedThai-SemiBold.ttf||69480:1655828711.0": { + "family_name": "Noto Looped Thai SemiBold", + "font-family": "Noto Looped Thai SemiBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Looped Thai SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedThai-SemiBold.ttf", + "preferred_family_name": "Noto Looped Thai", + "preferred_subfamily_name": "SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedThai-SemiCondensed.ttf||67776:1655828711.0": { + "family_name": "Noto Looped Thai SemiCond", + "font-family": "Noto Looped Thai SemiCond", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Looped Thai SemiCondensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedThai-SemiCondensed.ttf", + "preferred_family_name": "Noto Looped Thai", + "preferred_subfamily_name": "SemiCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedThai-SemiCondensedBlack.ttf||70260:1655828711.0": { + "family_name": "Noto Looped Thai SmCd Blk", + "font-family": "Noto Looped Thai SmCd Blk", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Looped Thai SemiCondensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedThai-SemiCondensedBlack.ttf", + "preferred_family_name": "Noto Looped Thai", + "preferred_subfamily_name": "SemiCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedThai-SemiCondensedBold.ttf||68780:1655828711.0": { + "family_name": "Noto Looped Thai SmCd Bold", + "font-family": "Noto Looped Thai SmCd Bold", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Looped Thai SemiCondensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedThai-SemiCondensedBold.ttf", + "preferred_family_name": "Noto Looped Thai", + "preferred_subfamily_name": "SemiCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedThai-SemiCondensedExtraBold.ttf||68780:1655828711.0": { + "family_name": "Noto Looped Thai SmCd ExBd", + "font-family": "Noto Looped Thai SmCd ExBd", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Looped Thai SemiCondensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedThai-SemiCondensedExtraBold.ttf", + "preferred_family_name": "Noto Looped Thai", + "preferred_subfamily_name": "SemiCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedThai-SemiCondensedExtraLight.ttf||68272:1655828711.0": { + "family_name": "Noto Looped Thai SmCd ExLt", + "font-family": "Noto Looped Thai SmCd ExLt", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Looped Thai SemiCondensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedThai-SemiCondensedExtraLight.ttf", + "preferred_family_name": "Noto Looped Thai", + "preferred_subfamily_name": "SemiCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedThai-SemiCondensedLight.ttf||65908:1655828711.0": { + "family_name": "Noto Looped Thai SmCd Lt", + "font-family": "Noto Looped Thai SmCd Lt", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Looped Thai SemiCondensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedThai-SemiCondensedLight.ttf", + "preferred_family_name": "Noto Looped Thai", + "preferred_subfamily_name": "SemiCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedThai-SemiCondensedMedium.ttf||68092:1655828711.0": { + "family_name": "Noto Looped Thai SmCd Med", + "font-family": "Noto Looped Thai SmCd Med", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Looped Thai SemiCondensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedThai-SemiCondensedMedium.ttf", + "preferred_family_name": "Noto Looped Thai", + "preferred_subfamily_name": "SemiCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedThai-SemiCondensedSemiBold.ttf||68688:1655828711.0": { + "family_name": "Noto Looped Thai SmCd SmBd", + "font-family": "Noto Looped Thai SmCd SmBd", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Looped Thai SemiCondensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedThai-SemiCondensedSemiBold.ttf", + "preferred_family_name": "Noto Looped Thai", + "preferred_subfamily_name": "SemiCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedThai-SemiCondensedThin.ttf||62760:1655828711.0": { + "family_name": "Noto Looped Thai SmCd Thin", + "font-family": "Noto Looped Thai SmCd Thin", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Looped Thai SemiCondensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedThai-SemiCondensedThin.ttf", + "preferred_family_name": "Noto Looped Thai", + "preferred_subfamily_name": "SemiCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedThai-Thin.ttf||63288:1655828711.0": { + "family_name": "Noto Looped Thai Thin", + "font-family": "Noto Looped Thai Thin", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Looped Thai Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedThai-Thin.ttf", + "preferred_family_name": "Noto Looped Thai", + "preferred_subfamily_name": "Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedThaiUI-Black.ttf||52092:1655828711.0": { + "family_name": "Noto Looped Thai UI Black", + "font-family": "Noto Looped Thai UI Black", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Looped Thai UI Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedThaiUI-Black.ttf", + "preferred_family_name": "Noto Looped Thai UI", + "preferred_subfamily_name": "Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedThaiUI-Bold.ttf||49888:1655828711.0": { + "family_name": "Noto Looped Thai UI Bold", + "font-family": "Noto Looped Thai UI Bold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Looped Thai UI Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedThaiUI-Bold.ttf", + "preferred_family_name": "Noto Looped Thai UI", + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedThaiUI-Condensed.ttf||50704:1655828711.0": { + "family_name": "Noto Looped Thai UI Condensed", + "font-family": "Noto Looped Thai UI Condensed", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Looped Thai UI Condensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedThaiUI-Condensed.ttf", + "preferred_family_name": "Noto Looped Thai UI", + "preferred_subfamily_name": "Condensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedThaiUI-CondensedBlack.ttf||50352:1655828711.0": { + "family_name": "Noto Looped Thai UI Cond Blk", + "font-family": "Noto Looped Thai UI Cond Blk", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Looped Thai UI Condensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedThaiUI-CondensedBlack.ttf", + "preferred_family_name": "Noto Looped Thai UI", + "preferred_subfamily_name": "Condensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedThaiUI-CondensedBold.ttf||50264:1655828711.0": { + "family_name": "Noto Looped Thai UI Cond Bold", + "font-family": "Noto Looped Thai UI Cond Bold", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Looped Thai UI Condensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedThaiUI-CondensedBold.ttf", + "preferred_family_name": "Noto Looped Thai UI", + "preferred_subfamily_name": "Condensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedThaiUI-CondensedExtraBold.ttf||49272:1655828711.0": { + "family_name": "Noto Looped Thai UI Cond ExBd", + "font-family": "Noto Looped Thai UI Cond ExBd", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Looped Thai UI Condensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedThaiUI-CondensedExtraBold.ttf", + "preferred_family_name": "Noto Looped Thai UI", + "preferred_subfamily_name": "Condensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedThaiUI-CondensedExtraLight.ttf||46804:1655828711.0": { + "family_name": "Noto Looped Thai UI Cond ExLt", + "font-family": "Noto Looped Thai UI Cond ExLt", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Looped Thai UI Condensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedThaiUI-CondensedExtraLight.ttf", + "preferred_family_name": "Noto Looped Thai UI", + "preferred_subfamily_name": "Condensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedThaiUI-CondensedLight.ttf||48040:1655828711.0": { + "family_name": "Noto Looped Thai UI Cond Lt", + "font-family": "Noto Looped Thai UI Cond Lt", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Looped Thai UI Condensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedThaiUI-CondensedLight.ttf", + "preferred_family_name": "Noto Looped Thai UI", + "preferred_subfamily_name": "Condensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedThaiUI-CondensedMedium.ttf||51136:1655828711.0": { + "family_name": "Noto Looped Thai UI Cond Med", + "font-family": "Noto Looped Thai UI Cond Med", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Looped Thai UI Condensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedThaiUI-CondensedMedium.ttf", + "preferred_family_name": "Noto Looped Thai UI", + "preferred_subfamily_name": "Condensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedThaiUI-CondensedSemiBold.ttf||50044:1655828711.0": { + "family_name": "Noto Looped Thai UI Cond SmBd", + "font-family": "Noto Looped Thai UI Cond SmBd", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Looped Thai UI Condensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedThaiUI-CondensedSemiBold.ttf", + "preferred_family_name": "Noto Looped Thai UI", + "preferred_subfamily_name": "Condensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedThaiUI-CondensedThin.ttf||45288:1655828711.0": { + "family_name": "Noto Looped Thai UI Cond Thin", + "font-family": "Noto Looped Thai UI Cond Thin", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Looped Thai UI Condensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedThaiUI-CondensedThin.ttf", + "preferred_family_name": "Noto Looped Thai UI", + "preferred_subfamily_name": "Condensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedThaiUI-ExtraBold.ttf||50784:1655828711.0": { + "family_name": "Noto Looped Thai UI ExtraBold", + "font-family": "Noto Looped Thai UI ExtraBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Looped Thai UI Extrabold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedThaiUI-ExtraBold.ttf", + "preferred_family_name": "Noto Looped Thai UI", + "preferred_subfamily_name": "Extrabold", + "subfamily_name": "Regular", + "weight": 800, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedThaiUI-ExtraCondensed.ttf||49932:1655828711.0": { + "family_name": "Noto Looped Thai UI ExtraCond", + "font-family": "Noto Looped Thai UI ExtraCond", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Looped Thai UI ExtraCondensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedThaiUI-ExtraCondensed.ttf", + "preferred_family_name": "Noto Looped Thai UI", + "preferred_subfamily_name": "ExtraCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedThaiUI-ExtraCondensedBlack.ttf||50552:1655828711.0": { + "family_name": "Noto Looped Thai UI ExCd Blk", + "font-family": "Noto Looped Thai UI ExCd Blk", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Looped Thai UI ExtraCondensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedThaiUI-ExtraCondensedBlack.ttf", + "preferred_family_name": "Noto Looped Thai UI", + "preferred_subfamily_name": "ExtraCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedThaiUI-ExtraCondensedBold.ttf||49736:1655828711.0": { + "family_name": "Noto Looped Thai UI ExCd Bold", + "font-family": "Noto Looped Thai UI ExCd Bold", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Looped Thai UI ExtraCondensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedThaiUI-ExtraCondensedBold.ttf", + "preferred_family_name": "Noto Looped Thai UI", + "preferred_subfamily_name": "ExtraCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedThaiUI-ExtraCondensedExtraBold.ttf||49660:1655828711.0": { + "family_name": "Noto Looped Thai UI ExCd ExBd", + "font-family": "Noto Looped Thai UI ExCd ExBd", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Looped Thai UI ExtraCondensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedThaiUI-ExtraCondensedExtraBold.ttf", + "preferred_family_name": "Noto Looped Thai UI", + "preferred_subfamily_name": "ExtraCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedThaiUI-ExtraCondensedExtraLight.ttf||46696:1655828711.0": { + "family_name": "Noto Looped Thai UI ExCd ExLt", + "font-family": "Noto Looped Thai UI ExCd ExLt", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Looped Thai UI ExtraCondensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedThaiUI-ExtraCondensedExtraLight.ttf", + "preferred_family_name": "Noto Looped Thai UI", + "preferred_subfamily_name": "ExtraCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedThaiUI-ExtraCondensedLight.ttf||47704:1655828711.0": { + "family_name": "Noto Looped Thai UI ExCd Lt", + "font-family": "Noto Looped Thai UI ExCd Lt", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Looped Thai UI ExtraCondensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedThaiUI-ExtraCondensedLight.ttf", + "preferred_family_name": "Noto Looped Thai UI", + "preferred_subfamily_name": "ExtraCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedThaiUI-ExtraCondensedMedium.ttf||50932:1655828711.0": { + "family_name": "Noto Looped Thai UI ExCd Med", + "font-family": "Noto Looped Thai UI ExCd Med", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Looped Thai UI ExtraCondensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedThaiUI-ExtraCondensedMedium.ttf", + "preferred_family_name": "Noto Looped Thai UI", + "preferred_subfamily_name": "ExtraCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedThaiUI-ExtraCondensedSemiBold.ttf||50648:1655828711.0": { + "family_name": "Noto Looped Thai UI ExCd SmBd", + "font-family": "Noto Looped Thai UI ExCd SmBd", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Looped Thai UI ExtraCondensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedThaiUI-ExtraCondensedSemiBold.ttf", + "preferred_family_name": "Noto Looped Thai UI", + "preferred_subfamily_name": "ExtraCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedThaiUI-ExtraCondensedThin.ttf||45008:1655828711.0": { + "family_name": "Noto Looped Thai UI ExCd Thin", + "font-family": "Noto Looped Thai UI ExCd Thin", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Looped Thai UI ExtraCondensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedThaiUI-ExtraCondensedThin.ttf", + "preferred_family_name": "Noto Looped Thai UI", + "preferred_subfamily_name": "ExtraCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedThaiUI-ExtraLight.ttf||47524:1655828711.0": { + "family_name": "Noto Looped Thai UI ExtLight", + "font-family": "Noto Looped Thai UI ExtLight", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Looped Thai UI ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedThaiUI-ExtraLight.ttf", + "preferred_family_name": "Noto Looped Thai UI", + "preferred_subfamily_name": "ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedThaiUI-Light.ttf||49792:1655828711.0": { + "family_name": "Noto Looped Thai UI Light", + "font-family": "Noto Looped Thai UI Light", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Looped Thai UI Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedThaiUI-Light.ttf", + "preferred_family_name": "Noto Looped Thai UI", + "preferred_subfamily_name": "Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedThaiUI-Medium.ttf||50164:1655828711.0": { + "family_name": "Noto Looped Thai UI Medium", + "font-family": "Noto Looped Thai UI Medium", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Looped Thai UI Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedThaiUI-Medium.ttf", + "preferred_family_name": "Noto Looped Thai UI", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedThaiUI-Regular.ttf||48864:1655828711.0": { + "family_name": "Noto Looped Thai UI Regular", + "font-family": "Noto Looped Thai UI Regular", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Looped Thai UI Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedThaiUI-Regular.ttf", + "preferred_family_name": "Noto Looped Thai UI", + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedThaiUI-SemiBold.ttf||50156:1655828711.0": { + "family_name": "Noto Looped Thai UI SemiBold", + "font-family": "Noto Looped Thai UI SemiBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Looped Thai UI SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedThaiUI-SemiBold.ttf", + "preferred_family_name": "Noto Looped Thai UI", + "preferred_subfamily_name": "SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedThaiUI-SemiCondensed.ttf||49948:1655828711.0": { + "family_name": "Noto Looped Thai UI SemiCond", + "font-family": "Noto Looped Thai UI SemiCond", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Looped Thai UI SemiCondensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedThaiUI-SemiCondensed.ttf", + "preferred_family_name": "Noto Looped Thai UI", + "preferred_subfamily_name": "SemiCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedThaiUI-SemiCondensedBlack.ttf||51816:1655828711.0": { + "family_name": "Noto Looped Thai UI SmCd Blk", + "font-family": "Noto Looped Thai UI SmCd Blk", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Looped Thai UI SemiCondensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedThaiUI-SemiCondensedBlack.ttf", + "preferred_family_name": "Noto Looped Thai UI", + "preferred_subfamily_name": "SemiCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedThaiUI-SemiCondensedBold.ttf||50224:1655828711.0": { + "family_name": "Noto Looped Thai UI SmCd Bold", + "font-family": "Noto Looped Thai UI SmCd Bold", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Looped Thai UI SemiCondensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedThaiUI-SemiCondensedBold.ttf", + "preferred_family_name": "Noto Looped Thai UI", + "preferred_subfamily_name": "SemiCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedThaiUI-SemiCondensedExtraBold.ttf||50380:1655828711.0": { + "family_name": "Noto Looped Thai UI SmCd ExBd", + "font-family": "Noto Looped Thai UI SmCd ExBd", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Looped Thai UI SemiCondensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedThaiUI-SemiCondensedExtraBold.ttf", + "preferred_family_name": "Noto Looped Thai UI", + "preferred_subfamily_name": "SemiCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedThaiUI-SemiCondensedExtraLight.ttf||47284:1655828711.0": { + "family_name": "Noto Looped Thai UI SmCd ExLt", + "font-family": "Noto Looped Thai UI SmCd ExLt", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Looped Thai UI SemiCondensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedThaiUI-SemiCondensedExtraLight.ttf", + "preferred_family_name": "Noto Looped Thai UI", + "preferred_subfamily_name": "SemiCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedThaiUI-SemiCondensedLight.ttf||48460:1655828711.0": { + "family_name": "Noto Looped Thai UI SmCd Lt", + "font-family": "Noto Looped Thai UI SmCd Lt", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Looped Thai UI SemiCondensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedThaiUI-SemiCondensedLight.ttf", + "preferred_family_name": "Noto Looped Thai UI", + "preferred_subfamily_name": "SemiCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedThaiUI-SemiCondensedMedium.ttf||50896:1655828711.0": { + "family_name": "Noto Looped Thai UI SmCd Med", + "font-family": "Noto Looped Thai UI SmCd Med", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Looped Thai UI SemiCondensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedThaiUI-SemiCondensedMedium.ttf", + "preferred_family_name": "Noto Looped Thai UI", + "preferred_subfamily_name": "SemiCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedThaiUI-SemiCondensedSemiBold.ttf||50828:1655828711.0": { + "family_name": "Noto Looped Thai UI SmCd SmBd", + "font-family": "Noto Looped Thai UI SmCd SmBd", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Looped Thai UI SemiCondensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedThaiUI-SemiCondensedSemiBold.ttf", + "preferred_family_name": "Noto Looped Thai UI", + "preferred_subfamily_name": "SemiCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedThaiUI-SemiCondensedThin.ttf||45460:1655828711.0": { + "family_name": "Noto Looped Thai UI SmCd Thin", + "font-family": "Noto Looped Thai UI SmCd Thin", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Looped Thai UI SemiCondensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedThaiUI-SemiCondensedThin.ttf", + "preferred_family_name": "Noto Looped Thai UI", + "preferred_subfamily_name": "SemiCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoLoopedThaiUI-Thin.ttf||45936:1655828711.0": { + "family_name": "Noto Looped Thai UI Thin", + "font-family": "Noto Looped Thai UI Thin", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Looped Thai UI Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoLoopedThaiUI-Thin.ttf", + "preferred_family_name": "Noto Looped Thai UI", + "preferred_subfamily_name": "Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoMusic-Regular.ttf||81392:1655828711.0": { + "family_name": "Noto Music", + "font-family": "Noto Music", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Music Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoMusic-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoNaskhArabic-Bold.ttf||184164:1655828711.0": { + "family_name": "Noto Naskh Arabic", + "font-family": "Noto Naskh Arabic", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Naskh Arabic Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoNaskhArabic-Bold.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoNaskhArabic-Medium.ttf||182496:1655828711.0": { + "family_name": "Noto Naskh Arabic Medium", + "font-family": "Noto Naskh Arabic Medium", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Naskh Arabic Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoNaskhArabic-Medium.ttf", + "preferred_family_name": "Noto Naskh Arabic", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoNaskhArabic-Regular.ttf||178388:1655828711.0": { + "family_name": "Noto Naskh Arabic", + "font-family": "Noto Naskh Arabic", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Naskh Arabic Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoNaskhArabic-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoNaskhArabic-SemiBold.ttf||184376:1655828711.0": { + "family_name": "Noto Naskh Arabic Semi Bold", + "font-family": "Noto Naskh Arabic Semi Bold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Naskh Arabic Semi Bold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoNaskhArabic-SemiBold.ttf", + "preferred_family_name": "Noto Naskh Arabic", + "preferred_subfamily_name": "Semi Bold", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoNaskhArabicUI-Bold.ttf||212712:1655828711.0": { + "family_name": "Noto Naskh Arabic UI", + "font-family": "Noto Naskh Arabic UI", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Naskh Arabic UI Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoNaskhArabicUI-Bold.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoNaskhArabicUI-Medium.ttf||212240:1655828711.0": { + "family_name": "Noto Naskh Arabic UI Medium", + "font-family": "Noto Naskh Arabic UI Medium", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Naskh Arabic UI Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoNaskhArabicUI-Medium.ttf", + "preferred_family_name": "Noto Naskh Arabic UI", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoNaskhArabicUI-Regular.ttf||204060:1655828711.0": { + "family_name": "Noto Naskh Arabic UI", + "font-family": "Noto Naskh Arabic UI", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Naskh Arabic UI Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoNaskhArabicUI-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoNaskhArabicUI-SemiBold.ttf||213200:1655828711.0": { + "family_name": "Noto Naskh Arabic UI Semi Bold", + "font-family": "Noto Naskh Arabic UI Semi Bold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Naskh Arabic UI Semi Bold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoNaskhArabicUI-SemiBold.ttf", + "preferred_family_name": "Noto Naskh Arabic UI", + "preferred_subfamily_name": "Semi Bold", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoNastaliqUrdu-Bold.ttf||1173220:1655828711.0": { + "family_name": "Noto Nastaliq Urdu", + "font-family": "Noto Nastaliq Urdu", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Nastaliq Urdu Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoNastaliqUrdu-Bold.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoNastaliqUrdu-Regular.ttf||1171972:1655828711.0": { + "family_name": "Noto Nastaliq Urdu", + "font-family": "Noto Nastaliq Urdu", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Nastaliq Urdu Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoNastaliqUrdu-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoRashiHebrew-Black.ttf||28092:1655828711.0": { + "family_name": "Noto Rashi Hebrew Blk", + "font-family": "Noto Rashi Hebrew Blk", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Rashi Hebrew Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 10, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoRashiHebrew-Black.ttf", + "preferred_family_name": "Noto Rashi Hebrew", + "preferred_subfamily_name": "Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoRashiHebrew-Bold.ttf||28048:1655828711.0": { + "family_name": "Noto Rashi Hebrew", + "font-family": "Noto Rashi Hebrew", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Rashi Hebrew Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 8, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoRashiHebrew-Bold.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoRashiHebrew-ExtraBold.ttf||28672:1655828711.0": { + "family_name": "Noto Rashi Hebrew ExtBd", + "font-family": "Noto Rashi Hebrew ExtBd", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Rashi Hebrew ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 9, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoRashiHebrew-ExtraBold.ttf", + "preferred_family_name": "Noto Rashi Hebrew", + "preferred_subfamily_name": "ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoRashiHebrew-ExtraLight.ttf||26328:1655828711.0": { + "family_name": "Noto Rashi Hebrew ExtLt", + "font-family": "Noto Rashi Hebrew ExtLt", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Rashi Hebrew ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 3, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoRashiHebrew-ExtraLight.ttf", + "preferred_family_name": "Noto Rashi Hebrew", + "preferred_subfamily_name": "ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoRashiHebrew-Light.ttf||27204:1655828711.0": { + "family_name": "Noto Rashi Hebrew Light", + "font-family": "Noto Rashi Hebrew Light", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Rashi Hebrew Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 4, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoRashiHebrew-Light.ttf", + "preferred_family_name": "Noto Rashi Hebrew", + "preferred_subfamily_name": "Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoRashiHebrew-Medium.ttf||27148:1655828711.0": { + "family_name": "Noto Rashi Hebrew Med", + "font-family": "Noto Rashi Hebrew Med", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Rashi Hebrew Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 6, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoRashiHebrew-Medium.ttf", + "preferred_family_name": "Noto Rashi Hebrew", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoRashiHebrew-Regular.ttf||27216:1655828711.0": { + "family_name": "Noto Rashi Hebrew", + "font-family": "Noto Rashi Hebrew", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Rashi Hebrew Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 5, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoRashiHebrew-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoRashiHebrew-SemiBold.ttf||28116:1655828711.0": { + "family_name": "Noto Rashi Hebrew SemBd", + "font-family": "Noto Rashi Hebrew SemBd", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Rashi Hebrew SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 7, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoRashiHebrew-SemiBold.ttf", + "preferred_family_name": "Noto Rashi Hebrew", + "preferred_subfamily_name": "SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoRashiHebrew-Thin.ttf||26072:1655828711.0": { + "family_name": "Noto Rashi Hebrew Thin", + "font-family": "Noto Rashi Hebrew Thin", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Rashi Hebrew Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 2, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoRashiHebrew-Thin.ttf", + "preferred_family_name": "Noto Rashi Hebrew", + "preferred_subfamily_name": "Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSans-Black.ttf||591488:1655828711.0": { + "family_name": "Noto Sans Black", + "font-family": "Noto Sans Black", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSans-Black.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSans-BlackItalic.ttf||567480:1655828711.0": { + "family_name": "Noto Sans Black", + "font-family": "Noto Sans Black", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Black Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 2, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSans-BlackItalic.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "Black Italic", + "subfamily_name": "Italic", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSans-Bold.ttf||575740:1655828711.0": { + "family_name": "Noto Sans", + "font-family": "Noto Sans", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSans-Bold.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSans-BoldItalic.ttf||555292:1655828711.0": { + "family_name": "Noto Sans", + "font-family": "Noto Sans", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Bold Italic", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 2, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSans-BoldItalic.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSans-Condensed.ttf||562276:1655828711.0": { + "family_name": "Noto Sans Condensed", + "font-family": "Noto Sans Condensed", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Condensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSans-Condensed.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "Condensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSans-CondensedBlack.ttf||584760:1655828711.0": { + "family_name": "Noto Sans Condensed Black", + "font-family": "Noto Sans Condensed Black", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Condensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSans-CondensedBlack.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "Condensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSans-CondensedBlackItalic.ttf||565492:1655828711.0": { + "family_name": "Noto Sans Condensed Black", + "font-family": "Noto Sans Condensed Black", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Condensed Black Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 6, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSans-CondensedBlackItalic.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "Condensed Black Italic", + "subfamily_name": "Italic", + "weight": 900, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSans-CondensedBold.ttf||574012:1655828711.0": { + "family_name": "Noto Sans Condensed", + "font-family": "Noto Sans Condensed", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Condensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSans-CondensedBold.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "Condensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSans-CondensedBoldItalic.ttf||554584:1655828711.0": { + "family_name": "Noto Sans Condensed", + "font-family": "Noto Sans Condensed", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Condensed Bold Italic", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 6, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSans-CondensedBoldItalic.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "Condensed Bold Italic", + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSans-CondensedExtraBold.ttf||571480:1655828711.0": { + "family_name": "Noto Sans Condensed ExtraBold", + "font-family": "Noto Sans Condensed ExtraBold", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Condensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSans-CondensedExtraBold.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "Condensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSans-CondensedExtraBoldItalic.ttf||556956:1655828711.0": { + "family_name": "Noto Sans Condensed ExtraBold", + "font-family": "Noto Sans Condensed ExtraBold", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Condensed ExtraBold Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 6, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSans-CondensedExtraBoldItalic.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "Condensed ExtraBold Italic", + "subfamily_name": "Italic", + "weight": 800, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSans-CondensedExtraLight.ttf||546364:1655828711.0": { + "family_name": "Noto Sans Condensed ExtraLight", + "font-family": "Noto Sans Condensed ExtraLight", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Condensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSans-CondensedExtraLight.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "Condensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSans-CondensedExtraLightItalic.ttf||533556:1655828711.0": { + "family_name": "Noto Sans Condensed ExtraLight", + "font-family": "Noto Sans Condensed ExtraLight", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Condensed ExtraLight Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 6, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSans-CondensedExtraLightItalic.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "Condensed ExtraLight Italic", + "subfamily_name": "Italic", + "weight": 200, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSans-CondensedItalic.ttf||552792:1655828711.0": { + "family_name": "Noto Sans Condensed", + "font-family": "Noto Sans Condensed", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Condensed Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 6, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSans-CondensedItalic.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "Condensed Italic", + "subfamily_name": "Italic", + "weight": 400, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSans-CondensedLight.ttf||555580:1655828711.0": { + "family_name": "Noto Sans Condensed Light", + "font-family": "Noto Sans Condensed Light", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Condensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSans-CondensedLight.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "Condensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSans-CondensedLightItalic.ttf||540088:1655828711.0": { + "family_name": "Noto Sans Condensed Light", + "font-family": "Noto Sans Condensed Light", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Condensed Light Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 6, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSans-CondensedLightItalic.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "Condensed Light Italic", + "subfamily_name": "Italic", + "weight": 300, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSans-CondensedMedium.ttf||564428:1655828711.0": { + "family_name": "Noto Sans Condensed Medium", + "font-family": "Noto Sans Condensed Medium", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Condensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSans-CondensedMedium.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "Condensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSans-CondensedMediumItalic.ttf||550592:1655828711.0": { + "family_name": "Noto Sans Condensed Medium", + "font-family": "Noto Sans Condensed Medium", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Condensed Medium Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 6, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSans-CondensedMediumItalic.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "Condensed Medium Italic", + "subfamily_name": "Italic", + "weight": 500, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSans-CondensedSemiBold.ttf||565508:1655828711.0": { + "family_name": "Noto Sans Condensed SemiBold", + "font-family": "Noto Sans Condensed SemiBold", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Condensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSans-CondensedSemiBold.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "Condensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSans-CondensedSemiBoldItalic.ttf||553904:1655828711.0": { + "family_name": "Noto Sans Condensed SemiBold", + "font-family": "Noto Sans Condensed SemiBold", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Condensed SemiBold Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 6, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSans-CondensedSemiBoldItalic.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "Condensed SemiBold Italic", + "subfamily_name": "Italic", + "weight": 600, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSans-CondensedThin.ttf||546888:1655828711.0": { + "family_name": "Noto Sans Condensed Thin", + "font-family": "Noto Sans Condensed Thin", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Condensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSans-CondensedThin.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "Condensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSans-CondensedThinItalic.ttf||534416:1655828711.0": { + "family_name": "Noto Sans Condensed Thin", + "font-family": "Noto Sans Condensed Thin", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Condensed Thin Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 6, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSans-CondensedThinItalic.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "Condensed Thin Italic", + "subfamily_name": "Italic", + "weight": 100, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSans-ExtraBold.ttf||577300:1655828711.0": { + "family_name": "Noto Sans ExtraBold", + "font-family": "Noto Sans ExtraBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSans-ExtraBold.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSans-ExtraBoldItalic.ttf||555212:1655828711.0": { + "family_name": "Noto Sans ExtraBold", + "font-family": "Noto Sans ExtraBold", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans ExtraBold Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 2, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSans-ExtraBoldItalic.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "ExtraBold Italic", + "subfamily_name": "Italic", + "weight": 800, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSans-ExtraCondensed.ttf||559232:1655828711.0": { + "family_name": "Noto Sans ExtraCondensed", + "font-family": "Noto Sans ExtraCondensed", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans ExtraCondensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSans-ExtraCondensed.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "ExtraCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSans-ExtraCondensedBlack.ttf||579360:1655828711.0": { + "family_name": "Noto Sans ExtraCondensed Black", + "font-family": "Noto Sans ExtraCondensed Black", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans ExtraCondensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSans-ExtraCondensedBlack.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "ExtraCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSans-ExtraCondensedBlackItalic.ttf||566748:1655828711.0": { + "family_name": "Noto Sans ExtraCondensed Black", + "font-family": "Noto Sans ExtraCondensed Black", + "font-stretch": "extra-condensed", + "font-style": "italic", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans ExtraCondensed Black Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 6, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSans-ExtraCondensedBlackItalic.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "ExtraCondensed Black Italic", + "subfamily_name": "Italic", + "weight": 900, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSans-ExtraCondensedBold.ttf||566216:1655828711.0": { + "family_name": "Noto Sans ExtraCondensed", + "font-family": "Noto Sans ExtraCondensed", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans ExtraCondensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSans-ExtraCondensedBold.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "ExtraCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSans-ExtraCondensedBoldItalic.ttf||553052:1655828711.0": { + "family_name": "Noto Sans ExtraCondensed", + "font-family": "Noto Sans ExtraCondensed", + "font-stretch": "extra-condensed", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans ExtraCondensed Bold Italic", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 6, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSans-ExtraCondensedBoldItalic.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "ExtraCondensed Bold Italic", + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSans-ExtraCondensedExtraBold.ttf||568324:1655828711.0": { + "family_name": "Noto Sans ExtraCondensed ExtraBold", + "font-family": "Noto Sans ExtraCondensed ExtraBold", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans ExtraCondensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSans-ExtraCondensedExtraBold.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "ExtraCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSans-ExtraCondensedExtraBoldItalic.ttf||557644:1655828711.0": { + "family_name": "Noto Sans ExtraCondensed ExtraBold", + "font-family": "Noto Sans ExtraCondensed ExtraBold", + "font-stretch": "extra-condensed", + "font-style": "italic", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans ExtraCondensed ExtraBold Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 6, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSans-ExtraCondensedExtraBoldItalic.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "ExtraCondensed ExtraBold Italic", + "subfamily_name": "Italic", + "weight": 800, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSans-ExtraCondensedExtraLight.ttf||544120:1655828711.0": { + "family_name": "Noto Sans ExtraCondensed ExtraLight", + "font-family": "Noto Sans ExtraCondensed ExtraLight", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans ExtraCondensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSans-ExtraCondensedExtraLight.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "ExtraCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSans-ExtraCondensedExtraLightItalic.ttf||532804:1655828711.0": { + "family_name": "Noto Sans ExtraCondensed ExtraLight", + "font-family": "Noto Sans ExtraCondensed ExtraLight", + "font-stretch": "extra-condensed", + "font-style": "italic", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans ExtraCondensed ExtraLight Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 6, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSans-ExtraCondensedExtraLightItalic.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "ExtraCondensed ExtraLight Italic", + "subfamily_name": "Italic", + "weight": 200, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSans-ExtraCondensedItalic.ttf||549244:1655828711.0": { + "family_name": "Noto Sans ExtraCondensed", + "font-family": "Noto Sans ExtraCondensed", + "font-stretch": "extra-condensed", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans ExtraCondensed Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 6, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSans-ExtraCondensedItalic.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "ExtraCondensed Italic", + "subfamily_name": "Italic", + "weight": 400, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSans-ExtraCondensedLight.ttf||552304:1655828711.0": { + "family_name": "Noto Sans ExtraCondensed Light", + "font-family": "Noto Sans ExtraCondensed Light", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans ExtraCondensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSans-ExtraCondensedLight.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "ExtraCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSans-ExtraCondensedLightItalic.ttf||540040:1655828711.0": { + "family_name": "Noto Sans ExtraCondensed Light", + "font-family": "Noto Sans ExtraCondensed Light", + "font-stretch": "extra-condensed", + "font-style": "italic", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans ExtraCondensed Light Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 6, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSans-ExtraCondensedLightItalic.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "ExtraCondensed Light Italic", + "subfamily_name": "Italic", + "weight": 300, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSans-ExtraCondensedMedium.ttf||558300:1655828711.0": { + "family_name": "Noto Sans ExtraCondensed Medium", + "font-family": "Noto Sans ExtraCondensed Medium", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans ExtraCondensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSans-ExtraCondensedMedium.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "ExtraCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSans-ExtraCondensedMediumItalic.ttf||550180:1655828711.0": { + "family_name": "Noto Sans ExtraCondensed Medium", + "font-family": "Noto Sans ExtraCondensed Medium", + "font-stretch": "extra-condensed", + "font-style": "italic", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans ExtraCondensed Medium Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 6, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSans-ExtraCondensedMediumItalic.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "ExtraCondensed Medium Italic", + "subfamily_name": "Italic", + "weight": 500, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSans-ExtraCondensedSemiBold.ttf||559340:1655828711.0": { + "family_name": "Noto Sans ExtraCondensed SemiBold", + "font-family": "Noto Sans ExtraCondensed SemiBold", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans ExtraCondensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSans-ExtraCondensedSemiBold.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "ExtraCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSans-ExtraCondensedSemiBoldItalic.ttf||551112:1655828711.0": { + "family_name": "Noto Sans ExtraCondensed SemiBold", + "font-family": "Noto Sans ExtraCondensed SemiBold", + "font-stretch": "extra-condensed", + "font-style": "italic", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans ExtraCondensed SemiBold Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 6, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSans-ExtraCondensedSemiBoldItalic.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "ExtraCondensed SemiBold Italic", + "subfamily_name": "Italic", + "weight": 600, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSans-ExtraCondensedThin.ttf||543836:1655828711.0": { + "family_name": "Noto Sans ExtraCondensed Thin", + "font-family": "Noto Sans ExtraCondensed Thin", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans ExtraCondensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSans-ExtraCondensedThin.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "ExtraCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSans-ExtraCondensedThinItalic.ttf||531676:1655828711.0": { + "family_name": "Noto Sans ExtraCondensed Thin", + "font-family": "Noto Sans ExtraCondensed Thin", + "font-stretch": "extra-condensed", + "font-style": "italic", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans ExtraCondensed Thin Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 6, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSans-ExtraCondensedThinItalic.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "ExtraCondensed Thin Italic", + "subfamily_name": "Italic", + "weight": 100, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSans-ExtraLight.ttf||547260:1655828711.0": { + "family_name": "Noto Sans ExtraLight", + "font-family": "Noto Sans ExtraLight", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSans-ExtraLight.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSans-ExtraLightItalic.ttf||535552:1655828711.0": { + "family_name": "Noto Sans ExtraLight", + "font-family": "Noto Sans ExtraLight", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans ExtraLight Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 2, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSans-ExtraLightItalic.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "ExtraLight Italic", + "subfamily_name": "Italic", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSans-Italic.ttf||552776:1655828711.0": { + "family_name": "Noto Sans", + "font-family": "Noto Sans", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSans-Italic.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSans-Light.ttf||555788:1655828711.0": { + "family_name": "Noto Sans Light", + "font-family": "Noto Sans Light", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSans-Light.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSans-LightItalic.ttf||544388:1655828711.0": { + "family_name": "Noto Sans Light", + "font-family": "Noto Sans Light", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Light Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 2, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSans-LightItalic.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "Light Italic", + "subfamily_name": "Italic", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSans-Medium.ttf||566428:1655828711.0": { + "family_name": "Noto Sans Medium", + "font-family": "Noto Sans Medium", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSans-Medium.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSans-MediumItalic.ttf||548688:1655828711.0": { + "family_name": "Noto Sans Medium", + "font-family": "Noto Sans Medium", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Medium Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 2, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSans-MediumItalic.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "Medium Italic", + "subfamily_name": "Italic", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSans-Regular.ttf||569208:1655828711.0": { + "family_name": "Noto Sans", + "font-family": "Noto Sans", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSans-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSans-SemiBold.ttf||572924:1655828711.0": { + "family_name": "Noto Sans SemiBold", + "font-family": "Noto Sans SemiBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSans-SemiBold.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSans-SemiBoldItalic.ttf||553424:1655828711.0": { + "family_name": "Noto Sans SemiBold", + "font-family": "Noto Sans SemiBold", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans SemiBold Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 2, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSans-SemiBoldItalic.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "SemiBold Italic", + "subfamily_name": "Italic", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSans-SemiCondensed.ttf||565760:1655828711.0": { + "family_name": "Noto Sans SemiCondensed", + "font-family": "Noto Sans SemiCondensed", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans SemiCondensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSans-SemiCondensed.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "SemiCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSans-SemiCondensedBlack.ttf||590140:1655828711.0": { + "family_name": "Noto Sans SemiCondensed Black", + "font-family": "Noto Sans SemiCondensed Black", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans SemiCondensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSans-SemiCondensedBlack.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "SemiCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSans-SemiCondensedBlackItalic.ttf||569584:1655828711.0": { + "family_name": "Noto Sans SemiCondensed Black", + "font-family": "Noto Sans SemiCondensed Black", + "font-stretch": "semi-condensed", + "font-style": "italic", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans SemiCondensed Black Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 2, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSans-SemiCondensedBlackItalic.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "SemiCondensed Black Italic", + "subfamily_name": "Italic", + "weight": 900, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSans-SemiCondensedBold.ttf||575104:1655828711.0": { + "family_name": "Noto Sans SemiCondensed", + "font-family": "Noto Sans SemiCondensed", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans SemiCondensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSans-SemiCondensedBold.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "SemiCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSans-SemiCondensedBoldItalic.ttf||557356:1655828711.0": { + "family_name": "Noto Sans SemiCondensed", + "font-family": "Noto Sans SemiCondensed", + "font-stretch": "semi-condensed", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans SemiCondensed Bold Italic", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 2, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSans-SemiCondensedBoldItalic.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "SemiCondensed Bold Italic", + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSans-SemiCondensedExtraBold.ttf||575692:1655828711.0": { + "family_name": "Noto Sans SemiCondensed ExtraBold", + "font-family": "Noto Sans SemiCondensed ExtraBold", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans SemiCondensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSans-SemiCondensedExtraBold.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "SemiCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSans-SemiCondensedExtraBoldItalic.ttf||559164:1655828711.0": { + "family_name": "Noto Sans SemiCondensed ExtraBold", + "font-family": "Noto Sans SemiCondensed ExtraBold", + "font-stretch": "semi-condensed", + "font-style": "italic", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans SemiCondensed ExtraBold Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 2, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSans-SemiCondensedExtraBoldItalic.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "SemiCondensed ExtraBold Italic", + "subfamily_name": "Italic", + "weight": 800, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSans-SemiCondensedExtraLight.ttf||547804:1655828711.0": { + "family_name": "Noto Sans SemiCondensed ExtraLight", + "font-family": "Noto Sans SemiCondensed ExtraLight", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans SemiCondensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSans-SemiCondensedExtraLight.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "SemiCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSans-SemiCondensedExtraLightItalic.ttf||534672:1655828711.0": { + "family_name": "Noto Sans SemiCondensed ExtraLight", + "font-family": "Noto Sans SemiCondensed ExtraLight", + "font-stretch": "semi-condensed", + "font-style": "italic", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans SemiCondensed ExtraLight Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 2, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSans-SemiCondensedExtraLightItalic.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "SemiCondensed ExtraLight Italic", + "subfamily_name": "Italic", + "weight": 200, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSans-SemiCondensedItalic.ttf||554368:1655828711.0": { + "family_name": "Noto Sans SemiCondensed", + "font-family": "Noto Sans SemiCondensed", + "font-stretch": "semi-condensed", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans SemiCondensed Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSans-SemiCondensedItalic.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "SemiCondensed Italic", + "subfamily_name": "Italic", + "weight": 400, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSans-SemiCondensedLight.ttf||556788:1655828711.0": { + "family_name": "Noto Sans SemiCondensed Light", + "font-family": "Noto Sans SemiCondensed Light", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans SemiCondensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSans-SemiCondensedLight.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "SemiCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSans-SemiCondensedLightItalic.ttf||547024:1655828711.0": { + "family_name": "Noto Sans SemiCondensed Light", + "font-family": "Noto Sans SemiCondensed Light", + "font-stretch": "semi-condensed", + "font-style": "italic", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans SemiCondensed Light Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 2, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSans-SemiCondensedLightItalic.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "SemiCondensed Light Italic", + "subfamily_name": "Italic", + "weight": 300, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSans-SemiCondensedMedium.ttf||565084:1655828711.0": { + "family_name": "Noto Sans SemiCondensed Medium", + "font-family": "Noto Sans SemiCondensed Medium", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans SemiCondensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSans-SemiCondensedMedium.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "SemiCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSans-SemiCondensedMediumItalic.ttf||551680:1655828711.0": { + "family_name": "Noto Sans SemiCondensed Medium", + "font-family": "Noto Sans SemiCondensed Medium", + "font-stretch": "semi-condensed", + "font-style": "italic", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans SemiCondensed Medium Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 2, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSans-SemiCondensedMediumItalic.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "SemiCondensed Medium Italic", + "subfamily_name": "Italic", + "weight": 500, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSans-SemiCondensedSemiBold.ttf||572240:1655828711.0": { + "family_name": "Noto Sans SemiCondensed SemiBold", + "font-family": "Noto Sans SemiCondensed SemiBold", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans SemiCondensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSans-SemiCondensedSemiBold.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "SemiCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSans-SemiCondensedSemiBoldItalic.ttf||556264:1655828711.0": { + "family_name": "Noto Sans SemiCondensed SemiBold", + "font-family": "Noto Sans SemiCondensed SemiBold", + "font-stretch": "semi-condensed", + "font-style": "italic", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans SemiCondensed SemiBold Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 2, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSans-SemiCondensedSemiBoldItalic.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "SemiCondensed SemiBold Italic", + "subfamily_name": "Italic", + "weight": 600, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSans-SemiCondensedThin.ttf||548536:1655828711.0": { + "family_name": "Noto Sans SemiCondensed Thin", + "font-family": "Noto Sans SemiCondensed Thin", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans SemiCondensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSans-SemiCondensedThin.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "SemiCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSans-SemiCondensedThinItalic.ttf||536000:1655828711.0": { + "family_name": "Noto Sans SemiCondensed Thin", + "font-family": "Noto Sans SemiCondensed Thin", + "font-stretch": "semi-condensed", + "font-style": "italic", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans SemiCondensed Thin Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 2, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSans-SemiCondensedThinItalic.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "SemiCondensed Thin Italic", + "subfamily_name": "Italic", + "weight": 100, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSans-Thin.ttf||546536:1655828711.0": { + "family_name": "Noto Sans Thin", + "font-family": "Noto Sans Thin", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSans-Thin.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSans-ThinItalic.ttf||536984:1655828711.0": { + "family_name": "Noto Sans Thin", + "font-family": "Noto Sans Thin", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Thin Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 2, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSans-ThinItalic.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "Thin Italic", + "subfamily_name": "Italic", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansAdlam-Bold.ttf||94380:1655828711.0": { + "family_name": "Noto Sans Adlam", + "font-family": "Noto Sans Adlam", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Adlam Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/noto/NotoSansAdlam-Bold.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansAdlam-Regular.ttf||94472:1655828711.0": { + "family_name": "Noto Sans Adlam", + "font-family": "Noto Sans Adlam", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Adlam Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/noto/NotoSansAdlam-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansAdlamUnjoined-Bold.ttf||36916:1655828711.0": { + "family_name": "Noto Sans Adlam Unjoined", + "font-family": "Noto Sans Adlam Unjoined", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Adlam Unjoined Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/noto/NotoSansAdlamUnjoined-Bold.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansAdlamUnjoined-Regular.ttf||36828:1655828711.0": { + "family_name": "Noto Sans Adlam Unjoined", + "font-family": "Noto Sans Adlam Unjoined", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Adlam Unjoined Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/noto/NotoSansAdlamUnjoined-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansAnatolianHieroglyphs-Regular.ttf||228424:1655828711.0": { + "family_name": "Noto Sans AnatoHiero", + "font-family": "Noto Sans AnatoHiero", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Anatolian Hieroglyphs Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansAnatolianHieroglyphs-Regular.ttf", + "preferred_family_name": "Noto Sans Anatolian Hieroglyphs", + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansArabic-Black.ttf||254936:1655828711.0": { + "family_name": "Noto Sans Arabic Blk", + "font-family": "Noto Sans Arabic Blk", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Arabic Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansArabic-Black.ttf", + "preferred_family_name": "Noto Sans Arabic", + "preferred_subfamily_name": "Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansArabic-Bold.ttf||248468:1655828711.0": { + "family_name": "Noto Sans Arabic", + "font-family": "Noto Sans Arabic", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Arabic Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansArabic-Bold.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansArabic-Condensed.ttf||239684:1655828711.0": { + "family_name": "Noto Sans Arabic Cond", + "font-family": "Noto Sans Arabic Cond", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Arabic Condensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansArabic-Condensed.ttf", + "preferred_family_name": "Noto Sans Arabic", + "preferred_subfamily_name": "Condensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansArabic-CondensedBlack.ttf||254968:1655828711.0": { + "family_name": "Noto Sans Arabic Cond Blk", + "font-family": "Noto Sans Arabic Cond Blk", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Arabic Condensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansArabic-CondensedBlack.ttf", + "preferred_family_name": "Noto Sans Arabic", + "preferred_subfamily_name": "Condensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansArabic-CondensedBold.ttf||251056:1655828711.0": { + "family_name": "Noto Sans Arabic Cond", + "font-family": "Noto Sans Arabic Cond", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Arabic Condensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansArabic-CondensedBold.ttf", + "preferred_family_name": "Noto Sans Arabic", + "preferred_subfamily_name": "Condensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansArabic-CondensedExtraBold.ttf||253172:1655828711.0": { + "family_name": "Noto Sans Arabic Cond ExtBd", + "font-family": "Noto Sans Arabic Cond ExtBd", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Arabic Condensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansArabic-CondensedExtraBold.ttf", + "preferred_family_name": "Noto Sans Arabic", + "preferred_subfamily_name": "Condensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansArabic-CondensedExtraLight.ttf||234344:1655828711.0": { + "family_name": "Noto Sans Arabic Cond ExtLt", + "font-family": "Noto Sans Arabic Cond ExtLt", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Arabic Condensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansArabic-CondensedExtraLight.ttf", + "preferred_family_name": "Noto Sans Arabic", + "preferred_subfamily_name": "Condensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansArabic-CondensedLight.ttf||233860:1655828711.0": { + "family_name": "Noto Sans Arabic Cond Light", + "font-family": "Noto Sans Arabic Cond Light", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Arabic Condensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansArabic-CondensedLight.ttf", + "preferred_family_name": "Noto Sans Arabic", + "preferred_subfamily_name": "Condensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansArabic-CondensedMedium.ttf||248292:1655828711.0": { + "family_name": "Noto Sans Arabic Cond Med", + "font-family": "Noto Sans Arabic Cond Med", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Arabic Condensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansArabic-CondensedMedium.ttf", + "preferred_family_name": "Noto Sans Arabic", + "preferred_subfamily_name": "Condensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansArabic-CondensedSemiBold.ttf||250156:1655828711.0": { + "family_name": "Noto Sans Arabic Cond SemBd", + "font-family": "Noto Sans Arabic Cond SemBd", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Arabic Condensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansArabic-CondensedSemiBold.ttf", + "preferred_family_name": "Noto Sans Arabic", + "preferred_subfamily_name": "Condensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansArabic-CondensedThin.ttf||232560:1655828711.0": { + "family_name": "Noto Sans Arabic Cond Thin", + "font-family": "Noto Sans Arabic Cond Thin", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Arabic Condensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansArabic-CondensedThin.ttf", + "preferred_family_name": "Noto Sans Arabic", + "preferred_subfamily_name": "Condensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansArabic-ExtraBold.ttf||252816:1655828711.0": { + "family_name": "Noto Sans Arabic ExtBd", + "font-family": "Noto Sans Arabic ExtBd", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Arabic ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansArabic-ExtraBold.ttf", + "preferred_family_name": "Noto Sans Arabic", + "preferred_subfamily_name": "ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansArabic-ExtraCondensed.ttf||238104:1655828711.0": { + "family_name": "Noto Sans Arabic ExtCond", + "font-family": "Noto Sans Arabic ExtCond", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Arabic ExtraCondensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansArabic-ExtraCondensed.ttf", + "preferred_family_name": "Noto Sans Arabic", + "preferred_subfamily_name": "ExtraCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansArabic-ExtraCondensedBlack.ttf||253464:1655828711.0": { + "family_name": "Noto Sans Arabic ExtCond Blk", + "font-family": "Noto Sans Arabic ExtCond Blk", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Arabic ExtraCondensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansArabic-ExtraCondensedBlack.ttf", + "preferred_family_name": "Noto Sans Arabic", + "preferred_subfamily_name": "ExtraCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansArabic-ExtraCondensedBold.ttf||251668:1655828711.0": { + "family_name": "Noto Sans Arabic ExtCond", + "font-family": "Noto Sans Arabic ExtCond", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Arabic ExtraCondensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansArabic-ExtraCondensedBold.ttf", + "preferred_family_name": "Noto Sans Arabic", + "preferred_subfamily_name": "ExtraCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansArabic-ExtraCondensedExtraBold.ttf||254448:1655828711.0": { + "family_name": "Noto Sans Arabic ExtCond ExtBd", + "font-family": "Noto Sans Arabic ExtCond ExtBd", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Arabic ExtraCondensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansArabic-ExtraCondensedExtraBold.ttf", + "preferred_family_name": "Noto Sans Arabic", + "preferred_subfamily_name": "ExtraCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansArabic-ExtraCondensedExtraLight.ttf||236400:1655828711.0": { + "family_name": "Noto Sans Arabic ExtCond ExtLt", + "font-family": "Noto Sans Arabic ExtCond ExtLt", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Arabic ExtraCondensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansArabic-ExtraCondensedExtraLight.ttf", + "preferred_family_name": "Noto Sans Arabic", + "preferred_subfamily_name": "ExtraCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansArabic-ExtraCondensedLight.ttf||231572:1655828711.0": { + "family_name": "Noto Sans Arabic ExtCond Light", + "font-family": "Noto Sans Arabic ExtCond Light", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Arabic ExtraCondensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansArabic-ExtraCondensedLight.ttf", + "preferred_family_name": "Noto Sans Arabic", + "preferred_subfamily_name": "ExtraCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansArabic-ExtraCondensedMedium.ttf||242152:1655828711.0": { + "family_name": "Noto Sans Arabic ExtCond Med", + "font-family": "Noto Sans Arabic ExtCond Med", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Arabic ExtraCondensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansArabic-ExtraCondensedMedium.ttf", + "preferred_family_name": "Noto Sans Arabic", + "preferred_subfamily_name": "ExtraCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansArabic-ExtraCondensedSemiBold.ttf||248904:1655828711.0": { + "family_name": "Noto Sans Arabic ExtCond SemBd", + "font-family": "Noto Sans Arabic ExtCond SemBd", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Arabic ExtraCondensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansArabic-ExtraCondensedSemiBold.ttf", + "preferred_family_name": "Noto Sans Arabic", + "preferred_subfamily_name": "ExtraCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansArabic-ExtraCondensedThin.ttf||232068:1655828711.0": { + "family_name": "Noto Sans Arabic ExtCond Thin", + "font-family": "Noto Sans Arabic ExtCond Thin", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Arabic ExtraCondensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansArabic-ExtraCondensedThin.ttf", + "preferred_family_name": "Noto Sans Arabic", + "preferred_subfamily_name": "ExtraCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansArabic-ExtraLight.ttf||235536:1655828711.0": { + "family_name": "Noto Sans Arabic ExtLt", + "font-family": "Noto Sans Arabic ExtLt", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Arabic ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansArabic-ExtraLight.ttf", + "preferred_family_name": "Noto Sans Arabic", + "preferred_subfamily_name": "ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansArabic-Light.ttf||234308:1655828711.0": { + "family_name": "Noto Sans Arabic Light", + "font-family": "Noto Sans Arabic Light", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Arabic Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansArabic-Light.ttf", + "preferred_family_name": "Noto Sans Arabic", + "preferred_subfamily_name": "Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansArabic-Medium.ttf||248860:1655828711.0": { + "family_name": "Noto Sans Arabic Med", + "font-family": "Noto Sans Arabic Med", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Arabic Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansArabic-Medium.ttf", + "preferred_family_name": "Noto Sans Arabic", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansArabic-Regular.ttf||240456:1655828711.0": { + "family_name": "Noto Sans Arabic", + "font-family": "Noto Sans Arabic", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Arabic Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansArabic-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansArabic-SemiBold.ttf||248724:1655828711.0": { + "family_name": "Noto Sans Arabic SemBd", + "font-family": "Noto Sans Arabic SemBd", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Arabic SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansArabic-SemiBold.ttf", + "preferred_family_name": "Noto Sans Arabic", + "preferred_subfamily_name": "SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansArabic-SemiCondensed.ttf||241020:1655828711.0": { + "family_name": "Noto Sans Arabic SemCond", + "font-family": "Noto Sans Arabic SemCond", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Arabic SemiCondensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansArabic-SemiCondensed.ttf", + "preferred_family_name": "Noto Sans Arabic", + "preferred_subfamily_name": "SemiCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansArabic-SemiCondensedBlack.ttf||256656:1655828711.0": { + "family_name": "Noto Sans Arabic SemCond Blk", + "font-family": "Noto Sans Arabic SemCond Blk", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Arabic SemiCondensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansArabic-SemiCondensedBlack.ttf", + "preferred_family_name": "Noto Sans Arabic", + "preferred_subfamily_name": "SemiCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansArabic-SemiCondensedBold.ttf||250280:1655828711.0": { + "family_name": "Noto Sans Arabic SemCond", + "font-family": "Noto Sans Arabic SemCond", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Arabic SemiCondensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansArabic-SemiCondensedBold.ttf", + "preferred_family_name": "Noto Sans Arabic", + "preferred_subfamily_name": "SemiCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansArabic-SemiCondensedExtraBold.ttf||251860:1655828711.0": { + "family_name": "Noto Sans Arabic SemCond ExtBd", + "font-family": "Noto Sans Arabic SemCond ExtBd", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Arabic SemiCondensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansArabic-SemiCondensedExtraBold.ttf", + "preferred_family_name": "Noto Sans Arabic", + "preferred_subfamily_name": "SemiCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansArabic-SemiCondensedExtraLight.ttf||234212:1655828711.0": { + "family_name": "Noto Sans Arabic SemCond ExtLt", + "font-family": "Noto Sans Arabic SemCond ExtLt", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Arabic SemiCondensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansArabic-SemiCondensedExtraLight.ttf", + "preferred_family_name": "Noto Sans Arabic", + "preferred_subfamily_name": "SemiCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansArabic-SemiCondensedLight.ttf||231992:1655828711.0": { + "family_name": "Noto Sans Arabic SemCond Light", + "font-family": "Noto Sans Arabic SemCond Light", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Arabic SemiCondensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansArabic-SemiCondensedLight.ttf", + "preferred_family_name": "Noto Sans Arabic", + "preferred_subfamily_name": "SemiCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansArabic-SemiCondensedMedium.ttf||246544:1655828711.0": { + "family_name": "Noto Sans Arabic SemCond Med", + "font-family": "Noto Sans Arabic SemCond Med", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Arabic SemiCondensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansArabic-SemiCondensedMedium.ttf", + "preferred_family_name": "Noto Sans Arabic", + "preferred_subfamily_name": "SemiCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansArabic-SemiCondensedSemiBold.ttf||249800:1655828711.0": { + "family_name": "Noto Sans Arabic SemCond SemBd", + "font-family": "Noto Sans Arabic SemCond SemBd", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Arabic SemiCondensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansArabic-SemiCondensedSemiBold.ttf", + "preferred_family_name": "Noto Sans Arabic", + "preferred_subfamily_name": "SemiCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansArabic-SemiCondensedThin.ttf||232300:1655828711.0": { + "family_name": "Noto Sans Arabic SemCond Thin", + "font-family": "Noto Sans Arabic SemCond Thin", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Arabic SemiCondensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansArabic-SemiCondensedThin.ttf", + "preferred_family_name": "Noto Sans Arabic", + "preferred_subfamily_name": "SemiCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansArabic-Thin.ttf||233784:1655828711.0": { + "family_name": "Noto Sans Arabic Thin", + "font-family": "Noto Sans Arabic Thin", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Arabic Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansArabic-Thin.ttf", + "preferred_family_name": "Noto Sans Arabic", + "preferred_subfamily_name": "Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansArabicUI-Black.ttf||293116:1655828711.0": { + "family_name": "Noto Sans Arabic UI Bk", + "font-family": "Noto Sans Arabic UI Bk", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Arabic UI Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansArabicUI-Black.ttf", + "preferred_family_name": "Noto Sans Arabic UI", + "preferred_subfamily_name": "Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansArabicUI-Bold.ttf||279404:1655828711.0": { + "family_name": "Noto Sans Arabic UI", + "font-family": "Noto Sans Arabic UI", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Arabic UI Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansArabicUI-Bold.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansArabicUI-Condensed.ttf||266824:1655828711.0": { + "family_name": "Noto Sans Arabic UI Cn", + "font-family": "Noto Sans Arabic UI Cn", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Arabic UI Condensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansArabicUI-Condensed.ttf", + "preferred_family_name": "Noto Sans Arabic UI", + "preferred_subfamily_name": "Condensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansArabicUI-CondensedBlack.ttf||288496:1655828711.0": { + "family_name": "Noto Sans Arabic UI Cn Bk", + "font-family": "Noto Sans Arabic UI Cn Bk", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Arabic UI Condensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansArabicUI-CondensedBlack.ttf", + "preferred_family_name": "Noto Sans Arabic UI", + "preferred_subfamily_name": "Condensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansArabicUI-CondensedBold.ttf||280040:1655828711.0": { + "family_name": "Noto Sans Arabic UI Cn", + "font-family": "Noto Sans Arabic UI Cn", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Arabic UI Condensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansArabicUI-CondensedBold.ttf", + "preferred_family_name": "Noto Sans Arabic UI", + "preferred_subfamily_name": "Condensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansArabicUI-CondensedExtraBold.ttf||287508:1655828711.0": { + "family_name": "Noto Sans Arabic UI Cn XBd", + "font-family": "Noto Sans Arabic UI Cn XBd", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Arabic UI Condensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansArabicUI-CondensedExtraBold.ttf", + "preferred_family_name": "Noto Sans Arabic UI", + "preferred_subfamily_name": "Condensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansArabicUI-CondensedExtraLight.ttf||260836:1655828711.0": { + "family_name": "Noto Sans Arabic UI Cn XLt", + "font-family": "Noto Sans Arabic UI Cn XLt", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Arabic UI Condensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansArabicUI-CondensedExtraLight.ttf", + "preferred_family_name": "Noto Sans Arabic UI", + "preferred_subfamily_name": "Condensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansArabicUI-CondensedLight.ttf||259924:1655828711.0": { + "family_name": "Noto Sans Arabic UI Cn Lt", + "font-family": "Noto Sans Arabic UI Cn Lt", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Arabic UI Condensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansArabicUI-CondensedLight.ttf", + "preferred_family_name": "Noto Sans Arabic UI", + "preferred_subfamily_name": "Condensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansArabicUI-CondensedMedium.ttf||277964:1655828711.0": { + "family_name": "Noto Sans Arabic UI Cn Md", + "font-family": "Noto Sans Arabic UI Cn Md", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Arabic UI Condensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansArabicUI-CondensedMedium.ttf", + "preferred_family_name": "Noto Sans Arabic UI", + "preferred_subfamily_name": "Condensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansArabicUI-CondensedSemiBold.ttf||280012:1655828711.0": { + "family_name": "Noto Sans Arabic UI Cn SmBd", + "font-family": "Noto Sans Arabic UI Cn SmBd", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Arabic UI Condensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansArabicUI-CondensedSemiBold.ttf", + "preferred_family_name": "Noto Sans Arabic UI", + "preferred_subfamily_name": "Condensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansArabicUI-CondensedThin.ttf||257316:1655828711.0": { + "family_name": "Noto Sans Arabic UI Cn Th", + "font-family": "Noto Sans Arabic UI Cn Th", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Arabic UI Condensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansArabicUI-CondensedThin.ttf", + "preferred_family_name": "Noto Sans Arabic UI", + "preferred_subfamily_name": "Condensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansArabicUI-ExtraBold.ttf||285612:1655828711.0": { + "family_name": "Noto Sans Arabic UI XBd", + "font-family": "Noto Sans Arabic UI XBd", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Arabic UI ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansArabicUI-ExtraBold.ttf", + "preferred_family_name": "Noto Sans Arabic UI", + "preferred_subfamily_name": "ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansArabicUI-ExtraCondensed.ttf||264964:1655828711.0": { + "family_name": "Noto Sans Arabic UI XCn", + "font-family": "Noto Sans Arabic UI XCn", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Arabic UI ExtraCondensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansArabicUI-ExtraCondensed.ttf", + "preferred_family_name": "Noto Sans Arabic UI", + "preferred_subfamily_name": "ExtraCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansArabicUI-ExtraCondensedBlack.ttf||285836:1655828711.0": { + "family_name": "Noto Sans Arabic UI XCn Bk", + "font-family": "Noto Sans Arabic UI XCn Bk", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Arabic UI ExtraCondensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansArabicUI-ExtraCondensedBlack.ttf", + "preferred_family_name": "Noto Sans Arabic UI", + "preferred_subfamily_name": "ExtraCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansArabicUI-ExtraCondensedBold.ttf||281508:1655828711.0": { + "family_name": "Noto Sans Arabic UI XCn", + "font-family": "Noto Sans Arabic UI XCn", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Arabic UI ExtraCondensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansArabicUI-ExtraCondensedBold.ttf", + "preferred_family_name": "Noto Sans Arabic UI", + "preferred_subfamily_name": "ExtraCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansArabicUI-ExtraCondensedExtraBold.ttf||284164:1655828711.0": { + "family_name": "Noto Sans Arabic UI XCn XBd", + "font-family": "Noto Sans Arabic UI XCn XBd", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Arabic UI ExtraCondensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansArabicUI-ExtraCondensedExtraBold.ttf", + "preferred_family_name": "Noto Sans Arabic UI", + "preferred_subfamily_name": "ExtraCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansArabicUI-ExtraCondensedExtraLight.ttf||261456:1655828711.0": { + "family_name": "Noto Sans Arabic UI XCn XLt", + "font-family": "Noto Sans Arabic UI XCn XLt", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Arabic UI ExtraCondensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansArabicUI-ExtraCondensedExtraLight.ttf", + "preferred_family_name": "Noto Sans Arabic UI", + "preferred_subfamily_name": "ExtraCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansArabicUI-ExtraCondensedLight.ttf||257768:1655828711.0": { + "family_name": "Noto Sans Arabic UI XCn Lt", + "font-family": "Noto Sans Arabic UI XCn Lt", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Arabic UI ExtraCondensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansArabicUI-ExtraCondensedLight.ttf", + "preferred_family_name": "Noto Sans Arabic UI", + "preferred_subfamily_name": "ExtraCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansArabicUI-ExtraCondensedMedium.ttf||270736:1655828711.0": { + "family_name": "Noto Sans Arabic UI XCn Md", + "font-family": "Noto Sans Arabic UI XCn Md", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Arabic UI ExtraCondensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansArabicUI-ExtraCondensedMedium.ttf", + "preferred_family_name": "Noto Sans Arabic UI", + "preferred_subfamily_name": "ExtraCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansArabicUI-ExtraCondensedSemiBold.ttf||277504:1655828711.0": { + "family_name": "Noto Sans Arabic UI XCn SmBd", + "font-family": "Noto Sans Arabic UI XCn SmBd", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Arabic UI ExtraCondensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansArabicUI-ExtraCondensedSemiBold.ttf", + "preferred_family_name": "Noto Sans Arabic UI", + "preferred_subfamily_name": "ExtraCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansArabicUI-ExtraCondensedThin.ttf||256216:1655828711.0": { + "family_name": "Noto Sans Arabic UI XCn Th", + "font-family": "Noto Sans Arabic UI XCn Th", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Arabic UI ExtraCondensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansArabicUI-ExtraCondensedThin.ttf", + "preferred_family_name": "Noto Sans Arabic UI", + "preferred_subfamily_name": "ExtraCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansArabicUI-ExtraLight.ttf||260576:1655828711.0": { + "family_name": "Noto Sans Arabic UI XLt", + "font-family": "Noto Sans Arabic UI XLt", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Arabic UI ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansArabicUI-ExtraLight.ttf", + "preferred_family_name": "Noto Sans Arabic UI", + "preferred_subfamily_name": "ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansArabicUI-Light.ttf||258376:1655828711.0": { + "family_name": "Noto Sans Arabic UI Lt", + "font-family": "Noto Sans Arabic UI Lt", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Arabic UI Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansArabicUI-Light.ttf", + "preferred_family_name": "Noto Sans Arabic UI", + "preferred_subfamily_name": "Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansArabicUI-Medium.ttf||276476:1655828711.0": { + "family_name": "Noto Sans Arabic UI Md", + "font-family": "Noto Sans Arabic UI Md", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Arabic UI Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansArabicUI-Medium.ttf", + "preferred_family_name": "Noto Sans Arabic UI", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansArabicUI-Regular.ttf||266792:1655828711.0": { + "family_name": "Noto Sans Arabic UI", + "font-family": "Noto Sans Arabic UI", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Arabic UI Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansArabicUI-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansArabicUI-SemiBold.ttf||280744:1655828711.0": { + "family_name": "Noto Sans Arabic UI SmBd", + "font-family": "Noto Sans Arabic UI SmBd", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Arabic UI SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansArabicUI-SemiBold.ttf", + "preferred_family_name": "Noto Sans Arabic UI", + "preferred_subfamily_name": "SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansArabicUI-SemiCondensed.ttf||268340:1655828711.0": { + "family_name": "Noto Sans Arabic UI SmCn", + "font-family": "Noto Sans Arabic UI SmCn", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Arabic UI SemiCondensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansArabicUI-SemiCondensed.ttf", + "preferred_family_name": "Noto Sans Arabic UI", + "preferred_subfamily_name": "SemiCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansArabicUI-SemiCondensedBlack.ttf||288080:1655828711.0": { + "family_name": "Noto Sans Arabic UI SmCn Bk", + "font-family": "Noto Sans Arabic UI SmCn Bk", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Arabic UI SemiCondensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansArabicUI-SemiCondensedBlack.ttf", + "preferred_family_name": "Noto Sans Arabic UI", + "preferred_subfamily_name": "SemiCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansArabicUI-SemiCondensedBold.ttf||281104:1655828711.0": { + "family_name": "Noto Sans Arabic UI SmCn", + "font-family": "Noto Sans Arabic UI SmCn", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Arabic UI SemiCondensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansArabicUI-SemiCondensedBold.ttf", + "preferred_family_name": "Noto Sans Arabic UI", + "preferred_subfamily_name": "SemiCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansArabicUI-SemiCondensedExtraBold.ttf||285376:1655828711.0": { + "family_name": "Noto Sans Arabic UI SmCn XBd", + "font-family": "Noto Sans Arabic UI SmCn XBd", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Arabic UI SemiCondensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansArabicUI-SemiCondensedExtraBold.ttf", + "preferred_family_name": "Noto Sans Arabic UI", + "preferred_subfamily_name": "SemiCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansArabicUI-SemiCondensedExtraLight.ttf||259588:1655828711.0": { + "family_name": "Noto Sans Arabic UI SmCn XLt", + "font-family": "Noto Sans Arabic UI SmCn XLt", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Arabic UI SemiCondensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansArabicUI-SemiCondensedExtraLight.ttf", + "preferred_family_name": "Noto Sans Arabic UI", + "preferred_subfamily_name": "SemiCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansArabicUI-SemiCondensedLight.ttf||256732:1655828711.0": { + "family_name": "Noto Sans Arabic UI SmCn Lt", + "font-family": "Noto Sans Arabic UI SmCn Lt", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Arabic UI SemiCondensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansArabicUI-SemiCondensedLight.ttf", + "preferred_family_name": "Noto Sans Arabic UI", + "preferred_subfamily_name": "SemiCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansArabicUI-SemiCondensedMedium.ttf||277504:1655828711.0": { + "family_name": "Noto Sans Arabic UI SmCn Md", + "font-family": "Noto Sans Arabic UI SmCn Md", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Arabic UI SemiCondensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansArabicUI-SemiCondensedMedium.ttf", + "preferred_family_name": "Noto Sans Arabic UI", + "preferred_subfamily_name": "SemiCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansArabicUI-SemiCondensedSemiBold.ttf||281364:1655828711.0": { + "family_name": "Noto Sans Arabic UI SmCn SmBd", + "font-family": "Noto Sans Arabic UI SmCn SmBd", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Arabic UI SemiCondensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansArabicUI-SemiCondensedSemiBold.ttf", + "preferred_family_name": "Noto Sans Arabic UI", + "preferred_subfamily_name": "SemiCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansArabicUI-SemiCondensedThin.ttf||255688:1655828711.0": { + "family_name": "Noto Sans Arabic UI SmCn Th", + "font-family": "Noto Sans Arabic UI SmCn Th", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Arabic UI SemiCondensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansArabicUI-SemiCondensedThin.ttf", + "preferred_family_name": "Noto Sans Arabic UI", + "preferred_subfamily_name": "SemiCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansArabicUI-Thin.ttf||258412:1655828711.0": { + "family_name": "Noto Sans Arabic UI Th", + "font-family": "Noto Sans Arabic UI Th", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Arabic UI Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansArabicUI-Thin.ttf", + "preferred_family_name": "Noto Sans Arabic UI", + "preferred_subfamily_name": "Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansArmenian-Black.ttf||32896:1655828711.0": { + "family_name": "Noto Sans Armenian Black", + "font-family": "Noto Sans Armenian Black", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Armenian Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansArmenian-Black.ttf", + "preferred_family_name": "Noto Sans Armenian", + "preferred_subfamily_name": "Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansArmenian-Bold.ttf||30908:1655828711.0": { + "family_name": "Noto Sans Armenian", + "font-family": "Noto Sans Armenian", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Armenian Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansArmenian-Bold.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansArmenian-Condensed.ttf||30660:1655828711.0": { + "family_name": "Noto Sans Armenian Condensed", + "font-family": "Noto Sans Armenian Condensed", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Armenian Condensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansArmenian-Condensed.ttf", + "preferred_family_name": "Noto Sans Armenian", + "preferred_subfamily_name": "Condensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansArmenian-CondensedBlack.ttf||31476:1655828711.0": { + "family_name": "Noto Sans Armenian Condensed Black", + "font-family": "Noto Sans Armenian Condensed Black", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Armenian Condensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansArmenian-CondensedBlack.ttf", + "preferred_family_name": "Noto Sans Armenian", + "preferred_subfamily_name": "Condensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansArmenian-CondensedBold.ttf||30956:1655828711.0": { + "family_name": "Noto Sans Armenian Condensed", + "font-family": "Noto Sans Armenian Condensed", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Armenian Condensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansArmenian-CondensedBold.ttf", + "preferred_family_name": "Noto Sans Armenian", + "preferred_subfamily_name": "Condensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansArmenian-CondensedExtraBold.ttf||31260:1655828711.0": { + "family_name": "Noto Sans Armenian Condensed ExtraBold", + "font-family": "Noto Sans Armenian Condensed ExtraBold", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Armenian Condensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansArmenian-CondensedExtraBold.ttf", + "preferred_family_name": "Noto Sans Armenian", + "preferred_subfamily_name": "Condensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansArmenian-CondensedExtraLight.ttf||29716:1655828711.0": { + "family_name": "Noto Sans Armenian Condensed ExtraLight", + "font-family": "Noto Sans Armenian Condensed ExtraLight", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Armenian Condensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansArmenian-CondensedExtraLight.ttf", + "preferred_family_name": "Noto Sans Armenian", + "preferred_subfamily_name": "Condensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansArmenian-CondensedLight.ttf||29700:1655828711.0": { + "family_name": "Noto Sans Armenian Condensed Light", + "font-family": "Noto Sans Armenian Condensed Light", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Armenian Condensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansArmenian-CondensedLight.ttf", + "preferred_family_name": "Noto Sans Armenian", + "preferred_subfamily_name": "Condensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansArmenian-CondensedMedium.ttf||30900:1655828711.0": { + "family_name": "Noto Sans Armenian Condensed Medium", + "font-family": "Noto Sans Armenian Condensed Medium", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Armenian Condensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansArmenian-CondensedMedium.ttf", + "preferred_family_name": "Noto Sans Armenian", + "preferred_subfamily_name": "Condensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansArmenian-CondensedSemiBold.ttf||30996:1655828711.0": { + "family_name": "Noto Sans Armenian Condensed SemiBold", + "font-family": "Noto Sans Armenian Condensed SemiBold", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Armenian Condensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansArmenian-CondensedSemiBold.ttf", + "preferred_family_name": "Noto Sans Armenian", + "preferred_subfamily_name": "Condensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansArmenian-CondensedThin.ttf||29636:1655828711.0": { + "family_name": "Noto Sans Armenian Condensed Thin", + "font-family": "Noto Sans Armenian Condensed Thin", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Armenian Condensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansArmenian-CondensedThin.ttf", + "preferred_family_name": "Noto Sans Armenian", + "preferred_subfamily_name": "Condensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansArmenian-ExtraBold.ttf||32528:1655828711.0": { + "family_name": "Noto Sans Armenian ExtraBold", + "font-family": "Noto Sans Armenian ExtraBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Armenian ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansArmenian-ExtraBold.ttf", + "preferred_family_name": "Noto Sans Armenian", + "preferred_subfamily_name": "ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansArmenian-ExtraCondensed.ttf||30040:1655828711.0": { + "family_name": "Noto Sans Armenian ExtraCondensed", + "font-family": "Noto Sans Armenian ExtraCondensed", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Armenian ExtraCondensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansArmenian-ExtraCondensed.ttf", + "preferred_family_name": "Noto Sans Armenian", + "preferred_subfamily_name": "ExtraCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansArmenian-ExtraCondensedBlack.ttf||30728:1655828711.0": { + "family_name": "Noto Sans Armenian ExtraCondensed Black", + "font-family": "Noto Sans Armenian ExtraCondensed Black", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Armenian ExtraCondensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansArmenian-ExtraCondensedBlack.ttf", + "preferred_family_name": "Noto Sans Armenian", + "preferred_subfamily_name": "ExtraCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansArmenian-ExtraCondensedBold.ttf||30280:1655828711.0": { + "family_name": "Noto Sans Armenian ExtraCondensed", + "font-family": "Noto Sans Armenian ExtraCondensed", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Armenian ExtraCondensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansArmenian-ExtraCondensedBold.ttf", + "preferred_family_name": "Noto Sans Armenian", + "preferred_subfamily_name": "ExtraCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansArmenian-ExtraCondensedExtraBold.ttf||30812:1655828711.0": { + "family_name": "Noto Sans Armenian ExtraCondensed ExtraBold", + "font-family": "Noto Sans Armenian ExtraCondensed ExtraBold", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Armenian ExtraCondensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansArmenian-ExtraCondensedExtraBold.ttf", + "preferred_family_name": "Noto Sans Armenian", + "preferred_subfamily_name": "ExtraCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansArmenian-ExtraCondensedExtraLight.ttf||29176:1655828711.0": { + "family_name": "Noto Sans Armenian ExtraCondensed ExtraLight", + "font-family": "Noto Sans Armenian ExtraCondensed ExtraLight", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Armenian ExtraCondensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansArmenian-ExtraCondensedExtraLight.ttf", + "preferred_family_name": "Noto Sans Armenian", + "preferred_subfamily_name": "ExtraCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansArmenian-ExtraCondensedLight.ttf||29000:1655828711.0": { + "family_name": "Noto Sans Armenian ExtraCondensed Light", + "font-family": "Noto Sans Armenian ExtraCondensed Light", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Armenian ExtraCondensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansArmenian-ExtraCondensedLight.ttf", + "preferred_family_name": "Noto Sans Armenian", + "preferred_subfamily_name": "ExtraCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansArmenian-ExtraCondensedMedium.ttf||30328:1655828711.0": { + "family_name": "Noto Sans Armenian ExtraCondensed Medium", + "font-family": "Noto Sans Armenian ExtraCondensed Medium", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Armenian ExtraCondensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansArmenian-ExtraCondensedMedium.ttf", + "preferred_family_name": "Noto Sans Armenian", + "preferred_subfamily_name": "ExtraCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansArmenian-ExtraCondensedSemiBold.ttf||30484:1655828711.0": { + "family_name": "Noto Sans Armenian ExtraCondensed SemiBold", + "font-family": "Noto Sans Armenian ExtraCondensed SemiBold", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Armenian ExtraCondensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansArmenian-ExtraCondensedSemiBold.ttf", + "preferred_family_name": "Noto Sans Armenian", + "preferred_subfamily_name": "ExtraCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansArmenian-ExtraCondensedThin.ttf||28956:1655828711.0": { + "family_name": "Noto Sans Armenian ExtraCondensed Thin", + "font-family": "Noto Sans Armenian ExtraCondensed Thin", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Armenian ExtraCondensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansArmenian-ExtraCondensedThin.ttf", + "preferred_family_name": "Noto Sans Armenian", + "preferred_subfamily_name": "ExtraCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansArmenian-ExtraLight.ttf||29824:1655828711.0": { + "family_name": "Noto Sans Armenian ExtraLight", + "font-family": "Noto Sans Armenian ExtraLight", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Armenian ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansArmenian-ExtraLight.ttf", + "preferred_family_name": "Noto Sans Armenian", + "preferred_subfamily_name": "ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansArmenian-Light.ttf||29724:1655828711.0": { + "family_name": "Noto Sans Armenian Light", + "font-family": "Noto Sans Armenian Light", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Armenian Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansArmenian-Light.ttf", + "preferred_family_name": "Noto Sans Armenian", + "preferred_subfamily_name": "Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansArmenian-Medium.ttf||30824:1655828711.0": { + "family_name": "Noto Sans Armenian Medium", + "font-family": "Noto Sans Armenian Medium", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Armenian Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansArmenian-Medium.ttf", + "preferred_family_name": "Noto Sans Armenian", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansArmenian-Regular.ttf||30876:1655828711.0": { + "family_name": "Noto Sans Armenian", + "font-family": "Noto Sans Armenian", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Armenian Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansArmenian-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansArmenian-SemiBold.ttf||31028:1655828711.0": { + "family_name": "Noto Sans Armenian SemiBold", + "font-family": "Noto Sans Armenian SemiBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Armenian SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansArmenian-SemiBold.ttf", + "preferred_family_name": "Noto Sans Armenian", + "preferred_subfamily_name": "SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansArmenian-SemiCondensed.ttf||30772:1655828711.0": { + "family_name": "Noto Sans Armenian SemiCondensed", + "font-family": "Noto Sans Armenian SemiCondensed", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Armenian SemiCondensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansArmenian-SemiCondensed.ttf", + "preferred_family_name": "Noto Sans Armenian", + "preferred_subfamily_name": "SemiCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansArmenian-SemiCondensedBlack.ttf||31748:1655828711.0": { + "family_name": "Noto Sans Armenian SemiCondensed Black", + "font-family": "Noto Sans Armenian SemiCondensed Black", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Armenian SemiCondensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansArmenian-SemiCondensedBlack.ttf", + "preferred_family_name": "Noto Sans Armenian", + "preferred_subfamily_name": "SemiCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansArmenian-SemiCondensedBold.ttf||30888:1655828711.0": { + "family_name": "Noto Sans Armenian SemiCondensed", + "font-family": "Noto Sans Armenian SemiCondensed", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Armenian SemiCondensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansArmenian-SemiCondensedBold.ttf", + "preferred_family_name": "Noto Sans Armenian", + "preferred_subfamily_name": "SemiCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansArmenian-SemiCondensedExtraBold.ttf||31440:1655828711.0": { + "family_name": "Noto Sans Armenian SemiCondensed ExtraBold", + "font-family": "Noto Sans Armenian SemiCondensed ExtraBold", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Armenian SemiCondensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansArmenian-SemiCondensedExtraBold.ttf", + "preferred_family_name": "Noto Sans Armenian", + "preferred_subfamily_name": "SemiCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansArmenian-SemiCondensedExtraLight.ttf||29744:1655828711.0": { + "family_name": "Noto Sans Armenian SemiCondensed ExtraLight", + "font-family": "Noto Sans Armenian SemiCondensed ExtraLight", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Armenian SemiCondensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansArmenian-SemiCondensedExtraLight.ttf", + "preferred_family_name": "Noto Sans Armenian", + "preferred_subfamily_name": "SemiCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansArmenian-SemiCondensedLight.ttf||29672:1655828711.0": { + "family_name": "Noto Sans Armenian SemiCondensed Light", + "font-family": "Noto Sans Armenian SemiCondensed Light", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Armenian SemiCondensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansArmenian-SemiCondensedLight.ttf", + "preferred_family_name": "Noto Sans Armenian", + "preferred_subfamily_name": "SemiCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansArmenian-SemiCondensedMedium.ttf||30940:1655828711.0": { + "family_name": "Noto Sans Armenian SemiCondensed Medium", + "font-family": "Noto Sans Armenian SemiCondensed Medium", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Armenian SemiCondensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansArmenian-SemiCondensedMedium.ttf", + "preferred_family_name": "Noto Sans Armenian", + "preferred_subfamily_name": "SemiCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansArmenian-SemiCondensedSemiBold.ttf||31376:1655828711.0": { + "family_name": "Noto Sans Armenian SemiCondensed SemiBold", + "font-family": "Noto Sans Armenian SemiCondensed SemiBold", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Armenian SemiCondensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansArmenian-SemiCondensedSemiBold.ttf", + "preferred_family_name": "Noto Sans Armenian", + "preferred_subfamily_name": "SemiCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansArmenian-SemiCondensedThin.ttf||29696:1655828711.0": { + "family_name": "Noto Sans Armenian SemiCondensed Thin", + "font-family": "Noto Sans Armenian SemiCondensed Thin", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Armenian SemiCondensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansArmenian-SemiCondensedThin.ttf", + "preferred_family_name": "Noto Sans Armenian", + "preferred_subfamily_name": "SemiCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansArmenian-Thin.ttf||30700:1655828711.0": { + "family_name": "Noto Sans Armenian Thin", + "font-family": "Noto Sans Armenian Thin", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Armenian Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansArmenian-Thin.ttf", + "preferred_family_name": "Noto Sans Armenian", + "preferred_subfamily_name": "Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansAvestan-Regular.ttf||23016:1655828711.0": { + "family_name": "Noto Sans Avestan", + "font-family": "Noto Sans Avestan", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Avestan Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansAvestan-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansBalinese-Bold.ttf||91972:1655828711.0": { + "family_name": "Noto Sans Balinese", + "font-family": "Noto Sans Balinese", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Balinese Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansBalinese-Bold.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansBalinese-Medium.ttf||90900:1655828711.0": { + "family_name": "Noto Sans Balinese Medium", + "font-family": "Noto Sans Balinese Medium", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Balinese Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansBalinese-Medium.ttf", + "preferred_family_name": "Noto Sans Balinese", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansBalinese-Regular.ttf||92388:1655828711.0": { + "family_name": "Noto Sans Balinese", + "font-family": "Noto Sans Balinese", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Balinese Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansBalinese-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansBalinese-SemiBold.ttf||91240:1655828711.0": { + "family_name": "Noto Sans Balinese SemiBold", + "font-family": "Noto Sans Balinese SemiBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Balinese SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansBalinese-SemiBold.ttf", + "preferred_family_name": "Noto Sans Balinese", + "preferred_subfamily_name": "SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansBamum-Bold.ttf||229348:1655828711.0": { + "family_name": "Noto Sans Bamum", + "font-family": "Noto Sans Bamum", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Bamum Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/noto/NotoSansBamum-Bold.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansBamum-Medium.ttf||229244:1655828711.0": { + "family_name": "Noto Sans Bamum Medium", + "font-family": "Noto Sans Bamum Medium", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Bamum Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/noto/NotoSansBamum-Medium.ttf", + "preferred_family_name": "Noto Sans Bamum", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansBamum-Regular.ttf||228928:1655828711.0": { + "family_name": "Noto Sans Bamum", + "font-family": "Noto Sans Bamum", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Bamum Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansBamum-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansBamum-SemiBold.ttf||229652:1655828711.0": { + "family_name": "Noto Sans Bamum SemiBold", + "font-family": "Noto Sans Bamum SemiBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Bamum SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/noto/NotoSansBamum-SemiBold.ttf", + "preferred_family_name": "Noto Sans Bamum", + "preferred_subfamily_name": "SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansBassaVah-Bold.ttf||8148:1655828711.0": { + "family_name": "Noto Sans Bassa Vah", + "font-family": "Noto Sans Bassa Vah", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Bassa Vah Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansBassaVah-Bold.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansBassaVah-Medium.ttf||8364:1655828711.0": { + "family_name": "Noto Sans Bassa Vah Medium", + "font-family": "Noto Sans Bassa Vah Medium", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Bassa Vah Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansBassaVah-Medium.ttf", + "preferred_family_name": "Noto Sans Bassa Vah", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansBassaVah-Regular.ttf||8396:1655828711.0": { + "family_name": "Noto Sans Bassa Vah", + "font-family": "Noto Sans Bassa Vah", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Bassa Vah Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansBassaVah-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansBassaVah-SemiBold.ttf||8324:1655828711.0": { + "family_name": "Noto Sans Bassa Vah SemiBold", + "font-family": "Noto Sans Bassa Vah SemiBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Bassa Vah SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansBassaVah-SemiBold.ttf", + "preferred_family_name": "Noto Sans Bassa Vah", + "preferred_subfamily_name": "SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansBatak-Regular.ttf||22372:1655828711.0": { + "family_name": "Noto Sans Batak", + "font-family": "Noto Sans Batak", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Batak Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansBatak-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansBengali-Black.ttf||214404:1655828711.0": { + "family_name": "Noto Sans Bengali Black", + "font-family": "Noto Sans Bengali Black", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Bengali Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansBengali-Black.ttf", + "preferred_family_name": "Noto Sans Bengali", + "preferred_subfamily_name": "Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansBengali-Bold.ttf||209084:1655828711.0": { + "family_name": "Noto Sans Bengali", + "font-family": "Noto Sans Bengali", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Bengali Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansBengali-Bold.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansBengali-Condensed.ttf||201712:1655828711.0": { + "family_name": "Noto Sans Bengali Condensed", + "font-family": "Noto Sans Bengali Condensed", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Bengali Condensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansBengali-Condensed.ttf", + "preferred_family_name": "Noto Sans Bengali", + "preferred_subfamily_name": "Condensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansBengali-ExtraBold.ttf||209632:1655828711.0": { + "family_name": "Noto Sans Bengali ExtraBold", + "font-family": "Noto Sans Bengali ExtraBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Bengali ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansBengali-ExtraBold.ttf", + "preferred_family_name": "Noto Sans Bengali", + "preferred_subfamily_name": "ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansBengali-ExtraCondensed.ttf||202972:1655828711.0": { + "family_name": "Noto Sans Bengali ExtraCondensed", + "font-family": "Noto Sans Bengali ExtraCondensed", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Bengali ExtraCondensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansBengali-ExtraCondensed.ttf", + "preferred_family_name": "Noto Sans Bengali", + "preferred_subfamily_name": "ExtraCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansBengali-ExtraLight.ttf||203952:1655828711.0": { + "family_name": "Noto Sans Bengali ExtraLight", + "font-family": "Noto Sans Bengali ExtraLight", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Bengali ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansBengali-ExtraLight.ttf", + "preferred_family_name": "Noto Sans Bengali", + "preferred_subfamily_name": "ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansBengali-Light.ttf||192156:1655828711.0": { + "family_name": "Noto Sans Bengali Light", + "font-family": "Noto Sans Bengali Light", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Bengali Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansBengali-Light.ttf", + "preferred_family_name": "Noto Sans Bengali", + "preferred_subfamily_name": "Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansBengali-Medium.ttf||204856:1655828711.0": { + "family_name": "Noto Sans Bengali Medium", + "font-family": "Noto Sans Bengali Medium", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Bengali Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansBengali-Medium.ttf", + "preferred_family_name": "Noto Sans Bengali", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansBengali-Regular.ttf||200048:1655828711.0": { + "family_name": "Noto Sans Bengali", + "font-family": "Noto Sans Bengali", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Bengali Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansBengali-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansBengali-SemiBold.ttf||206040:1655828711.0": { + "family_name": "Noto Sans Bengali SemiBold", + "font-family": "Noto Sans Bengali SemiBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Bengali SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansBengali-SemiBold.ttf", + "preferred_family_name": "Noto Sans Bengali", + "preferred_subfamily_name": "SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansBengali-SemiCondensed.ttf||204332:1655828711.0": { + "family_name": "Noto Sans Bengali SemiCondensed", + "font-family": "Noto Sans Bengali SemiCondensed", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Bengali SemiCondensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansBengali-SemiCondensed.ttf", + "preferred_family_name": "Noto Sans Bengali", + "preferred_subfamily_name": "SemiCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansBengali-Thin.ttf||186788:1655828711.0": { + "family_name": "Noto Sans Bengali Thin", + "font-family": "Noto Sans Bengali Thin", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Bengali Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansBengali-Thin.ttf", + "preferred_family_name": "Noto Sans Bengali", + "preferred_subfamily_name": "Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansBengaliUI-Black.ttf||216876:1655828711.0": { + "family_name": "Noto Sans Bengali UI Black", + "font-family": "Noto Sans Bengali UI Black", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Bengali UI Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansBengaliUI-Black.ttf", + "preferred_family_name": "Noto Sans Bengali UI", + "preferred_subfamily_name": "Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansBengaliUI-Bold.ttf||211420:1655828711.0": { + "family_name": "Noto Sans Bengali UI", + "font-family": "Noto Sans Bengali UI", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Bengali UI Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansBengaliUI-Bold.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansBengaliUI-Condensed.ttf||203828:1655828711.0": { + "family_name": "Noto Sans Bengali UI Condensed", + "font-family": "Noto Sans Bengali UI Condensed", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Bengali UI Condensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansBengaliUI-Condensed.ttf", + "preferred_family_name": "Noto Sans Bengali UI", + "preferred_subfamily_name": "Condensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansBengaliUI-ExtraBold.ttf||211748:1655828711.0": { + "family_name": "Noto Sans Bengali UI ExtraBold", + "font-family": "Noto Sans Bengali UI ExtraBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Bengali UI ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansBengaliUI-ExtraBold.ttf", + "preferred_family_name": "Noto Sans Bengali UI", + "preferred_subfamily_name": "ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansBengaliUI-ExtraCondensed.ttf||205052:1655828711.0": { + "family_name": "Noto Sans Bengali UI ExtraCondensed", + "font-family": "Noto Sans Bengali UI ExtraCondensed", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Bengali UI ExtraCondensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansBengaliUI-ExtraCondensed.ttf", + "preferred_family_name": "Noto Sans Bengali UI", + "preferred_subfamily_name": "ExtraCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansBengaliUI-ExtraLight.ttf||206140:1655828711.0": { + "family_name": "Noto Sans Bengali UI ExtraLight", + "font-family": "Noto Sans Bengali UI ExtraLight", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Bengali UI ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansBengaliUI-ExtraLight.ttf", + "preferred_family_name": "Noto Sans Bengali UI", + "preferred_subfamily_name": "ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansBengaliUI-Light.ttf||194716:1655828711.0": { + "family_name": "Noto Sans Bengali UI Light", + "font-family": "Noto Sans Bengali UI Light", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Bengali UI Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansBengaliUI-Light.ttf", + "preferred_family_name": "Noto Sans Bengali UI", + "preferred_subfamily_name": "Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansBengaliUI-Medium.ttf||207192:1655828711.0": { + "family_name": "Noto Sans Bengali UI Medium", + "font-family": "Noto Sans Bengali UI Medium", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Bengali UI Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansBengaliUI-Medium.ttf", + "preferred_family_name": "Noto Sans Bengali UI", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansBengaliUI-Regular.ttf||202456:1655828711.0": { + "family_name": "Noto Sans Bengali UI", + "font-family": "Noto Sans Bengali UI", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Bengali UI Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansBengaliUI-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansBengaliUI-SemiBold.ttf||208436:1655828711.0": { + "family_name": "Noto Sans Bengali UI SemiBold", + "font-family": "Noto Sans Bengali UI SemiBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Bengali UI SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansBengaliUI-SemiBold.ttf", + "preferred_family_name": "Noto Sans Bengali UI", + "preferred_subfamily_name": "SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansBengaliUI-SemiCondensed.ttf||206664:1655828711.0": { + "family_name": "Noto Sans Bengali UI SemiCondensed", + "font-family": "Noto Sans Bengali UI SemiCondensed", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Bengali UI SemiCondensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansBengaliUI-SemiCondensed.ttf", + "preferred_family_name": "Noto Sans Bengali UI", + "preferred_subfamily_name": "SemiCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansBengaliUI-Thin.ttf||189012:1655828711.0": { + "family_name": "Noto Sans Bengali UI Thin", + "font-family": "Noto Sans Bengali UI Thin", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Bengali UI Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansBengaliUI-Thin.ttf", + "preferred_family_name": "Noto Sans Bengali UI", + "preferred_subfamily_name": "Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansBhaiksuki-Regular.ttf||242532:1655828711.0": { + "family_name": "Noto Sans Bhaiksuki", + "font-family": "Noto Sans Bhaiksuki", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Bhaiksuki Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansBhaiksuki-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansBrahmi-Regular.ttf||41780:1655828711.0": { + "family_name": "Noto Sans Brahmi", + "font-family": "Noto Sans Brahmi", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Brahmi Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansBrahmi-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansBuginese-Regular.ttf||7200:1655828711.0": { + "family_name": "Noto Sans Buginese", + "font-family": "Noto Sans Buginese", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Buginese Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansBuginese-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansBuhid-Regular.ttf||11448:1655828711.0": { + "family_name": "Noto Sans Buhid", + "font-family": "Noto Sans Buhid", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Buhid Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansBuhid-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansCanadianAboriginal-Black.ttf||106136:1655828711.0": { + "family_name": "Noto Sans CanAborig Bk", + "font-family": "Noto Sans CanAborig Bk", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Canadian Aboriginal Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansCanadianAboriginal-Black.ttf", + "preferred_family_name": "Noto Sans Canadian Aboriginal", + "preferred_subfamily_name": "Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansCanadianAboriginal-Bold.ttf||107096:1655828711.0": { + "family_name": "Noto Sans CanAborig", + "font-family": "Noto Sans CanAborig", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Canadian Aboriginal Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansCanadianAboriginal-Bold.ttf", + "preferred_family_name": "Noto Sans Canadian Aboriginal", + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansCanadianAboriginal-ExtraBold.ttf||105892:1655828711.0": { + "family_name": "Noto Sans CanAborig XBd", + "font-family": "Noto Sans CanAborig XBd", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Canadian Aboriginal ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansCanadianAboriginal-ExtraBold.ttf", + "preferred_family_name": "Noto Sans Canadian Aboriginal", + "preferred_subfamily_name": "ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansCanadianAboriginal-ExtraLight.ttf||99796:1655828711.0": { + "family_name": "Noto Sans CanAborig XLt", + "font-family": "Noto Sans CanAborig XLt", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Canadian Aboriginal ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansCanadianAboriginal-ExtraLight.ttf", + "preferred_family_name": "Noto Sans Canadian Aboriginal", + "preferred_subfamily_name": "ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansCanadianAboriginal-Light.ttf||99716:1655828711.0": { + "family_name": "Noto Sans CanAborig Lt", + "font-family": "Noto Sans CanAborig Lt", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Canadian Aboriginal Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansCanadianAboriginal-Light.ttf", + "preferred_family_name": "Noto Sans Canadian Aboriginal", + "preferred_subfamily_name": "Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansCanadianAboriginal-Medium.ttf||110512:1655828711.0": { + "family_name": "Noto Sans CanAborig Md", + "font-family": "Noto Sans CanAborig Md", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Canadian Aboriginal Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansCanadianAboriginal-Medium.ttf", + "preferred_family_name": "Noto Sans Canadian Aboriginal", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansCanadianAboriginal-Regular.ttf||113740:1655828711.0": { + "family_name": "Noto Sans CanAborig", + "font-family": "Noto Sans CanAborig", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Canadian Aboriginal Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansCanadianAboriginal-Regular.ttf", + "preferred_family_name": "Noto Sans Canadian Aboriginal", + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansCanadianAboriginal-SemiBold.ttf||108316:1655828711.0": { + "family_name": "Noto Sans CanAborig SmBd", + "font-family": "Noto Sans CanAborig SmBd", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Canadian Aboriginal SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansCanadianAboriginal-SemiBold.ttf", + "preferred_family_name": "Noto Sans Canadian Aboriginal", + "preferred_subfamily_name": "SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansCanadianAboriginal-Thin.ttf||99824:1655828711.0": { + "family_name": "Noto Sans CanAborig Th", + "font-family": "Noto Sans CanAborig Th", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Canadian Aboriginal Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansCanadianAboriginal-Thin.ttf", + "preferred_family_name": "Noto Sans Canadian Aboriginal", + "preferred_subfamily_name": "Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansCarian-Regular.ttf||12856:1655828711.0": { + "family_name": "Noto Sans Carian", + "font-family": "Noto Sans Carian", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Carian Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansCarian-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansCaucasianAlbanian-Regular.ttf||26044:1655828711.0": { + "family_name": "Noto Sans CaucAlban", + "font-family": "Noto Sans CaucAlban", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Caucasian Albanian Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansCaucasianAlbanian-Regular.ttf", + "preferred_family_name": "Noto Sans Caucasian Albanian", + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansChakma-Regular.ttf||81704:1655828711.0": { + "family_name": "Noto Sans Chakma", + "font-family": "Noto Sans Chakma", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Chakma Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansChakma-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansCham-Black.ttf||31360:1655828711.0": { + "family_name": "Noto Sans Cham Blk", + "font-family": "Noto Sans Cham Blk", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Cham Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansCham-Black.ttf", + "preferred_family_name": "Noto Sans Cham", + "preferred_subfamily_name": "Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansCham-Bold.ttf||31324:1655828711.0": { + "family_name": "Noto Sans Cham", + "font-family": "Noto Sans Cham", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Cham Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansCham-Bold.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansCham-ExtraBold.ttf||31432:1655828711.0": { + "family_name": "Noto Sans Cham ExtBd", + "font-family": "Noto Sans Cham ExtBd", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Cham ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansCham-ExtraBold.ttf", + "preferred_family_name": "Noto Sans Cham", + "preferred_subfamily_name": "ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansCham-ExtraLight.ttf||31200:1655828711.0": { + "family_name": "Noto Sans Cham ExtLt", + "font-family": "Noto Sans Cham ExtLt", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Cham ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansCham-ExtraLight.ttf", + "preferred_family_name": "Noto Sans Cham", + "preferred_subfamily_name": "ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansCham-Light.ttf||30960:1655828711.0": { + "family_name": "Noto Sans Cham Light", + "font-family": "Noto Sans Cham Light", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Cham Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansCham-Light.ttf", + "preferred_family_name": "Noto Sans Cham", + "preferred_subfamily_name": "Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansCham-Medium.ttf||31288:1655828711.0": { + "family_name": "Noto Sans Cham Med", + "font-family": "Noto Sans Cham Med", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Cham Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansCham-Medium.ttf", + "preferred_family_name": "Noto Sans Cham", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansCham-Regular.ttf||31092:1655828711.0": { + "family_name": "Noto Sans Cham", + "font-family": "Noto Sans Cham", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Cham Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansCham-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansCham-SemiBold.ttf||31376:1655828711.0": { + "family_name": "Noto Sans Cham SemBd", + "font-family": "Noto Sans Cham SemBd", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Cham SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansCham-SemiBold.ttf", + "preferred_family_name": "Noto Sans Cham", + "preferred_subfamily_name": "SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansCham-Thin.ttf||31080:1655828711.0": { + "family_name": "Noto Sans Cham Thin", + "font-family": "Noto Sans Cham Thin", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Cham Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansCham-Thin.ttf", + "preferred_family_name": "Noto Sans Cham", + "preferred_subfamily_name": "Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansCherokee-Black.ttf||106216:1655828711.0": { + "family_name": "Noto Sans Cherokee Blk", + "font-family": "Noto Sans Cherokee Blk", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Cherokee Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansCherokee-Black.ttf", + "preferred_family_name": "Noto Sans Cherokee", + "preferred_subfamily_name": "Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansCherokee-Bold.ttf||108520:1655828711.0": { + "family_name": "Noto Sans Cherokee", + "font-family": "Noto Sans Cherokee", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Cherokee Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansCherokee-Bold.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansCherokee-ExtraBold.ttf||108996:1655828711.0": { + "family_name": "Noto Sans Cherokee ExtBd", + "font-family": "Noto Sans Cherokee ExtBd", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Cherokee ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansCherokee-ExtraBold.ttf", + "preferred_family_name": "Noto Sans Cherokee", + "preferred_subfamily_name": "ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansCherokee-ExtraLight.ttf||101112:1655828711.0": { + "family_name": "Noto Sans Cherokee ExtLt", + "font-family": "Noto Sans Cherokee ExtLt", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Cherokee ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansCherokee-ExtraLight.ttf", + "preferred_family_name": "Noto Sans Cherokee", + "preferred_subfamily_name": "ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansCherokee-Light.ttf||102400:1655828711.0": { + "family_name": "Noto Sans Cherokee Light", + "font-family": "Noto Sans Cherokee Light", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Cherokee Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansCherokee-Light.ttf", + "preferred_family_name": "Noto Sans Cherokee", + "preferred_subfamily_name": "Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansCherokee-Medium.ttf||107136:1655828711.0": { + "family_name": "Noto Sans Cherokee Med", + "font-family": "Noto Sans Cherokee Med", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Cherokee Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansCherokee-Medium.ttf", + "preferred_family_name": "Noto Sans Cherokee", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansCherokee-Regular.ttf||94600:1655828711.0": { + "family_name": "Noto Sans Cherokee", + "font-family": "Noto Sans Cherokee", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Cherokee Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansCherokee-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansCherokee-SemiBold.ttf||109140:1655828711.0": { + "family_name": "Noto Sans Cherokee SemBd", + "font-family": "Noto Sans Cherokee SemBd", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Cherokee SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansCherokee-SemiBold.ttf", + "preferred_family_name": "Noto Sans Cherokee", + "preferred_subfamily_name": "SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansCherokee-Thin.ttf||96940:1655828711.0": { + "family_name": "Noto Sans Cherokee Thin", + "font-family": "Noto Sans Cherokee Thin", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Cherokee Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansCherokee-Thin.ttf", + "preferred_family_name": "Noto Sans Cherokee", + "preferred_subfamily_name": "Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansChorasmian-Regular.ttf||17652:1655828711.0": { + "family_name": "Noto Sans Chorasmian", + "font-family": "Noto Sans Chorasmian", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 8, + "full_name": "Noto Sans Chorasmian Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/noto/NotoSansChorasmian-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansCoptic-Regular.ttf||50472:1655828711.0": { + "family_name": "Noto Sans Coptic", + "font-family": "Noto Sans Coptic", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Coptic Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansCoptic-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansCuneiform-Regular.ttf||820248:1655828711.0": { + "family_name": "Noto Sans Cuneiform", + "font-family": "Noto Sans Cuneiform", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Cuneiform Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansCuneiform-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansCypriot-Regular.ttf||15088:1655828711.0": { + "family_name": "Noto Sans Cypriot", + "font-family": "Noto Sans Cypriot", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Cypriot Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansCypriot-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansCyproMinoan-Regular.ttf||11860:1655828711.0": { + "family_name": "Noto Sans Cypro Minoan", + "font-family": "Noto Sans Cypro Minoan", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Cypro Minoan Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansCyproMinoan-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDeseret-Regular.ttf||19936:1655828711.0": { + "family_name": "Noto Sans Deseret", + "font-family": "Noto Sans Deseret", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Deseret Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDeseret-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDevanagari-Black.ttf||230944:1655828711.0": { + "family_name": "Noto Sans Devanagari Black", + "font-family": "Noto Sans Devanagari Black", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Devanagari Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDevanagari-Black.ttf", + "preferred_family_name": "Noto Sans Devanagari", + "preferred_subfamily_name": "Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDevanagari-Bold.ttf||225748:1655828711.0": { + "family_name": "Noto Sans Devanagari", + "font-family": "Noto Sans Devanagari", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Devanagari Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDevanagari-Bold.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDevanagari-Condensed.ttf||218776:1655828711.0": { + "family_name": "Noto Sans Devanagari Condensed", + "font-family": "Noto Sans Devanagari Condensed", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Devanagari Condensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDevanagari-Condensed.ttf", + "preferred_family_name": "Noto Sans Devanagari", + "preferred_subfamily_name": "Condensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDevanagari-CondensedBlack.ttf||232136:1655828711.0": { + "family_name": "Noto Sans Devanagari Condensed Black", + "font-family": "Noto Sans Devanagari Condensed Black", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Devanagari Condensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDevanagari-CondensedBlack.ttf", + "preferred_family_name": "Noto Sans Devanagari", + "preferred_subfamily_name": "Condensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDevanagari-CondensedBold.ttf||221740:1655828711.0": { + "family_name": "Noto Sans Devanagari Condensed", + "font-family": "Noto Sans Devanagari Condensed", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Devanagari Condensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDevanagari-CondensedBold.ttf", + "preferred_family_name": "Noto Sans Devanagari", + "preferred_subfamily_name": "Condensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDevanagari-CondensedExtraBold.ttf||226284:1655828711.0": { + "family_name": "Noto Sans Devanagari Condensed ExtraBold", + "font-family": "Noto Sans Devanagari Condensed ExtraBold", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Devanagari Condensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDevanagari-CondensedExtraBold.ttf", + "preferred_family_name": "Noto Sans Devanagari", + "preferred_subfamily_name": "Condensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDevanagari-CondensedExtraLight.ttf||212872:1655828711.0": { + "family_name": "Noto Sans Devanagari Condensed ExtraLight", + "font-family": "Noto Sans Devanagari Condensed ExtraLight", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Devanagari Condensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDevanagari-CondensedExtraLight.ttf", + "preferred_family_name": "Noto Sans Devanagari", + "preferred_subfamily_name": "Condensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDevanagari-CondensedLight.ttf||212820:1655828711.0": { + "family_name": "Noto Sans Devanagari Condensed Light", + "font-family": "Noto Sans Devanagari Condensed Light", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Devanagari Condensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDevanagari-CondensedLight.ttf", + "preferred_family_name": "Noto Sans Devanagari", + "preferred_subfamily_name": "Condensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDevanagari-CondensedMedium.ttf||220652:1655828711.0": { + "family_name": "Noto Sans Devanagari Condensed Medium", + "font-family": "Noto Sans Devanagari Condensed Medium", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Devanagari Condensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDevanagari-CondensedMedium.ttf", + "preferred_family_name": "Noto Sans Devanagari", + "preferred_subfamily_name": "Condensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDevanagari-CondensedSemiBold.ttf||220716:1655828711.0": { + "family_name": "Noto Sans Devanagari Condensed SemiBold", + "font-family": "Noto Sans Devanagari Condensed SemiBold", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Devanagari Condensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDevanagari-CondensedSemiBold.ttf", + "preferred_family_name": "Noto Sans Devanagari", + "preferred_subfamily_name": "Condensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDevanagari-CondensedThin.ttf||213228:1655828711.0": { + "family_name": "Noto Sans Devanagari Condensed Thin", + "font-family": "Noto Sans Devanagari Condensed Thin", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Devanagari Condensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDevanagari-CondensedThin.ttf", + "preferred_family_name": "Noto Sans Devanagari", + "preferred_subfamily_name": "Condensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDevanagari-ExtraBold.ttf||228356:1655828711.0": { + "family_name": "Noto Sans Devanagari ExtraBold", + "font-family": "Noto Sans Devanagari ExtraBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Devanagari ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDevanagari-ExtraBold.ttf", + "preferred_family_name": "Noto Sans Devanagari", + "preferred_subfamily_name": "ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDevanagari-ExtraCondensed.ttf||219504:1655828711.0": { + "family_name": "Noto Sans Devanagari ExtraCondensed", + "font-family": "Noto Sans Devanagari ExtraCondensed", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Devanagari ExtraCondensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDevanagari-ExtraCondensed.ttf", + "preferred_family_name": "Noto Sans Devanagari", + "preferred_subfamily_name": "ExtraCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDevanagari-ExtraCondensedBlack.ttf||227128:1655828711.0": { + "family_name": "Noto Sans Devanagari ExtraCondensed Black", + "font-family": "Noto Sans Devanagari ExtraCondensed Black", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Devanagari ExtraCondensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDevanagari-ExtraCondensedBlack.ttf", + "preferred_family_name": "Noto Sans Devanagari", + "preferred_subfamily_name": "ExtraCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDevanagari-ExtraCondensedBold.ttf||221536:1655828711.0": { + "family_name": "Noto Sans Devanagari ExtraCondensed", + "font-family": "Noto Sans Devanagari ExtraCondensed", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Devanagari ExtraCondensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDevanagari-ExtraCondensedBold.ttf", + "preferred_family_name": "Noto Sans Devanagari", + "preferred_subfamily_name": "ExtraCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDevanagari-ExtraCondensedExtraBold.ttf||223236:1655828711.0": { + "family_name": "Noto Sans Devanagari ExtraCondensed ExtraBold", + "font-family": "Noto Sans Devanagari ExtraCondensed ExtraBold", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Devanagari ExtraCondensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDevanagari-ExtraCondensedExtraBold.ttf", + "preferred_family_name": "Noto Sans Devanagari", + "preferred_subfamily_name": "ExtraCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDevanagari-ExtraCondensedExtraLight.ttf||211864:1655828711.0": { + "family_name": "Noto Sans Devanagari ExtraCondensed ExtraLight", + "font-family": "Noto Sans Devanagari ExtraCondensed ExtraLight", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Devanagari ExtraCondensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDevanagari-ExtraCondensedExtraLight.ttf", + "preferred_family_name": "Noto Sans Devanagari", + "preferred_subfamily_name": "ExtraCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDevanagari-ExtraCondensedLight.ttf||212608:1655828711.0": { + "family_name": "Noto Sans Devanagari ExtraCondensed Light", + "font-family": "Noto Sans Devanagari ExtraCondensed Light", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Devanagari ExtraCondensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDevanagari-ExtraCondensedLight.ttf", + "preferred_family_name": "Noto Sans Devanagari", + "preferred_subfamily_name": "ExtraCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDevanagari-ExtraCondensedMedium.ttf||219888:1655828711.0": { + "family_name": "Noto Sans Devanagari ExtraCondensed Medium", + "font-family": "Noto Sans Devanagari ExtraCondensed Medium", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Devanagari ExtraCondensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDevanagari-ExtraCondensedMedium.ttf", + "preferred_family_name": "Noto Sans Devanagari", + "preferred_subfamily_name": "ExtraCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDevanagari-ExtraCondensedSemiBold.ttf||219592:1655828711.0": { + "family_name": "Noto Sans Devanagari ExtraCondensed SemiBold", + "font-family": "Noto Sans Devanagari ExtraCondensed SemiBold", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Devanagari ExtraCondensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDevanagari-ExtraCondensedSemiBold.ttf", + "preferred_family_name": "Noto Sans Devanagari", + "preferred_subfamily_name": "ExtraCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDevanagari-ExtraCondensedThin.ttf||212784:1655828711.0": { + "family_name": "Noto Sans Devanagari ExtraCondensed Thin", + "font-family": "Noto Sans Devanagari ExtraCondensed Thin", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Devanagari ExtraCondensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDevanagari-ExtraCondensedThin.ttf", + "preferred_family_name": "Noto Sans Devanagari", + "preferred_subfamily_name": "ExtraCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDevanagari-ExtraLight.ttf||217552:1655828711.0": { + "family_name": "Noto Sans Devanagari ExtraLight", + "font-family": "Noto Sans Devanagari ExtraLight", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Devanagari ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDevanagari-ExtraLight.ttf", + "preferred_family_name": "Noto Sans Devanagari", + "preferred_subfamily_name": "ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDevanagari-Light.ttf||215320:1655828711.0": { + "family_name": "Noto Sans Devanagari Light", + "font-family": "Noto Sans Devanagari Light", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Devanagari Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDevanagari-Light.ttf", + "preferred_family_name": "Noto Sans Devanagari", + "preferred_subfamily_name": "Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDevanagari-Medium.ttf||223996:1655828711.0": { + "family_name": "Noto Sans Devanagari Medium", + "font-family": "Noto Sans Devanagari Medium", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Devanagari Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDevanagari-Medium.ttf", + "preferred_family_name": "Noto Sans Devanagari", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDevanagari-Regular.ttf||219212:1655828711.0": { + "family_name": "Noto Sans Devanagari", + "font-family": "Noto Sans Devanagari", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Devanagari Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDevanagari-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDevanagari-SemiBold.ttf||224040:1655828711.0": { + "family_name": "Noto Sans Devanagari SemiBold", + "font-family": "Noto Sans Devanagari SemiBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Devanagari SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDevanagari-SemiBold.ttf", + "preferred_family_name": "Noto Sans Devanagari", + "preferred_subfamily_name": "SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDevanagari-SemiCondensed.ttf||219900:1655828711.0": { + "family_name": "Noto Sans Devanagari SemiCondensed", + "font-family": "Noto Sans Devanagari SemiCondensed", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Devanagari SemiCondensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDevanagari-SemiCondensed.ttf", + "preferred_family_name": "Noto Sans Devanagari", + "preferred_subfamily_name": "SemiCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDevanagari-SemiCondensedBlack.ttf||228052:1655828711.0": { + "family_name": "Noto Sans Devanagari SemiCondensed Black", + "font-family": "Noto Sans Devanagari SemiCondensed Black", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Devanagari SemiCondensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDevanagari-SemiCondensedBlack.ttf", + "preferred_family_name": "Noto Sans Devanagari", + "preferred_subfamily_name": "SemiCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDevanagari-SemiCondensedBold.ttf||223960:1655828711.0": { + "family_name": "Noto Sans Devanagari SemiCondensed", + "font-family": "Noto Sans Devanagari SemiCondensed", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Devanagari SemiCondensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDevanagari-SemiCondensedBold.ttf", + "preferred_family_name": "Noto Sans Devanagari", + "preferred_subfamily_name": "SemiCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDevanagari-SemiCondensedExtraBold.ttf||227524:1655828711.0": { + "family_name": "Noto Sans Devanagari SemiCondensed ExtraBold", + "font-family": "Noto Sans Devanagari SemiCondensed ExtraBold", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Devanagari SemiCondensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDevanagari-SemiCondensedExtraBold.ttf", + "preferred_family_name": "Noto Sans Devanagari", + "preferred_subfamily_name": "SemiCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDevanagari-SemiCondensedExtraLight.ttf||214468:1655828711.0": { + "family_name": "Noto Sans Devanagari SemiCondensed ExtraLight", + "font-family": "Noto Sans Devanagari SemiCondensed ExtraLight", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Devanagari SemiCondensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDevanagari-SemiCondensedExtraLight.ttf", + "preferred_family_name": "Noto Sans Devanagari", + "preferred_subfamily_name": "SemiCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDevanagari-SemiCondensedLight.ttf||213796:1655828711.0": { + "family_name": "Noto Sans Devanagari SemiCondensed Light", + "font-family": "Noto Sans Devanagari SemiCondensed Light", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Devanagari SemiCondensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDevanagari-SemiCondensedLight.ttf", + "preferred_family_name": "Noto Sans Devanagari", + "preferred_subfamily_name": "SemiCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDevanagari-SemiCondensedMedium.ttf||222052:1655828711.0": { + "family_name": "Noto Sans Devanagari SemiCondensed Medium", + "font-family": "Noto Sans Devanagari SemiCondensed Medium", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Devanagari SemiCondensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDevanagari-SemiCondensedMedium.ttf", + "preferred_family_name": "Noto Sans Devanagari", + "preferred_subfamily_name": "SemiCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDevanagari-SemiCondensedSemiBold.ttf||222656:1655828711.0": { + "family_name": "Noto Sans Devanagari SemiCondensed SemiBold", + "font-family": "Noto Sans Devanagari SemiCondensed SemiBold", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Devanagari SemiCondensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDevanagari-SemiCondensedSemiBold.ttf", + "preferred_family_name": "Noto Sans Devanagari", + "preferred_subfamily_name": "SemiCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDevanagari-SemiCondensedThin.ttf||214696:1655828711.0": { + "family_name": "Noto Sans Devanagari SemiCondensed Thin", + "font-family": "Noto Sans Devanagari SemiCondensed Thin", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Devanagari SemiCondensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDevanagari-SemiCondensedThin.ttf", + "preferred_family_name": "Noto Sans Devanagari", + "preferred_subfamily_name": "SemiCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDevanagari-Thin.ttf||217652:1655828711.0": { + "family_name": "Noto Sans Devanagari Thin", + "font-family": "Noto Sans Devanagari Thin", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Devanagari Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDevanagari-Thin.ttf", + "preferred_family_name": "Noto Sans Devanagari", + "preferred_subfamily_name": "Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDevanagariUI-Black.ttf||231236:1655828711.0": { + "family_name": "Noto Sans Devanagari UI Black", + "font-family": "Noto Sans Devanagari UI Black", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Devanagari UI Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDevanagariUI-Black.ttf", + "preferred_family_name": "Noto Sans Devanagari UI", + "preferred_subfamily_name": "Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDevanagariUI-Bold.ttf||226272:1655828711.0": { + "family_name": "Noto Sans Devanagari UI", + "font-family": "Noto Sans Devanagari UI", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Devanagari UI Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDevanagariUI-Bold.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDevanagariUI-Condensed.ttf||219832:1655828711.0": { + "family_name": "Noto Sans Devanagari UI Condensed", + "font-family": "Noto Sans Devanagari UI Condensed", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Devanagari UI Condensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDevanagariUI-Condensed.ttf", + "preferred_family_name": "Noto Sans Devanagari UI", + "preferred_subfamily_name": "Condensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDevanagariUI-CondensedBlack.ttf||232560:1655828711.0": { + "family_name": "Noto Sans Devanagari UI Condensed Black", + "font-family": "Noto Sans Devanagari UI Condensed Black", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Devanagari UI Condensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDevanagariUI-CondensedBlack.ttf", + "preferred_family_name": "Noto Sans Devanagari UI", + "preferred_subfamily_name": "Condensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDevanagariUI-CondensedBold.ttf||222804:1655828711.0": { + "family_name": "Noto Sans Devanagari UI Condensed", + "font-family": "Noto Sans Devanagari UI Condensed", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Devanagari UI Condensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDevanagariUI-CondensedBold.ttf", + "preferred_family_name": "Noto Sans Devanagari UI", + "preferred_subfamily_name": "Condensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDevanagariUI-CondensedExtraBold.ttf||227080:1655828711.0": { + "family_name": "Noto Sans Devanagari UI Condensed ExtraBold", + "font-family": "Noto Sans Devanagari UI Condensed ExtraBold", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Devanagari UI Condensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDevanagariUI-CondensedExtraBold.ttf", + "preferred_family_name": "Noto Sans Devanagari UI", + "preferred_subfamily_name": "Condensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDevanagariUI-CondensedExtraLight.ttf||213692:1655828711.0": { + "family_name": "Noto Sans Devanagari UI Condensed ExtraLight", + "font-family": "Noto Sans Devanagari UI Condensed ExtraLight", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Devanagari UI Condensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDevanagariUI-CondensedExtraLight.ttf", + "preferred_family_name": "Noto Sans Devanagari UI", + "preferred_subfamily_name": "Condensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDevanagariUI-CondensedLight.ttf||213804:1655828711.0": { + "family_name": "Noto Sans Devanagari UI Condensed Light", + "font-family": "Noto Sans Devanagari UI Condensed Light", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Devanagari UI Condensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDevanagariUI-CondensedLight.ttf", + "preferred_family_name": "Noto Sans Devanagari UI", + "preferred_subfamily_name": "Condensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDevanagariUI-CondensedMedium.ttf||221776:1655828711.0": { + "family_name": "Noto Sans Devanagari UI Condensed Medium", + "font-family": "Noto Sans Devanagari UI Condensed Medium", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Devanagari UI Condensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDevanagariUI-CondensedMedium.ttf", + "preferred_family_name": "Noto Sans Devanagari UI", + "preferred_subfamily_name": "Condensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDevanagariUI-CondensedSemiBold.ttf||221276:1655828711.0": { + "family_name": "Noto Sans Devanagari UI Condensed SemiBold", + "font-family": "Noto Sans Devanagari UI Condensed SemiBold", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Devanagari UI Condensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDevanagariUI-CondensedSemiBold.ttf", + "preferred_family_name": "Noto Sans Devanagari UI", + "preferred_subfamily_name": "Condensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDevanagariUI-CondensedThin.ttf||214020:1655828711.0": { + "family_name": "Noto Sans Devanagari UI Condensed Thin", + "font-family": "Noto Sans Devanagari UI Condensed Thin", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Devanagari UI Condensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDevanagariUI-CondensedThin.ttf", + "preferred_family_name": "Noto Sans Devanagari UI", + "preferred_subfamily_name": "Condensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDevanagariUI-ExtraBold.ttf||228720:1655828711.0": { + "family_name": "Noto Sans Devanagari UI ExtraBold", + "font-family": "Noto Sans Devanagari UI ExtraBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Devanagari UI ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDevanagariUI-ExtraBold.ttf", + "preferred_family_name": "Noto Sans Devanagari UI", + "preferred_subfamily_name": "ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDevanagariUI-ExtraCondensed.ttf||220668:1655828711.0": { + "family_name": "Noto Sans Devanagari UI ExtraCondensed", + "font-family": "Noto Sans Devanagari UI ExtraCondensed", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Devanagari UI ExtraCondensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDevanagariUI-ExtraCondensed.ttf", + "preferred_family_name": "Noto Sans Devanagari UI", + "preferred_subfamily_name": "ExtraCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDevanagariUI-ExtraCondensedBlack.ttf||227548:1655828711.0": { + "family_name": "Noto Sans Devanagari UI ExtraCondensed Black", + "font-family": "Noto Sans Devanagari UI ExtraCondensed Black", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Devanagari UI ExtraCondensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDevanagariUI-ExtraCondensedBlack.ttf", + "preferred_family_name": "Noto Sans Devanagari UI", + "preferred_subfamily_name": "ExtraCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDevanagariUI-ExtraCondensedBold.ttf||222520:1655828711.0": { + "family_name": "Noto Sans Devanagari UI ExtraCondensed", + "font-family": "Noto Sans Devanagari UI ExtraCondensed", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Devanagari UI ExtraCondensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDevanagariUI-ExtraCondensedBold.ttf", + "preferred_family_name": "Noto Sans Devanagari UI", + "preferred_subfamily_name": "ExtraCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDevanagariUI-ExtraCondensedExtraBold.ttf||223888:1655828711.0": { + "family_name": "Noto Sans Devanagari UI ExtraCondensed ExtraBold", + "font-family": "Noto Sans Devanagari UI ExtraCondensed ExtraBold", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Devanagari UI ExtraCondensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDevanagariUI-ExtraCondensedExtraBold.ttf", + "preferred_family_name": "Noto Sans Devanagari UI", + "preferred_subfamily_name": "ExtraCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDevanagariUI-ExtraCondensedExtraLight.ttf||212608:1655828711.0": { + "family_name": "Noto Sans Devanagari UI ExtraCondensed ExtraLight", + "font-family": "Noto Sans Devanagari UI ExtraCondensed ExtraLight", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Devanagari UI ExtraCondensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDevanagariUI-ExtraCondensedExtraLight.ttf", + "preferred_family_name": "Noto Sans Devanagari UI", + "preferred_subfamily_name": "ExtraCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDevanagariUI-ExtraCondensedLight.ttf||213748:1655828711.0": { + "family_name": "Noto Sans Devanagari UI ExtraCondensed Light", + "font-family": "Noto Sans Devanagari UI ExtraCondensed Light", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Devanagari UI ExtraCondensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDevanagariUI-ExtraCondensedLight.ttf", + "preferred_family_name": "Noto Sans Devanagari UI", + "preferred_subfamily_name": "ExtraCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDevanagariUI-ExtraCondensedMedium.ttf||221088:1655828711.0": { + "family_name": "Noto Sans Devanagari UI ExtraCondensed Medium", + "font-family": "Noto Sans Devanagari UI ExtraCondensed Medium", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Devanagari UI ExtraCondensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDevanagariUI-ExtraCondensedMedium.ttf", + "preferred_family_name": "Noto Sans Devanagari UI", + "preferred_subfamily_name": "ExtraCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDevanagariUI-ExtraCondensedSemiBold.ttf||220636:1655828711.0": { + "family_name": "Noto Sans Devanagari UI ExtraCondensed SemiBold", + "font-family": "Noto Sans Devanagari UI ExtraCondensed SemiBold", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Devanagari UI ExtraCondensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDevanagariUI-ExtraCondensedSemiBold.ttf", + "preferred_family_name": "Noto Sans Devanagari UI", + "preferred_subfamily_name": "ExtraCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDevanagariUI-ExtraCondensedThin.ttf||213544:1655828711.0": { + "family_name": "Noto Sans Devanagari UI ExtraCondensed Thin", + "font-family": "Noto Sans Devanagari UI ExtraCondensed Thin", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Devanagari UI ExtraCondensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDevanagariUI-ExtraCondensedThin.ttf", + "preferred_family_name": "Noto Sans Devanagari UI", + "preferred_subfamily_name": "ExtraCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDevanagariUI-ExtraLight.ttf||218100:1655828711.0": { + "family_name": "Noto Sans Devanagari UI ExtraLight", + "font-family": "Noto Sans Devanagari UI ExtraLight", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Devanagari UI ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDevanagariUI-ExtraLight.ttf", + "preferred_family_name": "Noto Sans Devanagari UI", + "preferred_subfamily_name": "ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDevanagariUI-Light.ttf||216536:1655828711.0": { + "family_name": "Noto Sans Devanagari UI Light", + "font-family": "Noto Sans Devanagari UI Light", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Devanagari UI Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDevanagariUI-Light.ttf", + "preferred_family_name": "Noto Sans Devanagari UI", + "preferred_subfamily_name": "Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDevanagariUI-Medium.ttf||224676:1655828711.0": { + "family_name": "Noto Sans Devanagari UI Medium", + "font-family": "Noto Sans Devanagari UI Medium", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Devanagari UI Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDevanagariUI-Medium.ttf", + "preferred_family_name": "Noto Sans Devanagari UI", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDevanagariUI-Regular.ttf||219776:1655828711.0": { + "family_name": "Noto Sans Devanagari UI", + "font-family": "Noto Sans Devanagari UI", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Devanagari UI Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDevanagariUI-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDevanagariUI-SemiBold.ttf||225148:1655828711.0": { + "family_name": "Noto Sans Devanagari UI SemiBold", + "font-family": "Noto Sans Devanagari UI SemiBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Devanagari UI SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDevanagariUI-SemiBold.ttf", + "preferred_family_name": "Noto Sans Devanagari UI", + "preferred_subfamily_name": "SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDevanagariUI-SemiCondensed.ttf||220548:1655828711.0": { + "family_name": "Noto Sans Devanagari UI SemiCondensed", + "font-family": "Noto Sans Devanagari UI SemiCondensed", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Devanagari UI SemiCondensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDevanagariUI-SemiCondensed.ttf", + "preferred_family_name": "Noto Sans Devanagari UI", + "preferred_subfamily_name": "SemiCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDevanagariUI-SemiCondensedBlack.ttf||228636:1655828711.0": { + "family_name": "Noto Sans Devanagari UI SemiCondensed Black", + "font-family": "Noto Sans Devanagari UI SemiCondensed Black", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Devanagari UI SemiCondensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDevanagariUI-SemiCondensedBlack.ttf", + "preferred_family_name": "Noto Sans Devanagari UI", + "preferred_subfamily_name": "SemiCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDevanagariUI-SemiCondensedBold.ttf||224564:1655828711.0": { + "family_name": "Noto Sans Devanagari UI SemiCondensed", + "font-family": "Noto Sans Devanagari UI SemiCondensed", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Devanagari UI SemiCondensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDevanagariUI-SemiCondensedBold.ttf", + "preferred_family_name": "Noto Sans Devanagari UI", + "preferred_subfamily_name": "SemiCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDevanagariUI-SemiCondensedExtraBold.ttf||227956:1655828711.0": { + "family_name": "Noto Sans Devanagari UI SemiCondensed ExtraBold", + "font-family": "Noto Sans Devanagari UI SemiCondensed ExtraBold", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Devanagari UI SemiCondensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDevanagariUI-SemiCondensedExtraBold.ttf", + "preferred_family_name": "Noto Sans Devanagari UI", + "preferred_subfamily_name": "SemiCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDevanagariUI-SemiCondensedExtraLight.ttf||215380:1655828711.0": { + "family_name": "Noto Sans Devanagari UI SemiCondensed ExtraLight", + "font-family": "Noto Sans Devanagari UI SemiCondensed ExtraLight", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Devanagari UI SemiCondensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDevanagariUI-SemiCondensedExtraLight.ttf", + "preferred_family_name": "Noto Sans Devanagari UI", + "preferred_subfamily_name": "SemiCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDevanagariUI-SemiCondensedLight.ttf||214640:1655828711.0": { + "family_name": "Noto Sans Devanagari UI SemiCondensed Light", + "font-family": "Noto Sans Devanagari UI SemiCondensed Light", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Devanagari UI SemiCondensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDevanagariUI-SemiCondensedLight.ttf", + "preferred_family_name": "Noto Sans Devanagari UI", + "preferred_subfamily_name": "SemiCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDevanagariUI-SemiCondensedMedium.ttf||222628:1655828711.0": { + "family_name": "Noto Sans Devanagari UI SemiCondensed Medium", + "font-family": "Noto Sans Devanagari UI SemiCondensed Medium", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Devanagari UI SemiCondensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDevanagariUI-SemiCondensedMedium.ttf", + "preferred_family_name": "Noto Sans Devanagari UI", + "preferred_subfamily_name": "SemiCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDevanagariUI-SemiCondensedSemiBold.ttf||223556:1655828711.0": { + "family_name": "Noto Sans Devanagari UI SemiCondensed SemiBold", + "font-family": "Noto Sans Devanagari UI SemiCondensed SemiBold", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Devanagari UI SemiCondensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDevanagariUI-SemiCondensedSemiBold.ttf", + "preferred_family_name": "Noto Sans Devanagari UI", + "preferred_subfamily_name": "SemiCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDevanagariUI-SemiCondensedThin.ttf||215488:1655828711.0": { + "family_name": "Noto Sans Devanagari UI SemiCondensed Thin", + "font-family": "Noto Sans Devanagari UI SemiCondensed Thin", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Devanagari UI SemiCondensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDevanagariUI-SemiCondensedThin.ttf", + "preferred_family_name": "Noto Sans Devanagari UI", + "preferred_subfamily_name": "SemiCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDevanagariUI-Thin.ttf||218480:1655828711.0": { + "family_name": "Noto Sans Devanagari UI Thin", + "font-family": "Noto Sans Devanagari UI Thin", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Devanagari UI Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDevanagariUI-Thin.ttf", + "preferred_family_name": "Noto Sans Devanagari UI", + "preferred_subfamily_name": "Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDisplay-Black.ttf||559748:1655828711.0": { + "family_name": "Noto Sans Display Black", + "font-family": "Noto Sans Display Black", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Display Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDisplay-Black.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "Display Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDisplay-BlackItalic.ttf||565900:1655828711.0": { + "family_name": "Noto Sans Black", + "font-family": "Noto Sans Black", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Display Black Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 2, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDisplay-BlackItalic.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "Display Black Italic", + "subfamily_name": "Italic", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDisplay-Bold.ttf||542744:1655828711.0": { + "family_name": "Noto Sans Display Bold", + "font-family": "Noto Sans Display Bold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Display Bold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDisplay-Bold.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "Display Bold", + "subfamily_name": "Regular", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDisplay-BoldItalic.ttf||553148:1655828711.0": { + "family_name": "Noto Sans Display Bold Italic", + "font-family": "Noto Sans Display Bold Italic", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Display Bold Italic", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 2, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDisplay-BoldItalic.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "Display Bold Italic", + "subfamily_name": "Regular", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDisplay-Condensed.ttf||533824:1655828711.0": { + "family_name": "Noto Sans Display Condensed", + "font-family": "Noto Sans Display Condensed", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Display Condensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDisplay-Condensed.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "Display Condensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDisplay-CondensedBlack.ttf||553540:1655828711.0": { + "family_name": "Noto Sans Display Condensed Black", + "font-family": "Noto Sans Display Condensed Black", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Display Condensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDisplay-CondensedBlack.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "Display Condensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDisplay-CondensedBlackItalic.ttf||565420:1655828711.0": { + "family_name": "Noto Sans Condensed Black", + "font-family": "Noto Sans Condensed Black", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Display Condensed Black Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 6, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDisplay-CondensedBlackItalic.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "Display Condensed Black Italic", + "subfamily_name": "Italic", + "weight": 900, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDisplay-CondensedBold.ttf||542908:1655828711.0": { + "family_name": "Noto Sans Condensed", + "font-family": "Noto Sans Condensed", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Display Condensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDisplay-CondensedBold.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "Display Condensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDisplay-CondensedBoldItalic.ttf||552964:1655828711.0": { + "family_name": "Noto Sans Condensed", + "font-family": "Noto Sans Condensed", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Display Condensed Bold Italic", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 6, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDisplay-CondensedBoldItalic.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "Display Condensed Bold Italic", + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDisplay-CondensedExtraBold.ttf||540352:1655828711.0": { + "family_name": "Noto Sans Display Condensed ExtraBold", + "font-family": "Noto Sans Display Condensed ExtraBold", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Display Condensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDisplay-CondensedExtraBold.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "Display Condensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDisplay-CondensedExtraBoldItalic.ttf||556996:1655828711.0": { + "family_name": "Noto Sans Condensed ExtraBold", + "font-family": "Noto Sans Condensed ExtraBold", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Display Condensed ExtraBold Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 6, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDisplay-CondensedExtraBoldItalic.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "Display Condensed ExtraBold Italic", + "subfamily_name": "Italic", + "weight": 800, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDisplay-CondensedExtraLight.ttf||516732:1655828711.0": { + "family_name": "Noto Sans Display Condensed ExtraLight", + "font-family": "Noto Sans Display Condensed ExtraLight", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Display Condensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDisplay-CondensedExtraLight.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "Display Condensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDisplay-CondensedExtraLightItalic.ttf||534152:1655828711.0": { + "family_name": "Noto Sans Condensed ExtraLight", + "font-family": "Noto Sans Condensed ExtraLight", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Display Condensed ExtraLight Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 6, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDisplay-CondensedExtraLightItalic.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "Display Condensed ExtraLight Italic", + "subfamily_name": "Italic", + "weight": 200, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDisplay-CondensedItalic.ttf||549924:1655828711.0": { + "family_name": "Noto Sans Condensed", + "font-family": "Noto Sans Condensed", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Display Condensed Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 6, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDisplay-CondensedItalic.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "Display Condensed Italic", + "subfamily_name": "Italic", + "weight": 400, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDisplay-CondensedLight.ttf||527376:1655828711.0": { + "family_name": "Noto Sans Display Condensed Light", + "font-family": "Noto Sans Display Condensed Light", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Display Condensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDisplay-CondensedLight.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "Display Condensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDisplay-CondensedLightItalic.ttf||540460:1655828711.0": { + "family_name": "Noto Sans Condensed Light", + "font-family": "Noto Sans Condensed Light", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Display Condensed Light Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 6, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDisplay-CondensedLightItalic.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "Display Condensed Light Italic", + "subfamily_name": "Italic", + "weight": 300, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDisplay-CondensedMedium.ttf||535484:1655828711.0": { + "family_name": "Noto Sans Display Condensed Medium", + "font-family": "Noto Sans Display Condensed Medium", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Display Condensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDisplay-CondensedMedium.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "Display Condensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDisplay-CondensedMediumItalic.ttf||548044:1655828711.0": { + "family_name": "Noto Sans Condensed Medium", + "font-family": "Noto Sans Condensed Medium", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Display Condensed Medium Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 6, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDisplay-CondensedMediumItalic.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "Display Condensed Medium Italic", + "subfamily_name": "Italic", + "weight": 500, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDisplay-CondensedSemiBold.ttf||535688:1655828711.0": { + "family_name": "Noto Sans Display Condensed SemiBold", + "font-family": "Noto Sans Display Condensed SemiBold", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Display Condensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDisplay-CondensedSemiBold.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "Display Condensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDisplay-CondensedSemiBoldItalic.ttf||552456:1655828711.0": { + "family_name": "Noto Sans Condensed SemiBold", + "font-family": "Noto Sans Condensed SemiBold", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Display Condensed SemiBold Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 6, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDisplay-CondensedSemiBoldItalic.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "Display Condensed SemiBold Italic", + "subfamily_name": "Italic", + "weight": 600, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDisplay-CondensedThin.ttf||517704:1655828711.0": { + "family_name": "Noto Sans Display Condensed Thin", + "font-family": "Noto Sans Display Condensed Thin", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Display Condensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDisplay-CondensedThin.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "Display Condensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDisplay-CondensedThinItalic.ttf||534164:1655828711.0": { + "family_name": "Noto Sans Condensed Thin", + "font-family": "Noto Sans Condensed Thin", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Display Condensed Thin Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 6, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDisplay-CondensedThinItalic.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "Display Condensed Thin Italic", + "subfamily_name": "Italic", + "weight": 100, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDisplay-ExtraBold.ttf||545284:1655828711.0": { + "family_name": "Noto Sans Display ExtraBold", + "font-family": "Noto Sans Display ExtraBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Display ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDisplay-ExtraBold.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "Display ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDisplay-ExtraBoldItalic.ttf||553704:1655828711.0": { + "family_name": "Noto Sans ExtraBold", + "font-family": "Noto Sans ExtraBold", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Display ExtraBold Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 2, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDisplay-ExtraBoldItalic.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "Display ExtraBold Italic", + "subfamily_name": "Italic", + "weight": 800, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDisplay-ExtraCondensed.ttf||531312:1655828711.0": { + "family_name": "Noto Sans Display ExtraCondensed", + "font-family": "Noto Sans Display ExtraCondensed", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Display ExtraCondensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDisplay-ExtraCondensed.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "Display ExtraCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDisplay-ExtraCondensedBlack.ttf||547556:1655828711.0": { + "family_name": "Noto Sans Display ExtraCondensed Black", + "font-family": "Noto Sans Display ExtraCondensed Black", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Display ExtraCondensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDisplay-ExtraCondensedBlack.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "Display ExtraCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDisplay-ExtraCondensedBlackItalic.ttf||565764:1655828711.0": { + "family_name": "Noto Sans ExtraCondensed Black", + "font-family": "Noto Sans ExtraCondensed Black", + "font-stretch": "extra-condensed", + "font-style": "italic", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Display ExtraCondensed Black Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 6, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDisplay-ExtraCondensedBlackItalic.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "Display ExtraCondensed Black Italic", + "subfamily_name": "Italic", + "weight": 900, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDisplay-ExtraCondensedBold.ttf||534872:1655828711.0": { + "family_name": "Noto Sans ExtraCondensed", + "font-family": "Noto Sans ExtraCondensed", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Display ExtraCondensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDisplay-ExtraCondensedBold.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "Display ExtraCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDisplay-ExtraCondensedBoldItalic.ttf||551544:1655828711.0": { + "family_name": "Noto Sans ExtraCondensed", + "font-family": "Noto Sans ExtraCondensed", + "font-stretch": "extra-condensed", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Display ExtraCondensed Bold Italic", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 6, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDisplay-ExtraCondensedBoldItalic.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "Display ExtraCondensed Bold Italic", + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDisplay-ExtraCondensedExtraBold.ttf||536564:1655828711.0": { + "family_name": "Noto Sans Display ExtraCondensed ExtraBold", + "font-family": "Noto Sans Display ExtraCondensed ExtraBold", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Display ExtraCondensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDisplay-ExtraCondensedExtraBold.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "Display ExtraCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDisplay-ExtraCondensedExtraBoldItalic.ttf||557588:1655828711.0": { + "family_name": "Noto Sans ExtraCondensed ExtraBold", + "font-family": "Noto Sans ExtraCondensed ExtraBold", + "font-stretch": "extra-condensed", + "font-style": "italic", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Display ExtraCondensed ExtraBold Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 6, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDisplay-ExtraCondensedExtraBoldItalic.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "Display ExtraCondensed ExtraBold Italic", + "subfamily_name": "Italic", + "weight": 800, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDisplay-ExtraCondensedExtraLight.ttf||515652:1655828711.0": { + "family_name": "Noto Sans Display ExtraCondensed ExtraLight", + "font-family": "Noto Sans Display ExtraCondensed ExtraLight", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Display ExtraCondensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDisplay-ExtraCondensedExtraLight.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "Display ExtraCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDisplay-ExtraCondensedExtraLightItalic.ttf||530000:1655828711.0": { + "family_name": "Noto Sans ExtraCondensed ExtraLight", + "font-family": "Noto Sans ExtraCondensed ExtraLight", + "font-stretch": "extra-condensed", + "font-style": "italic", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Display ExtraCondensed ExtraLight Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 6, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDisplay-ExtraCondensedExtraLightItalic.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "Display ExtraCondensed ExtraLight Italic", + "subfamily_name": "Italic", + "weight": 200, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDisplay-ExtraCondensedItalic.ttf||547096:1655828711.0": { + "family_name": "Noto Sans ExtraCondensed", + "font-family": "Noto Sans ExtraCondensed", + "font-stretch": "extra-condensed", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Display ExtraCondensed Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 6, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDisplay-ExtraCondensedItalic.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "Display ExtraCondensed Italic", + "subfamily_name": "Italic", + "weight": 400, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDisplay-ExtraCondensedLight.ttf||523984:1655828711.0": { + "family_name": "Noto Sans Display ExtraCondensed Light", + "font-family": "Noto Sans Display ExtraCondensed Light", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Display ExtraCondensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDisplay-ExtraCondensedLight.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "Display ExtraCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDisplay-ExtraCondensedLightItalic.ttf||537412:1655828711.0": { + "family_name": "Noto Sans ExtraCondensed Light", + "font-family": "Noto Sans ExtraCondensed Light", + "font-stretch": "extra-condensed", + "font-style": "italic", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Display ExtraCondensed Light Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 6, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDisplay-ExtraCondensedLightItalic.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "Display ExtraCondensed Light Italic", + "subfamily_name": "Italic", + "weight": 300, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDisplay-ExtraCondensedMedium.ttf||530080:1655828711.0": { + "family_name": "Noto Sans Display ExtraCondensed Medium", + "font-family": "Noto Sans Display ExtraCondensed Medium", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Display ExtraCondensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDisplay-ExtraCondensedMedium.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "Display ExtraCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDisplay-ExtraCondensedMediumItalic.ttf||549184:1655828711.0": { + "family_name": "Noto Sans ExtraCondensed Medium", + "font-family": "Noto Sans ExtraCondensed Medium", + "font-stretch": "extra-condensed", + "font-style": "italic", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Display ExtraCondensed Medium Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 6, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDisplay-ExtraCondensedMediumItalic.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "Display ExtraCondensed Medium Italic", + "subfamily_name": "Italic", + "weight": 500, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDisplay-ExtraCondensedSemiBold.ttf||529860:1655828711.0": { + "family_name": "Noto Sans Display ExtraCondensed SemiBold", + "font-family": "Noto Sans Display ExtraCondensed SemiBold", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Display ExtraCondensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDisplay-ExtraCondensedSemiBold.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "Display ExtraCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDisplay-ExtraCondensedSemiBoldItalic.ttf||549820:1655828711.0": { + "family_name": "Noto Sans ExtraCondensed SemiBold", + "font-family": "Noto Sans ExtraCondensed SemiBold", + "font-stretch": "extra-condensed", + "font-style": "italic", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Display ExtraCondensed SemiBold Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 6, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDisplay-ExtraCondensedSemiBoldItalic.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "Display ExtraCondensed SemiBold Italic", + "subfamily_name": "Italic", + "weight": 600, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDisplay-ExtraCondensedThin.ttf||515096:1655828711.0": { + "family_name": "Noto Sans Display ExtraCondensed Thin", + "font-family": "Noto Sans Display ExtraCondensed Thin", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Display ExtraCondensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDisplay-ExtraCondensedThin.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "Display ExtraCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDisplay-ExtraCondensedThinItalic.ttf||528224:1655828711.0": { + "family_name": "Noto Sans ExtraCondensed Thin", + "font-family": "Noto Sans ExtraCondensed Thin", + "font-stretch": "extra-condensed", + "font-style": "italic", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Display ExtraCondensed Thin Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 6, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDisplay-ExtraCondensedThinItalic.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "Display ExtraCondensed Thin Italic", + "subfamily_name": "Italic", + "weight": 100, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDisplay-ExtraLight.ttf||518888:1655828711.0": { + "family_name": "Noto Sans Display ExtraLight", + "font-family": "Noto Sans Display ExtraLight", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Display ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDisplay-ExtraLight.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "Display ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDisplay-ExtraLightItalic.ttf||534620:1655828711.0": { + "family_name": "Noto Sans ExtraLight", + "font-family": "Noto Sans ExtraLight", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Display ExtraLight Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 2, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDisplay-ExtraLightItalic.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "Display ExtraLight Italic", + "subfamily_name": "Italic", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDisplay-Italic.ttf||550932:1655828711.0": { + "family_name": "Noto Sans Display Italic", + "font-family": "Noto Sans Display Italic", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Display Italic", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDisplay-Italic.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "Display Italic", + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDisplay-Light.ttf||527520:1655828711.0": { + "family_name": "Noto Sans Display Light", + "font-family": "Noto Sans Display Light", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Display Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDisplay-Light.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "Display Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDisplay-LightItalic.ttf||543352:1655828711.0": { + "family_name": "Noto Sans Light", + "font-family": "Noto Sans Light", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Display Light Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 2, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDisplay-LightItalic.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "Display Light Italic", + "subfamily_name": "Italic", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDisplay-Medium.ttf||536856:1655828711.0": { + "family_name": "Noto Sans Display Medium", + "font-family": "Noto Sans Display Medium", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Display Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDisplay-Medium.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "Display Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDisplay-MediumItalic.ttf||546496:1655828711.0": { + "family_name": "Noto Sans Medium", + "font-family": "Noto Sans Medium", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Display Medium Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 2, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDisplay-MediumItalic.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "Display Medium Italic", + "subfamily_name": "Italic", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDisplay-Regular.ttf||540020:1655828711.0": { + "family_name": "Noto Sans Display", + "font-family": "Noto Sans Display", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Display Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDisplay-Regular.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "Display Regular", + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDisplay-SemiBold.ttf||541544:1655828711.0": { + "family_name": "Noto Sans Display SemiBold", + "font-family": "Noto Sans Display SemiBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Display SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDisplay-SemiBold.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "Display SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDisplay-SemiBoldItalic.ttf||551376:1655828711.0": { + "family_name": "Noto Sans SemiBold", + "font-family": "Noto Sans SemiBold", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Display SemiBold Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 2, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDisplay-SemiBoldItalic.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "Display SemiBold Italic", + "subfamily_name": "Italic", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDisplay-SemiCondensed.ttf||537176:1655828711.0": { + "family_name": "Noto Sans Display SemiCondensed", + "font-family": "Noto Sans Display SemiCondensed", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Display SemiCondensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDisplay-SemiCondensed.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "Display SemiCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDisplay-SemiCondensedBlack.ttf||558048:1655828711.0": { + "family_name": "Noto Sans Display SemiCondensed Black", + "font-family": "Noto Sans Display SemiCondensed Black", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Display SemiCondensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDisplay-SemiCondensedBlack.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "Display SemiCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDisplay-SemiCondensedBlackItalic.ttf||569184:1655828711.0": { + "family_name": "Noto Sans SemiCondensed Black", + "font-family": "Noto Sans SemiCondensed Black", + "font-stretch": "semi-condensed", + "font-style": "italic", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Display SemiCondensed Black Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 2, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDisplay-SemiCondensedBlackItalic.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "Display SemiCondensed Black Italic", + "subfamily_name": "Italic", + "weight": 900, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDisplay-SemiCondensedBold.ttf||544480:1655828711.0": { + "family_name": "Noto Sans SemiCondensed", + "font-family": "Noto Sans SemiCondensed", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Display SemiCondensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDisplay-SemiCondensedBold.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "Display SemiCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDisplay-SemiCondensedBoldItalic.ttf||554468:1655828711.0": { + "family_name": "Noto Sans SemiCondensed", + "font-family": "Noto Sans SemiCondensed", + "font-stretch": "semi-condensed", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Display SemiCondensed Bold Italic", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 2, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDisplay-SemiCondensedBoldItalic.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "Display SemiCondensed Bold Italic", + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDisplay-SemiCondensedExtraBold.ttf||543952:1655828711.0": { + "family_name": "Noto Sans Display SemiCondensed ExtraBold", + "font-family": "Noto Sans Display SemiCondensed ExtraBold", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Display SemiCondensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDisplay-SemiCondensedExtraBold.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "Display SemiCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDisplay-SemiCondensedExtraBoldItalic.ttf||558212:1655828711.0": { + "family_name": "Noto Sans SemiCondensed ExtraBold", + "font-family": "Noto Sans SemiCondensed ExtraBold", + "font-stretch": "semi-condensed", + "font-style": "italic", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Display SemiCondensed ExtraBold Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 2, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDisplay-SemiCondensedExtraBoldItalic.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "Display SemiCondensed ExtraBold Italic", + "subfamily_name": "Italic", + "weight": 800, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDisplay-SemiCondensedExtraLight.ttf||519172:1655828711.0": { + "family_name": "Noto Sans Display SemiCondensed ExtraLight", + "font-family": "Noto Sans Display SemiCondensed ExtraLight", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Display SemiCondensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDisplay-SemiCondensedExtraLight.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "Display SemiCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDisplay-SemiCondensedExtraLightItalic.ttf||534816:1655828711.0": { + "family_name": "Noto Sans SemiCondensed ExtraLight", + "font-family": "Noto Sans SemiCondensed ExtraLight", + "font-stretch": "semi-condensed", + "font-style": "italic", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Display SemiCondensed ExtraLight Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 2, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDisplay-SemiCondensedExtraLightItalic.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "Display SemiCondensed ExtraLight Italic", + "subfamily_name": "Italic", + "weight": 200, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDisplay-SemiCondensedItalic.ttf||552440:1655828711.0": { + "family_name": "Noto Sans SemiCondensed", + "font-family": "Noto Sans SemiCondensed", + "font-stretch": "semi-condensed", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Display SemiCondensed Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDisplay-SemiCondensedItalic.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "Display SemiCondensed Italic", + "subfamily_name": "Italic", + "weight": 400, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDisplay-SemiCondensedLight.ttf||528396:1655828711.0": { + "family_name": "Noto Sans Display SemiCondensed Light", + "font-family": "Noto Sans Display SemiCondensed Light", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Display SemiCondensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDisplay-SemiCondensedLight.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "Display SemiCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDisplay-SemiCondensedLightItalic.ttf||547332:1655828711.0": { + "family_name": "Noto Sans SemiCondensed Light", + "font-family": "Noto Sans SemiCondensed Light", + "font-stretch": "semi-condensed", + "font-style": "italic", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Display SemiCondensed Light Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 2, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDisplay-SemiCondensedLightItalic.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "Display SemiCondensed Light Italic", + "subfamily_name": "Italic", + "weight": 300, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDisplay-SemiCondensedMedium.ttf||536496:1655828711.0": { + "family_name": "Noto Sans Display SemiCondensed Medium", + "font-family": "Noto Sans Display SemiCondensed Medium", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Display SemiCondensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDisplay-SemiCondensedMedium.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "Display SemiCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDisplay-SemiCondensedMediumItalic.ttf||549260:1655828711.0": { + "family_name": "Noto Sans SemiCondensed Medium", + "font-family": "Noto Sans SemiCondensed Medium", + "font-stretch": "semi-condensed", + "font-style": "italic", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Display SemiCondensed Medium Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 2, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDisplay-SemiCondensedMediumItalic.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "Display SemiCondensed Medium Italic", + "subfamily_name": "Italic", + "weight": 500, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDisplay-SemiCondensedSemiBold.ttf||540912:1655828711.0": { + "family_name": "Noto Sans Display SemiCondensed SemiBold", + "font-family": "Noto Sans Display SemiCondensed SemiBold", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Display SemiCondensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDisplay-SemiCondensedSemiBold.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "Display SemiCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDisplay-SemiCondensedSemiBoldItalic.ttf||555216:1655828711.0": { + "family_name": "Noto Sans SemiCondensed SemiBold", + "font-family": "Noto Sans SemiCondensed SemiBold", + "font-stretch": "semi-condensed", + "font-style": "italic", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Display SemiCondensed SemiBold Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 2, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDisplay-SemiCondensedSemiBoldItalic.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "Display SemiCondensed SemiBold Italic", + "subfamily_name": "Italic", + "weight": 600, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDisplay-SemiCondensedThin.ttf||519324:1655828711.0": { + "family_name": "Noto Sans Display SemiCondensed Thin", + "font-family": "Noto Sans Display SemiCondensed Thin", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Display SemiCondensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDisplay-SemiCondensedThin.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "Display SemiCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDisplay-SemiCondensedThinItalic.ttf||535536:1655828711.0": { + "family_name": "Noto Sans SemiCondensed Thin", + "font-family": "Noto Sans SemiCondensed Thin", + "font-stretch": "semi-condensed", + "font-style": "italic", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Display SemiCondensed Thin Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 2, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDisplay-SemiCondensedThinItalic.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "Display SemiCondensed Thin Italic", + "subfamily_name": "Italic", + "weight": 100, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDisplay-Thin.ttf||518724:1655828711.0": { + "family_name": "Noto Sans Display Thin", + "font-family": "Noto Sans Display Thin", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Display Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDisplay-Thin.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "Display Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDisplay-ThinItalic.ttf||534656:1655828711.0": { + "family_name": "Noto Sans Thin", + "font-family": "Noto Sans Thin", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Display Thin Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 2, + 4, + 5, + 4, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDisplay-ThinItalic.ttf", + "preferred_family_name": "Noto Sans", + "preferred_subfamily_name": "Display Thin Italic", + "subfamily_name": "Italic", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansDuployan-Regular.ttf||18728:1655828711.0": { + "family_name": "Noto Sans Duployan", + "font-family": "Noto Sans Duployan", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Duployan Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansDuployan-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansEgyptianHieroglyphs-Regular.ttf||585400:1655828711.0": { + "family_name": "Noto Sans EgyptHiero", + "font-family": "Noto Sans EgyptHiero", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Egyptian Hieroglyphs Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansEgyptianHieroglyphs-Regular.ttf", + "preferred_family_name": "Noto Sans Egyptian Hieroglyphs", + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansElbasan-Regular.ttf||19384:1655828711.0": { + "family_name": "Noto Sans Elbasan", + "font-family": "Noto Sans Elbasan", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Elbasan Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansElbasan-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansElymaic-Regular.ttf||9024:1655828711.0": { + "family_name": "Noto Sans Elymaic", + "font-family": "Noto Sans Elymaic", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Elymaic Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/noto/NotoSansElymaic-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansEthiopic-Black.ttf||343088:1655828711.0": { + "family_name": "Noto Sans Ethiopic Blk", + "font-family": "Noto Sans Ethiopic Blk", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Ethiopic Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansEthiopic-Black.ttf", + "preferred_family_name": "Noto Sans Ethiopic", + "preferred_subfamily_name": "Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansEthiopic-Bold.ttf||342152:1655828711.0": { + "family_name": "Noto Sans Ethiopic", + "font-family": "Noto Sans Ethiopic", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Ethiopic Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansEthiopic-Bold.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansEthiopic-Condensed.ttf||351784:1655828711.0": { + "family_name": "Noto Sans Ethiopic Cond", + "font-family": "Noto Sans Ethiopic Cond", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Ethiopic Condensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansEthiopic-Condensed.ttf", + "preferred_family_name": "Noto Sans Ethiopic", + "preferred_subfamily_name": "Condensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansEthiopic-CondensedBlack.ttf||356620:1655828711.0": { + "family_name": "Noto Sans Ethiopic Cond Blk", + "font-family": "Noto Sans Ethiopic Cond Blk", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Ethiopic Condensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansEthiopic-CondensedBlack.ttf", + "preferred_family_name": "Noto Sans Ethiopic", + "preferred_subfamily_name": "Condensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansEthiopic-CondensedBold.ttf||351528:1655828711.0": { + "family_name": "Noto Sans Ethiopic Cond", + "font-family": "Noto Sans Ethiopic Cond", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Ethiopic Condensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansEthiopic-CondensedBold.ttf", + "preferred_family_name": "Noto Sans Ethiopic", + "preferred_subfamily_name": "Condensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansEthiopic-CondensedExtraBold.ttf||352956:1655828711.0": { + "family_name": "Noto Sans Ethiopic Cond ExtBd", + "font-family": "Noto Sans Ethiopic Cond ExtBd", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Ethiopic Condensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansEthiopic-CondensedExtraBold.ttf", + "preferred_family_name": "Noto Sans Ethiopic", + "preferred_subfamily_name": "Condensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansEthiopic-CondensedExtraLight.ttf||355544:1655828711.0": { + "family_name": "Noto Sans Ethiopic Cond ExtLt", + "font-family": "Noto Sans Ethiopic Cond ExtLt", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Ethiopic Condensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansEthiopic-CondensedExtraLight.ttf", + "preferred_family_name": "Noto Sans Ethiopic", + "preferred_subfamily_name": "Condensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansEthiopic-CondensedLight.ttf||350772:1655828711.0": { + "family_name": "Noto Sans Ethiopic Cond Light", + "font-family": "Noto Sans Ethiopic Cond Light", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Ethiopic Condensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansEthiopic-CondensedLight.ttf", + "preferred_family_name": "Noto Sans Ethiopic", + "preferred_subfamily_name": "Condensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansEthiopic-CondensedMedium.ttf||355464:1655828711.0": { + "family_name": "Noto Sans Ethiopic Cond Med", + "font-family": "Noto Sans Ethiopic Cond Med", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Ethiopic Condensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansEthiopic-CondensedMedium.ttf", + "preferred_family_name": "Noto Sans Ethiopic", + "preferred_subfamily_name": "Condensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansEthiopic-CondensedSemiBold.ttf||352108:1655828711.0": { + "family_name": "Noto Sans Ethiopic Cond SemBd", + "font-family": "Noto Sans Ethiopic Cond SemBd", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Ethiopic Condensed SemiBold ", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansEthiopic-CondensedSemiBold.ttf", + "preferred_family_name": "Noto Sans Ethiopic", + "preferred_subfamily_name": "Condensed SemiBold ", + "subfamily_name": "Regular", + "weight": 600, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansEthiopic-CondensedThin.ttf||320144:1655828711.0": { + "family_name": "Noto Sans Ethiopic Cond Thin", + "font-family": "Noto Sans Ethiopic Cond Thin", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Ethiopic Condensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansEthiopic-CondensedThin.ttf", + "preferred_family_name": "Noto Sans Ethiopic", + "preferred_subfamily_name": "Condensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansEthiopic-ExtraBold.ttf||340572:1655828711.0": { + "family_name": "Noto Sans Ethiopic ExtBd", + "font-family": "Noto Sans Ethiopic ExtBd", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Ethiopic ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansEthiopic-ExtraBold.ttf", + "preferred_family_name": "Noto Sans Ethiopic", + "preferred_subfamily_name": "ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansEthiopic-ExtraCondensed.ttf||294696:1655828711.0": { + "family_name": "Noto Sans Ethiopic ExtCond", + "font-family": "Noto Sans Ethiopic ExtCond", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Ethiopic ExtraCondensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansEthiopic-ExtraCondensed.ttf", + "preferred_family_name": "Noto Sans Ethiopic", + "preferred_subfamily_name": "ExtraCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansEthiopic-ExtraCondensedBlack.ttf||293548:1655828711.0": { + "family_name": "Noto Sans Ethiopic ExtCond Blk", + "font-family": "Noto Sans Ethiopic ExtCond Blk", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Ethiopic ExtraCondensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansEthiopic-ExtraCondensedBlack.ttf", + "preferred_family_name": "Noto Sans Ethiopic", + "preferred_subfamily_name": "ExtraCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansEthiopic-ExtraCondensedBold.ttf||293872:1655828711.0": { + "family_name": "Noto Sans Ethiopic ExtCond", + "font-family": "Noto Sans Ethiopic ExtCond", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Ethiopic ExtraCondensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansEthiopic-ExtraCondensedBold.ttf", + "preferred_family_name": "Noto Sans Ethiopic", + "preferred_subfamily_name": "ExtraCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansEthiopic-ExtraCondensedExtraBold.ttf||303184:1655828711.0": { + "family_name": "Noto Sans Ethiopic ExtCond ExtBd", + "font-family": "Noto Sans Ethiopic ExtCond ExtBd", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Ethiopic ExtraCondensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansEthiopic-ExtraCondensedExtraBold.ttf", + "preferred_family_name": "Noto Sans Ethiopic", + "preferred_subfamily_name": "ExtraCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansEthiopic-ExtraCondensedExtraLight.ttf||298364:1655828711.0": { + "family_name": "Noto Sans Ethiopic ExtCond ExtLt", + "font-family": "Noto Sans Ethiopic ExtCond ExtLt", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Ethiopic ExtraCondensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansEthiopic-ExtraCondensedExtraLight.ttf", + "preferred_family_name": "Noto Sans Ethiopic", + "preferred_subfamily_name": "ExtraCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansEthiopic-ExtraCondensedLight.ttf||318668:1655828711.0": { + "family_name": "Noto Sans Ethiopic ExtCond Light", + "font-family": "Noto Sans Ethiopic ExtCond Light", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Ethiopic ExtraCondensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansEthiopic-ExtraCondensedLight.ttf", + "preferred_family_name": "Noto Sans Ethiopic", + "preferred_subfamily_name": "ExtraCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansEthiopic-ExtraCondensedMedium.ttf||306724:1655828711.0": { + "family_name": "Noto Sans Ethiopic ExtCond Med", + "font-family": "Noto Sans Ethiopic ExtCond Med", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Ethiopic ExtraCondensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansEthiopic-ExtraCondensedMedium.ttf", + "preferred_family_name": "Noto Sans Ethiopic", + "preferred_subfamily_name": "ExtraCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansEthiopic-ExtraCondensedSemiBold.ttf||302636:1655828711.0": { + "family_name": "Noto Sans Ethiopic ExtCond SemBd", + "font-family": "Noto Sans Ethiopic ExtCond SemBd", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Ethiopic ExtraCondensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansEthiopic-ExtraCondensedSemiBold.ttf", + "preferred_family_name": "Noto Sans Ethiopic", + "preferred_subfamily_name": "ExtraCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansEthiopic-ExtraCondensedThin.ttf||275052:1655828711.0": { + "family_name": "Noto Sans Ethiopic ExtCond Thin", + "font-family": "Noto Sans Ethiopic ExtCond Thin", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Ethiopic ExtraCondensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansEthiopic-ExtraCondensedThin.ttf", + "preferred_family_name": "Noto Sans Ethiopic", + "preferred_subfamily_name": "ExtraCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansEthiopic-ExtraLight.ttf||333480:1655828711.0": { + "family_name": "Noto Sans Ethiopic ExtLt", + "font-family": "Noto Sans Ethiopic ExtLt", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Ethiopic ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansEthiopic-ExtraLight.ttf", + "preferred_family_name": "Noto Sans Ethiopic", + "preferred_subfamily_name": "ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansEthiopic-Light.ttf||334568:1655828711.0": { + "family_name": "Noto Sans Ethiopic Light", + "font-family": "Noto Sans Ethiopic Light", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Ethiopic Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansEthiopic-Light.ttf", + "preferred_family_name": "Noto Sans Ethiopic", + "preferred_subfamily_name": "Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansEthiopic-Medium.ttf||344048:1655828711.0": { + "family_name": "Noto Sans Ethiopic Med", + "font-family": "Noto Sans Ethiopic Med", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Ethiopic Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansEthiopic-Medium.ttf", + "preferred_family_name": "Noto Sans Ethiopic", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansEthiopic-Regular.ttf||344328:1655828711.0": { + "family_name": "Noto Sans Ethiopic", + "font-family": "Noto Sans Ethiopic", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Ethiopic Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansEthiopic-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansEthiopic-SemiBold.ttf||338264:1655828711.0": { + "family_name": "Noto Sans Ethiopic SemBd", + "font-family": "Noto Sans Ethiopic SemBd", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Ethiopic SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansEthiopic-SemiBold.ttf", + "preferred_family_name": "Noto Sans Ethiopic", + "preferred_subfamily_name": "SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansEthiopic-SemiCondensed.ttf||356916:1655828711.0": { + "family_name": "Noto Sans Ethiopic SemCond", + "font-family": "Noto Sans Ethiopic SemCond", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Ethiopic SemiCondensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansEthiopic-SemiCondensed.ttf", + "preferred_family_name": "Noto Sans Ethiopic", + "preferred_subfamily_name": "SemiCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansEthiopic-SemiCondensedBlack.ttf||352128:1655828711.0": { + "family_name": "Noto Sans Ethiopic SemCond Blk", + "font-family": "Noto Sans Ethiopic SemCond Blk", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Ethiopic SemiCondensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansEthiopic-SemiCondensedBlack.ttf", + "preferred_family_name": "Noto Sans Ethiopic", + "preferred_subfamily_name": "SemiCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansEthiopic-SemiCondensedBold.ttf||353320:1655828711.0": { + "family_name": "Noto Sans Ethiopic SemCond", + "font-family": "Noto Sans Ethiopic SemCond", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Ethiopic SemiCondensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansEthiopic-SemiCondensedBold.ttf", + "preferred_family_name": "Noto Sans Ethiopic", + "preferred_subfamily_name": "SemiCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansEthiopic-SemiCondensedExtraBold.ttf||353848:1655828711.0": { + "family_name": "Noto Sans Ethiopic SemCond ExtBd", + "font-family": "Noto Sans Ethiopic SemCond ExtBd", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Ethiopic SemiCondensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansEthiopic-SemiCondensedExtraBold.ttf", + "preferred_family_name": "Noto Sans Ethiopic", + "preferred_subfamily_name": "SemiCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansEthiopic-SemiCondensedExtraLight.ttf||347412:1655828711.0": { + "family_name": "Noto Sans Ethiopic SemCond ExtLt", + "font-family": "Noto Sans Ethiopic SemCond ExtLt", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Ethiopic SemiCondensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansEthiopic-SemiCondensedExtraLight.ttf", + "preferred_family_name": "Noto Sans Ethiopic", + "preferred_subfamily_name": "SemiCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansEthiopic-SemiCondensedLight.ttf||351804:1655828711.0": { + "family_name": "Noto Sans Ethiopic SemCond Light", + "font-family": "Noto Sans Ethiopic SemCond Light", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Ethiopic SemiCondensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansEthiopic-SemiCondensedLight.ttf", + "preferred_family_name": "Noto Sans Ethiopic", + "preferred_subfamily_name": "SemiCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansEthiopic-SemiCondensedMedium.ttf||359184:1655828711.0": { + "family_name": "Noto Sans Ethiopic SemCond Med", + "font-family": "Noto Sans Ethiopic SemCond Med", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Ethiopic SemiCondensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansEthiopic-SemiCondensedMedium.ttf", + "preferred_family_name": "Noto Sans Ethiopic", + "preferred_subfamily_name": "SemiCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansEthiopic-SemiCondensedSemiBold.ttf||352412:1655828711.0": { + "family_name": "Noto Sans Ethiopic SemCond SemBd", + "font-family": "Noto Sans Ethiopic SemCond SemBd", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Ethiopic SemiCondensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansEthiopic-SemiCondensedSemiBold.ttf", + "preferred_family_name": "Noto Sans Ethiopic", + "preferred_subfamily_name": "SemiCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansEthiopic-SemiCondensedThin.ttf||331708:1655828711.0": { + "family_name": "Noto Sans Ethiopic SemCond Thin", + "font-family": "Noto Sans Ethiopic SemCond Thin", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Ethiopic SemiCondensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansEthiopic-SemiCondensedThin.ttf", + "preferred_family_name": "Noto Sans Ethiopic", + "preferred_subfamily_name": "SemiCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansEthiopic-Thin.ttf||304336:1655828711.0": { + "family_name": "Noto Sans Ethiopic Thin", + "font-family": "Noto Sans Ethiopic Thin", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Ethiopic Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansEthiopic-Thin.ttf", + "preferred_family_name": "Noto Sans Ethiopic", + "preferred_subfamily_name": "Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGeorgian-Black.ttf||57768:1655828711.0": { + "family_name": "Noto Sans Georgian Blk", + "font-family": "Noto Sans Georgian Blk", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Georgian Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGeorgian-Black.ttf", + "preferred_family_name": "Noto Sans Georgian", + "preferred_subfamily_name": "Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGeorgian-Bold.ttf||55876:1655828711.0": { + "family_name": "Noto Sans Georgian", + "font-family": "Noto Sans Georgian", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Georgian Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGeorgian-Bold.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGeorgian-Condensed.ttf||54072:1655828711.0": { + "family_name": "Noto Sans Georgian Cond", + "font-family": "Noto Sans Georgian Cond", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Georgian Condensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGeorgian-Condensed.ttf", + "preferred_family_name": "Noto Sans Georgian", + "preferred_subfamily_name": "Condensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGeorgian-CondensedBlack.ttf||57704:1655828711.0": { + "family_name": "Noto Sans Georgian Cond Blk", + "font-family": "Noto Sans Georgian Cond Blk", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Georgian Condensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGeorgian-CondensedBlack.ttf", + "preferred_family_name": "Noto Sans Georgian", + "preferred_subfamily_name": "Condensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGeorgian-CondensedBold.ttf||56212:1655828711.0": { + "family_name": "Noto Sans Georgian Cond", + "font-family": "Noto Sans Georgian Cond", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Georgian Condensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGeorgian-CondensedBold.ttf", + "preferred_family_name": "Noto Sans Georgian", + "preferred_subfamily_name": "Condensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGeorgian-CondensedExtraBold.ttf||56888:1655828711.0": { + "family_name": "Noto Sans Georgian Cond ExtBd", + "font-family": "Noto Sans Georgian Cond ExtBd", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Georgian Condensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGeorgian-CondensedExtraBold.ttf", + "preferred_family_name": "Noto Sans Georgian", + "preferred_subfamily_name": "Condensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGeorgian-CondensedExtraLight.ttf||53992:1655828711.0": { + "family_name": "Noto Sans Georgian Cond ExtLt", + "font-family": "Noto Sans Georgian Cond ExtLt", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Georgian Condensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGeorgian-CondensedExtraLight.ttf", + "preferred_family_name": "Noto Sans Georgian", + "preferred_subfamily_name": "Condensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGeorgian-CondensedLight.ttf||53688:1655828711.0": { + "family_name": "Noto Sans Georgian Cond Light", + "font-family": "Noto Sans Georgian Cond Light", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Georgian Condensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGeorgian-CondensedLight.ttf", + "preferred_family_name": "Noto Sans Georgian", + "preferred_subfamily_name": "Condensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGeorgian-CondensedMedium.ttf||55308:1655828711.0": { + "family_name": "Noto Sans Georgian Cond Med", + "font-family": "Noto Sans Georgian Cond Med", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Georgian Condensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGeorgian-CondensedMedium.ttf", + "preferred_family_name": "Noto Sans Georgian", + "preferred_subfamily_name": "Condensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGeorgian-CondensedSemiBold.ttf||55676:1655828711.0": { + "family_name": "Noto Sans Georgian Cond SemBd", + "font-family": "Noto Sans Georgian Cond SemBd", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Georgian Condensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGeorgian-CondensedSemiBold.ttf", + "preferred_family_name": "Noto Sans Georgian", + "preferred_subfamily_name": "Condensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGeorgian-CondensedThin.ttf||54000:1655828711.0": { + "family_name": "Noto Sans Georgian Cond Thin", + "font-family": "Noto Sans Georgian Cond Thin", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Georgian Condensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGeorgian-CondensedThin.ttf", + "preferred_family_name": "Noto Sans Georgian", + "preferred_subfamily_name": "Condensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGeorgian-ExtraBold.ttf||56576:1655828711.0": { + "family_name": "Noto Sans Georgian ExtBd", + "font-family": "Noto Sans Georgian ExtBd", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Georgian ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGeorgian-ExtraBold.ttf", + "preferred_family_name": "Noto Sans Georgian", + "preferred_subfamily_name": "ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGeorgian-ExtraCondensed.ttf||53948:1655828711.0": { + "family_name": "Noto Sans Georgian ExtCond", + "font-family": "Noto Sans Georgian ExtCond", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Georgian ExtraCondensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGeorgian-ExtraCondensed.ttf", + "preferred_family_name": "Noto Sans Georgian", + "preferred_subfamily_name": "ExtraCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGeorgian-ExtraCondensedBlack.ttf||56736:1655828711.0": { + "family_name": "Noto Sans Georgian ExtCond Blk", + "font-family": "Noto Sans Georgian ExtCond Blk", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Georgian ExtraCondensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGeorgian-ExtraCondensedBlack.ttf", + "preferred_family_name": "Noto Sans Georgian", + "preferred_subfamily_name": "ExtraCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGeorgian-ExtraCondensedBold.ttf||55504:1655828711.0": { + "family_name": "Noto Sans Georgian ExtCond", + "font-family": "Noto Sans Georgian ExtCond", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Georgian ExtraCondensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGeorgian-ExtraCondensedBold.ttf", + "preferred_family_name": "Noto Sans Georgian", + "preferred_subfamily_name": "ExtraCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGeorgian-ExtraCondensedExtraBold.ttf||56072:1655828711.0": { + "family_name": "Noto Sans Georgian ExtCond ExtBd", + "font-family": "Noto Sans Georgian ExtCond ExtBd", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Georgian ExtraCondensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGeorgian-ExtraCondensedExtraBold.ttf", + "preferred_family_name": "Noto Sans Georgian", + "preferred_subfamily_name": "ExtraCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGeorgian-ExtraCondensedExtraLight.ttf||53624:1655828711.0": { + "family_name": "Noto Sans Georgian ExtCond ExtLt", + "font-family": "Noto Sans Georgian ExtCond ExtLt", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Georgian ExtraCondensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGeorgian-ExtraCondensedExtraLight.ttf", + "preferred_family_name": "Noto Sans Georgian", + "preferred_subfamily_name": "ExtraCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGeorgian-ExtraCondensedLight.ttf||53296:1655828711.0": { + "family_name": "Noto Sans Georgian ExtCond Light", + "font-family": "Noto Sans Georgian ExtCond Light", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Georgian ExtraCondensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGeorgian-ExtraCondensedLight.ttf", + "preferred_family_name": "Noto Sans Georgian", + "preferred_subfamily_name": "ExtraCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGeorgian-ExtraCondensedMedium.ttf||54504:1655828711.0": { + "family_name": "Noto Sans Georgian ExtCond Med", + "font-family": "Noto Sans Georgian ExtCond Med", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Georgian ExtraCondensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGeorgian-ExtraCondensedMedium.ttf", + "preferred_family_name": "Noto Sans Georgian", + "preferred_subfamily_name": "ExtraCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGeorgian-ExtraCondensedSemiBold.ttf||54732:1655828711.0": { + "family_name": "Noto Sans Georgian ExtCond SemBd", + "font-family": "Noto Sans Georgian ExtCond SemBd", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Georgian ExtraCondensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGeorgian-ExtraCondensedSemiBold.ttf", + "preferred_family_name": "Noto Sans Georgian", + "preferred_subfamily_name": "ExtraCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGeorgian-ExtraCondensedThin.ttf||53568:1655828711.0": { + "family_name": "Noto Sans Georgian ExtCond Thin", + "font-family": "Noto Sans Georgian ExtCond Thin", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Georgian ExtraCondensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGeorgian-ExtraCondensedThin.ttf", + "preferred_family_name": "Noto Sans Georgian", + "preferred_subfamily_name": "ExtraCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGeorgian-ExtraLight.ttf||53648:1655828711.0": { + "family_name": "Noto Sans Georgian ExtLt", + "font-family": "Noto Sans Georgian ExtLt", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Georgian ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGeorgian-ExtraLight.ttf", + "preferred_family_name": "Noto Sans Georgian", + "preferred_subfamily_name": "ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGeorgian-Light.ttf||53360:1655828711.0": { + "family_name": "Noto Sans Georgian Light", + "font-family": "Noto Sans Georgian Light", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Georgian Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGeorgian-Light.ttf", + "preferred_family_name": "Noto Sans Georgian", + "preferred_subfamily_name": "Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGeorgian-Medium.ttf||54800:1655828711.0": { + "family_name": "Noto Sans Georgian Med", + "font-family": "Noto Sans Georgian Med", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Georgian Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGeorgian-Medium.ttf", + "preferred_family_name": "Noto Sans Georgian", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGeorgian-Regular.ttf||53948:1655828711.0": { + "family_name": "Noto Sans Georgian", + "font-family": "Noto Sans Georgian", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Georgian Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGeorgian-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGeorgian-SemiBold.ttf||55404:1655828711.0": { + "family_name": "Noto Sans Georgian SemBd", + "font-family": "Noto Sans Georgian SemBd", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Georgian SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGeorgian-SemiBold.ttf", + "preferred_family_name": "Noto Sans Georgian", + "preferred_subfamily_name": "SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGeorgian-SemiCondensed.ttf||54012:1655828711.0": { + "family_name": "Noto Sans Georgian SemCond", + "font-family": "Noto Sans Georgian SemCond", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Georgian SemiCondensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGeorgian-SemiCondensed.ttf", + "preferred_family_name": "Noto Sans Georgian", + "preferred_subfamily_name": "SemiCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGeorgian-SemiCondensedBlack.ttf||58272:1655828711.0": { + "family_name": "Noto Sans Georgian SemCond Blk", + "font-family": "Noto Sans Georgian SemCond Blk", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Georgian SemiCondensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGeorgian-SemiCondensedBlack.ttf", + "preferred_family_name": "Noto Sans Georgian", + "preferred_subfamily_name": "SemiCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGeorgian-SemiCondensedBold.ttf||56060:1655828711.0": { + "family_name": "Noto Sans Georgian SemCond", + "font-family": "Noto Sans Georgian SemCond", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Georgian SemiCondensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGeorgian-SemiCondensedBold.ttf", + "preferred_family_name": "Noto Sans Georgian", + "preferred_subfamily_name": "SemiCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGeorgian-SemiCondensedExtraBold.ttf||56880:1655828711.0": { + "family_name": "Noto Sans Georgian SemCond ExtBd", + "font-family": "Noto Sans Georgian SemCond ExtBd", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Georgian SemiCondensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGeorgian-SemiCondensedExtraBold.ttf", + "preferred_family_name": "Noto Sans Georgian", + "preferred_subfamily_name": "SemiCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGeorgian-SemiCondensedExtraLight.ttf||53988:1655828711.0": { + "family_name": "Noto Sans Georgian SemCond ExtLt", + "font-family": "Noto Sans Georgian SemCond ExtLt", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Georgian SemiCondensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGeorgian-SemiCondensedExtraLight.ttf", + "preferred_family_name": "Noto Sans Georgian", + "preferred_subfamily_name": "SemiCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGeorgian-SemiCondensedLight.ttf||53916:1655828711.0": { + "family_name": "Noto Sans Georgian SemCond Light", + "font-family": "Noto Sans Georgian SemCond Light", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Georgian SemiCondensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGeorgian-SemiCondensedLight.ttf", + "preferred_family_name": "Noto Sans Georgian", + "preferred_subfamily_name": "SemiCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGeorgian-SemiCondensedMedium.ttf||55316:1655828711.0": { + "family_name": "Noto Sans Georgian SemCond Med", + "font-family": "Noto Sans Georgian SemCond Med", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Georgian SemiCondensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGeorgian-SemiCondensedMedium.ttf", + "preferred_family_name": "Noto Sans Georgian", + "preferred_subfamily_name": "SemiCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGeorgian-SemiCondensedSemiBold.ttf||55748:1655828711.0": { + "family_name": "Noto Sans Georgian SemCond SemBd", + "font-family": "Noto Sans Georgian SemCond SemBd", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Georgian SemiCondensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGeorgian-SemiCondensedSemiBold.ttf", + "preferred_family_name": "Noto Sans Georgian", + "preferred_subfamily_name": "SemiCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGeorgian-SemiCondensedThin.ttf||53996:1655828711.0": { + "family_name": "Noto Sans Georgian SemCond Thin", + "font-family": "Noto Sans Georgian SemCond Thin", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Georgian SemiCondensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGeorgian-SemiCondensedThin.ttf", + "preferred_family_name": "Noto Sans Georgian", + "preferred_subfamily_name": "SemiCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGeorgian-Thin.ttf||53672:1655828711.0": { + "family_name": "Noto Sans Georgian Thin", + "font-family": "Noto Sans Georgian Thin", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Georgian Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGeorgian-Thin.ttf", + "preferred_family_name": "Noto Sans Georgian", + "preferred_subfamily_name": "Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGlagolitic-Regular.ttf||39764:1655828711.0": { + "family_name": "Noto Sans Glagolitic", + "font-family": "Noto Sans Glagolitic", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Glagolitic Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGlagolitic-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGothic-Regular.ttf||11668:1655828711.0": { + "family_name": "Noto Sans Gothic", + "font-family": "Noto Sans Gothic", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Gothic Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGothic-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGrantha-Regular.ttf||454624:1655828711.0": { + "family_name": "Noto Sans Grantha", + "font-family": "Noto Sans Grantha", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Grantha Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGrantha-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGujarati-Black.ttf||213984:1655828711.0": { + "family_name": "Noto Sans Gujarati Black", + "font-family": "Noto Sans Gujarati Black", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Gujarati Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGujarati-Black.ttf", + "preferred_family_name": "Noto Sans Gujarati", + "preferred_subfamily_name": "Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGujarati-Bold.ttf||208708:1655828711.0": { + "family_name": "Noto Sans Gujarati", + "font-family": "Noto Sans Gujarati", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Gujarati Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGujarati-Bold.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGujarati-Condensed.ttf||197444:1655828711.0": { + "family_name": "Noto Sans Gujarati Condensed", + "font-family": "Noto Sans Gujarati Condensed", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Gujarati Condensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGujarati-Condensed.ttf", + "preferred_family_name": "Noto Sans Gujarati", + "preferred_subfamily_name": "Condensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGujarati-CondensedBlack.ttf||210488:1655828711.0": { + "family_name": "Noto Sans Gujarati Condensed Black", + "font-family": "Noto Sans Gujarati Condensed Black", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Gujarati Condensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGujarati-CondensedBlack.ttf", + "preferred_family_name": "Noto Sans Gujarati", + "preferred_subfamily_name": "Condensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGujarati-CondensedBold.ttf||208456:1655828711.0": { + "family_name": "Noto Sans Gujarati Condensed", + "font-family": "Noto Sans Gujarati Condensed", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Gujarati Condensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGujarati-CondensedBold.ttf", + "preferred_family_name": "Noto Sans Gujarati", + "preferred_subfamily_name": "Condensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGujarati-CondensedExtraBold.ttf||214112:1655828711.0": { + "family_name": "Noto Sans Gujarati Condensed ExtraBold", + "font-family": "Noto Sans Gujarati Condensed ExtraBold", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Gujarati Condensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGujarati-CondensedExtraBold.ttf", + "preferred_family_name": "Noto Sans Gujarati", + "preferred_subfamily_name": "Condensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGujarati-CondensedExtraLight.ttf||199784:1655828711.0": { + "family_name": "Noto Sans Gujarati Condensed ExtraLight", + "font-family": "Noto Sans Gujarati Condensed ExtraLight", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Gujarati Condensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGujarati-CondensedExtraLight.ttf", + "preferred_family_name": "Noto Sans Gujarati", + "preferred_subfamily_name": "Condensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGujarati-CondensedLight.ttf||196672:1655828711.0": { + "family_name": "Noto Sans Gujarati Condensed Light", + "font-family": "Noto Sans Gujarati Condensed Light", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Gujarati Condensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGujarati-CondensedLight.ttf", + "preferred_family_name": "Noto Sans Gujarati", + "preferred_subfamily_name": "Condensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGujarati-CondensedMedium.ttf||204604:1655828711.0": { + "family_name": "Noto Sans Gujarati Condensed Medium", + "font-family": "Noto Sans Gujarati Condensed Medium", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Gujarati Condensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGujarati-CondensedMedium.ttf", + "preferred_family_name": "Noto Sans Gujarati", + "preferred_subfamily_name": "Condensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGujarati-CondensedSemiBold.ttf||206176:1655828711.0": { + "family_name": "Noto Sans Gujarati Condensed SemiBold", + "font-family": "Noto Sans Gujarati Condensed SemiBold", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Gujarati Condensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGujarati-CondensedSemiBold.ttf", + "preferred_family_name": "Noto Sans Gujarati", + "preferred_subfamily_name": "Condensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGujarati-CondensedThin.ttf||201436:1655828711.0": { + "family_name": "Noto Sans Gujarati Condensed Thin", + "font-family": "Noto Sans Gujarati Condensed Thin", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Gujarati Condensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGujarati-CondensedThin.ttf", + "preferred_family_name": "Noto Sans Gujarati", + "preferred_subfamily_name": "Condensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGujarati-ExtraBold.ttf||208996:1655828711.0": { + "family_name": "Noto Sans Gujarati ExtraBold", + "font-family": "Noto Sans Gujarati ExtraBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Gujarati ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGujarati-ExtraBold.ttf", + "preferred_family_name": "Noto Sans Gujarati", + "preferred_subfamily_name": "ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGujarati-ExtraCondensed.ttf||196264:1655828711.0": { + "family_name": "Noto Sans Gujarati ExtraCondensed", + "font-family": "Noto Sans Gujarati ExtraCondensed", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Gujarati ExtraCondensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGujarati-ExtraCondensed.ttf", + "preferred_family_name": "Noto Sans Gujarati", + "preferred_subfamily_name": "ExtraCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGujarati-ExtraCondensedBlack.ttf||209968:1655828711.0": { + "family_name": "Noto Sans Gujarati ExtraCondensed Black", + "font-family": "Noto Sans Gujarati ExtraCondensed Black", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Gujarati ExtraCondensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGujarati-ExtraCondensedBlack.ttf", + "preferred_family_name": "Noto Sans Gujarati", + "preferred_subfamily_name": "ExtraCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGujarati-ExtraCondensedBold.ttf||207456:1655828711.0": { + "family_name": "Noto Sans Gujarati ExtraCondensed", + "font-family": "Noto Sans Gujarati ExtraCondensed", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Gujarati ExtraCondensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGujarati-ExtraCondensedBold.ttf", + "preferred_family_name": "Noto Sans Gujarati", + "preferred_subfamily_name": "ExtraCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGujarati-ExtraCondensedExtraBold.ttf||206972:1655828711.0": { + "family_name": "Noto Sans Gujarati ExtraCondensed ExtraBold", + "font-family": "Noto Sans Gujarati ExtraCondensed ExtraBold", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Gujarati ExtraCondensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGujarati-ExtraCondensedExtraBold.ttf", + "preferred_family_name": "Noto Sans Gujarati", + "preferred_subfamily_name": "ExtraCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGujarati-ExtraCondensedExtraLight.ttf||201592:1655828711.0": { + "family_name": "Noto Sans Gujarati ExtraCondensed ExtraLight", + "font-family": "Noto Sans Gujarati ExtraCondensed ExtraLight", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Gujarati ExtraCondensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGujarati-ExtraCondensedExtraLight.ttf", + "preferred_family_name": "Noto Sans Gujarati", + "preferred_subfamily_name": "ExtraCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGujarati-ExtraCondensedLight.ttf||195232:1655828711.0": { + "family_name": "Noto Sans Gujarati ExtraCondensed Light", + "font-family": "Noto Sans Gujarati ExtraCondensed Light", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Gujarati ExtraCondensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGujarati-ExtraCondensedLight.ttf", + "preferred_family_name": "Noto Sans Gujarati", + "preferred_subfamily_name": "ExtraCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGujarati-ExtraCondensedMedium.ttf||204284:1655828711.0": { + "family_name": "Noto Sans Gujarati ExtraCondensed Medium", + "font-family": "Noto Sans Gujarati ExtraCondensed Medium", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Gujarati ExtraCondensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGujarati-ExtraCondensedMedium.ttf", + "preferred_family_name": "Noto Sans Gujarati", + "preferred_subfamily_name": "ExtraCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGujarati-ExtraCondensedSemiBold.ttf||205852:1655828711.0": { + "family_name": "Noto Sans Gujarati ExtraCondensed SemiBold", + "font-family": "Noto Sans Gujarati ExtraCondensed SemiBold", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Gujarati ExtraCondensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGujarati-ExtraCondensedSemiBold.ttf", + "preferred_family_name": "Noto Sans Gujarati", + "preferred_subfamily_name": "ExtraCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGujarati-ExtraCondensedThin.ttf||199316:1655828711.0": { + "family_name": "Noto Sans Gujarati ExtraCondensed Thin", + "font-family": "Noto Sans Gujarati ExtraCondensed Thin", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Gujarati ExtraCondensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGujarati-ExtraCondensedThin.ttf", + "preferred_family_name": "Noto Sans Gujarati", + "preferred_subfamily_name": "ExtraCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGujarati-ExtraLight.ttf||203916:1655828711.0": { + "family_name": "Noto Sans Gujarati ExtraLight", + "font-family": "Noto Sans Gujarati ExtraLight", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Gujarati ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGujarati-ExtraLight.ttf", + "preferred_family_name": "Noto Sans Gujarati", + "preferred_subfamily_name": "ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGujarati-Light.ttf||197100:1655828711.0": { + "family_name": "Noto Sans Gujarati Light", + "font-family": "Noto Sans Gujarati Light", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Gujarati Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGujarati-Light.ttf", + "preferred_family_name": "Noto Sans Gujarati", + "preferred_subfamily_name": "Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGujarati-Medium.ttf||209056:1655828711.0": { + "family_name": "Noto Sans Gujarati Medium", + "font-family": "Noto Sans Gujarati Medium", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Gujarati Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGujarati-Medium.ttf", + "preferred_family_name": "Noto Sans Gujarati", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGujarati-Regular.ttf||208452:1655828711.0": { + "family_name": "Noto Sans Gujarati", + "font-family": "Noto Sans Gujarati", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Gujarati Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGujarati-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGujarati-SemiBold.ttf||207356:1655828711.0": { + "family_name": "Noto Sans Gujarati SemiBold", + "font-family": "Noto Sans Gujarati SemiBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Gujarati SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGujarati-SemiBold.ttf", + "preferred_family_name": "Noto Sans Gujarati", + "preferred_subfamily_name": "SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGujarati-SemiCondensed.ttf||205724:1655828711.0": { + "family_name": "Noto Sans Gujarati SemiCondensed", + "font-family": "Noto Sans Gujarati SemiCondensed", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Gujarati SemiCondensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGujarati-SemiCondensed.ttf", + "preferred_family_name": "Noto Sans Gujarati", + "preferred_subfamily_name": "SemiCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGujarati-SemiCondensedBlack.ttf||212020:1655828711.0": { + "family_name": "Noto Sans Gujarati SemiCondensed Black", + "font-family": "Noto Sans Gujarati SemiCondensed Black", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Gujarati SemiCondensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGujarati-SemiCondensedBlack.ttf", + "preferred_family_name": "Noto Sans Gujarati", + "preferred_subfamily_name": "SemiCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGujarati-SemiCondensedBold.ttf||209544:1655828711.0": { + "family_name": "Noto Sans Gujarati SemiCondensed", + "font-family": "Noto Sans Gujarati SemiCondensed", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Gujarati SemiCondensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGujarati-SemiCondensedBold.ttf", + "preferred_family_name": "Noto Sans Gujarati", + "preferred_subfamily_name": "SemiCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGujarati-SemiCondensedExtraBold.ttf||214552:1655828711.0": { + "family_name": "Noto Sans Gujarati SemiCondensed ExtraBold", + "font-family": "Noto Sans Gujarati SemiCondensed ExtraBold", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Gujarati SemiCondensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGujarati-SemiCondensedExtraBold.ttf", + "preferred_family_name": "Noto Sans Gujarati", + "preferred_subfamily_name": "SemiCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGujarati-SemiCondensedExtraLight.ttf||204096:1655828711.0": { + "family_name": "Noto Sans Gujarati SemiCondensed ExtraLight", + "font-family": "Noto Sans Gujarati SemiCondensed ExtraLight", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Gujarati SemiCondensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGujarati-SemiCondensedExtraLight.ttf", + "preferred_family_name": "Noto Sans Gujarati", + "preferred_subfamily_name": "SemiCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGujarati-SemiCondensedLight.ttf||195112:1655828711.0": { + "family_name": "Noto Sans Gujarati SemiCondensed Light", + "font-family": "Noto Sans Gujarati SemiCondensed Light", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Gujarati SemiCondensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGujarati-SemiCondensedLight.ttf", + "preferred_family_name": "Noto Sans Gujarati", + "preferred_subfamily_name": "SemiCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGujarati-SemiCondensedMedium.ttf||206028:1655828711.0": { + "family_name": "Noto Sans Gujarati SemiCondensed Medium", + "font-family": "Noto Sans Gujarati SemiCondensed Medium", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Gujarati SemiCondensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGujarati-SemiCondensedMedium.ttf", + "preferred_family_name": "Noto Sans Gujarati", + "preferred_subfamily_name": "SemiCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGujarati-SemiCondensedSemiBold.ttf||206796:1655828711.0": { + "family_name": "Noto Sans Gujarati SemiCondensed SemiBold", + "font-family": "Noto Sans Gujarati SemiCondensed SemiBold", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Gujarati SemiCondensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGujarati-SemiCondensedSemiBold.ttf", + "preferred_family_name": "Noto Sans Gujarati", + "preferred_subfamily_name": "SemiCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGujarati-SemiCondensedThin.ttf||203484:1655828711.0": { + "family_name": "Noto Sans Gujarati SemiCondensed Thin", + "font-family": "Noto Sans Gujarati SemiCondensed Thin", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Gujarati SemiCondensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGujarati-SemiCondensedThin.ttf", + "preferred_family_name": "Noto Sans Gujarati", + "preferred_subfamily_name": "SemiCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGujarati-Thin.ttf||204964:1655828711.0": { + "family_name": "Noto Sans Gujarati Thin", + "font-family": "Noto Sans Gujarati Thin", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Gujarati Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGujarati-Thin.ttf", + "preferred_family_name": "Noto Sans Gujarati", + "preferred_subfamily_name": "Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGujaratiUI-Black.ttf||214008:1655828711.0": { + "family_name": "Noto Sans Gujarati UI Black", + "font-family": "Noto Sans Gujarati UI Black", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Gujarati UI Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGujaratiUI-Black.ttf", + "preferred_family_name": "Noto Sans Gujarati UI", + "preferred_subfamily_name": "Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGujaratiUI-Bold.ttf||208748:1655828711.0": { + "family_name": "Noto Sans Gujarati UI", + "font-family": "Noto Sans Gujarati UI", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Gujarati UI Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGujaratiUI-Bold.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGujaratiUI-Condensed.ttf||193316:1655828711.0": { + "family_name": "Noto Sans Gujarati UI Condensed", + "font-family": "Noto Sans Gujarati UI Condensed", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Gujarati UI Condensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGujaratiUI-Condensed.ttf", + "preferred_family_name": "Noto Sans Gujarati UI", + "preferred_subfamily_name": "Condensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGujaratiUI-CondensedBlack.ttf||210504:1655828711.0": { + "family_name": "Noto Sans Gujarati UI Condensed Black", + "font-family": "Noto Sans Gujarati UI Condensed Black", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Gujarati UI Condensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGujaratiUI-CondensedBlack.ttf", + "preferred_family_name": "Noto Sans Gujarati UI", + "preferred_subfamily_name": "Condensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGujaratiUI-CondensedBold.ttf||208508:1655828711.0": { + "family_name": "Noto Sans Gujarati UI Condensed", + "font-family": "Noto Sans Gujarati UI Condensed", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Gujarati UI Condensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGujaratiUI-CondensedBold.ttf", + "preferred_family_name": "Noto Sans Gujarati UI", + "preferred_subfamily_name": "Condensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGujaratiUI-CondensedExtraBold.ttf||214280:1655828711.0": { + "family_name": "Noto Sans Gujarati UI Condensed ExtraBold", + "font-family": "Noto Sans Gujarati UI Condensed ExtraBold", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Gujarati UI Condensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGujaratiUI-CondensedExtraBold.ttf", + "preferred_family_name": "Noto Sans Gujarati UI", + "preferred_subfamily_name": "Condensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGujaratiUI-CondensedExtraLight.ttf||199832:1655828711.0": { + "family_name": "Noto Sans Gujarati UI Condensed ExtraLight", + "font-family": "Noto Sans Gujarati UI Condensed ExtraLight", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Gujarati UI Condensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGujaratiUI-CondensedExtraLight.ttf", + "preferred_family_name": "Noto Sans Gujarati UI", + "preferred_subfamily_name": "Condensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGujaratiUI-CondensedLight.ttf||196716:1655828711.0": { + "family_name": "Noto Sans Gujarati UI Condensed Light", + "font-family": "Noto Sans Gujarati UI Condensed Light", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Gujarati UI Condensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGujaratiUI-CondensedLight.ttf", + "preferred_family_name": "Noto Sans Gujarati UI", + "preferred_subfamily_name": "Condensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGujaratiUI-CondensedMedium.ttf||204652:1655828711.0": { + "family_name": "Noto Sans Gujarati UI Condensed Medium", + "font-family": "Noto Sans Gujarati UI Condensed Medium", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Gujarati UI Condensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGujaratiUI-CondensedMedium.ttf", + "preferred_family_name": "Noto Sans Gujarati UI", + "preferred_subfamily_name": "Condensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGujaratiUI-CondensedSemiBold.ttf||206288:1655828711.0": { + "family_name": "Noto Sans Gujarati UI Condensed SemiBold", + "font-family": "Noto Sans Gujarati UI Condensed SemiBold", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Gujarati UI Condensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGujaratiUI-CondensedSemiBold.ttf", + "preferred_family_name": "Noto Sans Gujarati UI", + "preferred_subfamily_name": "Condensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGujaratiUI-CondensedThin.ttf||201484:1655828711.0": { + "family_name": "Noto Sans Gujarati UI Condensed Thin", + "font-family": "Noto Sans Gujarati UI Condensed Thin", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Gujarati UI Condensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGujaratiUI-CondensedThin.ttf", + "preferred_family_name": "Noto Sans Gujarati UI", + "preferred_subfamily_name": "Condensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGujaratiUI-ExtraBold.ttf||209104:1655828711.0": { + "family_name": "Noto Sans Gujarati UI ExtraBold", + "font-family": "Noto Sans Gujarati UI ExtraBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Gujarati UI ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGujaratiUI-ExtraBold.ttf", + "preferred_family_name": "Noto Sans Gujarati UI", + "preferred_subfamily_name": "ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGujaratiUI-ExtraCondensed.ttf||196312:1655828711.0": { + "family_name": "Noto Sans Gujarati UI ExtraCondensed", + "font-family": "Noto Sans Gujarati UI ExtraCondensed", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Gujarati UI ExtraCondensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGujaratiUI-ExtraCondensed.ttf", + "preferred_family_name": "Noto Sans Gujarati UI", + "preferred_subfamily_name": "ExtraCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGujaratiUI-ExtraCondensedBlack.ttf||210268:1655828711.0": { + "family_name": "Noto Sans Gujarati UI ExtraCondensed Black", + "font-family": "Noto Sans Gujarati UI ExtraCondensed Black", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Gujarati UI ExtraCondensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGujaratiUI-ExtraCondensedBlack.ttf", + "preferred_family_name": "Noto Sans Gujarati UI", + "preferred_subfamily_name": "ExtraCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGujaratiUI-ExtraCondensedBold.ttf||207508:1655828711.0": { + "family_name": "Noto Sans Gujarati UI ExtraCondensed", + "font-family": "Noto Sans Gujarati UI ExtraCondensed", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Gujarati UI ExtraCondensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGujaratiUI-ExtraCondensedBold.ttf", + "preferred_family_name": "Noto Sans Gujarati UI", + "preferred_subfamily_name": "ExtraCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGujaratiUI-ExtraCondensedExtraBold.ttf||207084:1655828711.0": { + "family_name": "Noto Sans Gujarati UI ExtraCondensed ExtraBold", + "font-family": "Noto Sans Gujarati UI ExtraCondensed ExtraBold", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Gujarati UI ExtraCondensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGujaratiUI-ExtraCondensedExtraBold.ttf", + "preferred_family_name": "Noto Sans Gujarati UI", + "preferred_subfamily_name": "ExtraCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGujaratiUI-ExtraCondensedExtraLight.ttf||201636:1655828711.0": { + "family_name": "Noto Sans Gujarati UI ExtraCondensed ExtraLight", + "font-family": "Noto Sans Gujarati UI ExtraCondensed ExtraLight", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Gujarati UI ExtraCondensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGujaratiUI-ExtraCondensedExtraLight.ttf", + "preferred_family_name": "Noto Sans Gujarati UI", + "preferred_subfamily_name": "ExtraCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGujaratiUI-ExtraCondensedLight.ttf||195280:1655828711.0": { + "family_name": "Noto Sans Gujarati UI ExtraCondensed Light", + "font-family": "Noto Sans Gujarati UI ExtraCondensed Light", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Gujarati UI ExtraCondensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGujaratiUI-ExtraCondensedLight.ttf", + "preferred_family_name": "Noto Sans Gujarati UI", + "preferred_subfamily_name": "ExtraCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGujaratiUI-ExtraCondensedMedium.ttf||204328:1655828711.0": { + "family_name": "Noto Sans Gujarati UI ExtraCondensed Medium", + "font-family": "Noto Sans Gujarati UI ExtraCondensed Medium", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Gujarati UI ExtraCondensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGujaratiUI-ExtraCondensedMedium.ttf", + "preferred_family_name": "Noto Sans Gujarati UI", + "preferred_subfamily_name": "ExtraCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGujaratiUI-ExtraCondensedSemiBold.ttf||205960:1655828711.0": { + "family_name": "Noto Sans Gujarati UI ExtraCondensed SemiBold", + "font-family": "Noto Sans Gujarati UI ExtraCondensed SemiBold", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Gujarati UI ExtraCondensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGujaratiUI-ExtraCondensedSemiBold.ttf", + "preferred_family_name": "Noto Sans Gujarati UI", + "preferred_subfamily_name": "ExtraCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGujaratiUI-ExtraCondensedThin.ttf||199360:1655828711.0": { + "family_name": "Noto Sans Gujarati UI ExtraCondensed Thin", + "font-family": "Noto Sans Gujarati UI ExtraCondensed Thin", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Gujarati UI ExtraCondensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGujaratiUI-ExtraCondensedThin.ttf", + "preferred_family_name": "Noto Sans Gujarati UI", + "preferred_subfamily_name": "ExtraCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGujaratiUI-ExtraLight.ttf||203964:1655828711.0": { + "family_name": "Noto Sans Gujarati UI ExtraLight", + "font-family": "Noto Sans Gujarati UI ExtraLight", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Gujarati UI ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGujaratiUI-ExtraLight.ttf", + "preferred_family_name": "Noto Sans Gujarati UI", + "preferred_subfamily_name": "ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGujaratiUI-Light.ttf||197144:1655828711.0": { + "family_name": "Noto Sans Gujarati UI Light", + "font-family": "Noto Sans Gujarati UI Light", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Gujarati UI Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGujaratiUI-Light.ttf", + "preferred_family_name": "Noto Sans Gujarati UI", + "preferred_subfamily_name": "Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGujaratiUI-Medium.ttf||209104:1655828711.0": { + "family_name": "Noto Sans Gujarati UI Medium", + "font-family": "Noto Sans Gujarati UI Medium", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Gujarati UI Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGujaratiUI-Medium.ttf", + "preferred_family_name": "Noto Sans Gujarati UI", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGujaratiUI-Regular.ttf||208492:1655828711.0": { + "family_name": "Noto Sans Gujarati UI", + "font-family": "Noto Sans Gujarati UI", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Gujarati UI Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGujaratiUI-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGujaratiUI-SemiBold.ttf||207472:1655828711.0": { + "family_name": "Noto Sans Gujarati UI SemiBold", + "font-family": "Noto Sans Gujarati UI SemiBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Gujarati UI SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGujaratiUI-SemiBold.ttf", + "preferred_family_name": "Noto Sans Gujarati UI", + "preferred_subfamily_name": "SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGujaratiUI-SemiCondensed.ttf||205768:1655828711.0": { + "family_name": "Noto Sans Gujarati UI SemiCondensed", + "font-family": "Noto Sans Gujarati UI SemiCondensed", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Gujarati UI SemiCondensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGujaratiUI-SemiCondensed.ttf", + "preferred_family_name": "Noto Sans Gujarati UI", + "preferred_subfamily_name": "SemiCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGujaratiUI-SemiCondensedBlack.ttf||212104:1655828711.0": { + "family_name": "Noto Sans Gujarati UI SemiCondensed Black", + "font-family": "Noto Sans Gujarati UI SemiCondensed Black", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Gujarati UI SemiCondensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGujaratiUI-SemiCondensedBlack.ttf", + "preferred_family_name": "Noto Sans Gujarati UI", + "preferred_subfamily_name": "SemiCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGujaratiUI-SemiCondensedBold.ttf||209704:1655828711.0": { + "family_name": "Noto Sans Gujarati UI SemiCondensed", + "font-family": "Noto Sans Gujarati UI SemiCondensed", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Gujarati UI SemiCondensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGujaratiUI-SemiCondensedBold.ttf", + "preferred_family_name": "Noto Sans Gujarati UI", + "preferred_subfamily_name": "SemiCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGujaratiUI-SemiCondensedExtraBold.ttf||214596:1655828711.0": { + "family_name": "Noto Sans Gujarati UI SemiCondensed ExtraBold", + "font-family": "Noto Sans Gujarati UI SemiCondensed ExtraBold", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Gujarati UI SemiCondensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGujaratiUI-SemiCondensedExtraBold.ttf", + "preferred_family_name": "Noto Sans Gujarati UI", + "preferred_subfamily_name": "SemiCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGujaratiUI-SemiCondensedExtraLight.ttf||204144:1655828711.0": { + "family_name": "Noto Sans Gujarati UI SemiCondensed ExtraLight", + "font-family": "Noto Sans Gujarati UI SemiCondensed ExtraLight", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Gujarati UI SemiCondensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGujaratiUI-SemiCondensedExtraLight.ttf", + "preferred_family_name": "Noto Sans Gujarati UI", + "preferred_subfamily_name": "SemiCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGujaratiUI-SemiCondensedLight.ttf||195156:1655828711.0": { + "family_name": "Noto Sans Gujarati UI SemiCondensed Light", + "font-family": "Noto Sans Gujarati UI SemiCondensed Light", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Gujarati UI SemiCondensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGujaratiUI-SemiCondensedLight.ttf", + "preferred_family_name": "Noto Sans Gujarati UI", + "preferred_subfamily_name": "SemiCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGujaratiUI-SemiCondensedMedium.ttf||206076:1655828711.0": { + "family_name": "Noto Sans Gujarati UI SemiCondensed Medium", + "font-family": "Noto Sans Gujarati UI SemiCondensed Medium", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Gujarati UI SemiCondensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGujaratiUI-SemiCondensedMedium.ttf", + "preferred_family_name": "Noto Sans Gujarati UI", + "preferred_subfamily_name": "SemiCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGujaratiUI-SemiCondensedSemiBold.ttf||206912:1655828711.0": { + "family_name": "Noto Sans Gujarati UI SemiCondensed SemiBold", + "font-family": "Noto Sans Gujarati UI SemiCondensed SemiBold", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Gujarati UI SemiCondensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGujaratiUI-SemiCondensedSemiBold.ttf", + "preferred_family_name": "Noto Sans Gujarati UI", + "preferred_subfamily_name": "SemiCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGujaratiUI-SemiCondensedThin.ttf||203532:1655828711.0": { + "family_name": "Noto Sans Gujarati UI SemiCondensed Thin", + "font-family": "Noto Sans Gujarati UI SemiCondensed Thin", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Gujarati UI SemiCondensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGujaratiUI-SemiCondensedThin.ttf", + "preferred_family_name": "Noto Sans Gujarati UI", + "preferred_subfamily_name": "SemiCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGujaratiUI-Thin.ttf||205012:1655828711.0": { + "family_name": "Noto Sans Gujarati UI Thin", + "font-family": "Noto Sans Gujarati UI Thin", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Gujarati UI Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGujaratiUI-Thin.ttf", + "preferred_family_name": "Noto Sans Gujarati UI", + "preferred_subfamily_name": "Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGunjalaGondi-Bold.ttf||70692:1655828711.0": { + "family_name": "Noto Sans Gunjala Gondi", + "font-family": "Noto Sans Gunjala Gondi", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Gunjala Gondi Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/noto/NotoSansGunjalaGondi-Bold.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGunjalaGondi-Medium.ttf||69624:1655828711.0": { + "family_name": "Noto Sans Gunjala Gondi Medium", + "font-family": "Noto Sans Gunjala Gondi Medium", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Gunjala Gondi Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/noto/NotoSansGunjalaGondi-Medium.ttf", + "preferred_family_name": "Noto Sans Gunjala Gondi", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGunjalaGondi-Regular.ttf||70180:1655828711.0": { + "family_name": "Noto Sans Gunjala Gondi", + "font-family": "Noto Sans Gunjala Gondi", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Gunjala Gondi Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/noto/NotoSansGunjalaGondi-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGunjalaGondi-Semibold.ttf||69708:1655828711.0": { + "family_name": "Noto Sans Gunjala Gondi Semibold", + "font-family": "Noto Sans Gunjala Gondi Semibold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Gunjala Gondi Semibold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/noto/NotoSansGunjalaGondi-Semibold.ttf", + "preferred_family_name": "Noto Sans Gunjala Gondi", + "preferred_subfamily_name": "Semibold", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGurmukhi-Black.ttf||55112:1655828711.0": { + "family_name": "Noto Sans Gurmukhi Black", + "font-family": "Noto Sans Gurmukhi Black", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Gurmukhi Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGurmukhi-Black.ttf", + "preferred_family_name": "Noto Sans Gurmukhi", + "preferred_subfamily_name": "Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGurmukhi-Bold.ttf||53004:1655828711.0": { + "family_name": "Noto Sans Gurmukhi", + "font-family": "Noto Sans Gurmukhi", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Gurmukhi Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGurmukhi-Bold.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGurmukhi-Condensed.ttf||51948:1655828711.0": { + "family_name": "Noto Sans Gurmukhi Condensed", + "font-family": "Noto Sans Gurmukhi Condensed", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Gurmukhi Condensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGurmukhi-Condensed.ttf", + "preferred_family_name": "Noto Sans Gurmukhi", + "preferred_subfamily_name": "Condensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGurmukhi-CondensedBlack.ttf||54008:1655828711.0": { + "family_name": "Noto Sans Gurmukhi Condensed Black", + "font-family": "Noto Sans Gurmukhi Condensed Black", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Gurmukhi Condensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGurmukhi-CondensedBlack.ttf", + "preferred_family_name": "Noto Sans Gurmukhi", + "preferred_subfamily_name": "Condensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGurmukhi-CondensedBold.ttf||52740:1655828711.0": { + "family_name": "Noto Sans Gurmukhi Condensed", + "font-family": "Noto Sans Gurmukhi Condensed", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Gurmukhi Condensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGurmukhi-CondensedBold.ttf", + "preferred_family_name": "Noto Sans Gurmukhi", + "preferred_subfamily_name": "Condensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGurmukhi-CondensedExtraBold.ttf||53468:1655828711.0": { + "family_name": "Noto Sans Gurmukhi Condensed ExtraBold", + "font-family": "Noto Sans Gurmukhi Condensed ExtraBold", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Gurmukhi Condensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGurmukhi-CondensedExtraBold.ttf", + "preferred_family_name": "Noto Sans Gurmukhi", + "preferred_subfamily_name": "Condensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGurmukhi-CondensedExtraLight.ttf||53228:1655828711.0": { + "family_name": "Noto Sans Gurmukhi Condensed ExtraLight", + "font-family": "Noto Sans Gurmukhi Condensed ExtraLight", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Gurmukhi Condensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGurmukhi-CondensedExtraLight.ttf", + "preferred_family_name": "Noto Sans Gurmukhi", + "preferred_subfamily_name": "Condensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGurmukhi-CondensedLight.ttf||52248:1655828711.0": { + "family_name": "Noto Sans Gurmukhi Condensed Light", + "font-family": "Noto Sans Gurmukhi Condensed Light", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Gurmukhi Condensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGurmukhi-CondensedLight.ttf", + "preferred_family_name": "Noto Sans Gurmukhi", + "preferred_subfamily_name": "Condensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGurmukhi-CondensedMedium.ttf||52196:1655828711.0": { + "family_name": "Noto Sans Gurmukhi Condensed Medium", + "font-family": "Noto Sans Gurmukhi Condensed Medium", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Gurmukhi Condensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGurmukhi-CondensedMedium.ttf", + "preferred_family_name": "Noto Sans Gurmukhi", + "preferred_subfamily_name": "Condensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGurmukhi-CondensedSemiBold.ttf||52820:1655828711.0": { + "family_name": "Noto Sans Gurmukhi Condensed SemiBold", + "font-family": "Noto Sans Gurmukhi Condensed SemiBold", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Gurmukhi Condensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGurmukhi-CondensedSemiBold.ttf", + "preferred_family_name": "Noto Sans Gurmukhi", + "preferred_subfamily_name": "Condensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGurmukhi-CondensedThin.ttf||51516:1655828711.0": { + "family_name": "Noto Sans Gurmukhi Condensed Thin", + "font-family": "Noto Sans Gurmukhi Condensed Thin", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Gurmukhi Condensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGurmukhi-CondensedThin.ttf", + "preferred_family_name": "Noto Sans Gurmukhi", + "preferred_subfamily_name": "Condensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGurmukhi-ExtraBold.ttf||54160:1655828711.0": { + "family_name": "Noto Sans Gurmukhi ExtraBold", + "font-family": "Noto Sans Gurmukhi ExtraBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Gurmukhi ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGurmukhi-ExtraBold.ttf", + "preferred_family_name": "Noto Sans Gurmukhi", + "preferred_subfamily_name": "ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGurmukhi-ExtraCondensed.ttf||51884:1655828711.0": { + "family_name": "Noto Sans Gurmukhi ExtraCondensed", + "font-family": "Noto Sans Gurmukhi ExtraCondensed", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Gurmukhi ExtraCondensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGurmukhi-ExtraCondensed.ttf", + "preferred_family_name": "Noto Sans Gurmukhi", + "preferred_subfamily_name": "ExtraCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGurmukhi-ExtraCondensedBlack.ttf||54208:1655828711.0": { + "family_name": "Noto Sans Gurmukhi ExtraCondensed Black", + "font-family": "Noto Sans Gurmukhi ExtraCondensed Black", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Gurmukhi ExtraCondensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGurmukhi-ExtraCondensedBlack.ttf", + "preferred_family_name": "Noto Sans Gurmukhi", + "preferred_subfamily_name": "ExtraCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGurmukhi-ExtraCondensedBold.ttf||52104:1655828711.0": { + "family_name": "Noto Sans Gurmukhi ExtraCondensed", + "font-family": "Noto Sans Gurmukhi ExtraCondensed", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Gurmukhi ExtraCondensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGurmukhi-ExtraCondensedBold.ttf", + "preferred_family_name": "Noto Sans Gurmukhi", + "preferred_subfamily_name": "ExtraCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGurmukhi-ExtraCondensedExtraBold.ttf||53100:1655828711.0": { + "family_name": "Noto Sans Gurmukhi ExtraCondensed ExtraBold", + "font-family": "Noto Sans Gurmukhi ExtraCondensed ExtraBold", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Gurmukhi ExtraCondensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGurmukhi-ExtraCondensedExtraBold.ttf", + "preferred_family_name": "Noto Sans Gurmukhi", + "preferred_subfamily_name": "ExtraCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGurmukhi-ExtraCondensedExtraLight.ttf||53076:1655828711.0": { + "family_name": "Noto Sans Gurmukhi ExtraCondensed ExtraLight", + "font-family": "Noto Sans Gurmukhi ExtraCondensed ExtraLight", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Gurmukhi ExtraCondensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGurmukhi-ExtraCondensedExtraLight.ttf", + "preferred_family_name": "Noto Sans Gurmukhi", + "preferred_subfamily_name": "ExtraCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGurmukhi-ExtraCondensedLight.ttf||51924:1655828711.0": { + "family_name": "Noto Sans Gurmukhi ExtraCondensed Light", + "font-family": "Noto Sans Gurmukhi ExtraCondensed Light", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Gurmukhi ExtraCondensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGurmukhi-ExtraCondensedLight.ttf", + "preferred_family_name": "Noto Sans Gurmukhi", + "preferred_subfamily_name": "ExtraCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGurmukhi-ExtraCondensedMedium.ttf||52468:1655828711.0": { + "family_name": "Noto Sans Gurmukhi ExtraCondensed Medium", + "font-family": "Noto Sans Gurmukhi ExtraCondensed Medium", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Gurmukhi ExtraCondensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGurmukhi-ExtraCondensedMedium.ttf", + "preferred_family_name": "Noto Sans Gurmukhi", + "preferred_subfamily_name": "ExtraCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGurmukhi-ExtraCondensedSemiBold.ttf||52964:1655828711.0": { + "family_name": "Noto Sans Gurmukhi ExtraCondensed SemiBold", + "font-family": "Noto Sans Gurmukhi ExtraCondensed SemiBold", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Gurmukhi ExtraCondensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGurmukhi-ExtraCondensedSemiBold.ttf", + "preferred_family_name": "Noto Sans Gurmukhi", + "preferred_subfamily_name": "ExtraCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGurmukhi-ExtraCondensedThin.ttf||51452:1655828711.0": { + "family_name": "Noto Sans Gurmukhi ExtraCondensed Thin", + "font-family": "Noto Sans Gurmukhi ExtraCondensed Thin", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Gurmukhi ExtraCondensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGurmukhi-ExtraCondensedThin.ttf", + "preferred_family_name": "Noto Sans Gurmukhi", + "preferred_subfamily_name": "ExtraCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGurmukhi-ExtraLight.ttf||53152:1655828711.0": { + "family_name": "Noto Sans Gurmukhi ExtraLight", + "font-family": "Noto Sans Gurmukhi ExtraLight", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Gurmukhi ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGurmukhi-ExtraLight.ttf", + "preferred_family_name": "Noto Sans Gurmukhi", + "preferred_subfamily_name": "ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGurmukhi-Light.ttf||52680:1655828711.0": { + "family_name": "Noto Sans Gurmukhi Light", + "font-family": "Noto Sans Gurmukhi Light", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Gurmukhi Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGurmukhi-Light.ttf", + "preferred_family_name": "Noto Sans Gurmukhi", + "preferred_subfamily_name": "Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGurmukhi-Medium.ttf||53112:1655828711.0": { + "family_name": "Noto Sans Gurmukhi Medium", + "font-family": "Noto Sans Gurmukhi Medium", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Gurmukhi Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGurmukhi-Medium.ttf", + "preferred_family_name": "Noto Sans Gurmukhi", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGurmukhi-Regular.ttf||53000:1655828711.0": { + "family_name": "Noto Sans Gurmukhi", + "font-family": "Noto Sans Gurmukhi", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Gurmukhi Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGurmukhi-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGurmukhi-SemiBold.ttf||53232:1655828711.0": { + "family_name": "Noto Sans Gurmukhi SemiBold", + "font-family": "Noto Sans Gurmukhi SemiBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Gurmukhi SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGurmukhi-SemiBold.ttf", + "preferred_family_name": "Noto Sans Gurmukhi", + "preferred_subfamily_name": "SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGurmukhi-SemiCondensed.ttf||52948:1655828711.0": { + "family_name": "Noto Sans Gurmukhi SemiCondensed", + "font-family": "Noto Sans Gurmukhi SemiCondensed", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Gurmukhi SemiCondensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGurmukhi-SemiCondensed.ttf", + "preferred_family_name": "Noto Sans Gurmukhi", + "preferred_subfamily_name": "SemiCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGurmukhi-SemiCondensedBlack.ttf||54368:1655828711.0": { + "family_name": "Noto Sans Gurmukhi SemiCondensed Black", + "font-family": "Noto Sans Gurmukhi SemiCondensed Black", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Gurmukhi SemiCondensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGurmukhi-SemiCondensedBlack.ttf", + "preferred_family_name": "Noto Sans Gurmukhi", + "preferred_subfamily_name": "SemiCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGurmukhi-SemiCondensedBold.ttf||53160:1655828711.0": { + "family_name": "Noto Sans Gurmukhi SemiCondensed", + "font-family": "Noto Sans Gurmukhi SemiCondensed", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Gurmukhi SemiCondensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGurmukhi-SemiCondensedBold.ttf", + "preferred_family_name": "Noto Sans Gurmukhi", + "preferred_subfamily_name": "SemiCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGurmukhi-SemiCondensedExtraBold.ttf||53592:1655828711.0": { + "family_name": "Noto Sans Gurmukhi SemiCondensed ExtraBold", + "font-family": "Noto Sans Gurmukhi SemiCondensed ExtraBold", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Gurmukhi SemiCondensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGurmukhi-SemiCondensedExtraBold.ttf", + "preferred_family_name": "Noto Sans Gurmukhi", + "preferred_subfamily_name": "SemiCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGurmukhi-SemiCondensedExtraLight.ttf||53008:1655828711.0": { + "family_name": "Noto Sans Gurmukhi SemiCondensed ExtraLight", + "font-family": "Noto Sans Gurmukhi SemiCondensed ExtraLight", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Gurmukhi SemiCondensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGurmukhi-SemiCondensedExtraLight.ttf", + "preferred_family_name": "Noto Sans Gurmukhi", + "preferred_subfamily_name": "SemiCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGurmukhi-SemiCondensedLight.ttf||52248:1655828711.0": { + "family_name": "Noto Sans Gurmukhi SemiCondensed Light", + "font-family": "Noto Sans Gurmukhi SemiCondensed Light", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Gurmukhi SemiCondensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGurmukhi-SemiCondensedLight.ttf", + "preferred_family_name": "Noto Sans Gurmukhi", + "preferred_subfamily_name": "SemiCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGurmukhi-SemiCondensedMedium.ttf||52720:1655828711.0": { + "family_name": "Noto Sans Gurmukhi SemiCondensed Medium", + "font-family": "Noto Sans Gurmukhi SemiCondensed Medium", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Gurmukhi SemiCondensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGurmukhi-SemiCondensedMedium.ttf", + "preferred_family_name": "Noto Sans Gurmukhi", + "preferred_subfamily_name": "SemiCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGurmukhi-SemiCondensedSemiBold.ttf||53076:1655828711.0": { + "family_name": "Noto Sans Gurmukhi SemiCondensed SemiBold", + "font-family": "Noto Sans Gurmukhi SemiCondensed SemiBold", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Gurmukhi SemiCondensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGurmukhi-SemiCondensedSemiBold.ttf", + "preferred_family_name": "Noto Sans Gurmukhi", + "preferred_subfamily_name": "SemiCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGurmukhi-SemiCondensedThin.ttf||51640:1655828711.0": { + "family_name": "Noto Sans Gurmukhi SemiCondensed Thin", + "font-family": "Noto Sans Gurmukhi SemiCondensed Thin", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Gurmukhi SemiCondensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGurmukhi-SemiCondensedThin.ttf", + "preferred_family_name": "Noto Sans Gurmukhi", + "preferred_subfamily_name": "SemiCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGurmukhi-Thin.ttf||51868:1655828711.0": { + "family_name": "Noto Sans Gurmukhi Thin", + "font-family": "Noto Sans Gurmukhi Thin", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Gurmukhi Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGurmukhi-Thin.ttf", + "preferred_family_name": "Noto Sans Gurmukhi", + "preferred_subfamily_name": "Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGurmukhiUI-Black.ttf||58336:1655828711.0": { + "family_name": "Noto Sans Gurmukhi UI Black", + "font-family": "Noto Sans Gurmukhi UI Black", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Gurmukhi UI Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGurmukhiUI-Black.ttf", + "preferred_family_name": "Noto Sans Gurmukhi UI", + "preferred_subfamily_name": "Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGurmukhiUI-Bold.ttf||56344:1655828711.0": { + "family_name": "Noto Sans Gurmukhi UI", + "font-family": "Noto Sans Gurmukhi UI", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Gurmukhi UI Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGurmukhiUI-Bold.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGurmukhiUI-Condensed.ttf||55480:1655828711.0": { + "family_name": "Noto Sans Gurmukhi UI Condensed", + "font-family": "Noto Sans Gurmukhi UI Condensed", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Gurmukhi UI Condensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGurmukhiUI-Condensed.ttf", + "preferred_family_name": "Noto Sans Gurmukhi UI", + "preferred_subfamily_name": "Condensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGurmukhiUI-CondensedBlack.ttf||57092:1655828711.0": { + "family_name": "Noto Sans Gurmukhi UI Condensed Black", + "font-family": "Noto Sans Gurmukhi UI Condensed Black", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Gurmukhi UI Condensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGurmukhiUI-CondensedBlack.ttf", + "preferred_family_name": "Noto Sans Gurmukhi UI", + "preferred_subfamily_name": "Condensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGurmukhiUI-CondensedBold.ttf||56140:1655828711.0": { + "family_name": "Noto Sans Gurmukhi UI Condensed", + "font-family": "Noto Sans Gurmukhi UI Condensed", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Gurmukhi UI Condensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGurmukhiUI-CondensedBold.ttf", + "preferred_family_name": "Noto Sans Gurmukhi UI", + "preferred_subfamily_name": "Condensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGurmukhiUI-CondensedExtraBold.ttf||56776:1655828711.0": { + "family_name": "Noto Sans Gurmukhi UI Condensed ExtraBold", + "font-family": "Noto Sans Gurmukhi UI Condensed ExtraBold", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Gurmukhi UI Condensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGurmukhiUI-CondensedExtraBold.ttf", + "preferred_family_name": "Noto Sans Gurmukhi UI", + "preferred_subfamily_name": "Condensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGurmukhiUI-CondensedExtraLight.ttf||56284:1655828711.0": { + "family_name": "Noto Sans Gurmukhi UI Condensed ExtraLight", + "font-family": "Noto Sans Gurmukhi UI Condensed ExtraLight", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Gurmukhi UI Condensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGurmukhiUI-CondensedExtraLight.ttf", + "preferred_family_name": "Noto Sans Gurmukhi UI", + "preferred_subfamily_name": "Condensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGurmukhiUI-CondensedLight.ttf||55508:1655828711.0": { + "family_name": "Noto Sans Gurmukhi UI Condensed Light", + "font-family": "Noto Sans Gurmukhi UI Condensed Light", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Gurmukhi UI Condensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGurmukhiUI-CondensedLight.ttf", + "preferred_family_name": "Noto Sans Gurmukhi UI", + "preferred_subfamily_name": "Condensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGurmukhiUI-CondensedMedium.ttf||55684:1655828711.0": { + "family_name": "Noto Sans Gurmukhi UI Condensed Medium", + "font-family": "Noto Sans Gurmukhi UI Condensed Medium", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Gurmukhi UI Condensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGurmukhiUI-CondensedMedium.ttf", + "preferred_family_name": "Noto Sans Gurmukhi UI", + "preferred_subfamily_name": "Condensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGurmukhiUI-CondensedSemiBold.ttf||55956:1655828711.0": { + "family_name": "Noto Sans Gurmukhi UI Condensed SemiBold", + "font-family": "Noto Sans Gurmukhi UI Condensed SemiBold", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Gurmukhi UI Condensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGurmukhiUI-CondensedSemiBold.ttf", + "preferred_family_name": "Noto Sans Gurmukhi UI", + "preferred_subfamily_name": "Condensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGurmukhiUI-CondensedThin.ttf||54900:1655828711.0": { + "family_name": "Noto Sans Gurmukhi UI Condensed Thin", + "font-family": "Noto Sans Gurmukhi UI Condensed Thin", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Gurmukhi UI Condensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGurmukhiUI-CondensedThin.ttf", + "preferred_family_name": "Noto Sans Gurmukhi UI", + "preferred_subfamily_name": "Condensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGurmukhiUI-ExtraBold.ttf||57348:1655828711.0": { + "family_name": "Noto Sans Gurmukhi UI ExtraBold", + "font-family": "Noto Sans Gurmukhi UI ExtraBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Gurmukhi UI ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGurmukhiUI-ExtraBold.ttf", + "preferred_family_name": "Noto Sans Gurmukhi UI", + "preferred_subfamily_name": "ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGurmukhiUI-ExtraCondensed.ttf||55260:1655828711.0": { + "family_name": "Noto Sans Gurmukhi UI ExtraCondensed", + "font-family": "Noto Sans Gurmukhi UI ExtraCondensed", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Gurmukhi UI ExtraCondensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGurmukhiUI-ExtraCondensed.ttf", + "preferred_family_name": "Noto Sans Gurmukhi UI", + "preferred_subfamily_name": "ExtraCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGurmukhiUI-ExtraCondensedBlack.ttf||57372:1655828711.0": { + "family_name": "Noto Sans Gurmukhi UI ExtraCondensed Black", + "font-family": "Noto Sans Gurmukhi UI ExtraCondensed Black", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Gurmukhi UI ExtraCondensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGurmukhiUI-ExtraCondensedBlack.ttf", + "preferred_family_name": "Noto Sans Gurmukhi UI", + "preferred_subfamily_name": "ExtraCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGurmukhiUI-ExtraCondensedBold.ttf||55604:1655828711.0": { + "family_name": "Noto Sans Gurmukhi UI ExtraCondensed", + "font-family": "Noto Sans Gurmukhi UI ExtraCondensed", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Gurmukhi UI ExtraCondensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGurmukhiUI-ExtraCondensedBold.ttf", + "preferred_family_name": "Noto Sans Gurmukhi UI", + "preferred_subfamily_name": "ExtraCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGurmukhiUI-ExtraCondensedExtraBold.ttf||56396:1655828711.0": { + "family_name": "Noto Sans Gurmukhi UI ExtraCondensed ExtraBold", + "font-family": "Noto Sans Gurmukhi UI ExtraCondensed ExtraBold", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Gurmukhi UI ExtraCondensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGurmukhiUI-ExtraCondensedExtraBold.ttf", + "preferred_family_name": "Noto Sans Gurmukhi UI", + "preferred_subfamily_name": "ExtraCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGurmukhiUI-ExtraCondensedExtraLight.ttf||56028:1655828711.0": { + "family_name": "Noto Sans Gurmukhi UI ExtraCondensed ExtraLight", + "font-family": "Noto Sans Gurmukhi UI ExtraCondensed ExtraLight", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Gurmukhi UI ExtraCondensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGurmukhiUI-ExtraCondensedExtraLight.ttf", + "preferred_family_name": "Noto Sans Gurmukhi UI", + "preferred_subfamily_name": "ExtraCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGurmukhiUI-ExtraCondensedLight.ttf||55276:1655828711.0": { + "family_name": "Noto Sans Gurmukhi UI ExtraCondensed Light", + "font-family": "Noto Sans Gurmukhi UI ExtraCondensed Light", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Gurmukhi UI ExtraCondensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGurmukhiUI-ExtraCondensedLight.ttf", + "preferred_family_name": "Noto Sans Gurmukhi UI", + "preferred_subfamily_name": "ExtraCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGurmukhiUI-ExtraCondensedMedium.ttf||55948:1655828711.0": { + "family_name": "Noto Sans Gurmukhi UI ExtraCondensed Medium", + "font-family": "Noto Sans Gurmukhi UI ExtraCondensed Medium", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Gurmukhi UI ExtraCondensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGurmukhiUI-ExtraCondensedMedium.ttf", + "preferred_family_name": "Noto Sans Gurmukhi UI", + "preferred_subfamily_name": "ExtraCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGurmukhiUI-ExtraCondensedSemiBold.ttf||56204:1655828711.0": { + "family_name": "Noto Sans Gurmukhi UI ExtraCondensed SemiBold", + "font-family": "Noto Sans Gurmukhi UI ExtraCondensed SemiBold", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Gurmukhi UI ExtraCondensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGurmukhiUI-ExtraCondensedSemiBold.ttf", + "preferred_family_name": "Noto Sans Gurmukhi UI", + "preferred_subfamily_name": "ExtraCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGurmukhiUI-ExtraCondensedThin.ttf||54868:1655828711.0": { + "family_name": "Noto Sans Gurmukhi UI ExtraCondensed Thin", + "font-family": "Noto Sans Gurmukhi UI ExtraCondensed Thin", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Gurmukhi UI ExtraCondensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGurmukhiUI-ExtraCondensedThin.ttf", + "preferred_family_name": "Noto Sans Gurmukhi UI", + "preferred_subfamily_name": "ExtraCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGurmukhiUI-ExtraLight.ttf||56600:1655828711.0": { + "family_name": "Noto Sans Gurmukhi UI ExtraLight", + "font-family": "Noto Sans Gurmukhi UI ExtraLight", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Gurmukhi UI ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGurmukhiUI-ExtraLight.ttf", + "preferred_family_name": "Noto Sans Gurmukhi UI", + "preferred_subfamily_name": "ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGurmukhiUI-Light.ttf||56044:1655828711.0": { + "family_name": "Noto Sans Gurmukhi UI Light", + "font-family": "Noto Sans Gurmukhi UI Light", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Gurmukhi UI Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGurmukhiUI-Light.ttf", + "preferred_family_name": "Noto Sans Gurmukhi UI", + "preferred_subfamily_name": "Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGurmukhiUI-Medium.ttf||56528:1655828711.0": { + "family_name": "Noto Sans Gurmukhi UI Medium", + "font-family": "Noto Sans Gurmukhi UI Medium", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Gurmukhi UI Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGurmukhiUI-Medium.ttf", + "preferred_family_name": "Noto Sans Gurmukhi UI", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGurmukhiUI-Regular.ttf||56440:1655828711.0": { + "family_name": "Noto Sans Gurmukhi UI", + "font-family": "Noto Sans Gurmukhi UI", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Gurmukhi UI Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGurmukhiUI-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGurmukhiUI-SemiBold.ttf||56492:1655828711.0": { + "family_name": "Noto Sans Gurmukhi UI SemiBold", + "font-family": "Noto Sans Gurmukhi UI SemiBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Gurmukhi UI SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGurmukhiUI-SemiBold.ttf", + "preferred_family_name": "Noto Sans Gurmukhi UI", + "preferred_subfamily_name": "SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGurmukhiUI-SemiCondensed.ttf||56144:1655828711.0": { + "family_name": "Noto Sans Gurmukhi UI SemiCondensed", + "font-family": "Noto Sans Gurmukhi UI SemiCondensed", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Gurmukhi UI SemiCondensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGurmukhiUI-SemiCondensed.ttf", + "preferred_family_name": "Noto Sans Gurmukhi UI", + "preferred_subfamily_name": "SemiCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGurmukhiUI-SemiCondensedBlack.ttf||57460:1655828711.0": { + "family_name": "Noto Sans Gurmukhi UI SemiCondensed Black", + "font-family": "Noto Sans Gurmukhi UI SemiCondensed Black", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Gurmukhi UI SemiCondensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGurmukhiUI-SemiCondensedBlack.ttf", + "preferred_family_name": "Noto Sans Gurmukhi UI", + "preferred_subfamily_name": "SemiCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGurmukhiUI-SemiCondensedBold.ttf||56460:1655828711.0": { + "family_name": "Noto Sans Gurmukhi UI SemiCondensed", + "font-family": "Noto Sans Gurmukhi UI SemiCondensed", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Gurmukhi UI SemiCondensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGurmukhiUI-SemiCondensedBold.ttf", + "preferred_family_name": "Noto Sans Gurmukhi UI", + "preferred_subfamily_name": "SemiCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGurmukhiUI-SemiCondensedExtraBold.ttf||56872:1655828711.0": { + "family_name": "Noto Sans Gurmukhi UI SemiCondensed ExtraBold", + "font-family": "Noto Sans Gurmukhi UI SemiCondensed ExtraBold", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Gurmukhi UI SemiCondensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGurmukhiUI-SemiCondensedExtraBold.ttf", + "preferred_family_name": "Noto Sans Gurmukhi UI", + "preferred_subfamily_name": "SemiCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGurmukhiUI-SemiCondensedExtraLight.ttf||56316:1655828711.0": { + "family_name": "Noto Sans Gurmukhi UI SemiCondensed ExtraLight", + "font-family": "Noto Sans Gurmukhi UI SemiCondensed ExtraLight", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Gurmukhi UI SemiCondensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGurmukhiUI-SemiCondensedExtraLight.ttf", + "preferred_family_name": "Noto Sans Gurmukhi UI", + "preferred_subfamily_name": "SemiCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGurmukhiUI-SemiCondensedLight.ttf||55628:1655828711.0": { + "family_name": "Noto Sans Gurmukhi UI SemiCondensed Light", + "font-family": "Noto Sans Gurmukhi UI SemiCondensed Light", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Gurmukhi UI SemiCondensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGurmukhiUI-SemiCondensedLight.ttf", + "preferred_family_name": "Noto Sans Gurmukhi UI", + "preferred_subfamily_name": "SemiCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGurmukhiUI-SemiCondensedMedium.ttf||56244:1655828711.0": { + "family_name": "Noto Sans Gurmukhi UI SemiCondensed Medium", + "font-family": "Noto Sans Gurmukhi UI SemiCondensed Medium", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Gurmukhi UI SemiCondensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGurmukhiUI-SemiCondensedMedium.ttf", + "preferred_family_name": "Noto Sans Gurmukhi UI", + "preferred_subfamily_name": "SemiCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGurmukhiUI-SemiCondensedSemiBold.ttf||56236:1655828711.0": { + "family_name": "Noto Sans Gurmukhi UI SemiCondensed SemiBold", + "font-family": "Noto Sans Gurmukhi UI SemiCondensed SemiBold", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Gurmukhi UI SemiCondensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGurmukhiUI-SemiCondensedSemiBold.ttf", + "preferred_family_name": "Noto Sans Gurmukhi UI", + "preferred_subfamily_name": "SemiCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGurmukhiUI-SemiCondensedThin.ttf||54980:1655828711.0": { + "family_name": "Noto Sans Gurmukhi UI SemiCondensed Thin", + "font-family": "Noto Sans Gurmukhi UI SemiCondensed Thin", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Gurmukhi UI SemiCondensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGurmukhiUI-SemiCondensedThin.ttf", + "preferred_family_name": "Noto Sans Gurmukhi UI", + "preferred_subfamily_name": "SemiCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansGurmukhiUI-Thin.ttf||55284:1655828711.0": { + "family_name": "Noto Sans Gurmukhi UI Thin", + "font-family": "Noto Sans Gurmukhi UI Thin", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Gurmukhi UI Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansGurmukhiUI-Thin.ttf", + "preferred_family_name": "Noto Sans Gurmukhi UI", + "preferred_subfamily_name": "Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansHanifiRohingya-Bold.ttf||27932:1655828711.0": { + "family_name": "Noto Sans Hanifi Rohingya", + "font-family": "Noto Sans Hanifi Rohingya", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Hanifi Rohingya Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/noto/NotoSansHanifiRohingya-Bold.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansHanifiRohingya-Medium.ttf||27844:1655828711.0": { + "family_name": "Noto Sans Hanifi Rohingya Medium", + "font-family": "Noto Sans Hanifi Rohingya Medium", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Hanifi Rohingya Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/noto/NotoSansHanifiRohingya-Medium.ttf", + "preferred_family_name": "Noto Sans Hanifi Rohingya", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansHanifiRohingya-Regular.ttf||27200:1655828711.0": { + "family_name": "Noto Sans Hanifi Rohingya", + "font-family": "Noto Sans Hanifi Rohingya", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Hanifi Rohingya Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/noto/NotoSansHanifiRohingya-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansHanifiRohingya-SemiBold.ttf||28264:1655828711.0": { + "family_name": "Noto Sans Hanifi Rohingya SemiBold", + "font-family": "Noto Sans Hanifi Rohingya SemiBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Hanifi Rohingya SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/noto/NotoSansHanifiRohingya-SemiBold.ttf", + "preferred_family_name": "Noto Sans Hanifi Rohingya", + "preferred_subfamily_name": "SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansHanunoo-Regular.ttf||7964:1655828711.0": { + "family_name": "Noto Sans Hanunoo", + "font-family": "Noto Sans Hanunoo", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Hanunoo Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansHanunoo-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansHatran-Regular.ttf||5044:1655828711.0": { + "family_name": "Noto Sans Hatran", + "font-family": "Noto Sans Hatran", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Hatran Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansHatran-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansHebrew-Black.ttf||26852:1655828711.0": { + "family_name": "Noto Sans Hebrew Blk", + "font-family": "Noto Sans Hebrew Blk", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Hebrew Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansHebrew-Black.ttf", + "preferred_family_name": "Noto Sans Hebrew", + "preferred_subfamily_name": "Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansHebrew-Bold.ttf||27164:1655828711.0": { + "family_name": "Noto Sans Hebrew", + "font-family": "Noto Sans Hebrew", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Hebrew Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansHebrew-Bold.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansHebrew-Condensed.ttf||27060:1655828711.0": { + "family_name": "Noto Sans Hebrew Cond", + "font-family": "Noto Sans Hebrew Cond", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Hebrew Condensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansHebrew-Condensed.ttf", + "preferred_family_name": "Noto Sans Hebrew", + "preferred_subfamily_name": "Condensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansHebrew-CondensedBlack.ttf||27028:1655828711.0": { + "family_name": "Noto Sans Hebrew Cond Blk", + "font-family": "Noto Sans Hebrew Cond Blk", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Hebrew Condensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansHebrew-CondensedBlack.ttf", + "preferred_family_name": "Noto Sans Hebrew", + "preferred_subfamily_name": "Condensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansHebrew-CondensedBold.ttf||27372:1655828711.0": { + "family_name": "Noto Sans Hebrew Cond", + "font-family": "Noto Sans Hebrew Cond", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Hebrew Condensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansHebrew-CondensedBold.ttf", + "preferred_family_name": "Noto Sans Hebrew", + "preferred_subfamily_name": "Condensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansHebrew-CondensedExtraBold.ttf||27616:1655828711.0": { + "family_name": "Noto Sans Hebrew Cond ExtBd", + "font-family": "Noto Sans Hebrew Cond ExtBd", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Hebrew Condensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansHebrew-CondensedExtraBold.ttf", + "preferred_family_name": "Noto Sans Hebrew", + "preferred_subfamily_name": "Condensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansHebrew-CondensedExtraLight.ttf||27028:1655828711.0": { + "family_name": "Noto Sans Hebrew Cond ExtLt", + "font-family": "Noto Sans Hebrew Cond ExtLt", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Hebrew Condensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansHebrew-CondensedExtraLight.ttf", + "preferred_family_name": "Noto Sans Hebrew", + "preferred_subfamily_name": "Condensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansHebrew-CondensedLight.ttf||27660:1655828711.0": { + "family_name": "Noto Sans Hebrew Cond Light", + "font-family": "Noto Sans Hebrew Cond Light", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Hebrew Condensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansHebrew-CondensedLight.ttf", + "preferred_family_name": "Noto Sans Hebrew", + "preferred_subfamily_name": "Condensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansHebrew-CondensedMedium.ttf||27156:1655828711.0": { + "family_name": "Noto Sans Hebrew Cond Med", + "font-family": "Noto Sans Hebrew Cond Med", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Hebrew Condensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansHebrew-CondensedMedium.ttf", + "preferred_family_name": "Noto Sans Hebrew", + "preferred_subfamily_name": "Condensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansHebrew-CondensedSemiBold.ttf||27380:1655828711.0": { + "family_name": "Noto Sans Hebrew Cond SemBd", + "font-family": "Noto Sans Hebrew Cond SemBd", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Hebrew Condensed SemiBold ", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansHebrew-CondensedSemiBold.ttf", + "preferred_family_name": "Noto Sans Hebrew", + "preferred_subfamily_name": "Condensed SemiBold ", + "subfamily_name": "Regular", + "weight": 600, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansHebrew-CondensedThin.ttf||27284:1655828711.0": { + "family_name": "Noto Sans Hebrew Cond Thin", + "font-family": "Noto Sans Hebrew Cond Thin", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Hebrew Condensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansHebrew-CondensedThin.ttf", + "preferred_family_name": "Noto Sans Hebrew", + "preferred_subfamily_name": "Condensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansHebrew-ExtraBold.ttf||27284:1655828711.0": { + "family_name": "Noto Sans Hebrew ExtBd", + "font-family": "Noto Sans Hebrew ExtBd", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Hebrew ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansHebrew-ExtraBold.ttf", + "preferred_family_name": "Noto Sans Hebrew", + "preferred_subfamily_name": "ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansHebrew-ExtraCondensed.ttf||26948:1655828711.0": { + "family_name": "Noto Sans Hebrew ExtCond", + "font-family": "Noto Sans Hebrew ExtCond", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Hebrew ExtraCondensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansHebrew-ExtraCondensed.ttf", + "preferred_family_name": "Noto Sans Hebrew", + "preferred_subfamily_name": "ExtraCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansHebrew-ExtraCondensedBlack.ttf||26900:1655828711.0": { + "family_name": "Noto Sans Hebrew ExtCond Blk", + "font-family": "Noto Sans Hebrew ExtCond Blk", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Hebrew ExtraCondensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansHebrew-ExtraCondensedBlack.ttf", + "preferred_family_name": "Noto Sans Hebrew", + "preferred_subfamily_name": "ExtraCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansHebrew-ExtraCondensedBold.ttf||27440:1655828711.0": { + "family_name": "Noto Sans Hebrew ExtCond", + "font-family": "Noto Sans Hebrew ExtCond", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Hebrew ExtraCondensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansHebrew-ExtraCondensedBold.ttf", + "preferred_family_name": "Noto Sans Hebrew", + "preferred_subfamily_name": "ExtraCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansHebrew-ExtraCondensedExtraBold.ttf||27392:1655828711.0": { + "family_name": "Noto Sans Hebrew ExtCond ExtBd", + "font-family": "Noto Sans Hebrew ExtCond ExtBd", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Hebrew ExtraCondensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansHebrew-ExtraCondensedExtraBold.ttf", + "preferred_family_name": "Noto Sans Hebrew", + "preferred_subfamily_name": "ExtraCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansHebrew-ExtraCondensedExtraLight.ttf||26760:1655828711.0": { + "family_name": "Noto Sans Hebrew ExtCond ExtLt", + "font-family": "Noto Sans Hebrew ExtCond ExtLt", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Hebrew ExtraCondensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansHebrew-ExtraCondensedExtraLight.ttf", + "preferred_family_name": "Noto Sans Hebrew", + "preferred_subfamily_name": "ExtraCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansHebrew-ExtraCondensedLight.ttf||27372:1655828711.0": { + "family_name": "Noto Sans Hebrew ExtCond Light", + "font-family": "Noto Sans Hebrew ExtCond Light", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Hebrew ExtraCondensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansHebrew-ExtraCondensedLight.ttf", + "preferred_family_name": "Noto Sans Hebrew", + "preferred_subfamily_name": "ExtraCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansHebrew-ExtraCondensedMedium.ttf||26924:1655828711.0": { + "family_name": "Noto Sans Hebrew ExtCond Med", + "font-family": "Noto Sans Hebrew ExtCond Med", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Hebrew ExtraCondensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansHebrew-ExtraCondensedMedium.ttf", + "preferred_family_name": "Noto Sans Hebrew", + "preferred_subfamily_name": "ExtraCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansHebrew-ExtraCondensedSemiBold.ttf||27056:1655828711.0": { + "family_name": "Noto Sans Hebrew ExtCond SemBd", + "font-family": "Noto Sans Hebrew ExtCond SemBd", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Hebrew ExtraCondensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansHebrew-ExtraCondensedSemiBold.ttf", + "preferred_family_name": "Noto Sans Hebrew", + "preferred_subfamily_name": "ExtraCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansHebrew-ExtraCondensedThin.ttf||27056:1655828711.0": { + "family_name": "Noto Sans Hebrew ExtCond Thin", + "font-family": "Noto Sans Hebrew ExtCond Thin", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Hebrew ExtraCondensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansHebrew-ExtraCondensedThin.ttf", + "preferred_family_name": "Noto Sans Hebrew", + "preferred_subfamily_name": "ExtraCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansHebrew-ExtraLight.ttf||26892:1655828711.0": { + "family_name": "Noto Sans Hebrew ExtLt", + "font-family": "Noto Sans Hebrew ExtLt", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Hebrew ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansHebrew-ExtraLight.ttf", + "preferred_family_name": "Noto Sans Hebrew", + "preferred_subfamily_name": "ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansHebrew-Light.ttf||27564:1655828711.0": { + "family_name": "Noto Sans Hebrew Light", + "font-family": "Noto Sans Hebrew Light", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Hebrew Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansHebrew-Light.ttf", + "preferred_family_name": "Noto Sans Hebrew", + "preferred_subfamily_name": "Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansHebrew-Medium.ttf||27024:1655828711.0": { + "family_name": "Noto Sans Hebrew Med", + "font-family": "Noto Sans Hebrew Med", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Hebrew Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansHebrew-Medium.ttf", + "preferred_family_name": "Noto Sans Hebrew", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansHebrew-Regular.ttf||26900:1655828711.0": { + "family_name": "Noto Sans Hebrew", + "font-family": "Noto Sans Hebrew", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Hebrew Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansHebrew-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansHebrew-SemiBold.ttf||27260:1655828711.0": { + "family_name": "Noto Sans Hebrew SemBd", + "font-family": "Noto Sans Hebrew SemBd", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Hebrew SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansHebrew-SemiBold.ttf", + "preferred_family_name": "Noto Sans Hebrew", + "preferred_subfamily_name": "SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansHebrew-SemiCondensed.ttf||27128:1655828711.0": { + "family_name": "Noto Sans Hebrew SemCond", + "font-family": "Noto Sans Hebrew SemCond", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Hebrew SemiCondensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansHebrew-SemiCondensed.ttf", + "preferred_family_name": "Noto Sans Hebrew", + "preferred_subfamily_name": "SemiCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansHebrew-SemiCondensedBlack.ttf||27120:1655828711.0": { + "family_name": "Noto Sans Hebrew SemCond Blk", + "font-family": "Noto Sans Hebrew SemCond Blk", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Hebrew SemiCondensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansHebrew-SemiCondensedBlack.ttf", + "preferred_family_name": "Noto Sans Hebrew", + "preferred_subfamily_name": "SemiCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansHebrew-SemiCondensedBold.ttf||27476:1655828711.0": { + "family_name": "Noto Sans Hebrew SemCond", + "font-family": "Noto Sans Hebrew SemCond", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Hebrew SemiCondensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansHebrew-SemiCondensedBold.ttf", + "preferred_family_name": "Noto Sans Hebrew", + "preferred_subfamily_name": "SemiCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansHebrew-SemiCondensedExtraBold.ttf||27664:1655828711.0": { + "family_name": "Noto Sans Hebrew SemCond ExtBd", + "font-family": "Noto Sans Hebrew SemCond ExtBd", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Hebrew SemiCondensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansHebrew-SemiCondensedExtraBold.ttf", + "preferred_family_name": "Noto Sans Hebrew", + "preferred_subfamily_name": "SemiCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansHebrew-SemiCondensedExtraLight.ttf||27184:1655828711.0": { + "family_name": "Noto Sans Hebrew SemCond ExtLt", + "font-family": "Noto Sans Hebrew SemCond ExtLt", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Hebrew SemiCondensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansHebrew-SemiCondensedExtraLight.ttf", + "preferred_family_name": "Noto Sans Hebrew", + "preferred_subfamily_name": "SemiCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansHebrew-SemiCondensedLight.ttf||27772:1655828711.0": { + "family_name": "Noto Sans Hebrew SemCond Light", + "font-family": "Noto Sans Hebrew SemCond Light", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Hebrew SemiCondensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansHebrew-SemiCondensedLight.ttf", + "preferred_family_name": "Noto Sans Hebrew", + "preferred_subfamily_name": "SemiCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansHebrew-SemiCondensedMedium.ttf||27216:1655828711.0": { + "family_name": "Noto Sans Hebrew SemCond Med", + "font-family": "Noto Sans Hebrew SemCond Med", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Hebrew SemiCondensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansHebrew-SemiCondensedMedium.ttf", + "preferred_family_name": "Noto Sans Hebrew", + "preferred_subfamily_name": "SemiCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansHebrew-SemiCondensedSemiBold.ttf||27460:1655828711.0": { + "family_name": "Noto Sans Hebrew SemCond SemBd", + "font-family": "Noto Sans Hebrew SemCond SemBd", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Hebrew SemiCondensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansHebrew-SemiCondensedSemiBold.ttf", + "preferred_family_name": "Noto Sans Hebrew", + "preferred_subfamily_name": "SemiCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansHebrew-SemiCondensedThin.ttf||27500:1655828711.0": { + "family_name": "Noto Sans Hebrew SemCond Thin", + "font-family": "Noto Sans Hebrew SemCond Thin", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Hebrew SemiCondensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansHebrew-SemiCondensedThin.ttf", + "preferred_family_name": "Noto Sans Hebrew", + "preferred_subfamily_name": "SemiCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansHebrew-Thin.ttf||27264:1655828711.0": { + "family_name": "Noto Sans Hebrew Thin", + "font-family": "Noto Sans Hebrew Thin", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Hebrew Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansHebrew-Thin.ttf", + "preferred_family_name": "Noto Sans Hebrew", + "preferred_subfamily_name": "Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansHebrewDroid-Bold.ttf||35340:1655828711.0": { + "family_name": "Noto Sans Hebrew Droid", + "font-family": "Noto Sans Hebrew Droid", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 8, + "full_name": "Noto Sans Hebrew Droid Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/noto/NotoSansHebrewDroid-Bold.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansHebrewDroid-Medium.ttf||35736:1655828711.0": { + "family_name": "Noto Sans Hebrew Droid Medium", + "font-family": "Noto Sans Hebrew Droid Medium", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 8, + "full_name": "Noto Sans Hebrew Droid Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/noto/NotoSansHebrewDroid-Medium.ttf", + "preferred_family_name": "Noto Sans Hebrew Droid", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansHebrewDroid-Regular.ttf||34780:1655828711.0": { + "family_name": "Noto Sans Hebrew Droid", + "font-family": "Noto Sans Hebrew Droid", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 8, + "full_name": "Noto Sans Hebrew Droid Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/noto/NotoSansHebrewDroid-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansHebrewDroid-SemiBold.ttf||35716:1655828711.0": { + "family_name": "Noto Sans Hebrew Droid SemiBold", + "font-family": "Noto Sans Hebrew Droid SemiBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 8, + "full_name": "Noto Sans Hebrew Droid SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/noto/NotoSansHebrewDroid-SemiBold.ttf", + "preferred_family_name": "Noto Sans Hebrew Droid", + "preferred_subfamily_name": "SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansHebrewNew-Black.ttf||26900:1655828711.0": { + "family_name": "Noto Sans Hebrew New Blk", + "font-family": "Noto Sans Hebrew New Blk", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Hebrew New Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/noto/NotoSansHebrewNew-Black.ttf", + "preferred_family_name": "Noto Sans Hebrew New", + "preferred_subfamily_name": "Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansHebrewNew-Bold.ttf||27264:1655828711.0": { + "family_name": "Noto Sans Hebrew New Bold", + "font-family": "Noto Sans Hebrew New Bold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Hebrew New Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/noto/NotoSansHebrewNew-Bold.ttf", + "preferred_family_name": "Noto Sans Hebrew New", + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansHebrewNew-Condensed.ttf||27104:1655828711.0": { + "family_name": "Noto Sans Hebrew New Cond", + "font-family": "Noto Sans Hebrew New Cond", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Hebrew New Condensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/noto/NotoSansHebrewNew-Condensed.ttf", + "preferred_family_name": "Noto Sans Hebrew New", + "preferred_subfamily_name": "Condensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansHebrewNew-CondensedBlack.ttf||27072:1655828711.0": { + "family_name": "Noto Sans Hebrew New Cond Blk", + "font-family": "Noto Sans Hebrew New Cond Blk", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Hebrew New Condensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/noto/NotoSansHebrewNew-CondensedBlack.ttf", + "preferred_family_name": "Noto Sans Hebrew New", + "preferred_subfamily_name": "Condensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansHebrewNew-CondensedBold.ttf||27436:1655828711.0": { + "family_name": "Noto Sans Hebrew New Cond Bold", + "font-family": "Noto Sans Hebrew New Cond Bold", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Hebrew New Condensed Bold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/noto/NotoSansHebrewNew-CondensedBold.ttf", + "preferred_family_name": "Noto Sans Hebrew New", + "preferred_subfamily_name": "Condensed Bold", + "subfamily_name": "Regular", + "weight": 700, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansHebrewNew-CondensedExtraBold.ttf||27660:1655828711.0": { + "family_name": "Noto Sans Hebrew New Cond ExtBd", + "font-family": "Noto Sans Hebrew New Cond ExtBd", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Hebrew New Condensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/noto/NotoSansHebrewNew-CondensedExtraBold.ttf", + "preferred_family_name": "Noto Sans Hebrew New", + "preferred_subfamily_name": "Condensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansHebrewNew-CondensedExtraLight.ttf||27072:1655828711.0": { + "family_name": "Noto Sans Hebrew New Cond ExtLt", + "font-family": "Noto Sans Hebrew New Cond ExtLt", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Hebrew New Condensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/noto/NotoSansHebrewNew-CondensedExtraLight.ttf", + "preferred_family_name": "Noto Sans Hebrew New", + "preferred_subfamily_name": "Condensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansHebrewNew-CondensedLight.ttf||27704:1655828711.0": { + "family_name": "Noto Sans Hebrew New Cond Light", + "font-family": "Noto Sans Hebrew New Cond Light", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Hebrew New Condensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/noto/NotoSansHebrewNew-CondensedLight.ttf", + "preferred_family_name": "Noto Sans Hebrew New", + "preferred_subfamily_name": "Condensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansHebrewNew-CondensedMedium.ttf||27200:1655828711.0": { + "family_name": "Noto Sans Hebrew New Cond Med", + "font-family": "Noto Sans Hebrew New Cond Med", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Hebrew New Condensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/noto/NotoSansHebrewNew-CondensedMedium.ttf", + "preferred_family_name": "Noto Sans Hebrew New", + "preferred_subfamily_name": "Condensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansHebrewNew-CondensedSemiBold.ttf||27424:1655828711.0": { + "family_name": "Noto Sans Hebrew New Cond SemBd", + "font-family": "Noto Sans Hebrew New Cond SemBd", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Hebrew New Condensed SemiBold ", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/noto/NotoSansHebrewNew-CondensedSemiBold.ttf", + "preferred_family_name": "Noto Sans Hebrew New", + "preferred_subfamily_name": "Condensed SemiBold ", + "subfamily_name": "Regular", + "weight": 600, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansHebrewNew-CondensedThin.ttf||27332:1655828711.0": { + "family_name": "Noto Sans Hebrew New Cond Thin", + "font-family": "Noto Sans Hebrew New Cond Thin", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Hebrew New Condensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/noto/NotoSansHebrewNew-CondensedThin.ttf", + "preferred_family_name": "Noto Sans Hebrew New", + "preferred_subfamily_name": "Condensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansHebrewNew-ExtraBold.ttf||27332:1655828711.0": { + "family_name": "Noto Sans Hebrew New ExtBd", + "font-family": "Noto Sans Hebrew New ExtBd", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Hebrew New ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/noto/NotoSansHebrewNew-ExtraBold.ttf", + "preferred_family_name": "Noto Sans Hebrew New", + "preferred_subfamily_name": "ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansHebrewNew-ExtraCondensed.ttf||26996:1655828711.0": { + "family_name": "Noto Sans Hebrew New ExtCond", + "font-family": "Noto Sans Hebrew New ExtCond", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Hebrew New ExtraCondensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/noto/NotoSansHebrewNew-ExtraCondensed.ttf", + "preferred_family_name": "Noto Sans Hebrew New", + "preferred_subfamily_name": "ExtraCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansHebrewNew-ExtraCondensedBlack.ttf||26948:1655828711.0": { + "family_name": "Noto Sans Hebrew New ExtCond Blk", + "font-family": "Noto Sans Hebrew New ExtCond Blk", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Hebrew New ExtraCondensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/noto/NotoSansHebrewNew-ExtraCondensedBlack.ttf", + "preferred_family_name": "Noto Sans Hebrew New", + "preferred_subfamily_name": "ExtraCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansHebrewNew-ExtraCondensedBold.ttf||27500:1655828711.0": { + "family_name": "Noto Sans Hebrew New ExtCond Bold", + "font-family": "Noto Sans Hebrew New ExtCond Bold", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Hebrew New ExtraCondensed Bold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/noto/NotoSansHebrewNew-ExtraCondensedBold.ttf", + "preferred_family_name": "Noto Sans Hebrew New", + "preferred_subfamily_name": "ExtraCondensed Bold", + "subfamily_name": "Regular", + "weight": 700, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansHebrewNew-ExtraCondensedExtraBold.ttf||27440:1655828711.0": { + "family_name": "Noto Sans Hebrew New ExtCond ExtBd", + "font-family": "Noto Sans Hebrew New ExtCond ExtBd", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Hebrew New ExtraCondensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/noto/NotoSansHebrewNew-ExtraCondensedExtraBold.ttf", + "preferred_family_name": "Noto Sans Hebrew New", + "preferred_subfamily_name": "ExtraCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansHebrewNew-ExtraCondensedExtraLight.ttf||26808:1655828711.0": { + "family_name": "Noto Sans Hebrew New ExtCond ExtLt", + "font-family": "Noto Sans Hebrew New ExtCond ExtLt", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Hebrew New ExtraCondensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/noto/NotoSansHebrewNew-ExtraCondensedExtraLight.ttf", + "preferred_family_name": "Noto Sans Hebrew New", + "preferred_subfamily_name": "ExtraCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansHebrewNew-ExtraCondensedLight.ttf||27420:1655828711.0": { + "family_name": "Noto Sans Hebrew New ExtCond Light", + "font-family": "Noto Sans Hebrew New ExtCond Light", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Hebrew New ExtraCondensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/noto/NotoSansHebrewNew-ExtraCondensedLight.ttf", + "preferred_family_name": "Noto Sans Hebrew New", + "preferred_subfamily_name": "ExtraCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansHebrewNew-ExtraCondensedMedium.ttf||26972:1655828711.0": { + "family_name": "Noto Sans Hebrew New ExtCond Med", + "font-family": "Noto Sans Hebrew New ExtCond Med", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Hebrew New ExtraCondensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/noto/NotoSansHebrewNew-ExtraCondensedMedium.ttf", + "preferred_family_name": "Noto Sans Hebrew New", + "preferred_subfamily_name": "ExtraCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansHebrewNew-ExtraCondensedSemiBold.ttf||27104:1655828711.0": { + "family_name": "Noto Sans Hebrew New ExtCond SemBd", + "font-family": "Noto Sans Hebrew New ExtCond SemBd", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Hebrew New ExtraCondensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/noto/NotoSansHebrewNew-ExtraCondensedSemiBold.ttf", + "preferred_family_name": "Noto Sans Hebrew New", + "preferred_subfamily_name": "ExtraCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansHebrewNew-ExtraCondensedThin.ttf||27100:1655828711.0": { + "family_name": "Noto Sans Hebrew New ExtCond Thin", + "font-family": "Noto Sans Hebrew New ExtCond Thin", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Hebrew New ExtraCondensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/noto/NotoSansHebrewNew-ExtraCondensedThin.ttf", + "preferred_family_name": "Noto Sans Hebrew New", + "preferred_subfamily_name": "ExtraCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansHebrewNew-ExtraLight.ttf||26940:1655828711.0": { + "family_name": "Noto Sans Hebrew New ExtLt", + "font-family": "Noto Sans Hebrew New ExtLt", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Hebrew New ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/noto/NotoSansHebrewNew-ExtraLight.ttf", + "preferred_family_name": "Noto Sans Hebrew New", + "preferred_subfamily_name": "ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansHebrewNew-Light.ttf||27612:1655828711.0": { + "family_name": "Noto Sans Hebrew New Light", + "font-family": "Noto Sans Hebrew New Light", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Hebrew New Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/noto/NotoSansHebrewNew-Light.ttf", + "preferred_family_name": "Noto Sans Hebrew New", + "preferred_subfamily_name": "Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansHebrewNew-Medium.ttf||27072:1655828711.0": { + "family_name": "Noto Sans Hebrew New Med", + "font-family": "Noto Sans Hebrew New Med", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Hebrew New Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/noto/NotoSansHebrewNew-Medium.ttf", + "preferred_family_name": "Noto Sans Hebrew New", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansHebrewNew-Regular.ttf||26936:1655828711.0": { + "family_name": "Noto Sans Hebrew New", + "font-family": "Noto Sans Hebrew New", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Hebrew New Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/noto/NotoSansHebrewNew-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansHebrewNew-SemiBold.ttf||27308:1655828711.0": { + "family_name": "Noto Sans Hebrew New SemBd", + "font-family": "Noto Sans Hebrew New SemBd", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Hebrew New SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/noto/NotoSansHebrewNew-SemiBold.ttf", + "preferred_family_name": "Noto Sans Hebrew New", + "preferred_subfamily_name": "SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansHebrewNew-SemiCondensed.ttf||27152:1655828711.0": { + "family_name": "Noto Sans Hebrew New SemCond", + "font-family": "Noto Sans Hebrew New SemCond", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Hebrew New SemiCondensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansHebrewNew-SemiCondensed.ttf", + "preferred_family_name": "Noto Sans Hebrew New", + "preferred_subfamily_name": "SemiCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansHebrewNew-SemiCondensedBlack.ttf||27152:1655828711.0": { + "family_name": "Noto Sans Hebrew New SemCond Blk", + "font-family": "Noto Sans Hebrew New SemCond Blk", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Hebrew New SemiCondensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/noto/NotoSansHebrewNew-SemiCondensedBlack.ttf", + "preferred_family_name": "Noto Sans Hebrew New", + "preferred_subfamily_name": "SemiCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansHebrewNew-SemiCondensedBold.ttf||27512:1655828711.0": { + "family_name": "Noto Sans Hebrew New SemCond Bold", + "font-family": "Noto Sans Hebrew New SemCond Bold", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Hebrew New SemiCondensed Bold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansHebrewNew-SemiCondensedBold.ttf", + "preferred_family_name": "Noto Sans Hebrew New", + "preferred_subfamily_name": "SemiCondensed Bold", + "subfamily_name": "Regular", + "weight": 700, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansHebrewNew-SemiCondensedExtraBold.ttf||27696:1655828711.0": { + "family_name": "Noto Sans Hebrew New SemCond ExtBd", + "font-family": "Noto Sans Hebrew New SemCond ExtBd", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Hebrew New SemiCondensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/noto/NotoSansHebrewNew-SemiCondensedExtraBold.ttf", + "preferred_family_name": "Noto Sans Hebrew New", + "preferred_subfamily_name": "SemiCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansHebrewNew-SemiCondensedExtraLight.ttf||27212:1655828711.0": { + "family_name": "Noto Sans Hebrew New SemCond ExtLt", + "font-family": "Noto Sans Hebrew New SemCond ExtLt", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Hebrew New SemiCondensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/noto/NotoSansHebrewNew-SemiCondensedExtraLight.ttf", + "preferred_family_name": "Noto Sans Hebrew New", + "preferred_subfamily_name": "SemiCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansHebrewNew-SemiCondensedLight.ttf||27800:1655828711.0": { + "family_name": "Noto Sans Hebrew New SemCond Light", + "font-family": "Noto Sans Hebrew New SemCond Light", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Hebrew New SemiCondensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/noto/NotoSansHebrewNew-SemiCondensedLight.ttf", + "preferred_family_name": "Noto Sans Hebrew New", + "preferred_subfamily_name": "SemiCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansHebrewNew-SemiCondensedMedium.ttf||27240:1655828711.0": { + "family_name": "Noto Sans Hebrew New SemCond Med", + "font-family": "Noto Sans Hebrew New SemCond Med", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Hebrew New SemiCondensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/noto/NotoSansHebrewNew-SemiCondensedMedium.ttf", + "preferred_family_name": "Noto Sans Hebrew New", + "preferred_subfamily_name": "SemiCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansHebrewNew-SemiCondensedSemiBold.ttf||27484:1655828711.0": { + "family_name": "Noto Sans Hebrew New SemCond SemBd", + "font-family": "Noto Sans Hebrew New SemCond SemBd", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Hebrew New SemiCondensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/noto/NotoSansHebrewNew-SemiCondensedSemiBold.ttf", + "preferred_family_name": "Noto Sans Hebrew New", + "preferred_subfamily_name": "SemiCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansHebrewNew-SemiCondensedThin.ttf||27520:1655828711.0": { + "family_name": "Noto Sans Hebrew New SemCond Thin", + "font-family": "Noto Sans Hebrew New SemCond Thin", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Hebrew New SemiCondensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/noto/NotoSansHebrewNew-SemiCondensedThin.ttf", + "preferred_family_name": "Noto Sans Hebrew New", + "preferred_subfamily_name": "SemiCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansHebrewNew-Thin.ttf||27308:1655828711.0": { + "family_name": "Noto Sans Hebrew New Thin", + "font-family": "Noto Sans Hebrew New Thin", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Hebrew New Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/noto/NotoSansHebrewNew-Thin.ttf", + "preferred_family_name": "Noto Sans Hebrew New", + "preferred_subfamily_name": "Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansImperialAramaic-Regular.ttf||6432:1655828711.0": { + "family_name": "Noto Sans ImpAramaic", + "font-family": "Noto Sans ImpAramaic", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Imperial Aramaic Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansImperialAramaic-Regular.ttf", + "preferred_family_name": "Noto Sans Imperial Aramaic", + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansIndicSiyaqNumbers-Regular.ttf||32668:1655828711.0": { + "family_name": "Noto Sans Indic Siyaq Numbers", + "font-family": "Noto Sans Indic Siyaq Numbers", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Indic Siyaq Numbers Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansIndicSiyaqNumbers-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansInscriptionalPahlavi-Regular.ttf||5896:1655828711.0": { + "family_name": "Noto Sans InsPahlavi", + "font-family": "Noto Sans InsPahlavi", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Inscriptional Pahlavi Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansInscriptionalPahlavi-Regular.ttf", + "preferred_family_name": "Noto Sans Inscriptional Pahlavi", + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansInscriptionalParthian-Regular.ttf||7728:1655828711.0": { + "family_name": "Noto Sans InsParthi", + "font-family": "Noto Sans InsParthi", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Inscriptional Parthian Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansInscriptionalParthian-Regular.ttf", + "preferred_family_name": "Noto Sans Inscriptional Parthian", + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansJavanese-Bold.ttf||112528:1655828711.0": { + "family_name": "Noto Sans Javanese", + "font-family": "Noto Sans Javanese", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Javanese Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansJavanese-Bold.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansJavanese-Regular.ttf||119684:1655828711.0": { + "family_name": "Noto Sans Javanese", + "font-family": "Noto Sans Javanese", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Javanese Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansJavanese-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKaithi-Regular.ttf||91284:1655828711.0": { + "family_name": "Noto Sans Kaithi", + "font-family": "Noto Sans Kaithi", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Kaithi Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKaithi-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKannada-Black.ttf||171328:1655828711.0": { + "family_name": "Noto Sans Kannada Black", + "font-family": "Noto Sans Kannada Black", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Kannada Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKannada-Black.ttf", + "preferred_family_name": "Noto Sans Kannada", + "preferred_subfamily_name": "Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKannada-Bold.ttf||156124:1655828711.0": { + "family_name": "Noto Sans Kannada", + "font-family": "Noto Sans Kannada", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Kannada Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKannada-Bold.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKannada-Condensed.ttf||153052:1655828711.0": { + "family_name": "Noto Sans Kannada Condensed", + "font-family": "Noto Sans Kannada Condensed", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Kannada Condensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKannada-Condensed.ttf", + "preferred_family_name": "Noto Sans Kannada", + "preferred_subfamily_name": "Condensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKannada-CondensedBlack.ttf||169448:1655828711.0": { + "family_name": "Noto Sans Kannada Condensed Black", + "font-family": "Noto Sans Kannada Condensed Black", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Kannada Condensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKannada-CondensedBlack.ttf", + "preferred_family_name": "Noto Sans Kannada", + "preferred_subfamily_name": "Condensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKannada-CondensedBold.ttf||158412:1655828711.0": { + "family_name": "Noto Sans Kannada Condensed", + "font-family": "Noto Sans Kannada Condensed", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Kannada Condensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKannada-CondensedBold.ttf", + "preferred_family_name": "Noto Sans Kannada", + "preferred_subfamily_name": "Condensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKannada-CondensedExtraBold.ttf||161772:1655828711.0": { + "family_name": "Noto Sans Kannada Condensed ExtraBold", + "font-family": "Noto Sans Kannada Condensed ExtraBold", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Kannada Condensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKannada-CondensedExtraBold.ttf", + "preferred_family_name": "Noto Sans Kannada", + "preferred_subfamily_name": "Condensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKannada-CondensedExtraLight.ttf||147692:1655828711.0": { + "family_name": "Noto Sans Kannada Condensed ExtraLight", + "font-family": "Noto Sans Kannada Condensed ExtraLight", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Kannada Condensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKannada-CondensedExtraLight.ttf", + "preferred_family_name": "Noto Sans Kannada", + "preferred_subfamily_name": "Condensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKannada-CondensedLight.ttf||147508:1655828711.0": { + "family_name": "Noto Sans Kannada Condensed Light", + "font-family": "Noto Sans Kannada Condensed Light", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Kannada Condensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKannada-CondensedLight.ttf", + "preferred_family_name": "Noto Sans Kannada", + "preferred_subfamily_name": "Condensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKannada-CondensedMedium.ttf||152568:1655828711.0": { + "family_name": "Noto Sans Kannada Condensed Medium", + "font-family": "Noto Sans Kannada Condensed Medium", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Kannada Condensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKannada-CondensedMedium.ttf", + "preferred_family_name": "Noto Sans Kannada", + "preferred_subfamily_name": "Condensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKannada-CondensedSemiBold.ttf||158096:1655828711.0": { + "family_name": "Noto Sans Kannada Condensed SemiBold", + "font-family": "Noto Sans Kannada Condensed SemiBold", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Kannada Condensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKannada-CondensedSemiBold.ttf", + "preferred_family_name": "Noto Sans Kannada", + "preferred_subfamily_name": "Condensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKannada-CondensedThin.ttf||146396:1655828711.0": { + "family_name": "Noto Sans Kannada Condensed Thin", + "font-family": "Noto Sans Kannada Condensed Thin", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Kannada Condensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKannada-CondensedThin.ttf", + "preferred_family_name": "Noto Sans Kannada", + "preferred_subfamily_name": "Condensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKannada-ExtraBold.ttf||163116:1655828711.0": { + "family_name": "Noto Sans Kannada ExtraBold", + "font-family": "Noto Sans Kannada ExtraBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Kannada ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKannada-ExtraBold.ttf", + "preferred_family_name": "Noto Sans Kannada", + "preferred_subfamily_name": "ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKannada-ExtraCondensed.ttf||150752:1655828711.0": { + "family_name": "Noto Sans Kannada ExtraCondensed", + "font-family": "Noto Sans Kannada ExtraCondensed", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Kannada ExtraCondensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKannada-ExtraCondensed.ttf", + "preferred_family_name": "Noto Sans Kannada", + "preferred_subfamily_name": "ExtraCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKannada-ExtraCondensedBlack.ttf||167816:1655828711.0": { + "family_name": "Noto Sans Kannada ExtraCondensed Black", + "font-family": "Noto Sans Kannada ExtraCondensed Black", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Kannada ExtraCondensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKannada-ExtraCondensedBlack.ttf", + "preferred_family_name": "Noto Sans Kannada", + "preferred_subfamily_name": "ExtraCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKannada-ExtraCondensedBold.ttf||158580:1655828711.0": { + "family_name": "Noto Sans Kannada ExtraCondensed", + "font-family": "Noto Sans Kannada ExtraCondensed", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Kannada ExtraCondensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKannada-ExtraCondensedBold.ttf", + "preferred_family_name": "Noto Sans Kannada", + "preferred_subfamily_name": "ExtraCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKannada-ExtraCondensedExtraBold.ttf||158848:1655828711.0": { + "family_name": "Noto Sans Kannada ExtraCondensed ExtraBold", + "font-family": "Noto Sans Kannada ExtraCondensed ExtraBold", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Kannada ExtraCondensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKannada-ExtraCondensedExtraBold.ttf", + "preferred_family_name": "Noto Sans Kannada", + "preferred_subfamily_name": "ExtraCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKannada-ExtraCondensedExtraLight.ttf||150096:1655828711.0": { + "family_name": "Noto Sans Kannada ExtraCondensed ExtraLight", + "font-family": "Noto Sans Kannada ExtraCondensed ExtraLight", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Kannada ExtraCondensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKannada-ExtraCondensedExtraLight.ttf", + "preferred_family_name": "Noto Sans Kannada", + "preferred_subfamily_name": "ExtraCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKannada-ExtraCondensedLight.ttf||147152:1655828711.0": { + "family_name": "Noto Sans Kannada ExtraCondensed Light", + "font-family": "Noto Sans Kannada ExtraCondensed Light", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Kannada ExtraCondensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKannada-ExtraCondensedLight.ttf", + "preferred_family_name": "Noto Sans Kannada", + "preferred_subfamily_name": "ExtraCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKannada-ExtraCondensedMedium.ttf||152228:1655828711.0": { + "family_name": "Noto Sans Kannada ExtraCondensed Medium", + "font-family": "Noto Sans Kannada ExtraCondensed Medium", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Kannada ExtraCondensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKannada-ExtraCondensedMedium.ttf", + "preferred_family_name": "Noto Sans Kannada", + "preferred_subfamily_name": "ExtraCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKannada-ExtraCondensedSemiBold.ttf||157588:1655828711.0": { + "family_name": "Noto Sans Kannada ExtraCondensed SemiBold", + "font-family": "Noto Sans Kannada ExtraCondensed SemiBold", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Kannada ExtraCondensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKannada-ExtraCondensedSemiBold.ttf", + "preferred_family_name": "Noto Sans Kannada", + "preferred_subfamily_name": "ExtraCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKannada-ExtraCondensedThin.ttf||146872:1655828711.0": { + "family_name": "Noto Sans Kannada ExtraCondensed Thin", + "font-family": "Noto Sans Kannada ExtraCondensed Thin", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Kannada ExtraCondensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKannada-ExtraCondensedThin.ttf", + "preferred_family_name": "Noto Sans Kannada", + "preferred_subfamily_name": "ExtraCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKannada-ExtraLight.ttf||153460:1655828711.0": { + "family_name": "Noto Sans Kannada ExtraLight", + "font-family": "Noto Sans Kannada ExtraLight", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Kannada ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKannada-ExtraLight.ttf", + "preferred_family_name": "Noto Sans Kannada", + "preferred_subfamily_name": "ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKannada-Light.ttf||149008:1655828711.0": { + "family_name": "Noto Sans Kannada Light", + "font-family": "Noto Sans Kannada Light", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Kannada Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKannada-Light.ttf", + "preferred_family_name": "Noto Sans Kannada", + "preferred_subfamily_name": "Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKannada-Medium.ttf||156840:1655828711.0": { + "family_name": "Noto Sans Kannada Medium", + "font-family": "Noto Sans Kannada Medium", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Kannada Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKannada-Medium.ttf", + "preferred_family_name": "Noto Sans Kannada", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKannada-Regular.ttf||151940:1655828711.0": { + "family_name": "Noto Sans Kannada", + "font-family": "Noto Sans Kannada", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Kannada Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKannada-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKannada-SemiBold.ttf||154200:1655828711.0": { + "family_name": "Noto Sans Kannada SemiBold", + "font-family": "Noto Sans Kannada SemiBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Kannada SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKannada-SemiBold.ttf", + "preferred_family_name": "Noto Sans Kannada", + "preferred_subfamily_name": "SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKannada-SemiCondensed.ttf||151036:1655828711.0": { + "family_name": "Noto Sans Kannada SemiCondensed", + "font-family": "Noto Sans Kannada SemiCondensed", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Kannada SemiCondensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKannada-SemiCondensed.ttf", + "preferred_family_name": "Noto Sans Kannada", + "preferred_subfamily_name": "SemiCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKannada-SemiCondensedBlack.ttf||170168:1655828711.0": { + "family_name": "Noto Sans Kannada SemiCondensed Black", + "font-family": "Noto Sans Kannada SemiCondensed Black", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Kannada SemiCondensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKannada-SemiCondensedBlack.ttf", + "preferred_family_name": "Noto Sans Kannada", + "preferred_subfamily_name": "SemiCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKannada-SemiCondensedBold.ttf||157736:1655828711.0": { + "family_name": "Noto Sans Kannada SemiCondensed", + "font-family": "Noto Sans Kannada SemiCondensed", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Kannada SemiCondensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKannada-SemiCondensedBold.ttf", + "preferred_family_name": "Noto Sans Kannada", + "preferred_subfamily_name": "SemiCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKannada-SemiCondensedExtraBold.ttf||162348:1655828711.0": { + "family_name": "Noto Sans Kannada SemiCondensed ExtraBold", + "font-family": "Noto Sans Kannada SemiCondensed ExtraBold", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Kannada SemiCondensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKannada-SemiCondensedExtraBold.ttf", + "preferred_family_name": "Noto Sans Kannada", + "preferred_subfamily_name": "SemiCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKannada-SemiCondensedExtraLight.ttf||148276:1655828711.0": { + "family_name": "Noto Sans Kannada SemiCondensed ExtraLight", + "font-family": "Noto Sans Kannada SemiCondensed ExtraLight", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Kannada SemiCondensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKannada-SemiCondensedExtraLight.ttf", + "preferred_family_name": "Noto Sans Kannada", + "preferred_subfamily_name": "SemiCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKannada-SemiCondensedLight.ttf||148060:1655828711.0": { + "family_name": "Noto Sans Kannada SemiCondensed Light", + "font-family": "Noto Sans Kannada SemiCondensed Light", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Kannada SemiCondensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKannada-SemiCondensedLight.ttf", + "preferred_family_name": "Noto Sans Kannada", + "preferred_subfamily_name": "SemiCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKannada-SemiCondensedMedium.ttf||152928:1655828711.0": { + "family_name": "Noto Sans Kannada SemiCondensed Medium", + "font-family": "Noto Sans Kannada SemiCondensed Medium", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Kannada SemiCondensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKannada-SemiCondensedMedium.ttf", + "preferred_family_name": "Noto Sans Kannada", + "preferred_subfamily_name": "SemiCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKannada-SemiCondensedSemiBold.ttf||154996:1655828711.0": { + "family_name": "Noto Sans Kannada SemiCondensed SemiBold", + "font-family": "Noto Sans Kannada SemiCondensed SemiBold", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Kannada SemiCondensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKannada-SemiCondensedSemiBold.ttf", + "preferred_family_name": "Noto Sans Kannada", + "preferred_subfamily_name": "SemiCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKannada-SemiCondensedThin.ttf||147740:1655828711.0": { + "family_name": "Noto Sans Kannada SemiCondensed Thin", + "font-family": "Noto Sans Kannada SemiCondensed Thin", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Kannada SemiCondensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKannada-SemiCondensedThin.ttf", + "preferred_family_name": "Noto Sans Kannada", + "preferred_subfamily_name": "SemiCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKannada-Thin.ttf||149488:1655828711.0": { + "family_name": "Noto Sans Kannada Thin", + "font-family": "Noto Sans Kannada Thin", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Kannada Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKannada-Thin.ttf", + "preferred_family_name": "Noto Sans Kannada", + "preferred_subfamily_name": "Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKannadaUI-Black.ttf||189392:1655828711.0": { + "family_name": "Noto Sans Kannada UI Black", + "font-family": "Noto Sans Kannada UI Black", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Kannada UI Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKannadaUI-Black.ttf", + "preferred_family_name": "Noto Sans Kannada UI", + "preferred_subfamily_name": "Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKannadaUI-Bold.ttf||172600:1655828711.0": { + "family_name": "Noto Sans Kannada UI", + "font-family": "Noto Sans Kannada UI", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Kannada UI Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKannadaUI-Bold.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKannadaUI-Condensed.ttf||168728:1655828711.0": { + "family_name": "Noto Sans Kannada UI Condensed", + "font-family": "Noto Sans Kannada UI Condensed", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Kannada UI Condensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKannadaUI-Condensed.ttf", + "preferred_family_name": "Noto Sans Kannada UI", + "preferred_subfamily_name": "Condensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKannadaUI-CondensedBlack.ttf||187708:1655828711.0": { + "family_name": "Noto Sans Kannada UI Condensed Black", + "font-family": "Noto Sans Kannada UI Condensed Black", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Kannada UI Condensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKannadaUI-CondensedBlack.ttf", + "preferred_family_name": "Noto Sans Kannada UI", + "preferred_subfamily_name": "Condensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKannadaUI-CondensedBold.ttf||174612:1655828711.0": { + "family_name": "Noto Sans Kannada UI Condensed", + "font-family": "Noto Sans Kannada UI Condensed", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Kannada UI Condensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKannadaUI-CondensedBold.ttf", + "preferred_family_name": "Noto Sans Kannada UI", + "preferred_subfamily_name": "Condensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKannadaUI-CondensedExtraBold.ttf||178504:1655828711.0": { + "family_name": "Noto Sans Kannada UI Condensed ExtraBold", + "font-family": "Noto Sans Kannada UI Condensed ExtraBold", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Kannada UI Condensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKannadaUI-CondensedExtraBold.ttf", + "preferred_family_name": "Noto Sans Kannada UI", + "preferred_subfamily_name": "Condensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKannadaUI-CondensedExtraLight.ttf||163916:1655828711.0": { + "family_name": "Noto Sans Kannada UI Condensed ExtraLight", + "font-family": "Noto Sans Kannada UI Condensed ExtraLight", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Kannada UI Condensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKannadaUI-CondensedExtraLight.ttf", + "preferred_family_name": "Noto Sans Kannada UI", + "preferred_subfamily_name": "Condensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKannadaUI-CondensedLight.ttf||163524:1655828711.0": { + "family_name": "Noto Sans Kannada UI Condensed Light", + "font-family": "Noto Sans Kannada UI Condensed Light", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Kannada UI Condensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKannadaUI-CondensedLight.ttf", + "preferred_family_name": "Noto Sans Kannada UI", + "preferred_subfamily_name": "Condensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKannadaUI-CondensedMedium.ttf||169044:1655828711.0": { + "family_name": "Noto Sans Kannada UI Condensed Medium", + "font-family": "Noto Sans Kannada UI Condensed Medium", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Kannada UI Condensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKannadaUI-CondensedMedium.ttf", + "preferred_family_name": "Noto Sans Kannada UI", + "preferred_subfamily_name": "Condensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKannadaUI-CondensedSemiBold.ttf||173936:1655828711.0": { + "family_name": "Noto Sans Kannada UI Condensed SemiBold", + "font-family": "Noto Sans Kannada UI Condensed SemiBold", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Kannada UI Condensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKannadaUI-CondensedSemiBold.ttf", + "preferred_family_name": "Noto Sans Kannada UI", + "preferred_subfamily_name": "Condensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKannadaUI-CondensedThin.ttf||162168:1655828711.0": { + "family_name": "Noto Sans Kannada UI Condensed Thin", + "font-family": "Noto Sans Kannada UI Condensed Thin", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Kannada UI Condensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKannadaUI-CondensedThin.ttf", + "preferred_family_name": "Noto Sans Kannada UI", + "preferred_subfamily_name": "Condensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKannadaUI-ExtraBold.ttf||180272:1655828711.0": { + "family_name": "Noto Sans Kannada UI ExtraBold", + "font-family": "Noto Sans Kannada UI ExtraBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Kannada UI ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKannadaUI-ExtraBold.ttf", + "preferred_family_name": "Noto Sans Kannada UI", + "preferred_subfamily_name": "ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKannadaUI-ExtraCondensed.ttf||166540:1655828711.0": { + "family_name": "Noto Sans Kannada UI ExtraCondensed", + "font-family": "Noto Sans Kannada UI ExtraCondensed", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Kannada UI ExtraCondensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKannadaUI-ExtraCondensed.ttf", + "preferred_family_name": "Noto Sans Kannada UI", + "preferred_subfamily_name": "ExtraCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKannadaUI-ExtraCondensedBlack.ttf||184600:1655828711.0": { + "family_name": "Noto Sans Kannada UI ExtraCondensed Black", + "font-family": "Noto Sans Kannada UI ExtraCondensed Black", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Kannada UI ExtraCondensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKannadaUI-ExtraCondensedBlack.ttf", + "preferred_family_name": "Noto Sans Kannada UI", + "preferred_subfamily_name": "ExtraCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKannadaUI-ExtraCondensedBold.ttf||174628:1655828711.0": { + "family_name": "Noto Sans Kannada UI ExtraCondensed", + "font-family": "Noto Sans Kannada UI ExtraCondensed", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Kannada UI ExtraCondensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKannadaUI-ExtraCondensedBold.ttf", + "preferred_family_name": "Noto Sans Kannada UI", + "preferred_subfamily_name": "ExtraCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKannadaUI-ExtraCondensedExtraBold.ttf||175572:1655828711.0": { + "family_name": "Noto Sans Kannada UI ExtraCondensed ExtraBold", + "font-family": "Noto Sans Kannada UI ExtraCondensed ExtraBold", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Kannada UI ExtraCondensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKannadaUI-ExtraCondensedExtraBold.ttf", + "preferred_family_name": "Noto Sans Kannada UI", + "preferred_subfamily_name": "ExtraCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKannadaUI-ExtraCondensedExtraLight.ttf||166988:1655828711.0": { + "family_name": "Noto Sans Kannada UI ExtraCondensed ExtraLight", + "font-family": "Noto Sans Kannada UI ExtraCondensed ExtraLight", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Kannada UI ExtraCondensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKannadaUI-ExtraCondensedExtraLight.ttf", + "preferred_family_name": "Noto Sans Kannada UI", + "preferred_subfamily_name": "ExtraCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKannadaUI-ExtraCondensedLight.ttf||162904:1655828711.0": { + "family_name": "Noto Sans Kannada UI ExtraCondensed Light", + "font-family": "Noto Sans Kannada UI ExtraCondensed Light", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Kannada UI ExtraCondensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKannadaUI-ExtraCondensedLight.ttf", + "preferred_family_name": "Noto Sans Kannada UI", + "preferred_subfamily_name": "ExtraCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKannadaUI-ExtraCondensedMedium.ttf||168548:1655828711.0": { + "family_name": "Noto Sans Kannada UI ExtraCondensed Medium", + "font-family": "Noto Sans Kannada UI ExtraCondensed Medium", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Kannada UI ExtraCondensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKannadaUI-ExtraCondensedMedium.ttf", + "preferred_family_name": "Noto Sans Kannada UI", + "preferred_subfamily_name": "ExtraCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKannadaUI-ExtraCondensedSemiBold.ttf||173284:1655828711.0": { + "family_name": "Noto Sans Kannada UI ExtraCondensed SemiBold", + "font-family": "Noto Sans Kannada UI ExtraCondensed SemiBold", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Kannada UI ExtraCondensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKannadaUI-ExtraCondensedSemiBold.ttf", + "preferred_family_name": "Noto Sans Kannada UI", + "preferred_subfamily_name": "ExtraCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKannadaUI-ExtraCondensedThin.ttf||162828:1655828711.0": { + "family_name": "Noto Sans Kannada UI ExtraCondensed Thin", + "font-family": "Noto Sans Kannada UI ExtraCondensed Thin", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Kannada UI ExtraCondensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKannadaUI-ExtraCondensedThin.ttf", + "preferred_family_name": "Noto Sans Kannada UI", + "preferred_subfamily_name": "ExtraCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKannadaUI-ExtraLight.ttf||169292:1655828711.0": { + "family_name": "Noto Sans Kannada UI ExtraLight", + "font-family": "Noto Sans Kannada UI ExtraLight", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Kannada UI ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKannadaUI-ExtraLight.ttf", + "preferred_family_name": "Noto Sans Kannada UI", + "preferred_subfamily_name": "ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKannadaUI-Light.ttf||165044:1655828711.0": { + "family_name": "Noto Sans Kannada UI Light", + "font-family": "Noto Sans Kannada UI Light", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Kannada UI Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKannadaUI-Light.ttf", + "preferred_family_name": "Noto Sans Kannada UI", + "preferred_subfamily_name": "Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKannadaUI-Medium.ttf||171612:1655828711.0": { + "family_name": "Noto Sans Kannada UI Medium", + "font-family": "Noto Sans Kannada UI Medium", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Kannada UI Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKannadaUI-Medium.ttf", + "preferred_family_name": "Noto Sans Kannada UI", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKannadaUI-Regular.ttf||167984:1655828711.0": { + "family_name": "Noto Sans Kannada UI", + "font-family": "Noto Sans Kannada UI", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Kannada UI Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKannadaUI-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKannadaUI-SemiBold.ttf||170428:1655828711.0": { + "family_name": "Noto Sans Kannada UI SemiBold", + "font-family": "Noto Sans Kannada UI SemiBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Kannada UI SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKannadaUI-SemiBold.ttf", + "preferred_family_name": "Noto Sans Kannada UI", + "preferred_subfamily_name": "SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKannadaUI-SemiCondensed.ttf||166916:1655828711.0": { + "family_name": "Noto Sans Kannada UI SemiCondensed", + "font-family": "Noto Sans Kannada UI SemiCondensed", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Kannada UI SemiCondensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKannadaUI-SemiCondensed.ttf", + "preferred_family_name": "Noto Sans Kannada UI", + "preferred_subfamily_name": "SemiCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKannadaUI-SemiCondensedBlack.ttf||187888:1655828711.0": { + "family_name": "Noto Sans Kannada UI SemiCondensed Black", + "font-family": "Noto Sans Kannada UI SemiCondensed Black", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Kannada UI SemiCondensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKannadaUI-SemiCondensedBlack.ttf", + "preferred_family_name": "Noto Sans Kannada UI", + "preferred_subfamily_name": "SemiCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKannadaUI-SemiCondensedBold.ttf||173884:1655828711.0": { + "family_name": "Noto Sans Kannada UI SemiCondensed", + "font-family": "Noto Sans Kannada UI SemiCondensed", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Kannada UI SemiCondensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKannadaUI-SemiCondensedBold.ttf", + "preferred_family_name": "Noto Sans Kannada UI", + "preferred_subfamily_name": "SemiCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKannadaUI-SemiCondensedExtraBold.ttf||179228:1655828711.0": { + "family_name": "Noto Sans Kannada UI SemiCondensed ExtraBold", + "font-family": "Noto Sans Kannada UI SemiCondensed ExtraBold", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Kannada UI SemiCondensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKannadaUI-SemiCondensedExtraBold.ttf", + "preferred_family_name": "Noto Sans Kannada UI", + "preferred_subfamily_name": "SemiCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKannadaUI-SemiCondensedExtraLight.ttf||164192:1655828711.0": { + "family_name": "Noto Sans Kannada UI SemiCondensed ExtraLight", + "font-family": "Noto Sans Kannada UI SemiCondensed ExtraLight", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Kannada UI SemiCondensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKannadaUI-SemiCondensedExtraLight.ttf", + "preferred_family_name": "Noto Sans Kannada UI", + "preferred_subfamily_name": "SemiCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKannadaUI-SemiCondensedLight.ttf||164056:1655828711.0": { + "family_name": "Noto Sans Kannada UI SemiCondensed Light", + "font-family": "Noto Sans Kannada UI SemiCondensed Light", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Kannada UI SemiCondensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKannadaUI-SemiCondensedLight.ttf", + "preferred_family_name": "Noto Sans Kannada UI", + "preferred_subfamily_name": "SemiCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKannadaUI-SemiCondensedMedium.ttf||168680:1655828711.0": { + "family_name": "Noto Sans Kannada UI SemiCondensed Medium", + "font-family": "Noto Sans Kannada UI SemiCondensed Medium", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Kannada UI SemiCondensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKannadaUI-SemiCondensedMedium.ttf", + "preferred_family_name": "Noto Sans Kannada UI", + "preferred_subfamily_name": "SemiCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKannadaUI-SemiCondensedSemiBold.ttf||170624:1655828711.0": { + "family_name": "Noto Sans Kannada UI SemiCondensed SemiBold", + "font-family": "Noto Sans Kannada UI SemiCondensed SemiBold", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Kannada UI SemiCondensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKannadaUI-SemiCondensedSemiBold.ttf", + "preferred_family_name": "Noto Sans Kannada UI", + "preferred_subfamily_name": "SemiCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKannadaUI-SemiCondensedThin.ttf||163516:1655828711.0": { + "family_name": "Noto Sans Kannada UI SemiCondensed Thin", + "font-family": "Noto Sans Kannada UI SemiCondensed Thin", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Kannada UI SemiCondensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKannadaUI-SemiCondensedThin.ttf", + "preferred_family_name": "Noto Sans Kannada UI", + "preferred_subfamily_name": "SemiCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKannadaUI-Thin.ttf||165464:1655828711.0": { + "family_name": "Noto Sans Kannada UI Thin", + "font-family": "Noto Sans Kannada UI Thin", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Kannada UI Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKannadaUI-Thin.ttf", + "preferred_family_name": "Noto Sans Kannada UI", + "preferred_subfamily_name": "Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKayahLi-Bold.ttf||17724:1655828711.0": { + "family_name": "Noto Sans Kayah Li", + "font-family": "Noto Sans Kayah Li", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Kayah Li Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKayahLi-Bold.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKayahLi-Medium.ttf||17912:1655828711.0": { + "family_name": "Noto Sans Kayah Li Medium", + "font-family": "Noto Sans Kayah Li Medium", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Kayah Li Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKayahLi-Medium.ttf", + "preferred_family_name": "Noto Sans Kayah Li", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKayahLi-Regular.ttf||17728:1655828711.0": { + "family_name": "Noto Sans Kayah Li", + "font-family": "Noto Sans Kayah Li", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Kayah Li Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKayahLi-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKayahLi-SemiBold.ttf||17692:1655828711.0": { + "family_name": "Noto Sans Kayah Li SemiBold", + "font-family": "Noto Sans Kayah Li SemiBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Kayah Li SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKayahLi-SemiBold.ttf", + "preferred_family_name": "Noto Sans Kayah Li", + "preferred_subfamily_name": "SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKharoshthi-Regular.ttf||33932:1655828711.0": { + "family_name": "Noto Sans Kharoshthi", + "font-family": "Noto Sans Kharoshthi", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Kharoshthi Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKharoshthi-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKhmer-Black.ttf||119268:1655828711.0": { + "family_name": "Noto Sans Khmer Black", + "font-family": "Noto Sans Khmer Black", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Khmer Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKhmer-Black.ttf", + "preferred_family_name": "Noto Sans Khmer", + "preferred_subfamily_name": "Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKhmer-Bold.ttf||113208:1655828711.0": { + "family_name": "Noto Sans Khmer", + "font-family": "Noto Sans Khmer", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Khmer Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKhmer-Bold.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKhmer-Condensed.ttf||108780:1655828711.0": { + "family_name": "Noto Sans Khmer Condensed", + "font-family": "Noto Sans Khmer Condensed", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Khmer Condensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKhmer-Condensed.ttf", + "preferred_family_name": "Noto Sans Khmer", + "preferred_subfamily_name": "Condensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKhmer-CondensedBlack.ttf||118568:1655828711.0": { + "family_name": "Noto Sans Khmer Condensed Black", + "font-family": "Noto Sans Khmer Condensed Black", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Khmer Condensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKhmer-CondensedBlack.ttf", + "preferred_family_name": "Noto Sans Khmer", + "preferred_subfamily_name": "Condensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKhmer-CondensedBold.ttf||111932:1655828711.0": { + "family_name": "Noto Sans Khmer Condensed", + "font-family": "Noto Sans Khmer Condensed", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Khmer Condensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKhmer-CondensedBold.ttf", + "preferred_family_name": "Noto Sans Khmer", + "preferred_subfamily_name": "Condensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKhmer-CondensedExtraBold.ttf||114172:1655828711.0": { + "family_name": "Noto Sans Khmer Condensed ExtraBold", + "font-family": "Noto Sans Khmer Condensed ExtraBold", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Khmer Condensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKhmer-CondensedExtraBold.ttf", + "preferred_family_name": "Noto Sans Khmer", + "preferred_subfamily_name": "Condensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKhmer-CondensedExtraLight.ttf||112208:1655828711.0": { + "family_name": "Noto Sans Khmer Condensed ExtraLight", + "font-family": "Noto Sans Khmer Condensed ExtraLight", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Khmer Condensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKhmer-CondensedExtraLight.ttf", + "preferred_family_name": "Noto Sans Khmer", + "preferred_subfamily_name": "Condensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKhmer-CondensedLight.ttf||109988:1655828711.0": { + "family_name": "Noto Sans Khmer Condensed Light", + "font-family": "Noto Sans Khmer Condensed Light", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Khmer Condensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKhmer-CondensedLight.ttf", + "preferred_family_name": "Noto Sans Khmer", + "preferred_subfamily_name": "Condensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKhmer-CondensedMedium.ttf||110912:1655828711.0": { + "family_name": "Noto Sans Khmer Condensed Medium", + "font-family": "Noto Sans Khmer Condensed Medium", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Khmer Condensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKhmer-CondensedMedium.ttf", + "preferred_family_name": "Noto Sans Khmer", + "preferred_subfamily_name": "Condensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKhmer-CondensedSemiBold.ttf||112092:1655828711.0": { + "family_name": "Noto Sans Khmer Condensed SemiBold", + "font-family": "Noto Sans Khmer Condensed SemiBold", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Khmer Condensed SemiBold ", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKhmer-CondensedSemiBold.ttf", + "preferred_family_name": "Noto Sans Khmer", + "preferred_subfamily_name": "Condensed SemiBold ", + "subfamily_name": "Regular", + "weight": 600, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKhmer-CondensedThin.ttf||110300:1655828711.0": { + "family_name": "Noto Sans Khmer Condensed Thin", + "font-family": "Noto Sans Khmer Condensed Thin", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Khmer Condensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKhmer-CondensedThin.ttf", + "preferred_family_name": "Noto Sans Khmer", + "preferred_subfamily_name": "Condensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKhmer-ExtraBold.ttf||115272:1655828711.0": { + "family_name": "Noto Sans Khmer ExtraBold", + "font-family": "Noto Sans Khmer ExtraBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Khmer ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKhmer-ExtraBold.ttf", + "preferred_family_name": "Noto Sans Khmer", + "preferred_subfamily_name": "ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKhmer-ExtraCondensed.ttf||108792:1655828711.0": { + "family_name": "Noto Sans Khmer ExtraCondensed", + "font-family": "Noto Sans Khmer ExtraCondensed", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Khmer ExtraCondensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKhmer-ExtraCondensed.ttf", + "preferred_family_name": "Noto Sans Khmer", + "preferred_subfamily_name": "ExtraCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKhmer-ExtraCondensedBlack.ttf||118212:1655828711.0": { + "family_name": "Noto Sans Khmer ExtraCondensed Black", + "font-family": "Noto Sans Khmer ExtraCondensed Black", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Khmer ExtraCondensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKhmer-ExtraCondensedBlack.ttf", + "preferred_family_name": "Noto Sans Khmer", + "preferred_subfamily_name": "ExtraCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKhmer-ExtraCondensedBold.ttf||111768:1655828711.0": { + "family_name": "Noto Sans Khmer ExtraCondensed", + "font-family": "Noto Sans Khmer ExtraCondensed", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Khmer ExtraCondensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKhmer-ExtraCondensedBold.ttf", + "preferred_family_name": "Noto Sans Khmer", + "preferred_subfamily_name": "ExtraCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKhmer-ExtraCondensedExtraBold.ttf||113840:1655828711.0": { + "family_name": "Noto Sans Khmer ExtraCondensed ExtraBold", + "font-family": "Noto Sans Khmer ExtraCondensed ExtraBold", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Khmer ExtraCondensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKhmer-ExtraCondensedExtraBold.ttf", + "preferred_family_name": "Noto Sans Khmer", + "preferred_subfamily_name": "ExtraCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKhmer-ExtraCondensedExtraLight.ttf||112244:1655828711.0": { + "family_name": "Noto Sans Khmer ExtraCondensed ExtraLight", + "font-family": "Noto Sans Khmer ExtraCondensed ExtraLight", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Khmer ExtraCondensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKhmer-ExtraCondensedExtraLight.ttf", + "preferred_family_name": "Noto Sans Khmer", + "preferred_subfamily_name": "ExtraCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKhmer-ExtraCondensedLight.ttf||109648:1655828711.0": { + "family_name": "Noto Sans Khmer ExtraCondensed Light", + "font-family": "Noto Sans Khmer ExtraCondensed Light", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Khmer ExtraCondensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKhmer-ExtraCondensedLight.ttf", + "preferred_family_name": "Noto Sans Khmer", + "preferred_subfamily_name": "ExtraCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKhmer-ExtraCondensedMedium.ttf||110032:1655828711.0": { + "family_name": "Noto Sans Khmer ExtraCondensed Medium", + "font-family": "Noto Sans Khmer ExtraCondensed Medium", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Khmer ExtraCondensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKhmer-ExtraCondensedMedium.ttf", + "preferred_family_name": "Noto Sans Khmer", + "preferred_subfamily_name": "ExtraCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKhmer-ExtraCondensedSemiBold.ttf||112088:1655828711.0": { + "family_name": "Noto Sans Khmer ExtraCondensed SemiBold", + "font-family": "Noto Sans Khmer ExtraCondensed SemiBold", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Khmer ExtraCondensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKhmer-ExtraCondensedSemiBold.ttf", + "preferred_family_name": "Noto Sans Khmer", + "preferred_subfamily_name": "ExtraCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKhmer-ExtraCondensedThin.ttf||108680:1655828711.0": { + "family_name": "Noto Sans Khmer ExtraCondensed Thin", + "font-family": "Noto Sans Khmer ExtraCondensed Thin", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Khmer ExtraCondensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKhmer-ExtraCondensedThin.ttf", + "preferred_family_name": "Noto Sans Khmer", + "preferred_subfamily_name": "ExtraCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKhmer-ExtraLight.ttf||111472:1655828711.0": { + "family_name": "Noto Sans Khmer ExtraLight", + "font-family": "Noto Sans Khmer ExtraLight", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Khmer ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKhmer-ExtraLight.ttf", + "preferred_family_name": "Noto Sans Khmer", + "preferred_subfamily_name": "ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKhmer-Light.ttf||110136:1655828711.0": { + "family_name": "Noto Sans Khmer Light", + "font-family": "Noto Sans Khmer Light", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Khmer Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKhmer-Light.ttf", + "preferred_family_name": "Noto Sans Khmer", + "preferred_subfamily_name": "Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKhmer-Medium.ttf||113660:1655828711.0": { + "family_name": "Noto Sans Khmer Medium", + "font-family": "Noto Sans Khmer Medium", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Khmer Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKhmer-Medium.ttf", + "preferred_family_name": "Noto Sans Khmer", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKhmer-Regular.ttf||114096:1655828711.0": { + "family_name": "Noto Sans Khmer", + "font-family": "Noto Sans Khmer", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Khmer Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKhmer-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKhmer-SemiBold.ttf||112276:1655828711.0": { + "family_name": "Noto Sans Khmer SemiBold", + "font-family": "Noto Sans Khmer SemiBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Khmer SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKhmer-SemiBold.ttf", + "preferred_family_name": "Noto Sans Khmer", + "preferred_subfamily_name": "SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKhmer-SemiCondensed.ttf||112048:1655828711.0": { + "family_name": "Noto Sans Khmer SemiCondensed", + "font-family": "Noto Sans Khmer SemiCondensed", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Khmer SemiCondensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKhmer-SemiCondensed.ttf", + "preferred_family_name": "Noto Sans Khmer", + "preferred_subfamily_name": "SemiCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKhmer-SemiCondensedBlack.ttf||117732:1655828711.0": { + "family_name": "Noto Sans Khmer SemiCondensed Black", + "font-family": "Noto Sans Khmer SemiCondensed Black", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Khmer SemiCondensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKhmer-SemiCondensedBlack.ttf", + "preferred_family_name": "Noto Sans Khmer", + "preferred_subfamily_name": "SemiCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKhmer-SemiCondensedBold.ttf||112004:1655828711.0": { + "family_name": "Noto Sans Khmer SemiCondensed", + "font-family": "Noto Sans Khmer SemiCondensed", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Khmer SemiCondensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKhmer-SemiCondensedBold.ttf", + "preferred_family_name": "Noto Sans Khmer", + "preferred_subfamily_name": "SemiCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKhmer-SemiCondensedExtraBold.ttf||114524:1655828711.0": { + "family_name": "Noto Sans Khmer SemiCondensed ExtraBold", + "font-family": "Noto Sans Khmer SemiCondensed ExtraBold", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Khmer SemiCondensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKhmer-SemiCondensedExtraBold.ttf", + "preferred_family_name": "Noto Sans Khmer", + "preferred_subfamily_name": "SemiCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKhmer-SemiCondensedExtraLight.ttf||112336:1655828711.0": { + "family_name": "Noto Sans Khmer SemiCondensed ExtraLight", + "font-family": "Noto Sans Khmer SemiCondensed ExtraLight", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Khmer SemiCondensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKhmer-SemiCondensedExtraLight.ttf", + "preferred_family_name": "Noto Sans Khmer", + "preferred_subfamily_name": "SemiCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKhmer-SemiCondensedLight.ttf||110512:1655828711.0": { + "family_name": "Noto Sans Khmer SemiCondensed Light", + "font-family": "Noto Sans Khmer SemiCondensed Light", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Khmer SemiCondensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKhmer-SemiCondensedLight.ttf", + "preferred_family_name": "Noto Sans Khmer", + "preferred_subfamily_name": "SemiCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKhmer-SemiCondensedMedium.ttf||110556:1655828711.0": { + "family_name": "Noto Sans Khmer SemiCondensed Medium", + "font-family": "Noto Sans Khmer SemiCondensed Medium", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Khmer SemiCondensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKhmer-SemiCondensedMedium.ttf", + "preferred_family_name": "Noto Sans Khmer", + "preferred_subfamily_name": "SemiCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKhmer-SemiCondensedSemiBold.ttf||112164:1655828711.0": { + "family_name": "Noto Sans Khmer SemiCondensed SemiBold", + "font-family": "Noto Sans Khmer SemiCondensed SemiBold", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Khmer SemiCondensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKhmer-SemiCondensedSemiBold.ttf", + "preferred_family_name": "Noto Sans Khmer", + "preferred_subfamily_name": "SemiCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKhmer-SemiCondensedThin.ttf||109972:1655828711.0": { + "family_name": "Noto Sans Khmer SemiCondensed Thin", + "font-family": "Noto Sans Khmer SemiCondensed Thin", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Khmer SemiCondensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKhmer-SemiCondensedThin.ttf", + "preferred_family_name": "Noto Sans Khmer", + "preferred_subfamily_name": "SemiCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKhmer-Thin.ttf||109728:1655828711.0": { + "family_name": "Noto Sans Khmer Thin", + "font-family": "Noto Sans Khmer Thin", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Khmer Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKhmer-Thin.ttf", + "preferred_family_name": "Noto Sans Khmer", + "preferred_subfamily_name": "Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKhmerUI-Black.ttf||139124:1655828711.0": { + "family_name": "Noto Sans Khmer UI Black", + "font-family": "Noto Sans Khmer UI Black", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Khmer UI Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKhmerUI-Black.ttf", + "preferred_family_name": "Noto Sans Khmer UI", + "preferred_subfamily_name": "Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKhmerUI-Bold.ttf||131948:1655828711.0": { + "family_name": "Noto Sans Khmer UI", + "font-family": "Noto Sans Khmer UI", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Khmer UI Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKhmerUI-Bold.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKhmerUI-Condensed.ttf||125744:1655828711.0": { + "family_name": "Noto Sans Khmer UI Condensed", + "font-family": "Noto Sans Khmer UI Condensed", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Khmer UI Condensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKhmerUI-Condensed.ttf", + "preferred_family_name": "Noto Sans Khmer UI", + "preferred_subfamily_name": "Condensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKhmerUI-CondensedBlack.ttf||137400:1655828711.0": { + "family_name": "Noto Sans Khmer UI Condensed Black", + "font-family": "Noto Sans Khmer UI Condensed Black", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Khmer UI Condensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKhmerUI-CondensedBlack.ttf", + "preferred_family_name": "Noto Sans Khmer UI", + "preferred_subfamily_name": "Condensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKhmerUI-CondensedBold.ttf||131460:1655828711.0": { + "family_name": "Noto Sans Khmer UI Condensed", + "font-family": "Noto Sans Khmer UI Condensed", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Khmer UI Condensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKhmerUI-CondensedBold.ttf", + "preferred_family_name": "Noto Sans Khmer UI", + "preferred_subfamily_name": "Condensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKhmerUI-CondensedExtraBold.ttf||133280:1655828711.0": { + "family_name": "Noto Sans Khmer UI Condensed ExtraBold", + "font-family": "Noto Sans Khmer UI Condensed ExtraBold", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Khmer UI Condensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKhmerUI-CondensedExtraBold.ttf", + "preferred_family_name": "Noto Sans Khmer UI", + "preferred_subfamily_name": "Condensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKhmerUI-CondensedExtraLight.ttf||127384:1655828711.0": { + "family_name": "Noto Sans Khmer UI Condensed ExtraLight", + "font-family": "Noto Sans Khmer UI Condensed ExtraLight", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Khmer UI Condensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKhmerUI-CondensedExtraLight.ttf", + "preferred_family_name": "Noto Sans Khmer UI", + "preferred_subfamily_name": "Condensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKhmerUI-CondensedLight.ttf||126792:1655828711.0": { + "family_name": "Noto Sans Khmer UI Condensed Light", + "font-family": "Noto Sans Khmer UI Condensed Light", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Khmer UI Condensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKhmerUI-CondensedLight.ttf", + "preferred_family_name": "Noto Sans Khmer UI", + "preferred_subfamily_name": "Condensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKhmerUI-CondensedMedium.ttf||128548:1655828711.0": { + "family_name": "Noto Sans Khmer UI Condensed Medium", + "font-family": "Noto Sans Khmer UI Condensed Medium", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Khmer UI Condensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKhmerUI-CondensedMedium.ttf", + "preferred_family_name": "Noto Sans Khmer UI", + "preferred_subfamily_name": "Condensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKhmerUI-CondensedSemiBold.ttf||128812:1655828711.0": { + "family_name": "Noto Sans Khmer UI Condensed SemiBold", + "font-family": "Noto Sans Khmer UI Condensed SemiBold", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Khmer UI Condensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKhmerUI-CondensedSemiBold.ttf", + "preferred_family_name": "Noto Sans Khmer UI", + "preferred_subfamily_name": "Condensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKhmerUI-CondensedThin.ttf||125640:1655828711.0": { + "family_name": "Noto Sans Khmer UI Condensed Thin", + "font-family": "Noto Sans Khmer UI Condensed Thin", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Khmer UI Condensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKhmerUI-CondensedThin.ttf", + "preferred_family_name": "Noto Sans Khmer UI", + "preferred_subfamily_name": "Condensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKhmerUI-ExtraBold.ttf||133580:1655828711.0": { + "family_name": "Noto Sans Khmer UI ExtraBold", + "font-family": "Noto Sans Khmer UI ExtraBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Khmer UI ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKhmerUI-ExtraBold.ttf", + "preferred_family_name": "Noto Sans Khmer UI", + "preferred_subfamily_name": "ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKhmerUI-ExtraCondensed.ttf||126348:1655828711.0": { + "family_name": "Noto Sans Khmer UI ExtraCondensed", + "font-family": "Noto Sans Khmer UI ExtraCondensed", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Khmer UI ExtraCondensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKhmerUI-ExtraCondensed.ttf", + "preferred_family_name": "Noto Sans Khmer UI", + "preferred_subfamily_name": "ExtraCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKhmerUI-ExtraCondensedBlack.ttf||137876:1655828711.0": { + "family_name": "Noto Sans Khmer UI ExtraCondensed Black", + "font-family": "Noto Sans Khmer UI ExtraCondensed Black", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Khmer UI ExtraCondensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKhmerUI-ExtraCondensedBlack.ttf", + "preferred_family_name": "Noto Sans Khmer UI", + "preferred_subfamily_name": "ExtraCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKhmerUI-ExtraCondensedBold.ttf||131984:1655828711.0": { + "family_name": "Noto Sans Khmer UI ExtraCondensed", + "font-family": "Noto Sans Khmer UI ExtraCondensed", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Khmer UI ExtraCondensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKhmerUI-ExtraCondensedBold.ttf", + "preferred_family_name": "Noto Sans Khmer UI", + "preferred_subfamily_name": "ExtraCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKhmerUI-ExtraCondensedExtraBold.ttf||132648:1655828711.0": { + "family_name": "Noto Sans Khmer UI ExtraCondensed ExtraBold", + "font-family": "Noto Sans Khmer UI ExtraCondensed ExtraBold", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Khmer UI ExtraCondensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKhmerUI-ExtraCondensedExtraBold.ttf", + "preferred_family_name": "Noto Sans Khmer UI", + "preferred_subfamily_name": "ExtraCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKhmerUI-ExtraCondensedExtraLight.ttf||127448:1655828711.0": { + "family_name": "Noto Sans Khmer UI ExtraCondensed ExtraLight", + "font-family": "Noto Sans Khmer UI ExtraCondensed ExtraLight", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Khmer UI ExtraCondensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKhmerUI-ExtraCondensedExtraLight.ttf", + "preferred_family_name": "Noto Sans Khmer UI", + "preferred_subfamily_name": "ExtraCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKhmerUI-ExtraCondensedLight.ttf||126036:1655828711.0": { + "family_name": "Noto Sans Khmer UI ExtraCondensed Light", + "font-family": "Noto Sans Khmer UI ExtraCondensed Light", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Khmer UI ExtraCondensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKhmerUI-ExtraCondensedLight.ttf", + "preferred_family_name": "Noto Sans Khmer UI", + "preferred_subfamily_name": "ExtraCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKhmerUI-ExtraCondensedMedium.ttf||128240:1655828711.0": { + "family_name": "Noto Sans Khmer UI ExtraCondensed Medium", + "font-family": "Noto Sans Khmer UI ExtraCondensed Medium", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Khmer UI ExtraCondensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKhmerUI-ExtraCondensedMedium.ttf", + "preferred_family_name": "Noto Sans Khmer UI", + "preferred_subfamily_name": "ExtraCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKhmerUI-ExtraCondensedSemiBold.ttf||129200:1655828711.0": { + "family_name": "Noto Sans Khmer UI ExtraCondensed SemiBold", + "font-family": "Noto Sans Khmer UI ExtraCondensed SemiBold", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Khmer UI ExtraCondensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKhmerUI-ExtraCondensedSemiBold.ttf", + "preferred_family_name": "Noto Sans Khmer UI", + "preferred_subfamily_name": "ExtraCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKhmerUI-ExtraCondensedThin.ttf||125212:1655828711.0": { + "family_name": "Noto Sans Khmer UI ExtraCondensed Thin", + "font-family": "Noto Sans Khmer UI ExtraCondensed Thin", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Khmer UI ExtraCondensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKhmerUI-ExtraCondensedThin.ttf", + "preferred_family_name": "Noto Sans Khmer UI", + "preferred_subfamily_name": "ExtraCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKhmerUI-ExtraLight.ttf||126980:1655828711.0": { + "family_name": "Noto Sans Khmer UI ExtraLight", + "font-family": "Noto Sans Khmer UI ExtraLight", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Khmer UI ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKhmerUI-ExtraLight.ttf", + "preferred_family_name": "Noto Sans Khmer UI", + "preferred_subfamily_name": "ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKhmerUI-Light.ttf||125728:1655828711.0": { + "family_name": "Noto Sans Khmer UI Light", + "font-family": "Noto Sans Khmer UI Light", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Khmer UI Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKhmerUI-Light.ttf", + "preferred_family_name": "Noto Sans Khmer UI", + "preferred_subfamily_name": "Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKhmerUI-Medium.ttf||131028:1655828711.0": { + "family_name": "Noto Sans Khmer UI Medium", + "font-family": "Noto Sans Khmer UI Medium", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Khmer UI Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKhmerUI-Medium.ttf", + "preferred_family_name": "Noto Sans Khmer UI", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKhmerUI-Regular.ttf||131640:1655828711.0": { + "family_name": "Noto Sans Khmer UI", + "font-family": "Noto Sans Khmer UI", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Khmer UI Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKhmerUI-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKhmerUI-SemiBold.ttf||129464:1655828711.0": { + "family_name": "Noto Sans Khmer UI SemiBold", + "font-family": "Noto Sans Khmer UI SemiBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Khmer UI SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKhmerUI-SemiBold.ttf", + "preferred_family_name": "Noto Sans Khmer UI", + "preferred_subfamily_name": "SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKhmerUI-SemiCondensed.ttf||128804:1655828711.0": { + "family_name": "Noto Sans Khmer UI SemiCondensed", + "font-family": "Noto Sans Khmer UI SemiCondensed", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Khmer UI SemiCondensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKhmerUI-SemiCondensed.ttf", + "preferred_family_name": "Noto Sans Khmer UI", + "preferred_subfamily_name": "SemiCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKhmerUI-SemiCondensedBlack.ttf||137860:1655828711.0": { + "family_name": "Noto Sans Khmer UI SemiCondensed Black", + "font-family": "Noto Sans Khmer UI SemiCondensed Black", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Khmer UI SemiCondensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKhmerUI-SemiCondensedBlack.ttf", + "preferred_family_name": "Noto Sans Khmer UI", + "preferred_subfamily_name": "SemiCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKhmerUI-SemiCondensedBold.ttf||131664:1655828711.0": { + "family_name": "Noto Sans Khmer UI SemiCondensed", + "font-family": "Noto Sans Khmer UI SemiCondensed", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Khmer UI SemiCondensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKhmerUI-SemiCondensedBold.ttf", + "preferred_family_name": "Noto Sans Khmer UI", + "preferred_subfamily_name": "SemiCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKhmerUI-SemiCondensedExtraBold.ttf||133332:1655828711.0": { + "family_name": "Noto Sans Khmer UI SemiCondensed ExtraBold", + "font-family": "Noto Sans Khmer UI SemiCondensed ExtraBold", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Khmer UI SemiCondensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKhmerUI-SemiCondensedExtraBold.ttf", + "preferred_family_name": "Noto Sans Khmer UI", + "preferred_subfamily_name": "SemiCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKhmerUI-SemiCondensedExtraLight.ttf||127564:1655828711.0": { + "family_name": "Noto Sans Khmer UI SemiCondensed ExtraLight", + "font-family": "Noto Sans Khmer UI SemiCondensed ExtraLight", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Khmer UI SemiCondensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKhmerUI-SemiCondensedExtraLight.ttf", + "preferred_family_name": "Noto Sans Khmer UI", + "preferred_subfamily_name": "SemiCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKhmerUI-SemiCondensedLight.ttf||125912:1655828711.0": { + "family_name": "Noto Sans Khmer UI SemiCondensed Light", + "font-family": "Noto Sans Khmer UI SemiCondensed Light", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Khmer UI SemiCondensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKhmerUI-SemiCondensedLight.ttf", + "preferred_family_name": "Noto Sans Khmer UI", + "preferred_subfamily_name": "SemiCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKhmerUI-SemiCondensedMedium.ttf||127784:1655828711.0": { + "family_name": "Noto Sans Khmer UI SemiCondensed Medium", + "font-family": "Noto Sans Khmer UI SemiCondensed Medium", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Khmer UI SemiCondensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKhmerUI-SemiCondensedMedium.ttf", + "preferred_family_name": "Noto Sans Khmer UI", + "preferred_subfamily_name": "SemiCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKhmerUI-SemiCondensedSemiBold.ttf||129232:1655828711.0": { + "family_name": "Noto Sans Khmer UI SemiCondensed SemiBold", + "font-family": "Noto Sans Khmer UI SemiCondensed SemiBold", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Khmer UI SemiCondensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKhmerUI-SemiCondensedSemiBold.ttf", + "preferred_family_name": "Noto Sans Khmer UI", + "preferred_subfamily_name": "SemiCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKhmerUI-SemiCondensedThin.ttf||125760:1655828711.0": { + "family_name": "Noto Sans Khmer UI SemiCondensed Thin", + "font-family": "Noto Sans Khmer UI SemiCondensed Thin", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Khmer UI SemiCondensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKhmerUI-SemiCondensedThin.ttf", + "preferred_family_name": "Noto Sans Khmer UI", + "preferred_subfamily_name": "SemiCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKhmerUI-Thin.ttf||125880:1655828711.0": { + "family_name": "Noto Sans Khmer UI Thin", + "font-family": "Noto Sans Khmer UI Thin", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Khmer UI Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKhmerUI-Thin.ttf", + "preferred_family_name": "Noto Sans Khmer UI", + "preferred_subfamily_name": "Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKhojki-Regular.ttf||68384:1655828711.0": { + "family_name": "Noto Sans Khojki", + "font-family": "Noto Sans Khojki", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Khojki Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKhojki-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansKhudawadi-Regular.ttf||18840:1655828711.0": { + "family_name": "Noto Sans Khudawadi", + "font-family": "Noto Sans Khudawadi", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Khudawadi Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansKhudawadi-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansLao-Black.ttf||32664:1655828711.0": { + "family_name": "Noto Sans Lao Blk", + "font-family": "Noto Sans Lao Blk", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Lao Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansLao-Black.ttf", + "preferred_family_name": "Noto Sans Lao", + "preferred_subfamily_name": "Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansLao-Bold.ttf||32596:1655828711.0": { + "family_name": "Noto Sans Lao", + "font-family": "Noto Sans Lao", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Lao Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansLao-Bold.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansLao-Condensed.ttf||31272:1655828711.0": { + "family_name": "Noto Sans Lao Cond", + "font-family": "Noto Sans Lao Cond", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Lao Condensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansLao-Condensed.ttf", + "preferred_family_name": "Noto Sans Lao", + "preferred_subfamily_name": "Condensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansLao-CondensedBlack.ttf||32124:1655828711.0": { + "family_name": "Noto Sans Lao Cond Blk", + "font-family": "Noto Sans Lao Cond Blk", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Lao Condensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansLao-CondensedBlack.ttf", + "preferred_family_name": "Noto Sans Lao", + "preferred_subfamily_name": "Condensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansLao-CondensedBold.ttf||31840:1655828711.0": { + "family_name": "Noto Sans Lao Cond", + "font-family": "Noto Sans Lao Cond", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Lao Condensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansLao-CondensedBold.ttf", + "preferred_family_name": "Noto Sans Lao", + "preferred_subfamily_name": "Condensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansLao-CondensedExtraBold.ttf||32152:1655828711.0": { + "family_name": "Noto Sans Lao Cond ExtBd", + "font-family": "Noto Sans Lao Cond ExtBd", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Lao Condensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansLao-CondensedExtraBold.ttf", + "preferred_family_name": "Noto Sans Lao", + "preferred_subfamily_name": "Condensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansLao-CondensedExtraLight.ttf||30580:1655828711.0": { + "family_name": "Noto Sans Lao Cond ExtLt", + "font-family": "Noto Sans Lao Cond ExtLt", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Lao Condensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansLao-CondensedExtraLight.ttf", + "preferred_family_name": "Noto Sans Lao", + "preferred_subfamily_name": "Condensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansLao-CondensedLight.ttf||30468:1655828711.0": { + "family_name": "Noto Sans Lao Cond Light", + "font-family": "Noto Sans Lao Cond Light", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Lao Condensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansLao-CondensedLight.ttf", + "preferred_family_name": "Noto Sans Lao", + "preferred_subfamily_name": "Condensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansLao-CondensedMedium.ttf||31312:1655828711.0": { + "family_name": "Noto Sans Lao Cond Med", + "font-family": "Noto Sans Lao Cond Med", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Lao Condensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansLao-CondensedMedium.ttf", + "preferred_family_name": "Noto Sans Lao", + "preferred_subfamily_name": "Condensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansLao-CondensedSemiBold.ttf||31316:1655828711.0": { + "family_name": "Noto Sans Lao Cond SemBd", + "font-family": "Noto Sans Lao Cond SemBd", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Lao Condensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansLao-CondensedSemiBold.ttf", + "preferred_family_name": "Noto Sans Lao", + "preferred_subfamily_name": "Condensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansLao-CondensedThin.ttf||30424:1655828711.0": { + "family_name": "Noto Sans Lao Cond Thin", + "font-family": "Noto Sans Lao Cond Thin", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Lao Condensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansLao-CondensedThin.ttf", + "preferred_family_name": "Noto Sans Lao", + "preferred_subfamily_name": "Condensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansLao-ExtraBold.ttf||32392:1655828711.0": { + "family_name": "Noto Sans Lao ExtBd", + "font-family": "Noto Sans Lao ExtBd", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Lao ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansLao-ExtraBold.ttf", + "preferred_family_name": "Noto Sans Lao", + "preferred_subfamily_name": "ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansLao-ExtraCondensed.ttf||31264:1655828711.0": { + "family_name": "Noto Sans Lao ExtCond", + "font-family": "Noto Sans Lao ExtCond", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Lao ExtraCondensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansLao-ExtraCondensed.ttf", + "preferred_family_name": "Noto Sans Lao", + "preferred_subfamily_name": "ExtraCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansLao-ExtraCondensedBlack.ttf||32100:1655828711.0": { + "family_name": "Noto Sans Lao ExtCond Blk", + "font-family": "Noto Sans Lao ExtCond Blk", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Lao ExtraCondensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansLao-ExtraCondensedBlack.ttf", + "preferred_family_name": "Noto Sans Lao", + "preferred_subfamily_name": "ExtraCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansLao-ExtraCondensedBold.ttf||31888:1655828711.0": { + "family_name": "Noto Sans Lao ExtCond", + "font-family": "Noto Sans Lao ExtCond", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Lao ExtraCondensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansLao-ExtraCondensedBold.ttf", + "preferred_family_name": "Noto Sans Lao", + "preferred_subfamily_name": "ExtraCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansLao-ExtraCondensedExtraBold.ttf||31596:1655828711.0": { + "family_name": "Noto Sans Lao ExtCond ExtBd", + "font-family": "Noto Sans Lao ExtCond ExtBd", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Lao ExtraCondensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansLao-ExtraCondensedExtraBold.ttf", + "preferred_family_name": "Noto Sans Lao", + "preferred_subfamily_name": "ExtraCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansLao-ExtraCondensedExtraLight.ttf||30508:1655828711.0": { + "family_name": "Noto Sans Lao ExtCond ExtLt", + "font-family": "Noto Sans Lao ExtCond ExtLt", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Lao ExtraCondensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansLao-ExtraCondensedExtraLight.ttf", + "preferred_family_name": "Noto Sans Lao", + "preferred_subfamily_name": "ExtraCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansLao-ExtraCondensedLight.ttf||30320:1655828711.0": { + "family_name": "Noto Sans Lao ExtCond Light", + "font-family": "Noto Sans Lao ExtCond Light", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Lao ExtraCondensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansLao-ExtraCondensedLight.ttf", + "preferred_family_name": "Noto Sans Lao", + "preferred_subfamily_name": "ExtraCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansLao-ExtraCondensedMedium.ttf||31416:1655828711.0": { + "family_name": "Noto Sans Lao ExtCond Med", + "font-family": "Noto Sans Lao ExtCond Med", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Lao ExtraCondensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansLao-ExtraCondensedMedium.ttf", + "preferred_family_name": "Noto Sans Lao", + "preferred_subfamily_name": "ExtraCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansLao-ExtraCondensedSemiBold.ttf||31592:1655828711.0": { + "family_name": "Noto Sans Lao ExtCond SemBd", + "font-family": "Noto Sans Lao ExtCond SemBd", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Lao ExtraCondensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansLao-ExtraCondensedSemiBold.ttf", + "preferred_family_name": "Noto Sans Lao", + "preferred_subfamily_name": "ExtraCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansLao-ExtraCondensedThin.ttf||30300:1655828711.0": { + "family_name": "Noto Sans Lao ExtCond Thin", + "font-family": "Noto Sans Lao ExtCond Thin", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Lao ExtraCondensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansLao-ExtraCondensedThin.ttf", + "preferred_family_name": "Noto Sans Lao", + "preferred_subfamily_name": "ExtraCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansLao-ExtraLight.ttf||31040:1655828711.0": { + "family_name": "Noto Sans Lao ExtLt", + "font-family": "Noto Sans Lao ExtLt", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Lao ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansLao-ExtraLight.ttf", + "preferred_family_name": "Noto Sans Lao", + "preferred_subfamily_name": "ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansLao-Light.ttf||30596:1655828711.0": { + "family_name": "Noto Sans Lao Light", + "font-family": "Noto Sans Lao Light", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Lao Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansLao-Light.ttf", + "preferred_family_name": "Noto Sans Lao", + "preferred_subfamily_name": "Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansLao-Medium.ttf||31328:1655828711.0": { + "family_name": "Noto Sans Lao Med", + "font-family": "Noto Sans Lao Med", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Lao Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansLao-Medium.ttf", + "preferred_family_name": "Noto Sans Lao", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansLao-Regular.ttf||31340:1655828711.0": { + "family_name": "Noto Sans Lao", + "font-family": "Noto Sans Lao", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Lao Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansLao-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansLao-SemiBold.ttf||31868:1655828711.0": { + "family_name": "Noto Sans Lao SemBd", + "font-family": "Noto Sans Lao SemBd", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Lao SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansLao-SemiBold.ttf", + "preferred_family_name": "Noto Sans Lao", + "preferred_subfamily_name": "SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansLao-SemiCondensed.ttf||31236:1655828711.0": { + "family_name": "Noto Sans Lao SemCond", + "font-family": "Noto Sans Lao SemCond", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Lao SemiCondensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansLao-SemiCondensed.ttf", + "preferred_family_name": "Noto Sans Lao", + "preferred_subfamily_name": "SemiCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansLao-SemiCondensedBlack.ttf||32860:1655828711.0": { + "family_name": "Noto Sans Lao SemCond Blk", + "font-family": "Noto Sans Lao SemCond Blk", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Lao SemiCondensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansLao-SemiCondensedBlack.ttf", + "preferred_family_name": "Noto Sans Lao", + "preferred_subfamily_name": "SemiCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansLao-SemiCondensedBold.ttf||32300:1655828711.0": { + "family_name": "Noto Sans Lao SemCond", + "font-family": "Noto Sans Lao SemCond", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Lao SemiCondensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansLao-SemiCondensedBold.ttf", + "preferred_family_name": "Noto Sans Lao", + "preferred_subfamily_name": "SemiCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansLao-SemiCondensedExtraBold.ttf||32780:1655828711.0": { + "family_name": "Noto Sans Lao SemCond ExtBd", + "font-family": "Noto Sans Lao SemCond ExtBd", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Lao SemiCondensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansLao-SemiCondensedExtraBold.ttf", + "preferred_family_name": "Noto Sans Lao", + "preferred_subfamily_name": "SemiCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansLao-SemiCondensedExtraLight.ttf||30944:1655828711.0": { + "family_name": "Noto Sans Lao SemCond ExtLt", + "font-family": "Noto Sans Lao SemCond ExtLt", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Lao SemiCondensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansLao-SemiCondensedExtraLight.ttf", + "preferred_family_name": "Noto Sans Lao", + "preferred_subfamily_name": "SemiCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansLao-SemiCondensedLight.ttf||30840:1655828711.0": { + "family_name": "Noto Sans Lao SemCond Light", + "font-family": "Noto Sans Lao SemCond Light", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Lao SemiCondensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansLao-SemiCondensedLight.ttf", + "preferred_family_name": "Noto Sans Lao", + "preferred_subfamily_name": "SemiCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansLao-SemiCondensedMedium.ttf||31460:1655828711.0": { + "family_name": "Noto Sans Lao SemCond Med", + "font-family": "Noto Sans Lao SemCond Med", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Lao SemiCondensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansLao-SemiCondensedMedium.ttf", + "preferred_family_name": "Noto Sans Lao", + "preferred_subfamily_name": "SemiCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansLao-SemiCondensedSemiBold.ttf||31580:1655828711.0": { + "family_name": "Noto Sans Lao SemCond SemBd", + "font-family": "Noto Sans Lao SemCond SemBd", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Lao SemiCondensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansLao-SemiCondensedSemiBold.ttf", + "preferred_family_name": "Noto Sans Lao", + "preferred_subfamily_name": "SemiCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansLao-SemiCondensedThin.ttf||30584:1655828711.0": { + "family_name": "Noto Sans Lao SemCond Thin", + "font-family": "Noto Sans Lao SemCond Thin", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Lao SemiCondensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansLao-SemiCondensedThin.ttf", + "preferred_family_name": "Noto Sans Lao", + "preferred_subfamily_name": "SemiCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansLao-Thin.ttf||30496:1655828711.0": { + "family_name": "Noto Sans Lao Thin", + "font-family": "Noto Sans Lao Thin", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Lao Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansLao-Thin.ttf", + "preferred_family_name": "Noto Sans Lao", + "preferred_subfamily_name": "Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansLaoUI-Black.ttf||34564:1655828711.0": { + "family_name": "Noto Sans Lao UI Blk", + "font-family": "Noto Sans Lao UI Blk", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Lao UI Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansLaoUI-Black.ttf", + "preferred_family_name": "Noto Sans Lao UI", + "preferred_subfamily_name": "Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansLaoUI-Bold.ttf||33544:1655828711.0": { + "family_name": "Noto Sans Lao UI", + "font-family": "Noto Sans Lao UI", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Lao UI Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansLaoUI-Bold.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansLaoUI-Condensed.ttf||31744:1655828711.0": { + "family_name": "Noto Sans Lao UI Cond", + "font-family": "Noto Sans Lao UI Cond", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Lao UI Condensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansLaoUI-Condensed.ttf", + "preferred_family_name": "Noto Sans Lao UI", + "preferred_subfamily_name": "Condensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansLaoUI-CondensedBlack.ttf||33884:1655828711.0": { + "family_name": "Noto Sans Lao UI Cond Blk", + "font-family": "Noto Sans Lao UI Cond Blk", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Lao UI Condensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansLaoUI-CondensedBlack.ttf", + "preferred_family_name": "Noto Sans Lao UI", + "preferred_subfamily_name": "Condensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansLaoUI-CondensedBold.ttf||32832:1655828711.0": { + "family_name": "Noto Sans Lao UI Cond", + "font-family": "Noto Sans Lao UI Cond", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Lao UI Condensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansLaoUI-CondensedBold.ttf", + "preferred_family_name": "Noto Sans Lao UI", + "preferred_subfamily_name": "Condensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansLaoUI-CondensedExtraBold.ttf||33368:1655828711.0": { + "family_name": "Noto Sans Lao UI Cond ExtBd", + "font-family": "Noto Sans Lao UI Cond ExtBd", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Lao UI Condensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansLaoUI-CondensedExtraBold.ttf", + "preferred_family_name": "Noto Sans Lao UI", + "preferred_subfamily_name": "Condensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansLaoUI-CondensedExtraLight.ttf||31516:1655828711.0": { + "family_name": "Noto Sans Lao UI Cond ExtLt", + "font-family": "Noto Sans Lao UI Cond ExtLt", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Lao UI Condensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansLaoUI-CondensedExtraLight.ttf", + "preferred_family_name": "Noto Sans Lao UI", + "preferred_subfamily_name": "Condensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansLaoUI-CondensedLight.ttf||32652:1655828711.0": { + "family_name": "Noto Sans Lao UI Cond Light", + "font-family": "Noto Sans Lao UI Cond Light", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Lao UI Condensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansLaoUI-CondensedLight.ttf", + "preferred_family_name": "Noto Sans Lao UI", + "preferred_subfamily_name": "Condensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansLaoUI-CondensedMedium.ttf||31756:1655828711.0": { + "family_name": "Noto Sans Lao UI Cond Med", + "font-family": "Noto Sans Lao UI Cond Med", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Lao UI Condensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansLaoUI-CondensedMedium.ttf", + "preferred_family_name": "Noto Sans Lao UI", + "preferred_subfamily_name": "Condensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansLaoUI-CondensedSemiBold.ttf||32552:1655828711.0": { + "family_name": "Noto Sans Lao UI Cond SemBd", + "font-family": "Noto Sans Lao UI Cond SemBd", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Lao UI Condensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansLaoUI-CondensedSemiBold.ttf", + "preferred_family_name": "Noto Sans Lao UI", + "preferred_subfamily_name": "Condensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansLaoUI-CondensedThin.ttf||31844:1655828711.0": { + "family_name": "Noto Sans Lao UI Cond Thin", + "font-family": "Noto Sans Lao UI Cond Thin", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Lao UI Condensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansLaoUI-CondensedThin.ttf", + "preferred_family_name": "Noto Sans Lao UI", + "preferred_subfamily_name": "Condensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansLaoUI-ExtraBold.ttf||33896:1655828711.0": { + "family_name": "Noto Sans Lao UI ExtBd", + "font-family": "Noto Sans Lao UI ExtBd", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Lao UI ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansLaoUI-ExtraBold.ttf", + "preferred_family_name": "Noto Sans Lao UI", + "preferred_subfamily_name": "ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansLaoUI-ExtraCondensed.ttf||31584:1655828711.0": { + "family_name": "Noto Sans Lao UI ExtCond", + "font-family": "Noto Sans Lao UI ExtCond", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Lao UI ExtraCondensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansLaoUI-ExtraCondensed.ttf", + "preferred_family_name": "Noto Sans Lao UI", + "preferred_subfamily_name": "ExtraCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansLaoUI-ExtraCondensedBlack.ttf||33292:1655828711.0": { + "family_name": "Noto Sans Lao UI ExtCond Blk", + "font-family": "Noto Sans Lao UI ExtCond Blk", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Lao UI ExtraCondensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansLaoUI-ExtraCondensedBlack.ttf", + "preferred_family_name": "Noto Sans Lao UI", + "preferred_subfamily_name": "ExtraCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansLaoUI-ExtraCondensedBold.ttf||32916:1655828711.0": { + "family_name": "Noto Sans Lao UI ExtCond", + "font-family": "Noto Sans Lao UI ExtCond", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Lao UI ExtraCondensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansLaoUI-ExtraCondensedBold.ttf", + "preferred_family_name": "Noto Sans Lao UI", + "preferred_subfamily_name": "ExtraCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansLaoUI-ExtraCondensedExtraBold.ttf||32612:1655828711.0": { + "family_name": "Noto Sans Lao UI ExtCond ExtBd", + "font-family": "Noto Sans Lao UI ExtCond ExtBd", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Lao UI ExtraCondensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansLaoUI-ExtraCondensedExtraBold.ttf", + "preferred_family_name": "Noto Sans Lao UI", + "preferred_subfamily_name": "ExtraCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansLaoUI-ExtraCondensedExtraLight.ttf||31396:1655828711.0": { + "family_name": "Noto Sans Lao UI ExtCond ExtLt", + "font-family": "Noto Sans Lao UI ExtCond ExtLt", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Lao UI ExtraCondensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansLaoUI-ExtraCondensedExtraLight.ttf", + "preferred_family_name": "Noto Sans Lao UI", + "preferred_subfamily_name": "ExtraCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansLaoUI-ExtraCondensedLight.ttf||32716:1655828711.0": { + "family_name": "Noto Sans Lao UI ExtCond Light", + "font-family": "Noto Sans Lao UI ExtCond Light", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Lao UI ExtraCondensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansLaoUI-ExtraCondensedLight.ttf", + "preferred_family_name": "Noto Sans Lao UI", + "preferred_subfamily_name": "ExtraCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansLaoUI-ExtraCondensedMedium.ttf||31552:1655828711.0": { + "family_name": "Noto Sans Lao UI ExtCond Med", + "font-family": "Noto Sans Lao UI ExtCond Med", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Lao UI ExtraCondensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansLaoUI-ExtraCondensedMedium.ttf", + "preferred_family_name": "Noto Sans Lao UI", + "preferred_subfamily_name": "ExtraCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansLaoUI-ExtraCondensedSemiBold.ttf||32300:1655828711.0": { + "family_name": "Noto Sans Lao UI ExtCond SemBd", + "font-family": "Noto Sans Lao UI ExtCond SemBd", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Lao UI ExtraCondensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansLaoUI-ExtraCondensedSemiBold.ttf", + "preferred_family_name": "Noto Sans Lao UI", + "preferred_subfamily_name": "ExtraCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansLaoUI-ExtraCondensedThin.ttf||31732:1655828711.0": { + "family_name": "Noto Sans Lao UI ExtCond Thin", + "font-family": "Noto Sans Lao UI ExtCond Thin", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Lao UI ExtraCondensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansLaoUI-ExtraCondensedThin.ttf", + "preferred_family_name": "Noto Sans Lao UI", + "preferred_subfamily_name": "ExtraCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansLaoUI-ExtraLight.ttf||31600:1655828711.0": { + "family_name": "Noto Sans Lao UI ExtLt", + "font-family": "Noto Sans Lao UI ExtLt", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Lao UI ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansLaoUI-ExtraLight.ttf", + "preferred_family_name": "Noto Sans Lao UI", + "preferred_subfamily_name": "ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansLaoUI-Light.ttf||32500:1655828711.0": { + "family_name": "Noto Sans Lao UI Light", + "font-family": "Noto Sans Lao UI Light", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Lao UI Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansLaoUI-Light.ttf", + "preferred_family_name": "Noto Sans Lao UI", + "preferred_subfamily_name": "Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansLaoUI-Medium.ttf||32080:1655828711.0": { + "family_name": "Noto Sans Lao UI Med", + "font-family": "Noto Sans Lao UI Med", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Lao UI Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansLaoUI-Medium.ttf", + "preferred_family_name": "Noto Sans Lao UI", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansLaoUI-Regular.ttf||32216:1655828711.0": { + "family_name": "Noto Sans Lao UI", + "font-family": "Noto Sans Lao UI", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Lao UI Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansLaoUI-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansLaoUI-SemiBold.ttf||32668:1655828711.0": { + "family_name": "Noto Sans Lao UI SemBd", + "font-family": "Noto Sans Lao UI SemBd", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Lao UI SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansLaoUI-SemiBold.ttf", + "preferred_family_name": "Noto Sans Lao UI", + "preferred_subfamily_name": "SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansLaoUI-SemiCondensed.ttf||31924:1655828711.0": { + "family_name": "Noto Sans Lao UI SemCond", + "font-family": "Noto Sans Lao UI SemCond", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Lao UI SemiCondensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansLaoUI-SemiCondensed.ttf", + "preferred_family_name": "Noto Sans Lao UI", + "preferred_subfamily_name": "SemiCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansLaoUI-SemiCondensedBlack.ttf||34488:1655828711.0": { + "family_name": "Noto Sans Lao UI SemCond Blk", + "font-family": "Noto Sans Lao UI SemCond Blk", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Lao UI SemiCondensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansLaoUI-SemiCondensedBlack.ttf", + "preferred_family_name": "Noto Sans Lao UI", + "preferred_subfamily_name": "SemiCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansLaoUI-SemiCondensedBold.ttf||32788:1655828711.0": { + "family_name": "Noto Sans Lao UI SemCond", + "font-family": "Noto Sans Lao UI SemCond", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Lao UI SemiCondensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansLaoUI-SemiCondensedBold.ttf", + "preferred_family_name": "Noto Sans Lao UI", + "preferred_subfamily_name": "SemiCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansLaoUI-SemiCondensedExtraBold.ttf||33972:1655828711.0": { + "family_name": "Noto Sans Lao UI SemCond ExtBd", + "font-family": "Noto Sans Lao UI SemCond ExtBd", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Lao UI SemiCondensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansLaoUI-SemiCondensedExtraBold.ttf", + "preferred_family_name": "Noto Sans Lao UI", + "preferred_subfamily_name": "SemiCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansLaoUI-SemiCondensedExtraLight.ttf||31580:1655828711.0": { + "family_name": "Noto Sans Lao UI SemCond ExtLt", + "font-family": "Noto Sans Lao UI SemCond ExtLt", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Lao UI SemiCondensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansLaoUI-SemiCondensedExtraLight.ttf", + "preferred_family_name": "Noto Sans Lao UI", + "preferred_subfamily_name": "SemiCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansLaoUI-SemiCondensedLight.ttf||32608:1655828711.0": { + "family_name": "Noto Sans Lao UI SemCond Light", + "font-family": "Noto Sans Lao UI SemCond Light", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Lao UI SemiCondensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansLaoUI-SemiCondensedLight.ttf", + "preferred_family_name": "Noto Sans Lao UI", + "preferred_subfamily_name": "SemiCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansLaoUI-SemiCondensedMedium.ttf||32136:1655828711.0": { + "family_name": "Noto Sans Lao UI SemCond Med", + "font-family": "Noto Sans Lao UI SemCond Med", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Lao UI SemiCondensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansLaoUI-SemiCondensedMedium.ttf", + "preferred_family_name": "Noto Sans Lao UI", + "preferred_subfamily_name": "SemiCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansLaoUI-SemiCondensedSemiBold.ttf||32264:1655828711.0": { + "family_name": "Noto Sans Lao UI SemCond SemBd", + "font-family": "Noto Sans Lao UI SemCond SemBd", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Lao UI SemiCondensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansLaoUI-SemiCondensedSemiBold.ttf", + "preferred_family_name": "Noto Sans Lao UI", + "preferred_subfamily_name": "SemiCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansLaoUI-SemiCondensedThin.ttf||32356:1655828711.0": { + "family_name": "Noto Sans Lao UI SemCond Thin", + "font-family": "Noto Sans Lao UI SemCond Thin", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Lao UI SemiCondensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansLaoUI-SemiCondensedThin.ttf", + "preferred_family_name": "Noto Sans Lao UI", + "preferred_subfamily_name": "SemiCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansLaoUI-Thin.ttf||32204:1655828711.0": { + "family_name": "Noto Sans Lao UI Thin", + "font-family": "Noto Sans Lao UI Thin", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Lao UI Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansLaoUI-Thin.ttf", + "preferred_family_name": "Noto Sans Lao UI", + "preferred_subfamily_name": "Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansLepcha-Regular.ttf||24724:1655828711.0": { + "family_name": "Noto Sans Lepcha", + "font-family": "Noto Sans Lepcha", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Lepcha Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansLepcha-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansLimbu-Regular.ttf||12980:1655828711.0": { + "family_name": "Noto Sans Limbu", + "font-family": "Noto Sans Limbu", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Limbu Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansLimbu-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansLinearA-Regular.ttf||58168:1655828711.0": { + "family_name": "Noto Sans Linear A", + "font-family": "Noto Sans Linear A", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Linear A Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansLinearA-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansLinearB-Regular.ttf||62892:1655828711.0": { + "family_name": "Noto Sans Linear B", + "font-family": "Noto Sans Linear B", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Linear B Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansLinearB-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansLisu-Bold.ttf||13172:1655828711.0": { + "family_name": "Noto Sans Lisu", + "font-family": "Noto Sans Lisu", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Lisu Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansLisu-Bold.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansLisu-Medium.ttf||13216:1655828711.0": { + "family_name": "Noto Sans Lisu Medium", + "font-family": "Noto Sans Lisu Medium", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Lisu Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansLisu-Medium.ttf", + "preferred_family_name": "Noto Sans Lisu", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansLisu-Regular.ttf||13164:1655828711.0": { + "family_name": "Noto Sans Lisu", + "font-family": "Noto Sans Lisu", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Lisu Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansLisu-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansLisu-SemiBold.ttf||13288:1655828711.0": { + "family_name": "Noto Sans Lisu SemiBold", + "font-family": "Noto Sans Lisu SemiBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Lisu SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansLisu-SemiBold.ttf", + "preferred_family_name": "Noto Sans Lisu", + "preferred_subfamily_name": "SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansLycian-Regular.ttf||4488:1655828711.0": { + "family_name": "Noto Sans Lycian", + "font-family": "Noto Sans Lycian", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Lycian Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansLycian-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansLydian-Regular.ttf||4524:1655828711.0": { + "family_name": "Noto Sans Lydian", + "font-family": "Noto Sans Lydian", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Lydian Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansLydian-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMahajani-Regular.ttf||22816:1655828711.0": { + "family_name": "Noto Sans Mahajani", + "font-family": "Noto Sans Mahajani", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Mahajani Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMahajani-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMalayalam-Black.ttf||117408:1655828711.0": { + "family_name": "Noto Sans Malayalam Black", + "font-family": "Noto Sans Malayalam Black", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Malayalam Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMalayalam-Black.ttf", + "preferred_family_name": "Noto Sans Malayalam", + "preferred_subfamily_name": "Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMalayalam-Bold.ttf||117236:1655828711.0": { + "family_name": "Noto Sans Malayalam", + "font-family": "Noto Sans Malayalam", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Malayalam Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMalayalam-Bold.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMalayalam-Condensed.ttf||132256:1655828711.0": { + "family_name": "Noto Sans Malayalam Condensed", + "font-family": "Noto Sans Malayalam Condensed", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Malayalam Condensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMalayalam-Condensed.ttf", + "preferred_family_name": "Noto Sans Malayalam", + "preferred_subfamily_name": "Condensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMalayalam-CondensedBlack.ttf||116512:1655828711.0": { + "family_name": "Noto Sans Malayalam Condensed Black", + "font-family": "Noto Sans Malayalam Condensed Black", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Malayalam Condensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMalayalam-CondensedBlack.ttf", + "preferred_family_name": "Noto Sans Malayalam", + "preferred_subfamily_name": "Condensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMalayalam-CondensedBold.ttf||116244:1655828711.0": { + "family_name": "Noto Sans Malayalam Condensed", + "font-family": "Noto Sans Malayalam Condensed", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Malayalam Condensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMalayalam-CondensedBold.ttf", + "preferred_family_name": "Noto Sans Malayalam", + "preferred_subfamily_name": "Condensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMalayalam-CondensedExtraBold.ttf||115612:1655828711.0": { + "family_name": "Noto Sans Malayalam Condensed ExtraBold", + "font-family": "Noto Sans Malayalam Condensed ExtraBold", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Malayalam Condensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMalayalam-CondensedExtraBold.ttf", + "preferred_family_name": "Noto Sans Malayalam", + "preferred_subfamily_name": "Condensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMalayalam-CondensedExtraLight.ttf||101864:1655828711.0": { + "family_name": "Noto Sans Malayalam Condensed ExtraLight", + "font-family": "Noto Sans Malayalam Condensed ExtraLight", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Malayalam Condensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMalayalam-CondensedExtraLight.ttf", + "preferred_family_name": "Noto Sans Malayalam", + "preferred_subfamily_name": "Condensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMalayalam-CondensedLight.ttf||102680:1655828711.0": { + "family_name": "Noto Sans Malayalam Condensed Light", + "font-family": "Noto Sans Malayalam Condensed Light", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Malayalam Condensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMalayalam-CondensedLight.ttf", + "preferred_family_name": "Noto Sans Malayalam", + "preferred_subfamily_name": "Condensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMalayalam-CondensedMedium.ttf||111512:1655828711.0": { + "family_name": "Noto Sans Malayalam Condensed Medium", + "font-family": "Noto Sans Malayalam Condensed Medium", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Malayalam Condensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMalayalam-CondensedMedium.ttf", + "preferred_family_name": "Noto Sans Malayalam", + "preferred_subfamily_name": "Condensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMalayalam-CondensedSemiBold.ttf||113524:1655828711.0": { + "family_name": "Noto Sans Malayalam Condensed SemiBold", + "font-family": "Noto Sans Malayalam Condensed SemiBold", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Malayalam Condensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMalayalam-CondensedSemiBold.ttf", + "preferred_family_name": "Noto Sans Malayalam", + "preferred_subfamily_name": "Condensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMalayalam-CondensedThin.ttf||104428:1655828711.0": { + "family_name": "Noto Sans Malayalam Condensed Thin", + "font-family": "Noto Sans Malayalam Condensed Thin", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Malayalam Condensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMalayalam-CondensedThin.ttf", + "preferred_family_name": "Noto Sans Malayalam", + "preferred_subfamily_name": "Condensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMalayalam-ExtraBold.ttf||116108:1655828711.0": { + "family_name": "Noto Sans Malayalam ExtraBold", + "font-family": "Noto Sans Malayalam ExtraBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Malayalam ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMalayalam-ExtraBold.ttf", + "preferred_family_name": "Noto Sans Malayalam", + "preferred_subfamily_name": "ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMalayalam-ExtraCondensed.ttf||132016:1655828711.0": { + "family_name": "Noto Sans Malayalam ExtraCondensed", + "font-family": "Noto Sans Malayalam ExtraCondensed", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Malayalam ExtraCondensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMalayalam-ExtraCondensed.ttf", + "preferred_family_name": "Noto Sans Malayalam", + "preferred_subfamily_name": "ExtraCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMalayalam-ExtraCondensedBlack.ttf||115736:1655828711.0": { + "family_name": "Noto Sans Malayalam ExtraCondensed Black", + "font-family": "Noto Sans Malayalam ExtraCondensed Black", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Malayalam ExtraCondensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMalayalam-ExtraCondensedBlack.ttf", + "preferred_family_name": "Noto Sans Malayalam", + "preferred_subfamily_name": "ExtraCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMalayalam-ExtraCondensedBold.ttf||114888:1655828711.0": { + "family_name": "Noto Sans Malayalam ExtraCondensed", + "font-family": "Noto Sans Malayalam ExtraCondensed", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Malayalam ExtraCondensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMalayalam-ExtraCondensedBold.ttf", + "preferred_family_name": "Noto Sans Malayalam", + "preferred_subfamily_name": "ExtraCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMalayalam-ExtraCondensedExtraBold.ttf||115648:1655828711.0": { + "family_name": "Noto Sans Malayalam ExtraCondensed ExtraBold", + "font-family": "Noto Sans Malayalam ExtraCondensed ExtraBold", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Malayalam ExtraCondensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMalayalam-ExtraCondensedExtraBold.ttf", + "preferred_family_name": "Noto Sans Malayalam", + "preferred_subfamily_name": "ExtraCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMalayalam-ExtraCondensedExtraLight.ttf||102660:1655828711.0": { + "family_name": "Noto Sans Malayalam ExtraCondensed ExtraLight", + "font-family": "Noto Sans Malayalam ExtraCondensed ExtraLight", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Malayalam ExtraCondensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMalayalam-ExtraCondensedExtraLight.ttf", + "preferred_family_name": "Noto Sans Malayalam", + "preferred_subfamily_name": "ExtraCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMalayalam-ExtraCondensedLight.ttf||102488:1655828711.0": { + "family_name": "Noto Sans Malayalam ExtraCondensed Light", + "font-family": "Noto Sans Malayalam ExtraCondensed Light", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Malayalam ExtraCondensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMalayalam-ExtraCondensedLight.ttf", + "preferred_family_name": "Noto Sans Malayalam", + "preferred_subfamily_name": "ExtraCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMalayalam-ExtraCondensedMedium.ttf||110652:1655828711.0": { + "family_name": "Noto Sans Malayalam ExtraCondensed Medium", + "font-family": "Noto Sans Malayalam ExtraCondensed Medium", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Malayalam ExtraCondensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMalayalam-ExtraCondensedMedium.ttf", + "preferred_family_name": "Noto Sans Malayalam", + "preferred_subfamily_name": "ExtraCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMalayalam-ExtraCondensedSemiBold.ttf||113076:1655828711.0": { + "family_name": "Noto Sans Malayalam ExtraCondensed SemiBold", + "font-family": "Noto Sans Malayalam ExtraCondensed SemiBold", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Malayalam ExtraCondensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMalayalam-ExtraCondensedSemiBold.ttf", + "preferred_family_name": "Noto Sans Malayalam", + "preferred_subfamily_name": "ExtraCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMalayalam-ExtraCondensedThin.ttf||106372:1655828711.0": { + "family_name": "Noto Sans Malayalam ExtraCondensed Thin", + "font-family": "Noto Sans Malayalam ExtraCondensed Thin", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Malayalam ExtraCondensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMalayalam-ExtraCondensedThin.ttf", + "preferred_family_name": "Noto Sans Malayalam", + "preferred_subfamily_name": "ExtraCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMalayalam-ExtraLight.ttf||104008:1655828711.0": { + "family_name": "Noto Sans Malayalam ExtraLight", + "font-family": "Noto Sans Malayalam ExtraLight", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Malayalam ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMalayalam-ExtraLight.ttf", + "preferred_family_name": "Noto Sans Malayalam", + "preferred_subfamily_name": "ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMalayalam-Light.ttf||105252:1655828711.0": { + "family_name": "Noto Sans Malayalam Light", + "font-family": "Noto Sans Malayalam Light", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Malayalam Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMalayalam-Light.ttf", + "preferred_family_name": "Noto Sans Malayalam", + "preferred_subfamily_name": "Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMalayalam-Medium.ttf||113368:1655828711.0": { + "family_name": "Noto Sans Malayalam Medium", + "font-family": "Noto Sans Malayalam Medium", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Malayalam Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMalayalam-Medium.ttf", + "preferred_family_name": "Noto Sans Malayalam", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMalayalam-Regular.ttf||111724:1655828711.0": { + "family_name": "Noto Sans Malayalam", + "font-family": "Noto Sans Malayalam", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Malayalam Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMalayalam-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMalayalam-SemiBold.ttf||115300:1655828711.0": { + "family_name": "Noto Sans Malayalam SemiBold", + "font-family": "Noto Sans Malayalam SemiBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Malayalam SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMalayalam-SemiBold.ttf", + "preferred_family_name": "Noto Sans Malayalam", + "preferred_subfamily_name": "SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMalayalam-SemiCondensed.ttf||111460:1655828711.0": { + "family_name": "Noto Sans Malayalam SemiCondensed", + "font-family": "Noto Sans Malayalam SemiCondensed", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Malayalam SemiCondensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMalayalam-SemiCondensed.ttf", + "preferred_family_name": "Noto Sans Malayalam", + "preferred_subfamily_name": "SemiCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMalayalam-SemiCondensedBlack.ttf||117316:1655828711.0": { + "family_name": "Noto Sans Malayalam SemiCondensed Black", + "font-family": "Noto Sans Malayalam SemiCondensed Black", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Malayalam SemiCondensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMalayalam-SemiCondensedBlack.ttf", + "preferred_family_name": "Noto Sans Malayalam", + "preferred_subfamily_name": "SemiCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMalayalam-SemiCondensedBold.ttf||117276:1655828711.0": { + "family_name": "Noto Sans Malayalam SemiCondensed", + "font-family": "Noto Sans Malayalam SemiCondensed", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Malayalam SemiCondensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMalayalam-SemiCondensedBold.ttf", + "preferred_family_name": "Noto Sans Malayalam", + "preferred_subfamily_name": "SemiCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMalayalam-SemiCondensedExtraBold.ttf||115696:1655828711.0": { + "family_name": "Noto Sans Malayalam SemiCondensed ExtraBold", + "font-family": "Noto Sans Malayalam SemiCondensed ExtraBold", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Malayalam SemiCondensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMalayalam-SemiCondensedExtraBold.ttf", + "preferred_family_name": "Noto Sans Malayalam", + "preferred_subfamily_name": "SemiCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMalayalam-SemiCondensedExtraLight.ttf||103116:1655828711.0": { + "family_name": "Noto Sans Malayalam SemiCondensed ExtraLight", + "font-family": "Noto Sans Malayalam SemiCondensed ExtraLight", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Malayalam SemiCondensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMalayalam-SemiCondensedExtraLight.ttf", + "preferred_family_name": "Noto Sans Malayalam", + "preferred_subfamily_name": "SemiCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMalayalam-SemiCondensedLight.ttf||103704:1655828711.0": { + "family_name": "Noto Sans Malayalam SemiCondensed Light", + "font-family": "Noto Sans Malayalam SemiCondensed Light", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Malayalam SemiCondensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMalayalam-SemiCondensedLight.ttf", + "preferred_family_name": "Noto Sans Malayalam", + "preferred_subfamily_name": "SemiCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMalayalam-SemiCondensedMedium.ttf||112812:1655828711.0": { + "family_name": "Noto Sans Malayalam SemiCondensed Medium", + "font-family": "Noto Sans Malayalam SemiCondensed Medium", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Malayalam SemiCondensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMalayalam-SemiCondensedMedium.ttf", + "preferred_family_name": "Noto Sans Malayalam", + "preferred_subfamily_name": "SemiCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMalayalam-SemiCondensedSemiBold.ttf||115132:1655828711.0": { + "family_name": "Noto Sans Malayalam SemiCondensed SemiBold", + "font-family": "Noto Sans Malayalam SemiCondensed SemiBold", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Malayalam SemiCondensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMalayalam-SemiCondensedSemiBold.ttf", + "preferred_family_name": "Noto Sans Malayalam", + "preferred_subfamily_name": "SemiCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMalayalam-SemiCondensedThin.ttf||103556:1655828711.0": { + "family_name": "Noto Sans Malayalam SemiCondensed Thin", + "font-family": "Noto Sans Malayalam SemiCondensed Thin", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Malayalam SemiCondensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMalayalam-SemiCondensedThin.ttf", + "preferred_family_name": "Noto Sans Malayalam", + "preferred_subfamily_name": "SemiCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMalayalam-Thin.ttf||104480:1655828711.0": { + "family_name": "Noto Sans Malayalam Thin", + "font-family": "Noto Sans Malayalam Thin", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Malayalam Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMalayalam-Thin.ttf", + "preferred_family_name": "Noto Sans Malayalam", + "preferred_subfamily_name": "Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMalayalamUI-Black.ttf||117200:1655828711.0": { + "family_name": "Noto Sans Malayalam UI Black", + "font-family": "Noto Sans Malayalam UI Black", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Malayalam UI Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMalayalamUI-Black.ttf", + "preferred_family_name": "Noto Sans Malayalam UI", + "preferred_subfamily_name": "Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMalayalamUI-Bold.ttf||116988:1655828711.0": { + "family_name": "Noto Sans Malayalam UI", + "font-family": "Noto Sans Malayalam UI", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Malayalam UI Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMalayalamUI-Bold.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMalayalamUI-Condensed.ttf||132488:1655828711.0": { + "family_name": "Noto Sans Malayalam UI Condensed", + "font-family": "Noto Sans Malayalam UI Condensed", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Malayalam UI Condensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMalayalamUI-Condensed.ttf", + "preferred_family_name": "Noto Sans Malayalam UI", + "preferred_subfamily_name": "Condensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMalayalamUI-CondensedBlack.ttf||116300:1655828711.0": { + "family_name": "Noto Sans Malayalam UI Condensed Black", + "font-family": "Noto Sans Malayalam UI Condensed Black", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Malayalam UI Condensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMalayalamUI-CondensedBlack.ttf", + "preferred_family_name": "Noto Sans Malayalam UI", + "preferred_subfamily_name": "Condensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMalayalamUI-CondensedBold.ttf||116004:1655828711.0": { + "family_name": "Noto Sans Malayalam UI Condensed", + "font-family": "Noto Sans Malayalam UI Condensed", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Malayalam UI Condensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMalayalamUI-CondensedBold.ttf", + "preferred_family_name": "Noto Sans Malayalam UI", + "preferred_subfamily_name": "Condensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMalayalamUI-CondensedExtraBold.ttf||115392:1655828711.0": { + "family_name": "Noto Sans Malayalam UI Condensed ExtraBold", + "font-family": "Noto Sans Malayalam UI Condensed ExtraBold", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Malayalam UI Condensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMalayalamUI-CondensedExtraBold.ttf", + "preferred_family_name": "Noto Sans Malayalam UI", + "preferred_subfamily_name": "Condensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMalayalamUI-CondensedExtraLight.ttf||101920:1655828711.0": { + "family_name": "Noto Sans Malayalam UI Condensed ExtraLight", + "font-family": "Noto Sans Malayalam UI Condensed ExtraLight", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Malayalam UI Condensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMalayalamUI-CondensedExtraLight.ttf", + "preferred_family_name": "Noto Sans Malayalam UI", + "preferred_subfamily_name": "Condensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMalayalamUI-CondensedLight.ttf||102744:1655828711.0": { + "family_name": "Noto Sans Malayalam UI Condensed Light", + "font-family": "Noto Sans Malayalam UI Condensed Light", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Malayalam UI Condensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMalayalamUI-CondensedLight.ttf", + "preferred_family_name": "Noto Sans Malayalam UI", + "preferred_subfamily_name": "Condensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMalayalamUI-CondensedMedium.ttf||111656:1655828711.0": { + "family_name": "Noto Sans Malayalam UI Condensed Medium", + "font-family": "Noto Sans Malayalam UI Condensed Medium", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Malayalam UI Condensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMalayalamUI-CondensedMedium.ttf", + "preferred_family_name": "Noto Sans Malayalam UI", + "preferred_subfamily_name": "Condensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMalayalamUI-CondensedSemiBold.ttf||113284:1655828711.0": { + "family_name": "Noto Sans Malayalam UI Condensed SemiBold", + "font-family": "Noto Sans Malayalam UI Condensed SemiBold", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Malayalam UI Condensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMalayalamUI-CondensedSemiBold.ttf", + "preferred_family_name": "Noto Sans Malayalam UI", + "preferred_subfamily_name": "Condensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMalayalamUI-CondensedThin.ttf||104668:1655828711.0": { + "family_name": "Noto Sans Malayalam UI Condensed Thin", + "font-family": "Noto Sans Malayalam UI Condensed Thin", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Malayalam UI Condensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMalayalamUI-CondensedThin.ttf", + "preferred_family_name": "Noto Sans Malayalam UI", + "preferred_subfamily_name": "Condensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMalayalamUI-ExtraBold.ttf||115864:1655828711.0": { + "family_name": "Noto Sans Malayalam UI ExtraBold", + "font-family": "Noto Sans Malayalam UI ExtraBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Malayalam UI ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMalayalamUI-ExtraBold.ttf", + "preferred_family_name": "Noto Sans Malayalam UI", + "preferred_subfamily_name": "ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMalayalamUI-ExtraCondensed.ttf||132240:1655828711.0": { + "family_name": "Noto Sans Malayalam UI ExtraCondensed", + "font-family": "Noto Sans Malayalam UI ExtraCondensed", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Malayalam UI ExtraCondensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMalayalamUI-ExtraCondensed.ttf", + "preferred_family_name": "Noto Sans Malayalam UI", + "preferred_subfamily_name": "ExtraCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMalayalamUI-ExtraCondensedBlack.ttf||115520:1655828711.0": { + "family_name": "Noto Sans Malayalam UI ExtraCondensed Black", + "font-family": "Noto Sans Malayalam UI ExtraCondensed Black", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Malayalam UI ExtraCondensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMalayalamUI-ExtraCondensedBlack.ttf", + "preferred_family_name": "Noto Sans Malayalam UI", + "preferred_subfamily_name": "ExtraCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMalayalamUI-ExtraCondensedBold.ttf||114656:1655828711.0": { + "family_name": "Noto Sans Malayalam UI ExtraCondensed", + "font-family": "Noto Sans Malayalam UI ExtraCondensed", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Malayalam UI ExtraCondensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMalayalamUI-ExtraCondensedBold.ttf", + "preferred_family_name": "Noto Sans Malayalam UI", + "preferred_subfamily_name": "ExtraCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMalayalamUI-ExtraCondensedExtraBold.ttf||115424:1655828711.0": { + "family_name": "Noto Sans Malayalam UI ExtraCondensed ExtraBold", + "font-family": "Noto Sans Malayalam UI ExtraCondensed ExtraBold", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Malayalam UI ExtraCondensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMalayalamUI-ExtraCondensedExtraBold.ttf", + "preferred_family_name": "Noto Sans Malayalam UI", + "preferred_subfamily_name": "ExtraCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMalayalamUI-ExtraCondensedExtraLight.ttf||102720:1655828711.0": { + "family_name": "Noto Sans Malayalam UI ExtraCondensed ExtraLight", + "font-family": "Noto Sans Malayalam UI ExtraCondensed ExtraLight", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Malayalam UI ExtraCondensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMalayalamUI-ExtraCondensedExtraLight.ttf", + "preferred_family_name": "Noto Sans Malayalam UI", + "preferred_subfamily_name": "ExtraCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMalayalamUI-ExtraCondensedLight.ttf||102548:1655828711.0": { + "family_name": "Noto Sans Malayalam UI ExtraCondensed Light", + "font-family": "Noto Sans Malayalam UI ExtraCondensed Light", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Malayalam UI ExtraCondensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMalayalamUI-ExtraCondensedLight.ttf", + "preferred_family_name": "Noto Sans Malayalam UI", + "preferred_subfamily_name": "ExtraCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMalayalamUI-ExtraCondensedMedium.ttf||110716:1655828711.0": { + "family_name": "Noto Sans Malayalam UI ExtraCondensed Medium", + "font-family": "Noto Sans Malayalam UI ExtraCondensed Medium", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Malayalam UI ExtraCondensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMalayalamUI-ExtraCondensedMedium.ttf", + "preferred_family_name": "Noto Sans Malayalam UI", + "preferred_subfamily_name": "ExtraCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMalayalamUI-ExtraCondensedSemiBold.ttf||112840:1655828711.0": { + "family_name": "Noto Sans Malayalam UI ExtraCondensed SemiBold", + "font-family": "Noto Sans Malayalam UI ExtraCondensed SemiBold", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Malayalam UI ExtraCondensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMalayalamUI-ExtraCondensedSemiBold.ttf", + "preferred_family_name": "Noto Sans Malayalam UI", + "preferred_subfamily_name": "ExtraCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMalayalamUI-ExtraCondensedThin.ttf||106604:1655828711.0": { + "family_name": "Noto Sans Malayalam UI ExtraCondensed Thin", + "font-family": "Noto Sans Malayalam UI ExtraCondensed Thin", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Malayalam UI ExtraCondensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMalayalamUI-ExtraCondensedThin.ttf", + "preferred_family_name": "Noto Sans Malayalam UI", + "preferred_subfamily_name": "ExtraCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMalayalamUI-ExtraLight.ttf||104068:1655828711.0": { + "family_name": "Noto Sans Malayalam UI ExtraLight", + "font-family": "Noto Sans Malayalam UI ExtraLight", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Malayalam UI ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMalayalamUI-ExtraLight.ttf", + "preferred_family_name": "Noto Sans Malayalam UI", + "preferred_subfamily_name": "ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMalayalamUI-Light.ttf||105312:1655828711.0": { + "family_name": "Noto Sans Malayalam UI Light", + "font-family": "Noto Sans Malayalam UI Light", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Malayalam UI Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMalayalamUI-Light.ttf", + "preferred_family_name": "Noto Sans Malayalam UI", + "preferred_subfamily_name": "Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMalayalamUI-Medium.ttf||113512:1655828711.0": { + "family_name": "Noto Sans Malayalam UI Medium", + "font-family": "Noto Sans Malayalam UI Medium", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Malayalam UI Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMalayalamUI-Medium.ttf", + "preferred_family_name": "Noto Sans Malayalam UI", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMalayalamUI-Regular.ttf||111856:1655828711.0": { + "family_name": "Noto Sans Malayalam UI", + "font-family": "Noto Sans Malayalam UI", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Malayalam UI Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMalayalamUI-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMalayalamUI-SemiBold.ttf||115060:1655828711.0": { + "family_name": "Noto Sans Malayalam UI SemiBold", + "font-family": "Noto Sans Malayalam UI SemiBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Malayalam UI SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMalayalamUI-SemiBold.ttf", + "preferred_family_name": "Noto Sans Malayalam UI", + "preferred_subfamily_name": "SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMalayalamUI-SemiCondensed.ttf||111600:1655828711.0": { + "family_name": "Noto Sans Malayalam UI SemiCondensed", + "font-family": "Noto Sans Malayalam UI SemiCondensed", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Malayalam UI SemiCondensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMalayalamUI-SemiCondensed.ttf", + "preferred_family_name": "Noto Sans Malayalam UI", + "preferred_subfamily_name": "SemiCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMalayalamUI-SemiCondensedBlack.ttf||117100:1655828711.0": { + "family_name": "Noto Sans Malayalam UI SemiCondensed Black", + "font-family": "Noto Sans Malayalam UI SemiCondensed Black", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Malayalam UI SemiCondensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMalayalamUI-SemiCondensedBlack.ttf", + "preferred_family_name": "Noto Sans Malayalam UI", + "preferred_subfamily_name": "SemiCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMalayalamUI-SemiCondensedBold.ttf||117036:1655828711.0": { + "family_name": "Noto Sans Malayalam UI SemiCondensed", + "font-family": "Noto Sans Malayalam UI SemiCondensed", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Malayalam UI SemiCondensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMalayalamUI-SemiCondensedBold.ttf", + "preferred_family_name": "Noto Sans Malayalam UI", + "preferred_subfamily_name": "SemiCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMalayalamUI-SemiCondensedExtraBold.ttf||115460:1655828711.0": { + "family_name": "Noto Sans Malayalam UI SemiCondensed ExtraBold", + "font-family": "Noto Sans Malayalam UI SemiCondensed ExtraBold", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Malayalam UI SemiCondensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMalayalamUI-SemiCondensedExtraBold.ttf", + "preferred_family_name": "Noto Sans Malayalam UI", + "preferred_subfamily_name": "SemiCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMalayalamUI-SemiCondensedExtraLight.ttf||103176:1655828711.0": { + "family_name": "Noto Sans Malayalam UI SemiCondensed ExtraLight", + "font-family": "Noto Sans Malayalam UI SemiCondensed ExtraLight", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Malayalam UI SemiCondensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMalayalamUI-SemiCondensedExtraLight.ttf", + "preferred_family_name": "Noto Sans Malayalam UI", + "preferred_subfamily_name": "SemiCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMalayalamUI-SemiCondensedLight.ttf||103768:1655828711.0": { + "family_name": "Noto Sans Malayalam UI SemiCondensed Light", + "font-family": "Noto Sans Malayalam UI SemiCondensed Light", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Malayalam UI SemiCondensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMalayalamUI-SemiCondensedLight.ttf", + "preferred_family_name": "Noto Sans Malayalam UI", + "preferred_subfamily_name": "SemiCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMalayalamUI-SemiCondensedMedium.ttf||112952:1655828711.0": { + "family_name": "Noto Sans Malayalam UI SemiCondensed Medium", + "font-family": "Noto Sans Malayalam UI SemiCondensed Medium", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Malayalam UI SemiCondensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMalayalamUI-SemiCondensedMedium.ttf", + "preferred_family_name": "Noto Sans Malayalam UI", + "preferred_subfamily_name": "SemiCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMalayalamUI-SemiCondensedSemiBold.ttf||114892:1655828711.0": { + "family_name": "Noto Sans Malayalam UI SemiCondensed SemiBold", + "font-family": "Noto Sans Malayalam UI SemiCondensed SemiBold", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Malayalam UI SemiCondensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMalayalamUI-SemiCondensedSemiBold.ttf", + "preferred_family_name": "Noto Sans Malayalam UI", + "preferred_subfamily_name": "SemiCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMalayalamUI-SemiCondensedThin.ttf||103808:1655828711.0": { + "family_name": "Noto Sans Malayalam UI SemiCondensed Thin", + "font-family": "Noto Sans Malayalam UI SemiCondensed Thin", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Malayalam UI SemiCondensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMalayalamUI-SemiCondensedThin.ttf", + "preferred_family_name": "Noto Sans Malayalam UI", + "preferred_subfamily_name": "SemiCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMalayalamUI-Thin.ttf||104716:1655828711.0": { + "family_name": "Noto Sans Malayalam UI Thin", + "font-family": "Noto Sans Malayalam UI Thin", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Malayalam UI Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMalayalamUI-Thin.ttf", + "preferred_family_name": "Noto Sans Malayalam UI", + "preferred_subfamily_name": "Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMandaic-Regular.ttf||29076:1655828711.0": { + "family_name": "Noto Sans Mandaic", + "font-family": "Noto Sans Mandaic", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Mandaic Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMandaic-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansManichaean-Regular.ttf||52216:1655828711.0": { + "family_name": "Noto Sans Manichaean", + "font-family": "Noto Sans Manichaean", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Manichaean Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansManichaean-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMarchen-Regular.ttf||131648:1655828711.0": { + "family_name": "Noto Sans Marchen", + "font-family": "Noto Sans Marchen", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Marchen Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMarchen-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMasaramGondi-Regular.ttf||30504:1655828711.0": { + "family_name": "Noto Sans Masaram Gondi", + "font-family": "Noto Sans Masaram Gondi", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Masaram Gondi Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 4, + 4, + 2, + 2, + 3 + ], + "path": "/usr/share/fonts/noto/NotoSansMasaramGondi-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMath-Regular.ttf||590904:1655828711.0": { + "family_name": "Noto Sans Math", + "font-family": "Noto Sans Math", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Math Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMath-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMayanNumerals-Regular.ttf||4716:1655828711.0": { + "family_name": "Noto Sans Mayan Numerals", + "font-family": "Noto Sans Mayan Numerals", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Mayan Numerals Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMayanNumerals-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMedefaidrin-Bold.ttf||30404:1655828711.0": { + "family_name": "Noto Sans Medefaidrin", + "font-family": "Noto Sans Medefaidrin", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Medefaidrin Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 8, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMedefaidrin-Bold.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMedefaidrin-Medium.ttf||30484:1655828711.0": { + "family_name": "Noto Sans Medefaidrin Medium", + "font-family": "Noto Sans Medefaidrin Medium", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Medefaidrin Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 6, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMedefaidrin-Medium.ttf", + "preferred_family_name": "Noto Sans Medefaidrin", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMedefaidrin-Regular.ttf||30736:1655828711.0": { + "family_name": "Noto Sans Medefaidrin", + "font-family": "Noto Sans Medefaidrin", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Medefaidrin Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 5, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMedefaidrin-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMedefaidrin-SemiBold.ttf||30432:1655828711.0": { + "family_name": "Noto Sans Medefaidrin SemiBold", + "font-family": "Noto Sans Medefaidrin SemiBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Medefaidrin SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 7, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMedefaidrin-SemiBold.ttf", + "preferred_family_name": "Noto Sans Medefaidrin", + "preferred_subfamily_name": "SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMeeteiMayek-Black.ttf||16916:1655828711.0": { + "family_name": "Noto Sans MeeteiMayek Black", + "font-family": "Noto Sans MeeteiMayek Black", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Meetei Mayek Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMeeteiMayek-Black.ttf", + "preferred_family_name": "Noto Sans Meetei Mayek", + "preferred_subfamily_name": "Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMeeteiMayek-Bold.ttf||16908:1655828711.0": { + "family_name": "Noto Sans MeeteiMayek", + "font-family": "Noto Sans MeeteiMayek", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Meetei Mayek Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMeeteiMayek-Bold.ttf", + "preferred_family_name": "Noto Sans Meetei Mayek", + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMeeteiMayek-ExtraBold.ttf||16964:1655828711.0": { + "family_name": "Noto Sans MeeteiMayek ExtraBold", + "font-family": "Noto Sans MeeteiMayek ExtraBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Meetei Mayek ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMeeteiMayek-ExtraBold.ttf", + "preferred_family_name": "Noto Sans Meetei Mayek", + "preferred_subfamily_name": "ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMeeteiMayek-ExtraLight.ttf||17208:1655828711.0": { + "family_name": "Noto Sans MeeteiMayek ExtraLight", + "font-family": "Noto Sans MeeteiMayek ExtraLight", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Meetei Mayek ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMeeteiMayek-ExtraLight.ttf", + "preferred_family_name": "Noto Sans Meetei Mayek", + "preferred_subfamily_name": "ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMeeteiMayek-Light.ttf||17216:1655828711.0": { + "family_name": "Noto Sans MeeteiMayek Light", + "font-family": "Noto Sans MeeteiMayek Light", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Meetei Mayek Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMeeteiMayek-Light.ttf", + "preferred_family_name": "Noto Sans Meetei Mayek", + "preferred_subfamily_name": "Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMeeteiMayek-Medium.ttf||17096:1655828711.0": { + "family_name": "Noto Sans MeeteiMayek Medium", + "font-family": "Noto Sans MeeteiMayek Medium", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Meetei Mayek Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMeeteiMayek-Medium.ttf", + "preferred_family_name": "Noto Sans Meetei Mayek", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMeeteiMayek-Regular.ttf||17152:1655828711.0": { + "family_name": "Noto Sans MeeteiMayek", + "font-family": "Noto Sans MeeteiMayek", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Meetei Mayek Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMeeteiMayek-Regular.ttf", + "preferred_family_name": "Noto Sans Meetei Mayek", + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMeeteiMayek-SemiBold.ttf||17020:1655828711.0": { + "family_name": "Noto Sans MeeteiMayek SemiBold", + "font-family": "Noto Sans MeeteiMayek SemiBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Meetei Mayek SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMeeteiMayek-SemiBold.ttf", + "preferred_family_name": "Noto Sans Meetei Mayek", + "preferred_subfamily_name": "SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMeeteiMayek-Thin.ttf||17200:1655828711.0": { + "family_name": "Noto Sans MeeteiMayek Thin", + "font-family": "Noto Sans MeeteiMayek Thin", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Meetei Mayek Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMeeteiMayek-Thin.ttf", + "preferred_family_name": "Noto Sans Meetei Mayek", + "preferred_subfamily_name": "Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMendeKikakui-Regular.ttf||35456:1655828711.0": { + "family_name": "Noto Sans Mende Kikakui", + "font-family": "Noto Sans Mende Kikakui", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Mende Kikakui Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMendeKikakui-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMeroitic-Regular.ttf||33688:1655828711.0": { + "family_name": "Noto Sans Meroitic", + "font-family": "Noto Sans Meroitic", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Meroitic Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMeroitic-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMiao-Regular.ttf||36276:1655828711.0": { + "family_name": "Noto Sans Miao", + "font-family": "Noto Sans Miao", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Miao Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMiao-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansModi-Regular.ttf||44384:1655828711.0": { + "family_name": "Noto Sans Modi", + "font-family": "Noto Sans Modi", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Modi Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansModi-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMongolian-Regular.ttf||183016:1655828711.0": { + "family_name": "Noto Sans Mongolian", + "font-family": "Noto Sans Mongolian", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Mongolian Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMongolian-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMono-Black.ttf||530520:1655828711.0": { + "family_name": "Noto Sans Mono Black", + "font-family": "Noto Sans Mono Black", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Mono Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 9, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMono-Black.ttf", + "preferred_family_name": "Noto Sans Mono", + "preferred_subfamily_name": "Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMono-Bold.ttf||525664:1655828711.0": { + "family_name": "Noto Sans Mono", + "font-family": "Noto Sans Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Mono Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 9, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMono-Bold.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMono-Condensed.ttf||511768:1655828711.0": { + "family_name": "Noto Sans Mono Condensed", + "font-family": "Noto Sans Mono Condensed", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Mono Condensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 9, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMono-Condensed.ttf", + "preferred_family_name": "Noto Sans Mono", + "preferred_subfamily_name": "Condensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMono-CondensedBlack.ttf||520572:1655828711.0": { + "family_name": "Noto Sans Mono Condensed Black", + "font-family": "Noto Sans Mono Condensed Black", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Mono Condensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 9, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMono-CondensedBlack.ttf", + "preferred_family_name": "Noto Sans Mono", + "preferred_subfamily_name": "Condensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMono-CondensedBold.ttf||517004:1655828711.0": { + "family_name": "Noto Sans Mono Condensed", + "font-family": "Noto Sans Mono Condensed", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Mono Condensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 9, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMono-CondensedBold.ttf", + "preferred_family_name": "Noto Sans Mono", + "preferred_subfamily_name": "Condensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMono-CondensedExtraBold.ttf||517084:1655828711.0": { + "family_name": "Noto Sans Mono Condensed ExtraBold", + "font-family": "Noto Sans Mono Condensed ExtraBold", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Mono Condensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 9, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMono-CondensedExtraBold.ttf", + "preferred_family_name": "Noto Sans Mono", + "preferred_subfamily_name": "Condensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMono-CondensedExtraLight.ttf||498084:1655828711.0": { + "family_name": "Noto Sans Mono Condensed ExtraLight", + "font-family": "Noto Sans Mono Condensed ExtraLight", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Mono Condensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 9, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMono-CondensedExtraLight.ttf", + "preferred_family_name": "Noto Sans Mono", + "preferred_subfamily_name": "Condensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMono-CondensedLight.ttf||504896:1655828711.0": { + "family_name": "Noto Sans Mono Condensed Light", + "font-family": "Noto Sans Mono Condensed Light", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Mono Condensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 9, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMono-CondensedLight.ttf", + "preferred_family_name": "Noto Sans Mono", + "preferred_subfamily_name": "Condensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMono-CondensedMedium.ttf||514756:1655828711.0": { + "family_name": "Noto Sans Mono Condensed Medium", + "font-family": "Noto Sans Mono Condensed Medium", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Mono Condensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 9, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMono-CondensedMedium.ttf", + "preferred_family_name": "Noto Sans Mono", + "preferred_subfamily_name": "Condensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMono-CondensedSemiBold.ttf||516852:1655828711.0": { + "family_name": "Noto Sans Mono Condensed SemiBold", + "font-family": "Noto Sans Mono Condensed SemiBold", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Mono Condensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 9, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMono-CondensedSemiBold.ttf", + "preferred_family_name": "Noto Sans Mono", + "preferred_subfamily_name": "Condensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMono-CondensedThin.ttf||501584:1655828711.0": { + "family_name": "Noto Sans Mono Condensed Thin", + "font-family": "Noto Sans Mono Condensed Thin", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Mono Condensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 9, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMono-CondensedThin.ttf", + "preferred_family_name": "Noto Sans Mono", + "preferred_subfamily_name": "Condensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMono-ExtraBold.ttf||523736:1655828711.0": { + "family_name": "Noto Sans Mono ExtraBold", + "font-family": "Noto Sans Mono ExtraBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Mono ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 9, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMono-ExtraBold.ttf", + "preferred_family_name": "Noto Sans Mono", + "preferred_subfamily_name": "ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMono-ExtraCondensed.ttf||510844:1655828711.0": { + "family_name": "Noto Sans Mono ExtraCondensed", + "font-family": "Noto Sans Mono ExtraCondensed", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Mono ExtraCondensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 9, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMono-ExtraCondensed.ttf", + "preferred_family_name": "Noto Sans Mono", + "preferred_subfamily_name": "ExtraCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMono-ExtraCondensedBlack.ttf||520664:1655828711.0": { + "family_name": "Noto Sans Mono ExtraCondensed Black", + "font-family": "Noto Sans Mono ExtraCondensed Black", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Mono ExtraCondensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 9, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMono-ExtraCondensedBlack.ttf", + "preferred_family_name": "Noto Sans Mono", + "preferred_subfamily_name": "ExtraCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMono-ExtraCondensedBold.ttf||516828:1655828711.0": { + "family_name": "Noto Sans Mono ExtraCondensed", + "font-family": "Noto Sans Mono ExtraCondensed", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Mono ExtraCondensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 9, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMono-ExtraCondensedBold.ttf", + "preferred_family_name": "Noto Sans Mono", + "preferred_subfamily_name": "ExtraCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMono-ExtraCondensedExtraBold.ttf||518396:1655828711.0": { + "family_name": "Noto Sans Mono ExtraCondensed ExtraBold", + "font-family": "Noto Sans Mono ExtraCondensed ExtraBold", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Mono ExtraCondensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 9, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMono-ExtraCondensedExtraBold.ttf", + "preferred_family_name": "Noto Sans Mono", + "preferred_subfamily_name": "ExtraCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMono-ExtraCondensedExtraLight.ttf||497852:1655828711.0": { + "family_name": "Noto Sans Mono ExtraCondensed ExtraLight", + "font-family": "Noto Sans Mono ExtraCondensed ExtraLight", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Mono ExtraCondensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 9, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMono-ExtraCondensedExtraLight.ttf", + "preferred_family_name": "Noto Sans Mono", + "preferred_subfamily_name": "ExtraCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMono-ExtraCondensedLight.ttf||498600:1655828711.0": { + "family_name": "Noto Sans Mono ExtraCondensed Light", + "font-family": "Noto Sans Mono ExtraCondensed Light", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Mono ExtraCondensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 9, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMono-ExtraCondensedLight.ttf", + "preferred_family_name": "Noto Sans Mono", + "preferred_subfamily_name": "ExtraCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMono-ExtraCondensedMedium.ttf||511760:1655828711.0": { + "family_name": "Noto Sans Mono ExtraCondensed Medium", + "font-family": "Noto Sans Mono ExtraCondensed Medium", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Mono ExtraCondensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 9, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMono-ExtraCondensedMedium.ttf", + "preferred_family_name": "Noto Sans Mono", + "preferred_subfamily_name": "ExtraCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMono-ExtraCondensedSemiBold.ttf||512744:1655828711.0": { + "family_name": "Noto Sans Mono ExtraCondensed SemiBold", + "font-family": "Noto Sans Mono ExtraCondensed SemiBold", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Mono ExtraCondensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 9, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMono-ExtraCondensedSemiBold.ttf", + "preferred_family_name": "Noto Sans Mono", + "preferred_subfamily_name": "ExtraCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMono-ExtraCondensedThin.ttf||500012:1655828711.0": { + "family_name": "Noto Sans Mono ExtraCondensed Thin", + "font-family": "Noto Sans Mono ExtraCondensed Thin", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Mono ExtraCondensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 9, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMono-ExtraCondensedThin.ttf", + "preferred_family_name": "Noto Sans Mono", + "preferred_subfamily_name": "ExtraCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMono-ExtraLight.ttf||499720:1655828711.0": { + "family_name": "Noto Sans Mono ExtraLight", + "font-family": "Noto Sans Mono ExtraLight", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Mono ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 9, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMono-ExtraLight.ttf", + "preferred_family_name": "Noto Sans Mono", + "preferred_subfamily_name": "ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMono-Light.ttf||507116:1655828711.0": { + "family_name": "Noto Sans Mono Light", + "font-family": "Noto Sans Mono Light", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Mono Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 9, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMono-Light.ttf", + "preferred_family_name": "Noto Sans Mono", + "preferred_subfamily_name": "Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMono-Medium.ttf||512912:1655828711.0": { + "family_name": "Noto Sans Mono Medium", + "font-family": "Noto Sans Mono Medium", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Mono Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 9, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMono-Medium.ttf", + "preferred_family_name": "Noto Sans Mono", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMono-Regular.ttf||512836:1655828711.0": { + "family_name": "Noto Sans Mono", + "font-family": "Noto Sans Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Mono Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 9, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMono-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMono-SemiBold.ttf||519292:1655828711.0": { + "family_name": "Noto Sans Mono SemiBold", + "font-family": "Noto Sans Mono SemiBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Mono SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 9, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMono-SemiBold.ttf", + "preferred_family_name": "Noto Sans Mono", + "preferred_subfamily_name": "SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMono-SemiCondensed.ttf||511412:1655828711.0": { + "family_name": "Noto Sans Mono SemiCondensed", + "font-family": "Noto Sans Mono SemiCondensed", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Mono SemiCondensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 9, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMono-SemiCondensed.ttf", + "preferred_family_name": "Noto Sans Mono", + "preferred_subfamily_name": "SemiCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMono-SemiCondensedBlack.ttf||528000:1655828711.0": { + "family_name": "Noto Sans Mono SemiCondensed Black", + "font-family": "Noto Sans Mono SemiCondensed Black", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Mono SemiCondensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 9, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMono-SemiCondensedBlack.ttf", + "preferred_family_name": "Noto Sans Mono", + "preferred_subfamily_name": "SemiCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMono-SemiCondensedBold.ttf||516956:1655828711.0": { + "family_name": "Noto Sans Mono SemiCondensed", + "font-family": "Noto Sans Mono SemiCondensed", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Mono SemiCondensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 9, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMono-SemiCondensedBold.ttf", + "preferred_family_name": "Noto Sans Mono", + "preferred_subfamily_name": "SemiCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMono-SemiCondensedExtraBold.ttf||516200:1655828711.0": { + "family_name": "Noto Sans Mono SemiCondensed ExtraBold", + "font-family": "Noto Sans Mono SemiCondensed ExtraBold", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Mono SemiCondensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 9, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMono-SemiCondensedExtraBold.ttf", + "preferred_family_name": "Noto Sans Mono", + "preferred_subfamily_name": "SemiCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMono-SemiCondensedExtraLight.ttf||499444:1655828711.0": { + "family_name": "Noto Sans Mono SemiCondensed ExtraLight", + "font-family": "Noto Sans Mono SemiCondensed ExtraLight", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Mono SemiCondensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 9, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMono-SemiCondensedExtraLight.ttf", + "preferred_family_name": "Noto Sans Mono", + "preferred_subfamily_name": "SemiCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMono-SemiCondensedLight.ttf||505984:1655828711.0": { + "family_name": "Noto Sans Mono SemiCondensed Light", + "font-family": "Noto Sans Mono SemiCondensed Light", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Mono SemiCondensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 9, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMono-SemiCondensedLight.ttf", + "preferred_family_name": "Noto Sans Mono", + "preferred_subfamily_name": "SemiCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMono-SemiCondensedMedium.ttf||512356:1655828711.0": { + "family_name": "Noto Sans Mono SemiCondensed Medium", + "font-family": "Noto Sans Mono SemiCondensed Medium", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Mono SemiCondensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 9, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMono-SemiCondensedMedium.ttf", + "preferred_family_name": "Noto Sans Mono", + "preferred_subfamily_name": "SemiCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMono-SemiCondensedSemiBold.ttf||516236:1655828711.0": { + "family_name": "Noto Sans Mono SemiCondensed SemiBold", + "font-family": "Noto Sans Mono SemiCondensed SemiBold", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Mono SemiCondensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 9, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMono-SemiCondensedSemiBold.ttf", + "preferred_family_name": "Noto Sans Mono", + "preferred_subfamily_name": "SemiCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMono-SemiCondensedThin.ttf||500160:1655828711.0": { + "family_name": "Noto Sans Mono SemiCondensed Thin", + "font-family": "Noto Sans Mono SemiCondensed Thin", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Mono SemiCondensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 9, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMono-SemiCondensedThin.ttf", + "preferred_family_name": "Noto Sans Mono", + "preferred_subfamily_name": "SemiCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMono-Thin.ttf||502624:1655828711.0": { + "family_name": "Noto Sans Mono Thin", + "font-family": "Noto Sans Mono Thin", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Mono Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 9, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMono-Thin.ttf", + "preferred_family_name": "Noto Sans Mono", + "preferred_subfamily_name": "Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMro-Regular.ttf||6920:1655828711.0": { + "family_name": "Noto Sans Mro", + "font-family": "Noto Sans Mro", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Mro Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMro-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMultani-Regular.ttf||16928:1655828711.0": { + "family_name": "Noto Sans Multani", + "font-family": "Noto Sans Multani", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Multani Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMultani-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMyanmar-Black.ttf||223216:1655828711.0": { + "family_name": "Noto Sans Myanmar Black", + "font-family": "Noto Sans Myanmar Black", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Myanmar Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMyanmar-Black.ttf", + "preferred_family_name": "Noto Sans Myanmar", + "preferred_subfamily_name": "Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMyanmar-Bold.ttf||209068:1655828711.0": { + "family_name": "Noto Sans Myanmar", + "font-family": "Noto Sans Myanmar", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Myanmar Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMyanmar-Bold.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMyanmar-Condensed.ttf||198956:1655828711.0": { + "family_name": "Noto Sans Myanmar Condensed", + "font-family": "Noto Sans Myanmar Condensed", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Myanmar Condensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMyanmar-Condensed.ttf", + "preferred_family_name": "Noto Sans Myanmar", + "preferred_subfamily_name": "Condensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMyanmar-CondensedBlack.ttf||209584:1655828711.0": { + "family_name": "Noto Sans Myanmar Condensed Black", + "font-family": "Noto Sans Myanmar Condensed Black", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Myanmar Condensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMyanmar-CondensedBlack.ttf", + "preferred_family_name": "Noto Sans Myanmar", + "preferred_subfamily_name": "Condensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMyanmar-CondensedBold.ttf||204404:1655828711.0": { + "family_name": "Noto Sans Myanmar Condensed", + "font-family": "Noto Sans Myanmar Condensed", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Myanmar Condensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMyanmar-CondensedBold.ttf", + "preferred_family_name": "Noto Sans Myanmar", + "preferred_subfamily_name": "Condensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMyanmar-CondensedExtraBold.ttf||206628:1655828711.0": { + "family_name": "Noto Sans Myanmar Condensed ExtraBold", + "font-family": "Noto Sans Myanmar Condensed ExtraBold", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Myanmar Condensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMyanmar-CondensedExtraBold.ttf", + "preferred_family_name": "Noto Sans Myanmar", + "preferred_subfamily_name": "Condensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMyanmar-CondensedExtraLight.ttf||194092:1655828711.0": { + "family_name": "Noto Sans Myanmar Condensed ExtraLight", + "font-family": "Noto Sans Myanmar Condensed ExtraLight", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Myanmar Condensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMyanmar-CondensedExtraLight.ttf", + "preferred_family_name": "Noto Sans Myanmar", + "preferred_subfamily_name": "Condensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMyanmar-CondensedLight.ttf||192132:1655828711.0": { + "family_name": "Noto Sans Myanmar Condensed Light", + "font-family": "Noto Sans Myanmar Condensed Light", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Myanmar Condensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMyanmar-CondensedLight.ttf", + "preferred_family_name": "Noto Sans Myanmar", + "preferred_subfamily_name": "Condensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMyanmar-CondensedMedium.ttf||196748:1655828711.0": { + "family_name": "Noto Sans Myanmar Condensed Medium", + "font-family": "Noto Sans Myanmar Condensed Medium", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Myanmar Condensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMyanmar-CondensedMedium.ttf", + "preferred_family_name": "Noto Sans Myanmar", + "preferred_subfamily_name": "Condensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMyanmar-CondensedSemiBold.ttf||197788:1655828711.0": { + "family_name": "Noto Sans Myanmar Condensed SemiBold", + "font-family": "Noto Sans Myanmar Condensed SemiBold", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Myanmar Condensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMyanmar-CondensedSemiBold.ttf", + "preferred_family_name": "Noto Sans Myanmar", + "preferred_subfamily_name": "Condensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMyanmar-CondensedThin.ttf||195396:1655828711.0": { + "family_name": "Noto Sans Myanmar Condensed Thin", + "font-family": "Noto Sans Myanmar Condensed Thin", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Myanmar Condensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMyanmar-CondensedThin.ttf", + "preferred_family_name": "Noto Sans Myanmar", + "preferred_subfamily_name": "Condensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMyanmar-ExtraBold.ttf||211920:1655828711.0": { + "family_name": "Noto Sans Myanmar ExtraBold", + "font-family": "Noto Sans Myanmar ExtraBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Myanmar ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMyanmar-ExtraBold.ttf", + "preferred_family_name": "Noto Sans Myanmar", + "preferred_subfamily_name": "ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMyanmar-ExtraCondensed.ttf||199528:1655828711.0": { + "family_name": "Noto Sans Myanmar ExtraCondensed", + "font-family": "Noto Sans Myanmar ExtraCondensed", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Myanmar ExtraCondensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMyanmar-ExtraCondensed.ttf", + "preferred_family_name": "Noto Sans Myanmar", + "preferred_subfamily_name": "ExtraCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMyanmar-ExtraCondensedBlack.ttf||209064:1655828711.0": { + "family_name": "Noto Sans Myanmar ExtraCondensed Black", + "font-family": "Noto Sans Myanmar ExtraCondensed Black", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Myanmar ExtraCondensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMyanmar-ExtraCondensedBlack.ttf", + "preferred_family_name": "Noto Sans Myanmar", + "preferred_subfamily_name": "ExtraCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMyanmar-ExtraCondensedBold.ttf||200880:1655828711.0": { + "family_name": "Noto Sans Myanmar ExtraCondensed", + "font-family": "Noto Sans Myanmar ExtraCondensed", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Myanmar ExtraCondensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMyanmar-ExtraCondensedBold.ttf", + "preferred_family_name": "Noto Sans Myanmar", + "preferred_subfamily_name": "ExtraCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMyanmar-ExtraCondensedExtraBold.ttf||205976:1655828711.0": { + "family_name": "Noto Sans Myanmar ExtraCondensed ExtraBold", + "font-family": "Noto Sans Myanmar ExtraCondensed ExtraBold", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Myanmar ExtraCondensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMyanmar-ExtraCondensedExtraBold.ttf", + "preferred_family_name": "Noto Sans Myanmar", + "preferred_subfamily_name": "ExtraCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMyanmar-ExtraCondensedExtraLight.ttf||192992:1655828711.0": { + "family_name": "Noto Sans Myanmar ExtraCondensed ExtraLight", + "font-family": "Noto Sans Myanmar ExtraCondensed ExtraLight", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Myanmar ExtraCondensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMyanmar-ExtraCondensedExtraLight.ttf", + "preferred_family_name": "Noto Sans Myanmar", + "preferred_subfamily_name": "ExtraCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMyanmar-ExtraCondensedLight.ttf||192888:1655828711.0": { + "family_name": "Noto Sans Myanmar ExtraCondensed Light", + "font-family": "Noto Sans Myanmar ExtraCondensed Light", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Myanmar ExtraCondensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMyanmar-ExtraCondensedLight.ttf", + "preferred_family_name": "Noto Sans Myanmar", + "preferred_subfamily_name": "ExtraCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMyanmar-ExtraCondensedMedium.ttf||196724:1655828711.0": { + "family_name": "Noto Sans Myanmar ExtraCondensed Medium", + "font-family": "Noto Sans Myanmar ExtraCondensed Medium", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Myanmar ExtraCondensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMyanmar-ExtraCondensedMedium.ttf", + "preferred_family_name": "Noto Sans Myanmar", + "preferred_subfamily_name": "ExtraCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMyanmar-ExtraCondensedSemiBold.ttf||199324:1655828711.0": { + "family_name": "Noto Sans Myanmar ExtraCondensed SemiBold", + "font-family": "Noto Sans Myanmar ExtraCondensed SemiBold", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Myanmar ExtraCondensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMyanmar-ExtraCondensedSemiBold.ttf", + "preferred_family_name": "Noto Sans Myanmar", + "preferred_subfamily_name": "ExtraCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMyanmar-ExtraCondensedThin.ttf||194324:1655828711.0": { + "family_name": "Noto Sans Myanmar ExtraCondensed Thin", + "font-family": "Noto Sans Myanmar ExtraCondensed Thin", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Myanmar ExtraCondensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMyanmar-ExtraCondensedThin.ttf", + "preferred_family_name": "Noto Sans Myanmar", + "preferred_subfamily_name": "ExtraCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMyanmar-ExtraLight.ttf||195336:1655828711.0": { + "family_name": "Noto Sans Myanmar ExtraLight", + "font-family": "Noto Sans Myanmar ExtraLight", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Myanmar ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMyanmar-ExtraLight.ttf", + "preferred_family_name": "Noto Sans Myanmar", + "preferred_subfamily_name": "ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMyanmar-Light.ttf||194492:1655828711.0": { + "family_name": "Noto Sans Myanmar Light", + "font-family": "Noto Sans Myanmar Light", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Myanmar Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMyanmar-Light.ttf", + "preferred_family_name": "Noto Sans Myanmar", + "preferred_subfamily_name": "Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMyanmar-Medium.ttf||197716:1655828711.0": { + "family_name": "Noto Sans Myanmar Medium", + "font-family": "Noto Sans Myanmar Medium", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Myanmar Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMyanmar-Medium.ttf", + "preferred_family_name": "Noto Sans Myanmar", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMyanmar-Regular.ttf||195408:1655828711.0": { + "family_name": "Noto Sans Myanmar", + "font-family": "Noto Sans Myanmar", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Myanmar Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMyanmar-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMyanmar-SemiBold.ttf||200552:1655828711.0": { + "family_name": "Noto Sans Myanmar SemiBold", + "font-family": "Noto Sans Myanmar SemiBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Myanmar SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMyanmar-SemiBold.ttf", + "preferred_family_name": "Noto Sans Myanmar", + "preferred_subfamily_name": "SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMyanmar-SemiCondensed.ttf||194748:1655828711.0": { + "family_name": "Noto Sans Myanmar SemiCondensed", + "font-family": "Noto Sans Myanmar SemiCondensed", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Myanmar SemiCondensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMyanmar-SemiCondensed.ttf", + "preferred_family_name": "Noto Sans Myanmar", + "preferred_subfamily_name": "SemiCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMyanmar-SemiCondensedBlack.ttf||221844:1655828711.0": { + "family_name": "Noto Sans Myanmar SemiCondensed Black", + "font-family": "Noto Sans Myanmar SemiCondensed Black", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Myanmar SemiCondensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMyanmar-SemiCondensedBlack.ttf", + "preferred_family_name": "Noto Sans Myanmar", + "preferred_subfamily_name": "SemiCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMyanmar-SemiCondensedBold.ttf||205192:1655828711.0": { + "family_name": "Noto Sans Myanmar SemiCondensed", + "font-family": "Noto Sans Myanmar SemiCondensed", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Myanmar SemiCondensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMyanmar-SemiCondensedBold.ttf", + "preferred_family_name": "Noto Sans Myanmar", + "preferred_subfamily_name": "SemiCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMyanmar-SemiCondensedExtraBold.ttf||211080:1655828711.0": { + "family_name": "Noto Sans Myanmar SemiCondensed ExtraBold", + "font-family": "Noto Sans Myanmar SemiCondensed ExtraBold", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Myanmar SemiCondensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMyanmar-SemiCondensedExtraBold.ttf", + "preferred_family_name": "Noto Sans Myanmar", + "preferred_subfamily_name": "SemiCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMyanmar-SemiCondensedExtraLight.ttf||194760:1655828711.0": { + "family_name": "Noto Sans Myanmar SemiCondensed ExtraLight", + "font-family": "Noto Sans Myanmar SemiCondensed ExtraLight", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Myanmar SemiCondensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMyanmar-SemiCondensedExtraLight.ttf", + "preferred_family_name": "Noto Sans Myanmar", + "preferred_subfamily_name": "SemiCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMyanmar-SemiCondensedLight.ttf||192932:1655828711.0": { + "family_name": "Noto Sans Myanmar SemiCondensed Light", + "font-family": "Noto Sans Myanmar SemiCondensed Light", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Myanmar SemiCondensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMyanmar-SemiCondensedLight.ttf", + "preferred_family_name": "Noto Sans Myanmar", + "preferred_subfamily_name": "SemiCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMyanmar-SemiCondensedMedium.ttf||197160:1655828711.0": { + "family_name": "Noto Sans Myanmar SemiCondensed Medium", + "font-family": "Noto Sans Myanmar SemiCondensed Medium", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Myanmar SemiCondensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMyanmar-SemiCondensedMedium.ttf", + "preferred_family_name": "Noto Sans Myanmar", + "preferred_subfamily_name": "SemiCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMyanmar-SemiCondensedSemiBold.ttf||198420:1655828711.0": { + "family_name": "Noto Sans Myanmar SemiCondensed SemiBold", + "font-family": "Noto Sans Myanmar SemiCondensed SemiBold", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Myanmar SemiCondensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMyanmar-SemiCondensedSemiBold.ttf", + "preferred_family_name": "Noto Sans Myanmar", + "preferred_subfamily_name": "SemiCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMyanmar-SemiCondensedThin.ttf||196144:1655828711.0": { + "family_name": "Noto Sans Myanmar SemiCondensed Thin", + "font-family": "Noto Sans Myanmar SemiCondensed Thin", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Myanmar SemiCondensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMyanmar-SemiCondensedThin.ttf", + "preferred_family_name": "Noto Sans Myanmar", + "preferred_subfamily_name": "SemiCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMyanmar-Thin.ttf||197192:1655828711.0": { + "family_name": "Noto Sans Myanmar Thin", + "font-family": "Noto Sans Myanmar Thin", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Myanmar Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMyanmar-Thin.ttf", + "preferred_family_name": "Noto Sans Myanmar", + "preferred_subfamily_name": "Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMyanmarUI-Black.ttf||217308:1655828711.0": { + "family_name": "Noto Sans Myanmar UI Black", + "font-family": "Noto Sans Myanmar UI Black", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Myanmar UI Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMyanmarUI-Black.ttf", + "preferred_family_name": "Noto Sans Myanmar UI", + "preferred_subfamily_name": "Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMyanmarUI-Bold.ttf||213780:1655828711.0": { + "family_name": "Noto Sans Myanmar UI", + "font-family": "Noto Sans Myanmar UI", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Myanmar UI Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMyanmarUI-Bold.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMyanmarUI-Condensed.ttf||203568:1655828711.0": { + "family_name": "Noto Sans Myanmar UI Condensed", + "font-family": "Noto Sans Myanmar UI Condensed", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Myanmar UI Condensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMyanmarUI-Condensed.ttf", + "preferred_family_name": "Noto Sans Myanmar UI", + "preferred_subfamily_name": "Condensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMyanmarUI-CondensedBlack.ttf||212328:1655828711.0": { + "family_name": "Noto Sans Myanmar UI Condensed Black", + "font-family": "Noto Sans Myanmar UI Condensed Black", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Myanmar UI Condensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMyanmarUI-CondensedBlack.ttf", + "preferred_family_name": "Noto Sans Myanmar UI", + "preferred_subfamily_name": "Condensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMyanmarUI-CondensedBold.ttf||206696:1655828711.0": { + "family_name": "Noto Sans Myanmar UI Condensed", + "font-family": "Noto Sans Myanmar UI Condensed", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Myanmar UI Condensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMyanmarUI-CondensedBold.ttf", + "preferred_family_name": "Noto Sans Myanmar UI", + "preferred_subfamily_name": "Condensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMyanmarUI-CondensedExtraBold.ttf||211968:1655828711.0": { + "family_name": "Noto Sans Myanmar UI Condensed ExtraBold", + "font-family": "Noto Sans Myanmar UI Condensed ExtraBold", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Myanmar UI Condensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMyanmarUI-CondensedExtraBold.ttf", + "preferred_family_name": "Noto Sans Myanmar UI", + "preferred_subfamily_name": "Condensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMyanmarUI-CondensedExtraLight.ttf||198336:1655828711.0": { + "family_name": "Noto Sans Myanmar UI Condensed ExtraLight", + "font-family": "Noto Sans Myanmar UI Condensed ExtraLight", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Myanmar UI Condensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMyanmarUI-CondensedExtraLight.ttf", + "preferred_family_name": "Noto Sans Myanmar UI", + "preferred_subfamily_name": "Condensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMyanmarUI-CondensedLight.ttf||195456:1655828711.0": { + "family_name": "Noto Sans Myanmar UI Condensed Light", + "font-family": "Noto Sans Myanmar UI Condensed Light", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Myanmar UI Condensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMyanmarUI-CondensedLight.ttf", + "preferred_family_name": "Noto Sans Myanmar UI", + "preferred_subfamily_name": "Condensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMyanmarUI-CondensedMedium.ttf||206216:1655828711.0": { + "family_name": "Noto Sans Myanmar UI Condensed Medium", + "font-family": "Noto Sans Myanmar UI Condensed Medium", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Myanmar UI Condensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMyanmarUI-CondensedMedium.ttf", + "preferred_family_name": "Noto Sans Myanmar UI", + "preferred_subfamily_name": "Condensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMyanmarUI-CondensedSemiBold.ttf||205672:1655828711.0": { + "family_name": "Noto Sans Myanmar UI Condensed SemiBold", + "font-family": "Noto Sans Myanmar UI Condensed SemiBold", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Myanmar UI Condensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMyanmarUI-CondensedSemiBold.ttf", + "preferred_family_name": "Noto Sans Myanmar UI", + "preferred_subfamily_name": "Condensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMyanmarUI-CondensedThin.ttf||199052:1655828711.0": { + "family_name": "Noto Sans Myanmar UI Condensed Thin", + "font-family": "Noto Sans Myanmar UI Condensed Thin", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Myanmar UI Condensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMyanmarUI-CondensedThin.ttf", + "preferred_family_name": "Noto Sans Myanmar UI", + "preferred_subfamily_name": "Condensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMyanmarUI-ExtraBold.ttf||214920:1655828711.0": { + "family_name": "Noto Sans Myanmar UI ExtraBold", + "font-family": "Noto Sans Myanmar UI ExtraBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Myanmar UI ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMyanmarUI-ExtraBold.ttf", + "preferred_family_name": "Noto Sans Myanmar UI", + "preferred_subfamily_name": "ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMyanmarUI-ExtraCondensed.ttf||204220:1655828711.0": { + "family_name": "Noto Sans Myanmar UI ExtraCondensed", + "font-family": "Noto Sans Myanmar UI ExtraCondensed", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Myanmar UI ExtraCondensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMyanmarUI-ExtraCondensed.ttf", + "preferred_family_name": "Noto Sans Myanmar UI", + "preferred_subfamily_name": "ExtraCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMyanmarUI-ExtraCondensedBlack.ttf||211132:1655828711.0": { + "family_name": "Noto Sans Myanmar UI ExtraCondensed Black", + "font-family": "Noto Sans Myanmar UI ExtraCondensed Black", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Myanmar UI ExtraCondensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMyanmarUI-ExtraCondensedBlack.ttf", + "preferred_family_name": "Noto Sans Myanmar UI", + "preferred_subfamily_name": "ExtraCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMyanmarUI-ExtraCondensedBold.ttf||205784:1655828711.0": { + "family_name": "Noto Sans Myanmar UI ExtraCondensed", + "font-family": "Noto Sans Myanmar UI ExtraCondensed", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Myanmar UI ExtraCondensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMyanmarUI-ExtraCondensedBold.ttf", + "preferred_family_name": "Noto Sans Myanmar UI", + "preferred_subfamily_name": "ExtraCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMyanmarUI-ExtraCondensedExtraBold.ttf||208828:1655828711.0": { + "family_name": "Noto Sans Myanmar UI ExtraCondensed ExtraBold", + "font-family": "Noto Sans Myanmar UI ExtraCondensed ExtraBold", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Myanmar UI ExtraCondensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMyanmarUI-ExtraCondensedExtraBold.ttf", + "preferred_family_name": "Noto Sans Myanmar UI", + "preferred_subfamily_name": "ExtraCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMyanmarUI-ExtraCondensedExtraLight.ttf||196520:1655828711.0": { + "family_name": "Noto Sans Myanmar UI ExtraCondensed ExtraLight", + "font-family": "Noto Sans Myanmar UI ExtraCondensed ExtraLight", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Myanmar UI ExtraCondensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMyanmarUI-ExtraCondensedExtraLight.ttf", + "preferred_family_name": "Noto Sans Myanmar UI", + "preferred_subfamily_name": "ExtraCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMyanmarUI-ExtraCondensedLight.ttf||194828:1655828711.0": { + "family_name": "Noto Sans Myanmar UI ExtraCondensed Light", + "font-family": "Noto Sans Myanmar UI ExtraCondensed Light", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Myanmar UI ExtraCondensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMyanmarUI-ExtraCondensedLight.ttf", + "preferred_family_name": "Noto Sans Myanmar UI", + "preferred_subfamily_name": "ExtraCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMyanmarUI-ExtraCondensedMedium.ttf||206784:1655828711.0": { + "family_name": "Noto Sans Myanmar UI ExtraCondensed Medium", + "font-family": "Noto Sans Myanmar UI ExtraCondensed Medium", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Myanmar UI ExtraCondensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMyanmarUI-ExtraCondensedMedium.ttf", + "preferred_family_name": "Noto Sans Myanmar UI", + "preferred_subfamily_name": "ExtraCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMyanmarUI-ExtraCondensedSemiBold.ttf||205820:1655828711.0": { + "family_name": "Noto Sans Myanmar UI ExtraCondensed SemiBold", + "font-family": "Noto Sans Myanmar UI ExtraCondensed SemiBold", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Myanmar UI ExtraCondensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMyanmarUI-ExtraCondensedSemiBold.ttf", + "preferred_family_name": "Noto Sans Myanmar UI", + "preferred_subfamily_name": "ExtraCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMyanmarUI-ExtraCondensedThin.ttf||197604:1655828711.0": { + "family_name": "Noto Sans Myanmar UI ExtraCondensed Thin", + "font-family": "Noto Sans Myanmar UI ExtraCondensed Thin", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Myanmar UI ExtraCondensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMyanmarUI-ExtraCondensedThin.ttf", + "preferred_family_name": "Noto Sans Myanmar UI", + "preferred_subfamily_name": "ExtraCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMyanmarUI-ExtraLight.ttf||199824:1655828711.0": { + "family_name": "Noto Sans Myanmar UI ExtraLight", + "font-family": "Noto Sans Myanmar UI ExtraLight", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Myanmar UI ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMyanmarUI-ExtraLight.ttf", + "preferred_family_name": "Noto Sans Myanmar UI", + "preferred_subfamily_name": "ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMyanmarUI-Light.ttf||199096:1655828711.0": { + "family_name": "Noto Sans Myanmar UI Light", + "font-family": "Noto Sans Myanmar UI Light", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Myanmar UI Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMyanmarUI-Light.ttf", + "preferred_family_name": "Noto Sans Myanmar UI", + "preferred_subfamily_name": "Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMyanmarUI-Medium.ttf||203740:1655828711.0": { + "family_name": "Noto Sans Myanmar UI Medium", + "font-family": "Noto Sans Myanmar UI Medium", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Myanmar UI Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMyanmarUI-Medium.ttf", + "preferred_family_name": "Noto Sans Myanmar UI", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMyanmarUI-Regular.ttf||199680:1655828711.0": { + "family_name": "Noto Sans Myanmar UI", + "font-family": "Noto Sans Myanmar UI", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Myanmar UI Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMyanmarUI-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMyanmarUI-SemiBold.ttf||208320:1655828711.0": { + "family_name": "Noto Sans Myanmar UI SemiBold", + "font-family": "Noto Sans Myanmar UI SemiBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Myanmar UI SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMyanmarUI-SemiBold.ttf", + "preferred_family_name": "Noto Sans Myanmar UI", + "preferred_subfamily_name": "SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMyanmarUI-SemiCondensed.ttf||200912:1655828711.0": { + "family_name": "Noto Sans Myanmar UI SemiCondensed", + "font-family": "Noto Sans Myanmar UI SemiCondensed", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Myanmar UI SemiCondensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMyanmarUI-SemiCondensed.ttf", + "preferred_family_name": "Noto Sans Myanmar UI", + "preferred_subfamily_name": "SemiCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMyanmarUI-SemiCondensedBlack.ttf||216044:1655828711.0": { + "family_name": "Noto Sans Myanmar UI SemiCondensed Black", + "font-family": "Noto Sans Myanmar UI SemiCondensed Black", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Myanmar UI SemiCondensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMyanmarUI-SemiCondensedBlack.ttf", + "preferred_family_name": "Noto Sans Myanmar UI", + "preferred_subfamily_name": "SemiCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMyanmarUI-SemiCondensedBold.ttf||211128:1655828711.0": { + "family_name": "Noto Sans Myanmar UI SemiCondensed", + "font-family": "Noto Sans Myanmar UI SemiCondensed", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Myanmar UI SemiCondensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMyanmarUI-SemiCondensedBold.ttf", + "preferred_family_name": "Noto Sans Myanmar UI", + "preferred_subfamily_name": "SemiCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMyanmarUI-SemiCondensedExtraBold.ttf||215292:1655828711.0": { + "family_name": "Noto Sans Myanmar UI SemiCondensed ExtraBold", + "font-family": "Noto Sans Myanmar UI SemiCondensed ExtraBold", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Myanmar UI SemiCondensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMyanmarUI-SemiCondensedExtraBold.ttf", + "preferred_family_name": "Noto Sans Myanmar UI", + "preferred_subfamily_name": "SemiCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMyanmarUI-SemiCondensedExtraLight.ttf||198484:1655828711.0": { + "family_name": "Noto Sans Myanmar UI SemiCondensed ExtraLight", + "font-family": "Noto Sans Myanmar UI SemiCondensed ExtraLight", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Myanmar UI SemiCondensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMyanmarUI-SemiCondensedExtraLight.ttf", + "preferred_family_name": "Noto Sans Myanmar UI", + "preferred_subfamily_name": "SemiCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMyanmarUI-SemiCondensedLight.ttf||196496:1655828711.0": { + "family_name": "Noto Sans Myanmar UI SemiCondensed Light", + "font-family": "Noto Sans Myanmar UI SemiCondensed Light", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Myanmar UI SemiCondensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMyanmarUI-SemiCondensedLight.ttf", + "preferred_family_name": "Noto Sans Myanmar UI", + "preferred_subfamily_name": "SemiCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMyanmarUI-SemiCondensedMedium.ttf||206960:1655828711.0": { + "family_name": "Noto Sans Myanmar UI SemiCondensed Medium", + "font-family": "Noto Sans Myanmar UI SemiCondensed Medium", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Myanmar UI SemiCondensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMyanmarUI-SemiCondensedMedium.ttf", + "preferred_family_name": "Noto Sans Myanmar UI", + "preferred_subfamily_name": "SemiCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMyanmarUI-SemiCondensedSemiBold.ttf||211568:1655828711.0": { + "family_name": "Noto Sans Myanmar UI SemiCondensed SemiBold", + "font-family": "Noto Sans Myanmar UI SemiCondensed SemiBold", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Myanmar UI SemiCondensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMyanmarUI-SemiCondensedSemiBold.ttf", + "preferred_family_name": "Noto Sans Myanmar UI", + "preferred_subfamily_name": "SemiCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMyanmarUI-SemiCondensedThin.ttf||201104:1655828711.0": { + "family_name": "Noto Sans Myanmar UI SemiCondensed Thin", + "font-family": "Noto Sans Myanmar UI SemiCondensed Thin", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Myanmar UI SemiCondensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMyanmarUI-SemiCondensedThin.ttf", + "preferred_family_name": "Noto Sans Myanmar UI", + "preferred_subfamily_name": "SemiCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansMyanmarUI-Thin.ttf||201596:1655828711.0": { + "family_name": "Noto Sans Myanmar UI Thin", + "font-family": "Noto Sans Myanmar UI Thin", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Myanmar UI Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansMyanmarUI-Thin.ttf", + "preferred_family_name": "Noto Sans Myanmar UI", + "preferred_subfamily_name": "Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansNKo-Regular.ttf||38352:1655828711.0": { + "family_name": "Noto Sans NKo", + "font-family": "Noto Sans NKo", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans NKo Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansNKo-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansNabataean-Regular.ttf||8328:1655828711.0": { + "family_name": "Noto Sans Nabataean", + "font-family": "Noto Sans Nabataean", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Nabataean Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansNabataean-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansNandinagari-Regular.ttf||212628:1655828711.0": { + "family_name": "Noto Sans Nandinagari", + "font-family": "Noto Sans Nandinagari", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Nandinagari Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/noto/NotoSansNandinagari-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansNewTaiLue-Regular.ttf||17024:1655828711.0": { + "family_name": "Noto Sans NewTaiLue", + "font-family": "Noto Sans NewTaiLue", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans New Tai Lue Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansNewTaiLue-Regular.ttf", + "preferred_family_name": "Noto Sans New Tai Lue", + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansNewa-Regular.ttf||151720:1655828711.0": { + "family_name": "Noto Sans Newa", + "font-family": "Noto Sans Newa", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Newa Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansNewa-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansNushu-Regular.ttf||116564:1655828711.0": { + "family_name": "Noto Sans Nushu", + "font-family": "Noto Sans Nushu", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Nushu Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansNushu-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansOgham-Regular.ttf||4684:1655828711.0": { + "family_name": "Noto Sans Ogham", + "font-family": "Noto Sans Ogham", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Ogham Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansOgham-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansOlChiki-Bold.ttf||14508:1655828711.0": { + "family_name": "Noto Sans Ol Chiki", + "font-family": "Noto Sans Ol Chiki", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Ol Chiki Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/noto/NotoSansOlChiki-Bold.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansOlChiki-Medium.ttf||15112:1655828711.0": { + "family_name": "Noto Sans Ol Chiki Medium", + "font-family": "Noto Sans Ol Chiki Medium", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Ol Chiki Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/noto/NotoSansOlChiki-Medium.ttf", + "preferred_family_name": "Noto Sans Ol Chiki", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansOlChiki-Regular.ttf||15180:1655828711.0": { + "family_name": "Noto Sans Ol Chiki", + "font-family": "Noto Sans Ol Chiki", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Ol Chiki Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/noto/NotoSansOlChiki-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansOlChiki-SemiBold.ttf||14812:1655828711.0": { + "family_name": "Noto Sans Ol Chiki SemiBold", + "font-family": "Noto Sans Ol Chiki SemiBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Ol Chiki SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/noto/NotoSansOlChiki-SemiBold.ttf", + "preferred_family_name": "Noto Sans Ol Chiki", + "preferred_subfamily_name": "SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansOldHungarian-Regular.ttf||53944:1655828711.0": { + "family_name": "Noto Sans OldHung", + "font-family": "Noto Sans OldHung", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Old Hungarian Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansOldHungarian-Regular.ttf", + "preferred_family_name": "Noto Sans Old Hungarian", + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansOldItalic-Regular.ttf||7548:1655828711.0": { + "family_name": "Noto Sans Old Italic", + "font-family": "Noto Sans Old Italic", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Old Italic Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansOldItalic-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansOldNorthArabian-Regular.ttf||7228:1655828711.0": { + "family_name": "Noto Sans OldNorArab", + "font-family": "Noto Sans OldNorArab", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Old North Arabian Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansOldNorthArabian-Regular.ttf", + "preferred_family_name": "Noto Sans Old North Arabian", + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansOldPermic-Regular.ttf||9976:1655828711.0": { + "family_name": "Noto Sans Old Permic", + "font-family": "Noto Sans Old Permic", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Old Permic Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansOldPermic-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansOldPersian-Regular.ttf||12764:1655828711.0": { + "family_name": "Noto Sans OldPersian", + "font-family": "Noto Sans OldPersian", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Old Persian Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansOldPersian-Regular.ttf", + "preferred_family_name": "Noto Sans Old Persian", + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansOldSogdian-Regular.ttf||15540:1655828711.0": { + "family_name": "Noto Sans OldSogdian", + "font-family": "Noto Sans OldSogdian", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Old Sogdian Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansOldSogdian-Regular.ttf", + "preferred_family_name": "Noto Sans Old Sogdian", + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansOldSouthArabian-Regular.ttf||5276:1655828711.0": { + "family_name": "Noto Sans OldSouArab", + "font-family": "Noto Sans OldSouArab", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Old South Arabian Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansOldSouthArabian-Regular.ttf", + "preferred_family_name": "Noto Sans Old South Arabian", + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansOldTurkic-Regular.ttf||15392:1655828711.0": { + "family_name": "Noto Sans Old Turkic", + "font-family": "Noto Sans Old Turkic", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Old Turkic Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansOldTurkic-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansOriya-Black.ttf||91388:1655828711.0": { + "family_name": "Noto Sans Oriya Blk", + "font-family": "Noto Sans Oriya Blk", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Oriya Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/noto/NotoSansOriya-Black.ttf", + "preferred_family_name": "Noto Sans Oriya", + "preferred_subfamily_name": "Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansOriya-Bold.ttf||92940:1655828711.0": { + "family_name": "Noto Sans Oriya", + "font-family": "Noto Sans Oriya", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Oriya Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/noto/NotoSansOriya-Bold.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansOriya-Condensed.ttf||93568:1655828711.0": { + "family_name": "Noto Sans Oriya Cond", + "font-family": "Noto Sans Oriya Cond", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Oriya Condensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/noto/NotoSansOriya-Condensed.ttf", + "preferred_family_name": "Noto Sans Oriya", + "preferred_subfamily_name": "Condensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansOriya-CondensedBlack.ttf||90376:1655828711.0": { + "family_name": "Noto Sans Oriya Cond Blk", + "font-family": "Noto Sans Oriya Cond Blk", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Oriya Condensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/noto/NotoSansOriya-CondensedBlack.ttf", + "preferred_family_name": "Noto Sans Oriya", + "preferred_subfamily_name": "Condensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansOriya-CondensedBold.ttf||91392:1655828711.0": { + "family_name": "Noto Sans Oriya Cond Bold", + "font-family": "Noto Sans Oriya Cond Bold", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Oriya Condensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/noto/NotoSansOriya-CondensedBold.ttf", + "preferred_family_name": "Noto Sans Oriya", + "preferred_subfamily_name": "Condensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansOriya-CondensedThin.ttf||96628:1655828711.0": { + "family_name": "Noto Sans Oriya Cond Thin", + "font-family": "Noto Sans Oriya Cond Thin", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Oriya Condensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/noto/NotoSansOriya-CondensedThin.ttf", + "preferred_family_name": "Noto Sans Oriya", + "preferred_subfamily_name": "Condensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansOriya-ExtraCondensed.ttf||93276:1655828711.0": { + "family_name": "Noto Sans Oriya ExtCond", + "font-family": "Noto Sans Oriya ExtCond", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Oriya ExtraCondensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/noto/NotoSansOriya-ExtraCondensed.ttf", + "preferred_family_name": "Noto Sans Oriya", + "preferred_subfamily_name": "ExtraCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansOriya-ExtraCondensedBlack.ttf||90652:1655828711.0": { + "family_name": "Noto Sans Oriya ExtCond Blk", + "font-family": "Noto Sans Oriya ExtCond Blk", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Oriya ExtraCondensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/noto/NotoSansOriya-ExtraCondensedBlack.ttf", + "preferred_family_name": "Noto Sans Oriya", + "preferred_subfamily_name": "ExtraCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansOriya-ExtraCondensedBold.ttf||91176:1655828711.0": { + "family_name": "Noto Sans Oriya ExtCond Bold", + "font-family": "Noto Sans Oriya ExtCond Bold", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Oriya ExtraCondensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/noto/NotoSansOriya-ExtraCondensedBold.ttf", + "preferred_family_name": "Noto Sans Oriya", + "preferred_subfamily_name": "ExtraCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansOriya-ExtraCondensedThin.ttf||95904:1655828711.0": { + "family_name": "Noto Sans Oriya ExtCond Thin", + "font-family": "Noto Sans Oriya ExtCond Thin", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Oriya ExtraCondensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/noto/NotoSansOriya-ExtraCondensedThin.ttf", + "preferred_family_name": "Noto Sans Oriya", + "preferred_subfamily_name": "ExtraCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansOriya-Regular.ttf||95776:1655828711.0": { + "family_name": "Noto Sans Oriya", + "font-family": "Noto Sans Oriya", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Oriya Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/noto/NotoSansOriya-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansOriya-Thin.ttf||99044:1655828711.0": { + "family_name": "Noto Sans Oriya Thin", + "font-family": "Noto Sans Oriya Thin", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Oriya Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/noto/NotoSansOriya-Thin.ttf", + "preferred_family_name": "Noto Sans Oriya", + "preferred_subfamily_name": "Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansOriyaUI-Black.ttf||91432:1655828711.0": { + "family_name": "Noto Sans Oriya UI Blk", + "font-family": "Noto Sans Oriya UI Blk", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Oriya UI Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/noto/NotoSansOriyaUI-Black.ttf", + "preferred_family_name": "Noto Sans Oriya UI", + "preferred_subfamily_name": "Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansOriyaUI-Bold.ttf||92996:1655828711.0": { + "family_name": "Noto Sans Oriya UI", + "font-family": "Noto Sans Oriya UI", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Oriya UI Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/noto/NotoSansOriyaUI-Bold.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansOriyaUI-Condensed.ttf||93644:1655828711.0": { + "family_name": "Noto Sans Oriya UI Cond", + "font-family": "Noto Sans Oriya UI Cond", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Oriya UI Condensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/noto/NotoSansOriyaUI-Condensed.ttf", + "preferred_family_name": "Noto Sans Oriya UI", + "preferred_subfamily_name": "Condensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansOriyaUI-CondensedBlack.ttf||90428:1655828711.0": { + "family_name": "Noto Sans Oriya UI Cond Blk", + "font-family": "Noto Sans Oriya UI Cond Blk", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Oriya UI Condensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/noto/NotoSansOriyaUI-CondensedBlack.ttf", + "preferred_family_name": "Noto Sans Oriya UI", + "preferred_subfamily_name": "Condensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansOriyaUI-CondensedBold.ttf||91444:1655828711.0": { + "family_name": "Noto Sans Oriya UI Cond Bold", + "font-family": "Noto Sans Oriya UI Cond Bold", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Oriya UI Condensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/noto/NotoSansOriyaUI-CondensedBold.ttf", + "preferred_family_name": "Noto Sans Oriya UI", + "preferred_subfamily_name": "Condensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansOriyaUI-CondensedThin.ttf||96692:1655828711.0": { + "family_name": "Noto Sans Oriya UI Cond Thin", + "font-family": "Noto Sans Oriya UI Cond Thin", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Oriya UI Condensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/noto/NotoSansOriyaUI-CondensedThin.ttf", + "preferred_family_name": "Noto Sans Oriya UI", + "preferred_subfamily_name": "Condensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansOriyaUI-ExtraCondensed.ttf||93352:1655828711.0": { + "family_name": "Noto Sans Oriya UI ExtCond", + "font-family": "Noto Sans Oriya UI ExtCond", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Oriya UI ExtraCondensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/noto/NotoSansOriyaUI-ExtraCondensed.ttf", + "preferred_family_name": "Noto Sans Oriya UI", + "preferred_subfamily_name": "ExtraCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansOriyaUI-ExtraCondensedBlack.ttf||90712:1655828711.0": { + "family_name": "Noto Sans Oriya UI ExtCond Blk", + "font-family": "Noto Sans Oriya UI ExtCond Blk", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Oriya UI ExtraCondensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/noto/NotoSansOriyaUI-ExtraCondensedBlack.ttf", + "preferred_family_name": "Noto Sans Oriya UI", + "preferred_subfamily_name": "ExtraCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansOriyaUI-ExtraCondensedBold.ttf||91236:1655828711.0": { + "family_name": "Noto Sans Oriya UI ExtCond Bold", + "font-family": "Noto Sans Oriya UI ExtCond Bold", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Oriya UI ExtraCondensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/noto/NotoSansOriyaUI-ExtraCondensedBold.ttf", + "preferred_family_name": "Noto Sans Oriya UI", + "preferred_subfamily_name": "ExtraCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansOriyaUI-ExtraCondensedThin.ttf||95996:1655828711.0": { + "family_name": "Noto Sans Oriya UI ExtCond Thin", + "font-family": "Noto Sans Oriya UI ExtCond Thin", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Oriya UI ExtraCondensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/noto/NotoSansOriyaUI-ExtraCondensedThin.ttf", + "preferred_family_name": "Noto Sans Oriya UI", + "preferred_subfamily_name": "ExtraCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansOriyaUI-Regular.ttf||95844:1655828711.0": { + "family_name": "Noto Sans Oriya UI", + "font-family": "Noto Sans Oriya UI", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Oriya UI Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/noto/NotoSansOriyaUI-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansOriyaUI-Thin.ttf||99112:1655828711.0": { + "family_name": "Noto Sans Oriya UI Thin", + "font-family": "Noto Sans Oriya UI Thin", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Oriya UI Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/noto/NotoSansOriyaUI-Thin.ttf", + "preferred_family_name": "Noto Sans Oriya UI", + "preferred_subfamily_name": "Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansOsage-Regular.ttf||21044:1655828711.0": { + "family_name": "Noto Sans Osage", + "font-family": "Noto Sans Osage", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Osage Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansOsage-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansOsmanya-Regular.ttf||17016:1655828711.0": { + "family_name": "Noto Sans Osmanya", + "font-family": "Noto Sans Osmanya", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Osmanya Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansOsmanya-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansPahawhHmong-Regular.ttf||18248:1655828711.0": { + "family_name": "Noto Sans Pahawh Hmong", + "font-family": "Noto Sans Pahawh Hmong", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Pahawh Hmong Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansPahawhHmong-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansPalmyrene-Regular.ttf||15660:1655828711.0": { + "family_name": "Noto Sans Palmyrene", + "font-family": "Noto Sans Palmyrene", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Palmyrene Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansPalmyrene-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansPauCinHau-Regular.ttf||9840:1655828711.0": { + "family_name": "Noto Sans PauCinHau", + "font-family": "Noto Sans PauCinHau", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Pau Cin Hau Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansPauCinHau-Regular.ttf", + "preferred_family_name": "Noto Sans Pau Cin Hau", + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansPhagsPa-Regular.ttf||39904:1655828711.0": { + "family_name": "Noto Sans PhagsPa", + "font-family": "Noto Sans PhagsPa", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans PhagsPa Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansPhagsPa-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansPhoenician-Regular.ttf||6192:1655828711.0": { + "family_name": "Noto Sans Phoenician", + "font-family": "Noto Sans Phoenician", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Phoenician Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansPhoenician-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansPsalterPahlavi-Regular.ttf||33308:1655828711.0": { + "family_name": "Noto Sans PsaPahlavi", + "font-family": "Noto Sans PsaPahlavi", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Psalter Pahlavi Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansPsalterPahlavi-Regular.ttf", + "preferred_family_name": "Noto Sans Psalter Pahlavi", + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansRejang-Regular.ttf||7528:1655828711.0": { + "family_name": "Noto Sans Rejang", + "font-family": "Noto Sans Rejang", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Rejang Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansRejang-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansRunic-Regular.ttf||9576:1655828711.0": { + "family_name": "Noto Sans Runic", + "font-family": "Noto Sans Runic", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Runic Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansRunic-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansSamaritan-Regular.ttf||11068:1655828711.0": { + "family_name": "Noto Sans Samaritan", + "font-family": "Noto Sans Samaritan", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Samaritan Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansSamaritan-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansSaurashtra-Regular.ttf||35316:1655828711.0": { + "family_name": "Noto Sans Saurashtra", + "font-family": "Noto Sans Saurashtra", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Saurashtra Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansSaurashtra-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansSharada-Regular.ttf||52132:1655828711.0": { + "family_name": "Noto Sans Sharada", + "font-family": "Noto Sans Sharada", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Sharada Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansSharada-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansShavian-Regular.ttf||13428:1655828711.0": { + "family_name": "Noto Sans Shavian", + "font-family": "Noto Sans Shavian", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Shavian Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansShavian-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansSiddham-Regular.ttf||141744:1655828711.0": { + "family_name": "Noto Sans Siddham", + "font-family": "Noto Sans Siddham", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Siddham Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansSiddham-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansSignWriting-Regular.ttf||5216448:1655828711.0": { + "family_name": "Noto Sans SignWrit", + "font-family": "Noto Sans SignWrit", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans SignWriting Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansSignWriting-Regular.ttf", + "preferred_family_name": "Noto Sans SignWriting", + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansSinhala-Black.ttf||359212:1655828711.0": { + "family_name": "Noto Sans Sinhala Black", + "font-family": "Noto Sans Sinhala Black", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Sinhala Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansSinhala-Black.ttf", + "preferred_family_name": "Noto Sans Sinhala", + "preferred_subfamily_name": "Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansSinhala-Bold.ttf||342464:1655828711.0": { + "family_name": "Noto Sans Sinhala", + "font-family": "Noto Sans Sinhala", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Sinhala Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansSinhala-Bold.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansSinhala-Condensed.ttf||315016:1655828711.0": { + "family_name": "Noto Sans Sinhala Condensed", + "font-family": "Noto Sans Sinhala Condensed", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Sinhala Condensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansSinhala-Condensed.ttf", + "preferred_family_name": "Noto Sans Sinhala", + "preferred_subfamily_name": "Condensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansSinhala-CondensedBlack.ttf||350536:1655828711.0": { + "family_name": "Noto Sans Sinhala Condensed Black", + "font-family": "Noto Sans Sinhala Condensed Black", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Sinhala Condensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansSinhala-CondensedBlack.ttf", + "preferred_family_name": "Noto Sans Sinhala", + "preferred_subfamily_name": "Condensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansSinhala-CondensedBold.ttf||353260:1655828711.0": { + "family_name": "Noto Sans Sinhala Condensed", + "font-family": "Noto Sans Sinhala Condensed", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Sinhala Condensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansSinhala-CondensedBold.ttf", + "preferred_family_name": "Noto Sans Sinhala", + "preferred_subfamily_name": "Condensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansSinhala-CondensedExtraBold.ttf||352280:1655828711.0": { + "family_name": "Noto Sans Sinhala Condensed ExtraBold", + "font-family": "Noto Sans Sinhala Condensed ExtraBold", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Sinhala Condensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansSinhala-CondensedExtraBold.ttf", + "preferred_family_name": "Noto Sans Sinhala", + "preferred_subfamily_name": "Condensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansSinhala-CondensedExtraLight.ttf||280940:1655828711.0": { + "family_name": "Noto Sans Sinhala Condensed ExtraLight", + "font-family": "Noto Sans Sinhala Condensed ExtraLight", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Sinhala Condensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansSinhala-CondensedExtraLight.ttf", + "preferred_family_name": "Noto Sans Sinhala", + "preferred_subfamily_name": "Condensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansSinhala-CondensedLight.ttf||324520:1655828711.0": { + "family_name": "Noto Sans Sinhala Condensed Light", + "font-family": "Noto Sans Sinhala Condensed Light", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Sinhala Condensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansSinhala-CondensedLight.ttf", + "preferred_family_name": "Noto Sans Sinhala", + "preferred_subfamily_name": "Condensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansSinhala-CondensedMedium.ttf||310616:1655828711.0": { + "family_name": "Noto Sans Sinhala Condensed Medium", + "font-family": "Noto Sans Sinhala Condensed Medium", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Sinhala Condensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansSinhala-CondensedMedium.ttf", + "preferred_family_name": "Noto Sans Sinhala", + "preferred_subfamily_name": "Condensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansSinhala-CondensedSemiBold.ttf||347948:1655828711.0": { + "family_name": "Noto Sans Sinhala Condensed SemiBold", + "font-family": "Noto Sans Sinhala Condensed SemiBold", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Sinhala Condensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansSinhala-CondensedSemiBold.ttf", + "preferred_family_name": "Noto Sans Sinhala", + "preferred_subfamily_name": "Condensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansSinhala-CondensedThin.ttf||284748:1655828711.0": { + "family_name": "Noto Sans Sinhala Condensed Thin", + "font-family": "Noto Sans Sinhala Condensed Thin", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Sinhala Condensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansSinhala-CondensedThin.ttf", + "preferred_family_name": "Noto Sans Sinhala", + "preferred_subfamily_name": "Condensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansSinhala-ExtraBold.ttf||347308:1655828711.0": { + "family_name": "Noto Sans Sinhala ExtraBold", + "font-family": "Noto Sans Sinhala ExtraBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Sinhala ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansSinhala-ExtraBold.ttf", + "preferred_family_name": "Noto Sans Sinhala", + "preferred_subfamily_name": "ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansSinhala-ExtraCondensed.ttf||321636:1655828711.0": { + "family_name": "Noto Sans Sinhala ExtraCondensed", + "font-family": "Noto Sans Sinhala ExtraCondensed", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Sinhala ExtraCondensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansSinhala-ExtraCondensed.ttf", + "preferred_family_name": "Noto Sans Sinhala", + "preferred_subfamily_name": "ExtraCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansSinhala-ExtraCondensedBlack.ttf||338404:1655828711.0": { + "family_name": "Noto Sans Sinhala ExtraCondensed Black", + "font-family": "Noto Sans Sinhala ExtraCondensed Black", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Sinhala ExtraCondensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansSinhala-ExtraCondensedBlack.ttf", + "preferred_family_name": "Noto Sans Sinhala", + "preferred_subfamily_name": "ExtraCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansSinhala-ExtraCondensedBold.ttf||361872:1655828711.0": { + "family_name": "Noto Sans Sinhala ExtraCondensed", + "font-family": "Noto Sans Sinhala ExtraCondensed", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Sinhala ExtraCondensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansSinhala-ExtraCondensedBold.ttf", + "preferred_family_name": "Noto Sans Sinhala", + "preferred_subfamily_name": "ExtraCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansSinhala-ExtraCondensedExtraBold.ttf||341880:1655828711.0": { + "family_name": "Noto Sans Sinhala ExtraCondensed ExtraBold", + "font-family": "Noto Sans Sinhala ExtraCondensed ExtraBold", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Sinhala ExtraCondensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansSinhala-ExtraCondensedExtraBold.ttf", + "preferred_family_name": "Noto Sans Sinhala", + "preferred_subfamily_name": "ExtraCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansSinhala-ExtraCondensedExtraLight.ttf||280960:1655828711.0": { + "family_name": "Noto Sans Sinhala ExtraCondensed ExtraLight", + "font-family": "Noto Sans Sinhala ExtraCondensed ExtraLight", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Sinhala ExtraCondensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansSinhala-ExtraCondensedExtraLight.ttf", + "preferred_family_name": "Noto Sans Sinhala", + "preferred_subfamily_name": "ExtraCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansSinhala-ExtraCondensedLight.ttf||318184:1655828711.0": { + "family_name": "Noto Sans Sinhala ExtraCondensed Light", + "font-family": "Noto Sans Sinhala ExtraCondensed Light", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Sinhala ExtraCondensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansSinhala-ExtraCondensedLight.ttf", + "preferred_family_name": "Noto Sans Sinhala", + "preferred_subfamily_name": "ExtraCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansSinhala-ExtraCondensedMedium.ttf||317916:1655828711.0": { + "family_name": "Noto Sans Sinhala ExtraCondensed Medium", + "font-family": "Noto Sans Sinhala ExtraCondensed Medium", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Sinhala ExtraCondensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansSinhala-ExtraCondensedMedium.ttf", + "preferred_family_name": "Noto Sans Sinhala", + "preferred_subfamily_name": "ExtraCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansSinhala-ExtraCondensedSemiBold.ttf||347716:1655828711.0": { + "family_name": "Noto Sans Sinhala ExtraCondensed SemiBold", + "font-family": "Noto Sans Sinhala ExtraCondensed SemiBold", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Sinhala ExtraCondensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansSinhala-ExtraCondensedSemiBold.ttf", + "preferred_family_name": "Noto Sans Sinhala", + "preferred_subfamily_name": "ExtraCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansSinhala-ExtraCondensedThin.ttf||282120:1655828711.0": { + "family_name": "Noto Sans Sinhala ExtraCondensed Thin", + "font-family": "Noto Sans Sinhala ExtraCondensed Thin", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Sinhala ExtraCondensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansSinhala-ExtraCondensedThin.ttf", + "preferred_family_name": "Noto Sans Sinhala", + "preferred_subfamily_name": "ExtraCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansSinhala-ExtraLight.ttf||294504:1655828711.0": { + "family_name": "Noto Sans Sinhala ExtraLight", + "font-family": "Noto Sans Sinhala ExtraLight", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Sinhala ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansSinhala-ExtraLight.ttf", + "preferred_family_name": "Noto Sans Sinhala", + "preferred_subfamily_name": "ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansSinhala-Light.ttf||326096:1655828711.0": { + "family_name": "Noto Sans Sinhala Light", + "font-family": "Noto Sans Sinhala Light", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Sinhala Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansSinhala-Light.ttf", + "preferred_family_name": "Noto Sans Sinhala", + "preferred_subfamily_name": "Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansSinhala-Medium.ttf||315556:1655828711.0": { + "family_name": "Noto Sans Sinhala Medium", + "font-family": "Noto Sans Sinhala Medium", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Sinhala Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansSinhala-Medium.ttf", + "preferred_family_name": "Noto Sans Sinhala", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansSinhala-Regular.ttf||310232:1655828711.0": { + "family_name": "Noto Sans Sinhala", + "font-family": "Noto Sans Sinhala", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Sinhala Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansSinhala-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansSinhala-SemiBold.ttf||338348:1655828711.0": { + "family_name": "Noto Sans Sinhala SemiBold", + "font-family": "Noto Sans Sinhala SemiBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Sinhala SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansSinhala-SemiBold.ttf", + "preferred_family_name": "Noto Sans Sinhala", + "preferred_subfamily_name": "SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansSinhala-SemiCondensed.ttf||310784:1655828711.0": { + "family_name": "Noto Sans Sinhala SemiCondensed", + "font-family": "Noto Sans Sinhala SemiCondensed", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Sinhala SemiCondensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansSinhala-SemiCondensed.ttf", + "preferred_family_name": "Noto Sans Sinhala", + "preferred_subfamily_name": "SemiCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansSinhala-SemiCondensedBlack.ttf||355380:1655828711.0": { + "family_name": "Noto Sans Sinhala SemiCondensed Black", + "font-family": "Noto Sans Sinhala SemiCondensed Black", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Sinhala SemiCondensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansSinhala-SemiCondensedBlack.ttf", + "preferred_family_name": "Noto Sans Sinhala", + "preferred_subfamily_name": "SemiCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansSinhala-SemiCondensedBold.ttf||348364:1655828711.0": { + "family_name": "Noto Sans Sinhala SemiCondensed", + "font-family": "Noto Sans Sinhala SemiCondensed", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Sinhala SemiCondensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansSinhala-SemiCondensedBold.ttf", + "preferred_family_name": "Noto Sans Sinhala", + "preferred_subfamily_name": "SemiCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansSinhala-SemiCondensedExtraBold.ttf||342012:1655828711.0": { + "family_name": "Noto Sans Sinhala SemiCondensed ExtraBold", + "font-family": "Noto Sans Sinhala SemiCondensed ExtraBold", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Sinhala SemiCondensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansSinhala-SemiCondensedExtraBold.ttf", + "preferred_family_name": "Noto Sans Sinhala", + "preferred_subfamily_name": "SemiCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansSinhala-SemiCondensedExtraLight.ttf||294840:1655828711.0": { + "family_name": "Noto Sans Sinhala SemiCondensed ExtraLight", + "font-family": "Noto Sans Sinhala SemiCondensed ExtraLight", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Sinhala SemiCondensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansSinhala-SemiCondensedExtraLight.ttf", + "preferred_family_name": "Noto Sans Sinhala", + "preferred_subfamily_name": "SemiCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansSinhala-SemiCondensedLight.ttf||325792:1655828711.0": { + "family_name": "Noto Sans Sinhala SemiCondensed Light", + "font-family": "Noto Sans Sinhala SemiCondensed Light", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Sinhala SemiCondensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansSinhala-SemiCondensedLight.ttf", + "preferred_family_name": "Noto Sans Sinhala", + "preferred_subfamily_name": "SemiCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansSinhala-SemiCondensedMedium.ttf||317320:1655828711.0": { + "family_name": "Noto Sans Sinhala SemiCondensed Medium", + "font-family": "Noto Sans Sinhala SemiCondensed Medium", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Sinhala SemiCondensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansSinhala-SemiCondensedMedium.ttf", + "preferred_family_name": "Noto Sans Sinhala", + "preferred_subfamily_name": "SemiCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansSinhala-SemiCondensedSemiBold.ttf||344672:1655828711.0": { + "family_name": "Noto Sans Sinhala SemiCondensed SemiBold", + "font-family": "Noto Sans Sinhala SemiCondensed SemiBold", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Sinhala SemiCondensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansSinhala-SemiCondensedSemiBold.ttf", + "preferred_family_name": "Noto Sans Sinhala", + "preferred_subfamily_name": "SemiCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansSinhala-SemiCondensedThin.ttf||285536:1655828711.0": { + "family_name": "Noto Sans Sinhala SemiCondensed Thin", + "font-family": "Noto Sans Sinhala SemiCondensed Thin", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Sinhala SemiCondensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansSinhala-SemiCondensedThin.ttf", + "preferred_family_name": "Noto Sans Sinhala", + "preferred_subfamily_name": "SemiCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansSinhala-Thin.ttf||288692:1655828711.0": { + "family_name": "Noto Sans Sinhala Thin", + "font-family": "Noto Sans Sinhala Thin", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Sinhala Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansSinhala-Thin.ttf", + "preferred_family_name": "Noto Sans Sinhala", + "preferred_subfamily_name": "Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansSinhalaUI-Black.ttf||359236:1655828711.0": { + "family_name": "Noto Sans Sinhala UI Black", + "font-family": "Noto Sans Sinhala UI Black", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Sinhala UI Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansSinhalaUI-Black.ttf", + "preferred_family_name": "Noto Sans Sinhala UI", + "preferred_subfamily_name": "Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansSinhalaUI-Bold.ttf||342484:1655828711.0": { + "family_name": "Noto Sans Sinhala UI", + "font-family": "Noto Sans Sinhala UI", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Sinhala UI Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansSinhalaUI-Bold.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansSinhalaUI-Condensed.ttf||315040:1655828711.0": { + "family_name": "Noto Sans Sinhala UI Condensed", + "font-family": "Noto Sans Sinhala UI Condensed", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Sinhala UI Condensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansSinhalaUI-Condensed.ttf", + "preferred_family_name": "Noto Sans Sinhala UI", + "preferred_subfamily_name": "Condensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansSinhalaUI-CondensedBlack.ttf||350560:1655828711.0": { + "family_name": "Noto Sans Sinhala UI Condensed Black", + "font-family": "Noto Sans Sinhala UI Condensed Black", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Sinhala UI Condensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansSinhalaUI-CondensedBlack.ttf", + "preferred_family_name": "Noto Sans Sinhala UI", + "preferred_subfamily_name": "Condensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansSinhalaUI-CondensedBold.ttf||353288:1655828711.0": { + "family_name": "Noto Sans Sinhala UI Condensed", + "font-family": "Noto Sans Sinhala UI Condensed", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Sinhala UI Condensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansSinhalaUI-CondensedBold.ttf", + "preferred_family_name": "Noto Sans Sinhala UI", + "preferred_subfamily_name": "Condensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansSinhalaUI-CondensedExtraBold.ttf||352304:1655828711.0": { + "family_name": "Noto Sans Sinhala UI Condensed ExtraBold", + "font-family": "Noto Sans Sinhala UI Condensed ExtraBold", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Sinhala UI Condensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansSinhalaUI-CondensedExtraBold.ttf", + "preferred_family_name": "Noto Sans Sinhala UI", + "preferred_subfamily_name": "Condensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansSinhalaUI-CondensedExtraLight.ttf||280968:1655828711.0": { + "family_name": "Noto Sans Sinhala UI Condensed ExtraLight", + "font-family": "Noto Sans Sinhala UI Condensed ExtraLight", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Sinhala UI Condensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansSinhalaUI-CondensedExtraLight.ttf", + "preferred_family_name": "Noto Sans Sinhala UI", + "preferred_subfamily_name": "Condensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansSinhalaUI-CondensedLight.ttf||324544:1655828711.0": { + "family_name": "Noto Sans Sinhala UI Condensed Light", + "font-family": "Noto Sans Sinhala UI Condensed Light", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Sinhala UI Condensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansSinhalaUI-CondensedLight.ttf", + "preferred_family_name": "Noto Sans Sinhala UI", + "preferred_subfamily_name": "Condensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansSinhalaUI-CondensedMedium.ttf||310644:1655828711.0": { + "family_name": "Noto Sans Sinhala UI Condensed Medium", + "font-family": "Noto Sans Sinhala UI Condensed Medium", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Sinhala UI Condensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansSinhalaUI-CondensedMedium.ttf", + "preferred_family_name": "Noto Sans Sinhala UI", + "preferred_subfamily_name": "Condensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansSinhalaUI-CondensedSemiBold.ttf||347976:1655828711.0": { + "family_name": "Noto Sans Sinhala UI Condensed SemiBold", + "font-family": "Noto Sans Sinhala UI Condensed SemiBold", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Sinhala UI Condensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansSinhalaUI-CondensedSemiBold.ttf", + "preferred_family_name": "Noto Sans Sinhala UI", + "preferred_subfamily_name": "Condensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansSinhalaUI-CondensedThin.ttf||284776:1655828711.0": { + "family_name": "Noto Sans Sinhala UI Condensed Thin", + "font-family": "Noto Sans Sinhala UI Condensed Thin", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Sinhala UI Condensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansSinhalaUI-CondensedThin.ttf", + "preferred_family_name": "Noto Sans Sinhala UI", + "preferred_subfamily_name": "Condensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansSinhalaUI-ExtraBold.ttf||347332:1655828711.0": { + "family_name": "Noto Sans Sinhala UI ExtraBold", + "font-family": "Noto Sans Sinhala UI ExtraBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Sinhala UI ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansSinhalaUI-ExtraBold.ttf", + "preferred_family_name": "Noto Sans Sinhala UI", + "preferred_subfamily_name": "ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansSinhalaUI-ExtraCondensed.ttf||321664:1655828711.0": { + "family_name": "Noto Sans Sinhala UI ExtraCondensed", + "font-family": "Noto Sans Sinhala UI ExtraCondensed", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Sinhala UI ExtraCondensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansSinhalaUI-ExtraCondensed.ttf", + "preferred_family_name": "Noto Sans Sinhala UI", + "preferred_subfamily_name": "ExtraCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansSinhalaUI-ExtraCondensedBlack.ttf||338432:1655828711.0": { + "family_name": "Noto Sans Sinhala UI ExtraCondensed Black", + "font-family": "Noto Sans Sinhala UI ExtraCondensed Black", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Sinhala UI ExtraCondensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansSinhalaUI-ExtraCondensedBlack.ttf", + "preferred_family_name": "Noto Sans Sinhala UI", + "preferred_subfamily_name": "ExtraCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansSinhalaUI-ExtraCondensedBold.ttf||361896:1655828711.0": { + "family_name": "Noto Sans Sinhala UI ExtraCondensed", + "font-family": "Noto Sans Sinhala UI ExtraCondensed", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Sinhala UI ExtraCondensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansSinhalaUI-ExtraCondensedBold.ttf", + "preferred_family_name": "Noto Sans Sinhala UI", + "preferred_subfamily_name": "ExtraCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansSinhalaUI-ExtraCondensedExtraBold.ttf||341908:1655828711.0": { + "family_name": "Noto Sans Sinhala UI ExtraCondensed ExtraBold", + "font-family": "Noto Sans Sinhala UI ExtraCondensed ExtraBold", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Sinhala UI ExtraCondensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansSinhalaUI-ExtraCondensedExtraBold.ttf", + "preferred_family_name": "Noto Sans Sinhala UI", + "preferred_subfamily_name": "ExtraCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansSinhalaUI-ExtraCondensedExtraLight.ttf||280984:1655828711.0": { + "family_name": "Noto Sans Sinhala UI ExtraCondensed ExtraLight", + "font-family": "Noto Sans Sinhala UI ExtraCondensed ExtraLight", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Sinhala UI ExtraCondensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansSinhalaUI-ExtraCondensedExtraLight.ttf", + "preferred_family_name": "Noto Sans Sinhala UI", + "preferred_subfamily_name": "ExtraCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansSinhalaUI-ExtraCondensedLight.ttf||318212:1655828711.0": { + "family_name": "Noto Sans Sinhala UI ExtraCondensed Light", + "font-family": "Noto Sans Sinhala UI ExtraCondensed Light", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Sinhala UI ExtraCondensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansSinhalaUI-ExtraCondensedLight.ttf", + "preferred_family_name": "Noto Sans Sinhala UI", + "preferred_subfamily_name": "ExtraCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansSinhalaUI-ExtraCondensedMedium.ttf||317940:1655828711.0": { + "family_name": "Noto Sans Sinhala UI ExtraCondensed Medium", + "font-family": "Noto Sans Sinhala UI ExtraCondensed Medium", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Sinhala UI ExtraCondensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansSinhalaUI-ExtraCondensedMedium.ttf", + "preferred_family_name": "Noto Sans Sinhala UI", + "preferred_subfamily_name": "ExtraCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansSinhalaUI-ExtraCondensedSemiBold.ttf||347740:1655828711.0": { + "family_name": "Noto Sans Sinhala UI ExtraCondensed SemiBold", + "font-family": "Noto Sans Sinhala UI ExtraCondensed SemiBold", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Sinhala UI ExtraCondensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansSinhalaUI-ExtraCondensedSemiBold.ttf", + "preferred_family_name": "Noto Sans Sinhala UI", + "preferred_subfamily_name": "ExtraCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansSinhalaUI-ExtraCondensedThin.ttf||282144:1655828711.0": { + "family_name": "Noto Sans Sinhala UI ExtraCondensed Thin", + "font-family": "Noto Sans Sinhala UI ExtraCondensed Thin", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Sinhala UI ExtraCondensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansSinhalaUI-ExtraCondensedThin.ttf", + "preferred_family_name": "Noto Sans Sinhala UI", + "preferred_subfamily_name": "ExtraCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansSinhalaUI-ExtraLight.ttf||294532:1655828711.0": { + "family_name": "Noto Sans Sinhala UI ExtraLight", + "font-family": "Noto Sans Sinhala UI ExtraLight", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Sinhala UI ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansSinhalaUI-ExtraLight.ttf", + "preferred_family_name": "Noto Sans Sinhala UI", + "preferred_subfamily_name": "ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansSinhalaUI-Light.ttf||326120:1655828711.0": { + "family_name": "Noto Sans Sinhala UI Light", + "font-family": "Noto Sans Sinhala UI Light", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Sinhala UI Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansSinhalaUI-Light.ttf", + "preferred_family_name": "Noto Sans Sinhala UI", + "preferred_subfamily_name": "Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansSinhalaUI-Medium.ttf||315584:1655828711.0": { + "family_name": "Noto Sans Sinhala UI Medium", + "font-family": "Noto Sans Sinhala UI Medium", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Sinhala UI Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansSinhalaUI-Medium.ttf", + "preferred_family_name": "Noto Sans Sinhala UI", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansSinhalaUI-Regular.ttf||310252:1655828711.0": { + "family_name": "Noto Sans Sinhala UI", + "font-family": "Noto Sans Sinhala UI", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Sinhala UI Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansSinhalaUI-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansSinhalaUI-SemiBold.ttf||338376:1655828711.0": { + "family_name": "Noto Sans Sinhala UI SemiBold", + "font-family": "Noto Sans Sinhala UI SemiBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Sinhala UI SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansSinhalaUI-SemiBold.ttf", + "preferred_family_name": "Noto Sans Sinhala UI", + "preferred_subfamily_name": "SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansSinhalaUI-SemiCondensed.ttf||310808:1655828711.0": { + "family_name": "Noto Sans Sinhala UI SemiCondensed", + "font-family": "Noto Sans Sinhala UI SemiCondensed", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Sinhala UI SemiCondensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansSinhalaUI-SemiCondensed.ttf", + "preferred_family_name": "Noto Sans Sinhala UI", + "preferred_subfamily_name": "SemiCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansSinhalaUI-SemiCondensedBlack.ttf||355404:1655828711.0": { + "family_name": "Noto Sans Sinhala UI SemiCondensed Black", + "font-family": "Noto Sans Sinhala UI SemiCondensed Black", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Sinhala UI SemiCondensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansSinhalaUI-SemiCondensedBlack.ttf", + "preferred_family_name": "Noto Sans Sinhala UI", + "preferred_subfamily_name": "SemiCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansSinhalaUI-SemiCondensedBold.ttf||348392:1655828711.0": { + "family_name": "Noto Sans Sinhala UI SemiCondensed", + "font-family": "Noto Sans Sinhala UI SemiCondensed", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Sinhala UI SemiCondensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansSinhalaUI-SemiCondensedBold.ttf", + "preferred_family_name": "Noto Sans Sinhala UI", + "preferred_subfamily_name": "SemiCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansSinhalaUI-SemiCondensedExtraBold.ttf||342036:1655828711.0": { + "family_name": "Noto Sans Sinhala UI SemiCondensed ExtraBold", + "font-family": "Noto Sans Sinhala UI SemiCondensed ExtraBold", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Sinhala UI SemiCondensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansSinhalaUI-SemiCondensedExtraBold.ttf", + "preferred_family_name": "Noto Sans Sinhala UI", + "preferred_subfamily_name": "SemiCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansSinhalaUI-SemiCondensedExtraLight.ttf||294868:1655828711.0": { + "family_name": "Noto Sans Sinhala UI SemiCondensed ExtraLight", + "font-family": "Noto Sans Sinhala UI SemiCondensed ExtraLight", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Sinhala UI SemiCondensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansSinhalaUI-SemiCondensedExtraLight.ttf", + "preferred_family_name": "Noto Sans Sinhala UI", + "preferred_subfamily_name": "SemiCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansSinhalaUI-SemiCondensedLight.ttf||325816:1655828711.0": { + "family_name": "Noto Sans Sinhala UI SemiCondensed Light", + "font-family": "Noto Sans Sinhala UI SemiCondensed Light", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Sinhala UI SemiCondensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansSinhalaUI-SemiCondensedLight.ttf", + "preferred_family_name": "Noto Sans Sinhala UI", + "preferred_subfamily_name": "SemiCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansSinhalaUI-SemiCondensedMedium.ttf||317348:1655828711.0": { + "family_name": "Noto Sans Sinhala UI SemiCondensed Medium", + "font-family": "Noto Sans Sinhala UI SemiCondensed Medium", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Sinhala UI SemiCondensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansSinhalaUI-SemiCondensedMedium.ttf", + "preferred_family_name": "Noto Sans Sinhala UI", + "preferred_subfamily_name": "SemiCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansSinhalaUI-SemiCondensedSemiBold.ttf||344700:1655828711.0": { + "family_name": "Noto Sans Sinhala UI SemiCondensed SemiBold", + "font-family": "Noto Sans Sinhala UI SemiCondensed SemiBold", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Sinhala UI SemiCondensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansSinhalaUI-SemiCondensedSemiBold.ttf", + "preferred_family_name": "Noto Sans Sinhala UI", + "preferred_subfamily_name": "SemiCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansSinhalaUI-SemiCondensedThin.ttf||285564:1655828711.0": { + "family_name": "Noto Sans Sinhala UI SemiCondensed Thin", + "font-family": "Noto Sans Sinhala UI SemiCondensed Thin", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Sinhala UI SemiCondensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansSinhalaUI-SemiCondensedThin.ttf", + "preferred_family_name": "Noto Sans Sinhala UI", + "preferred_subfamily_name": "SemiCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansSinhalaUI-Thin.ttf||288720:1655828711.0": { + "family_name": "Noto Sans Sinhala UI Thin", + "font-family": "Noto Sans Sinhala UI Thin", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Sinhala UI Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansSinhalaUI-Thin.ttf", + "preferred_family_name": "Noto Sans Sinhala UI", + "preferred_subfamily_name": "Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansSogdian-Regular.ttf||101656:1655828711.0": { + "family_name": "Noto Sans Sogdian", + "font-family": "Noto Sans Sogdian", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Sogdian Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansSogdian-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansSoraSompeng-Bold.ttf||8324:1655828711.0": { + "family_name": "Noto Sans Sora Sompeng", + "font-family": "Noto Sans Sora Sompeng", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Sora Sompeng Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansSoraSompeng-Bold.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansSoraSompeng-Medium.ttf||8184:1655828711.0": { + "family_name": "Noto Sans Sora Sompeng Medium", + "font-family": "Noto Sans Sora Sompeng Medium", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Sora Sompeng Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansSoraSompeng-Medium.ttf", + "preferred_family_name": "Noto Sans Sora Sompeng", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansSoraSompeng-Regular.ttf||8164:1655828711.0": { + "family_name": "Noto Sans Sora Sompeng", + "font-family": "Noto Sans Sora Sompeng", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Sora Sompeng Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansSoraSompeng-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansSoraSompeng-SemiBold.ttf||8260:1655828711.0": { + "family_name": "Noto Sans Sora Sompeng Semi Bold", + "font-family": "Noto Sans Sora Sompeng Semi Bold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Sora Sompeng Semi Bold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansSoraSompeng-SemiBold.ttf", + "preferred_family_name": "Noto Sans Sora Sompeng", + "preferred_subfamily_name": "Semi Bold", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansSoyombo-Regular.ttf||67080:1655828711.0": { + "family_name": "Noto Sans Soyombo", + "font-family": "Noto Sans Soyombo", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Soyombo Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansSoyombo-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansSundanese-Bold.ttf||22968:1655828711.0": { + "family_name": "Noto Sans Sundanese", + "font-family": "Noto Sans Sundanese", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Sundanese Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansSundanese-Bold.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansSundanese-Medium.ttf||22656:1655828711.0": { + "family_name": "Noto Sans Sundanese", + "font-family": "Noto Sans Sundanese", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Sundanese Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansSundanese-Medium.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansSundanese-Regular.ttf||22896:1655828711.0": { + "family_name": "Noto Sans Sundanese", + "font-family": "Noto Sans Sundanese", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Sundanese Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansSundanese-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansSundanese-SemiBold.ttf||24296:1655828711.0": { + "family_name": "Noto Sans Sundanese", + "font-family": "Noto Sans Sundanese", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Sundanese SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansSundanese-SemiBold.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": "SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansSylotiNagri-Regular.ttf||16600:1655828711.0": { + "family_name": "Noto Sans Syloti Nagri", + "font-family": "Noto Sans Syloti Nagri", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Syloti Nagri Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansSylotiNagri-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansSymbols-Black.ttf||267196:1655828711.0": { + "family_name": "Noto Sans Symbols Black", + "font-family": "Noto Sans Symbols Black", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Symbols Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansSymbols-Black.ttf", + "preferred_family_name": "Noto Sans Symbols", + "preferred_subfamily_name": "Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansSymbols-Bold.ttf||258920:1655828711.0": { + "family_name": "Noto Sans Symbols", + "font-family": "Noto Sans Symbols", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Symbols Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansSymbols-Bold.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansSymbols-ExtraBold.ttf||260668:1655828711.0": { + "family_name": "Noto Sans Symbols ExtraBold", + "font-family": "Noto Sans Symbols ExtraBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Symbols ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansSymbols-ExtraBold.ttf", + "preferred_family_name": "Noto Sans Symbols", + "preferred_subfamily_name": "ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansSymbols-ExtraLight.ttf||263596:1655828711.0": { + "family_name": "Noto Sans Symbols ExtraLight", + "font-family": "Noto Sans Symbols ExtraLight", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Symbols ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansSymbols-ExtraLight.ttf", + "preferred_family_name": "Noto Sans Symbols", + "preferred_subfamily_name": "ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansSymbols-Light.ttf||259936:1655828711.0": { + "family_name": "Noto Sans Symbols Light", + "font-family": "Noto Sans Symbols Light", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Symbols Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansSymbols-Light.ttf", + "preferred_family_name": "Noto Sans Symbols", + "preferred_subfamily_name": "Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansSymbols-Medium.ttf||258628:1655828711.0": { + "family_name": "Noto Sans Symbols Medium", + "font-family": "Noto Sans Symbols Medium", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Symbols Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansSymbols-Medium.ttf", + "preferred_family_name": "Noto Sans Symbols", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansSymbols-Regular.ttf||258156:1655828711.0": { + "family_name": "Noto Sans Symbols", + "font-family": "Noto Sans Symbols", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Symbols Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansSymbols-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansSymbols-SemiBold.ttf||259292:1655828711.0": { + "family_name": "Noto Sans Symbols SemiBold", + "font-family": "Noto Sans Symbols SemiBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Symbols SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansSymbols-SemiBold.ttf", + "preferred_family_name": "Noto Sans Symbols", + "preferred_subfamily_name": "SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansSymbols-Thin.ttf||262460:1655828711.0": { + "family_name": "Noto Sans Symbols Thin", + "font-family": "Noto Sans Symbols Thin", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Symbols Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansSymbols-Thin.ttf", + "preferred_family_name": "Noto Sans Symbols", + "preferred_subfamily_name": "Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansSymbols2-Regular.ttf||656852:1655828711.0": { + "family_name": "Noto Sans Symbols2", + "font-family": "Noto Sans Symbols2", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Symbols2 Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansSymbols2-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansSyriac-Black.ttf||237712:1655828711.0": { + "family_name": "Noto Sans Syriac Black", + "font-family": "Noto Sans Syriac Black", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Syriac Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansSyriac-Black.ttf", + "preferred_family_name": "Noto Sans Syriac", + "preferred_subfamily_name": "Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansSyriac-Regular.ttf||233516:1655828711.0": { + "family_name": "Noto Sans Syriac", + "font-family": "Noto Sans Syriac", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Syriac Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansSyriac-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansSyriac-Thin.ttf||234348:1655828711.0": { + "family_name": "Noto Sans Syriac Thin", + "font-family": "Noto Sans Syriac Thin", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Syriac Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansSyriac-Thin.ttf", + "preferred_family_name": "Noto Sans Syriac", + "preferred_subfamily_name": "Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTagalog-Regular.ttf||6564:1655828711.0": { + "family_name": "Noto Sans Tagalog", + "font-family": "Noto Sans Tagalog", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Tagalog Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTagalog-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTagbanwa-Regular.ttf||6224:1655828711.0": { + "family_name": "Noto Sans Tagbanwa", + "font-family": "Noto Sans Tagbanwa", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Tagbanwa Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTagbanwa-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTaiLe-Regular.ttf||19944:1655828711.0": { + "family_name": "Noto Sans Tai Le", + "font-family": "Noto Sans Tai Le", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Tai Le Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTaiLe-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTaiTham-Bold.ttf||94600:1655828711.0": { + "family_name": "Noto Sans Tai Tham", + "font-family": "Noto Sans Tai Tham", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Tai Tham Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 3, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTaiTham-Bold.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTaiTham-Medium.ttf||94924:1655828711.0": { + "family_name": "Noto Sans Tai Tham Medium", + "font-family": "Noto Sans Tai Tham Medium", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "482", + "fs_type": 0, + "full_name": "Noto Sans Tai Tham Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 3, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTaiTham-Medium.ttf", + "preferred_family_name": "Noto Sans Tai Tham", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 482, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTaiTham-Regular.ttf||95024:1655828711.0": { + "family_name": "Noto Sans Tai Tham", + "font-family": "Noto Sans Tai Tham", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Tai Tham Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 3, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTaiTham-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTaiTham-SemiBold.ttf||94752:1655828711.0": { + "family_name": "Noto Sans Tai Tham SemiBold", + "font-family": "Noto Sans Tai Tham SemiBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "586", + "fs_type": 0, + "full_name": "Noto Sans Tai Tham SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 3, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTaiTham-SemiBold.ttf", + "preferred_family_name": "Noto Sans Tai Tham", + "preferred_subfamily_name": "SemiBold", + "subfamily_name": "Regular", + "weight": 586, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTaiViet-Regular.ttf||30456:1655828711.0": { + "family_name": "Noto Sans Tai Viet", + "font-family": "Noto Sans Tai Viet", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Tai Viet Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTaiViet-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTakri-Regular.ttf||18516:1655828711.0": { + "family_name": "Noto Sans Takri", + "font-family": "Noto Sans Takri", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Takri Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTakri-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTamil-Black.ttf||76596:1655828711.0": { + "family_name": "Noto Sans Tamil Black", + "font-family": "Noto Sans Tamil Black", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Tamil Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTamil-Black.ttf", + "preferred_family_name": "Noto Sans Tamil", + "preferred_subfamily_name": "Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTamil-Bold.ttf||77428:1655828711.0": { + "family_name": "Noto Sans Tamil", + "font-family": "Noto Sans Tamil", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Tamil Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTamil-Bold.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTamil-Condensed.ttf||88296:1655828711.0": { + "family_name": "Noto Sans Tamil Condensed", + "font-family": "Noto Sans Tamil Condensed", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Tamil Condensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTamil-Condensed.ttf", + "preferred_family_name": "Noto Sans Tamil", + "preferred_subfamily_name": "Condensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTamil-CondensedBlack.ttf||78180:1655828711.0": { + "family_name": "Noto Sans Tamil Condensed Black", + "font-family": "Noto Sans Tamil Condensed Black", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Tamil Condensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTamil-CondensedBlack.ttf", + "preferred_family_name": "Noto Sans Tamil", + "preferred_subfamily_name": "Condensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTamil-CondensedBold.ttf||77544:1655828711.0": { + "family_name": "Noto Sans Tamil Condensed", + "font-family": "Noto Sans Tamil Condensed", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Tamil Condensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTamil-CondensedBold.ttf", + "preferred_family_name": "Noto Sans Tamil", + "preferred_subfamily_name": "Condensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTamil-CondensedExtraBold.ttf||78856:1655828711.0": { + "family_name": "Noto Sans Tamil Condensed ExtraBold", + "font-family": "Noto Sans Tamil Condensed ExtraBold", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Tamil Condensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTamil-CondensedExtraBold.ttf", + "preferred_family_name": "Noto Sans Tamil", + "preferred_subfamily_name": "Condensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTamil-CondensedExtraLight.ttf||65960:1655828711.0": { + "family_name": "Noto Sans Tamil Condensed ExtraLight", + "font-family": "Noto Sans Tamil Condensed ExtraLight", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Tamil Condensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTamil-CondensedExtraLight.ttf", + "preferred_family_name": "Noto Sans Tamil", + "preferred_subfamily_name": "Condensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTamil-CondensedLight.ttf||66144:1655828711.0": { + "family_name": "Noto Sans Tamil Condensed Light", + "font-family": "Noto Sans Tamil Condensed Light", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Tamil Condensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTamil-CondensedLight.ttf", + "preferred_family_name": "Noto Sans Tamil", + "preferred_subfamily_name": "Condensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTamil-CondensedMedium.ttf||74592:1655828711.0": { + "family_name": "Noto Sans Tamil Condensed Medium", + "font-family": "Noto Sans Tamil Condensed Medium", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Tamil Condensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTamil-CondensedMedium.ttf", + "preferred_family_name": "Noto Sans Tamil", + "preferred_subfamily_name": "Condensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTamil-CondensedSemiBold.ttf||77808:1655828711.0": { + "family_name": "Noto Sans Tamil Condensed SemiBold", + "font-family": "Noto Sans Tamil Condensed SemiBold", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Tamil Condensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTamil-CondensedSemiBold.ttf", + "preferred_family_name": "Noto Sans Tamil", + "preferred_subfamily_name": "Condensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTamil-CondensedThin.ttf||66008:1655828711.0": { + "family_name": "Noto Sans Tamil Condensed Thin", + "font-family": "Noto Sans Tamil Condensed Thin", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Tamil Condensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTamil-CondensedThin.ttf", + "preferred_family_name": "Noto Sans Tamil", + "preferred_subfamily_name": "Condensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTamil-ExtraBold.ttf||77976:1655828711.0": { + "family_name": "Noto Sans Tamil ExtraBold", + "font-family": "Noto Sans Tamil ExtraBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Tamil ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTamil-ExtraBold.ttf", + "preferred_family_name": "Noto Sans Tamil", + "preferred_subfamily_name": "ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTamil-ExtraCondensed.ttf||88180:1655828711.0": { + "family_name": "Noto Sans Tamil ExtraCondensed", + "font-family": "Noto Sans Tamil ExtraCondensed", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Tamil ExtraCondensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTamil-ExtraCondensed.ttf", + "preferred_family_name": "Noto Sans Tamil", + "preferred_subfamily_name": "ExtraCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTamil-ExtraCondensedBlack.ttf||78872:1655828711.0": { + "family_name": "Noto Sans Tamil ExtraCondensed Black", + "font-family": "Noto Sans Tamil ExtraCondensed Black", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Tamil ExtraCondensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTamil-ExtraCondensedBlack.ttf", + "preferred_family_name": "Noto Sans Tamil", + "preferred_subfamily_name": "ExtraCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTamil-ExtraCondensedBold.ttf||76628:1655828711.0": { + "family_name": "Noto Sans Tamil ExtraCondensed", + "font-family": "Noto Sans Tamil ExtraCondensed", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Tamil ExtraCondensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTamil-ExtraCondensedBold.ttf", + "preferred_family_name": "Noto Sans Tamil", + "preferred_subfamily_name": "ExtraCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTamil-ExtraCondensedExtraBold.ttf||78040:1655828711.0": { + "family_name": "Noto Sans Tamil ExtraCondensed ExtraBold", + "font-family": "Noto Sans Tamil ExtraCondensed ExtraBold", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Tamil ExtraCondensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTamil-ExtraCondensedExtraBold.ttf", + "preferred_family_name": "Noto Sans Tamil", + "preferred_subfamily_name": "ExtraCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTamil-ExtraCondensedExtraLight.ttf||65920:1655828711.0": { + "family_name": "Noto Sans Tamil ExtraCondensed ExtraLight", + "font-family": "Noto Sans Tamil ExtraCondensed ExtraLight", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Tamil ExtraCondensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTamil-ExtraCondensedExtraLight.ttf", + "preferred_family_name": "Noto Sans Tamil", + "preferred_subfamily_name": "ExtraCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTamil-ExtraCondensedLight.ttf||66728:1655828711.0": { + "family_name": "Noto Sans Tamil ExtraCondensed Light", + "font-family": "Noto Sans Tamil ExtraCondensed Light", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Tamil ExtraCondensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTamil-ExtraCondensedLight.ttf", + "preferred_family_name": "Noto Sans Tamil", + "preferred_subfamily_name": "ExtraCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTamil-ExtraCondensedMedium.ttf||75072:1655828711.0": { + "family_name": "Noto Sans Tamil ExtraCondensed Medium", + "font-family": "Noto Sans Tamil ExtraCondensed Medium", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Tamil ExtraCondensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTamil-ExtraCondensedMedium.ttf", + "preferred_family_name": "Noto Sans Tamil", + "preferred_subfamily_name": "ExtraCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTamil-ExtraCondensedSemiBold.ttf||76444:1655828711.0": { + "family_name": "Noto Sans Tamil ExtraCondensed SemiBold", + "font-family": "Noto Sans Tamil ExtraCondensed SemiBold", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Tamil ExtraCondensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTamil-ExtraCondensedSemiBold.ttf", + "preferred_family_name": "Noto Sans Tamil", + "preferred_subfamily_name": "ExtraCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTamil-ExtraCondensedThin.ttf||65660:1655828711.0": { + "family_name": "Noto Sans Tamil ExtraCondensed Thin", + "font-family": "Noto Sans Tamil ExtraCondensed Thin", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Tamil ExtraCondensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTamil-ExtraCondensedThin.ttf", + "preferred_family_name": "Noto Sans Tamil", + "preferred_subfamily_name": "ExtraCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTamil-ExtraLight.ttf||66220:1655828711.0": { + "family_name": "Noto Sans Tamil ExtraLight", + "font-family": "Noto Sans Tamil ExtraLight", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Tamil ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTamil-ExtraLight.ttf", + "preferred_family_name": "Noto Sans Tamil", + "preferred_subfamily_name": "ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTamil-Light.ttf||66644:1655828711.0": { + "family_name": "Noto Sans Tamil Light", + "font-family": "Noto Sans Tamil Light", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Tamil Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTamil-Light.ttf", + "preferred_family_name": "Noto Sans Tamil", + "preferred_subfamily_name": "Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTamil-Medium.ttf||74420:1655828711.0": { + "family_name": "Noto Sans Tamil Medium", + "font-family": "Noto Sans Tamil Medium", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Tamil Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTamil-Medium.ttf", + "preferred_family_name": "Noto Sans Tamil", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTamil-Regular.ttf||74248:1655828711.0": { + "family_name": "Noto Sans Tamil", + "font-family": "Noto Sans Tamil", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Tamil Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTamil-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTamil-SemiBold.ttf||79088:1655828711.0": { + "family_name": "Noto Sans Tamil SemiBold", + "font-family": "Noto Sans Tamil SemiBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Tamil SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTamil-SemiBold.ttf", + "preferred_family_name": "Noto Sans Tamil", + "preferred_subfamily_name": "SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTamil-SemiCondensed.ttf||73828:1655828711.0": { + "family_name": "Noto Sans Tamil SemiCondensed", + "font-family": "Noto Sans Tamil SemiCondensed", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Tamil SemiCondensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTamil-SemiCondensed.ttf", + "preferred_family_name": "Noto Sans Tamil", + "preferred_subfamily_name": "SemiCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTamil-SemiCondensedBlack.ttf||77820:1655828711.0": { + "family_name": "Noto Sans Tamil SemiCondensed Black", + "font-family": "Noto Sans Tamil SemiCondensed Black", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Tamil SemiCondensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTamil-SemiCondensedBlack.ttf", + "preferred_family_name": "Noto Sans Tamil", + "preferred_subfamily_name": "SemiCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTamil-SemiCondensedBold.ttf||77608:1655828711.0": { + "family_name": "Noto Sans Tamil SemiCondensed", + "font-family": "Noto Sans Tamil SemiCondensed", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Tamil SemiCondensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTamil-SemiCondensedBold.ttf", + "preferred_family_name": "Noto Sans Tamil", + "preferred_subfamily_name": "SemiCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTamil-SemiCondensedExtraBold.ttf||77612:1655828711.0": { + "family_name": "Noto Sans Tamil SemiCondensed ExtraBold", + "font-family": "Noto Sans Tamil SemiCondensed ExtraBold", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Tamil SemiCondensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTamil-SemiCondensedExtraBold.ttf", + "preferred_family_name": "Noto Sans Tamil", + "preferred_subfamily_name": "SemiCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTamil-SemiCondensedExtraLight.ttf||66124:1655828711.0": { + "family_name": "Noto Sans Tamil SemiCondensed ExtraLight", + "font-family": "Noto Sans Tamil SemiCondensed ExtraLight", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Tamil SemiCondensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTamil-SemiCondensedExtraLight.ttf", + "preferred_family_name": "Noto Sans Tamil", + "preferred_subfamily_name": "SemiCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTamil-SemiCondensedLight.ttf||66352:1655828711.0": { + "family_name": "Noto Sans Tamil SemiCondensed Light", + "font-family": "Noto Sans Tamil SemiCondensed Light", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Tamil SemiCondensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTamil-SemiCondensedLight.ttf", + "preferred_family_name": "Noto Sans Tamil", + "preferred_subfamily_name": "SemiCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTamil-SemiCondensedMedium.ttf||74700:1655828711.0": { + "family_name": "Noto Sans Tamil SemiCondensed Medium", + "font-family": "Noto Sans Tamil SemiCondensed Medium", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Tamil SemiCondensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTamil-SemiCondensedMedium.ttf", + "preferred_family_name": "Noto Sans Tamil", + "preferred_subfamily_name": "SemiCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTamil-SemiCondensedSemiBold.ttf||77332:1655828711.0": { + "family_name": "Noto Sans Tamil SemiCondensed SemiBold", + "font-family": "Noto Sans Tamil SemiCondensed SemiBold", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Tamil SemiCondensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTamil-SemiCondensedSemiBold.ttf", + "preferred_family_name": "Noto Sans Tamil", + "preferred_subfamily_name": "SemiCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTamil-SemiCondensedThin.ttf||65980:1655828711.0": { + "family_name": "Noto Sans Tamil SemiCondensed Thin", + "font-family": "Noto Sans Tamil SemiCondensed Thin", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Tamil SemiCondensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTamil-SemiCondensedThin.ttf", + "preferred_family_name": "Noto Sans Tamil", + "preferred_subfamily_name": "SemiCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTamil-Thin.ttf||66532:1655828711.0": { + "family_name": "Noto Sans Tamil Thin", + "font-family": "Noto Sans Tamil Thin", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Tamil Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTamil-Thin.ttf", + "preferred_family_name": "Noto Sans Tamil", + "preferred_subfamily_name": "Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTamilSupplement-Regular.ttf||15780:1655828711.0": { + "family_name": "Noto Sans Tamil Supplement", + "font-family": "Noto Sans Tamil Supplement", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Tamil Supplement Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/noto/NotoSansTamilSupplement-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTamilUI-Black.ttf||76620:1655828711.0": { + "family_name": "Noto Sans Tamil UI Black", + "font-family": "Noto Sans Tamil UI Black", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Tamil UI Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTamilUI-Black.ttf", + "preferred_family_name": "Noto Sans Tamil UI", + "preferred_subfamily_name": "Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTamilUI-Bold.ttf||77448:1655828711.0": { + "family_name": "Noto Sans Tamil UI", + "font-family": "Noto Sans Tamil UI", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Tamil UI Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTamilUI-Bold.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTamilUI-Condensed.ttf||88320:1655828711.0": { + "family_name": "Noto Sans Tamil UI Condensed", + "font-family": "Noto Sans Tamil UI Condensed", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Tamil UI Condensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTamilUI-Condensed.ttf", + "preferred_family_name": "Noto Sans Tamil UI", + "preferred_subfamily_name": "Condensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTamilUI-CondensedBlack.ttf||78204:1655828711.0": { + "family_name": "Noto Sans Tamil UI Condensed Black", + "font-family": "Noto Sans Tamil UI Condensed Black", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Tamil UI Condensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTamilUI-CondensedBlack.ttf", + "preferred_family_name": "Noto Sans Tamil UI", + "preferred_subfamily_name": "Condensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTamilUI-CondensedBold.ttf||77572:1655828711.0": { + "family_name": "Noto Sans Tamil UI Condensed", + "font-family": "Noto Sans Tamil UI Condensed", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Tamil UI Condensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTamilUI-CondensedBold.ttf", + "preferred_family_name": "Noto Sans Tamil UI", + "preferred_subfamily_name": "Condensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTamilUI-CondensedExtraBold.ttf||78880:1655828711.0": { + "family_name": "Noto Sans Tamil UI Condensed ExtraBold", + "font-family": "Noto Sans Tamil UI Condensed ExtraBold", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Tamil UI Condensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTamilUI-CondensedExtraBold.ttf", + "preferred_family_name": "Noto Sans Tamil UI", + "preferred_subfamily_name": "Condensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTamilUI-CondensedExtraLight.ttf||65988:1655828711.0": { + "family_name": "Noto Sans Tamil UI Condensed ExtraLight", + "font-family": "Noto Sans Tamil UI Condensed ExtraLight", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Tamil UI Condensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTamilUI-CondensedExtraLight.ttf", + "preferred_family_name": "Noto Sans Tamil UI", + "preferred_subfamily_name": "Condensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTamilUI-CondensedLight.ttf||66168:1655828711.0": { + "family_name": "Noto Sans Tamil UI Condensed Light", + "font-family": "Noto Sans Tamil UI Condensed Light", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Tamil UI Condensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTamilUI-CondensedLight.ttf", + "preferred_family_name": "Noto Sans Tamil UI", + "preferred_subfamily_name": "Condensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTamilUI-CondensedMedium.ttf||74620:1655828711.0": { + "family_name": "Noto Sans Tamil UI Condensed Medium", + "font-family": "Noto Sans Tamil UI Condensed Medium", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Tamil UI Condensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTamilUI-CondensedMedium.ttf", + "preferred_family_name": "Noto Sans Tamil UI", + "preferred_subfamily_name": "Condensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTamilUI-CondensedSemiBold.ttf||77836:1655828711.0": { + "family_name": "Noto Sans Tamil UI Condensed SemiBold", + "font-family": "Noto Sans Tamil UI Condensed SemiBold", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Tamil UI Condensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTamilUI-CondensedSemiBold.ttf", + "preferred_family_name": "Noto Sans Tamil UI", + "preferred_subfamily_name": "Condensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTamilUI-CondensedThin.ttf||66036:1655828711.0": { + "family_name": "Noto Sans Tamil UI Condensed Thin", + "font-family": "Noto Sans Tamil UI Condensed Thin", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Tamil UI Condensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTamilUI-CondensedThin.ttf", + "preferred_family_name": "Noto Sans Tamil UI", + "preferred_subfamily_name": "Condensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTamilUI-ExtraBold.ttf||78000:1655828711.0": { + "family_name": "Noto Sans Tamil UI ExtraBold", + "font-family": "Noto Sans Tamil UI ExtraBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Tamil UI ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTamilUI-ExtraBold.ttf", + "preferred_family_name": "Noto Sans Tamil UI", + "preferred_subfamily_name": "ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTamilUI-ExtraCondensed.ttf||88208:1655828711.0": { + "family_name": "Noto Sans Tamil UI ExtraCondensed", + "font-family": "Noto Sans Tamil UI ExtraCondensed", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Tamil UI ExtraCondensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTamilUI-ExtraCondensed.ttf", + "preferred_family_name": "Noto Sans Tamil UI", + "preferred_subfamily_name": "ExtraCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTamilUI-ExtraCondensedBlack.ttf||78900:1655828711.0": { + "family_name": "Noto Sans Tamil UI ExtraCondensed Black", + "font-family": "Noto Sans Tamil UI ExtraCondensed Black", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Tamil UI ExtraCondensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTamilUI-ExtraCondensedBlack.ttf", + "preferred_family_name": "Noto Sans Tamil UI", + "preferred_subfamily_name": "ExtraCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTamilUI-ExtraCondensedBold.ttf||76652:1655828711.0": { + "family_name": "Noto Sans Tamil UI ExtraCondensed", + "font-family": "Noto Sans Tamil UI ExtraCondensed", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Tamil UI ExtraCondensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTamilUI-ExtraCondensedBold.ttf", + "preferred_family_name": "Noto Sans Tamil UI", + "preferred_subfamily_name": "ExtraCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTamilUI-ExtraCondensedExtraBold.ttf||78068:1655828711.0": { + "family_name": "Noto Sans Tamil UI ExtraCondensed ExtraBold", + "font-family": "Noto Sans Tamil UI ExtraCondensed ExtraBold", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Tamil UI ExtraCondensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTamilUI-ExtraCondensedExtraBold.ttf", + "preferred_family_name": "Noto Sans Tamil UI", + "preferred_subfamily_name": "ExtraCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTamilUI-ExtraCondensedExtraLight.ttf||65944:1655828711.0": { + "family_name": "Noto Sans Tamil UI ExtraCondensed ExtraLight", + "font-family": "Noto Sans Tamil UI ExtraCondensed ExtraLight", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Tamil UI ExtraCondensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTamilUI-ExtraCondensedExtraLight.ttf", + "preferred_family_name": "Noto Sans Tamil UI", + "preferred_subfamily_name": "ExtraCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTamilUI-ExtraCondensedLight.ttf||66756:1655828711.0": { + "family_name": "Noto Sans Tamil UI ExtraCondensed Light", + "font-family": "Noto Sans Tamil UI ExtraCondensed Light", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Tamil UI ExtraCondensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTamilUI-ExtraCondensedLight.ttf", + "preferred_family_name": "Noto Sans Tamil UI", + "preferred_subfamily_name": "ExtraCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTamilUI-ExtraCondensedMedium.ttf||75096:1655828711.0": { + "family_name": "Noto Sans Tamil UI ExtraCondensed Medium", + "font-family": "Noto Sans Tamil UI ExtraCondensed Medium", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Tamil UI ExtraCondensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTamilUI-ExtraCondensedMedium.ttf", + "preferred_family_name": "Noto Sans Tamil UI", + "preferred_subfamily_name": "ExtraCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTamilUI-ExtraCondensedSemiBold.ttf||76468:1655828711.0": { + "family_name": "Noto Sans Tamil UI ExtraCondensed SemiBold", + "font-family": "Noto Sans Tamil UI ExtraCondensed SemiBold", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Tamil UI ExtraCondensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTamilUI-ExtraCondensedSemiBold.ttf", + "preferred_family_name": "Noto Sans Tamil UI", + "preferred_subfamily_name": "ExtraCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTamilUI-ExtraCondensedThin.ttf||65684:1655828711.0": { + "family_name": "Noto Sans Tamil UI ExtraCondensed Thin", + "font-family": "Noto Sans Tamil UI ExtraCondensed Thin", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Tamil UI ExtraCondensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTamilUI-ExtraCondensedThin.ttf", + "preferred_family_name": "Noto Sans Tamil UI", + "preferred_subfamily_name": "ExtraCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTamilUI-ExtraLight.ttf||66248:1655828711.0": { + "family_name": "Noto Sans Tamil UI ExtraLight", + "font-family": "Noto Sans Tamil UI ExtraLight", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Tamil UI ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTamilUI-ExtraLight.ttf", + "preferred_family_name": "Noto Sans Tamil UI", + "preferred_subfamily_name": "ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTamilUI-Light.ttf||66668:1655828711.0": { + "family_name": "Noto Sans Tamil UI Light", + "font-family": "Noto Sans Tamil UI Light", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Tamil UI Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTamilUI-Light.ttf", + "preferred_family_name": "Noto Sans Tamil UI", + "preferred_subfamily_name": "Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTamilUI-Medium.ttf||74448:1655828711.0": { + "family_name": "Noto Sans Tamil UI Medium", + "font-family": "Noto Sans Tamil UI Medium", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Tamil UI Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTamilUI-Medium.ttf", + "preferred_family_name": "Noto Sans Tamil UI", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTamilUI-Regular.ttf||74268:1655828711.0": { + "family_name": "Noto Sans Tamil UI", + "font-family": "Noto Sans Tamil UI", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Tamil UI Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTamilUI-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTamilUI-SemiBold.ttf||79116:1655828711.0": { + "family_name": "Noto Sans Tamil UI SemiBold", + "font-family": "Noto Sans Tamil UI SemiBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Tamil UI SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTamilUI-SemiBold.ttf", + "preferred_family_name": "Noto Sans Tamil UI", + "preferred_subfamily_name": "SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTamilUI-SemiCondensed.ttf||73852:1655828711.0": { + "family_name": "Noto Sans Tamil UI SemiCondensed", + "font-family": "Noto Sans Tamil UI SemiCondensed", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Tamil UI SemiCondensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTamilUI-SemiCondensed.ttf", + "preferred_family_name": "Noto Sans Tamil UI", + "preferred_subfamily_name": "SemiCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTamilUI-SemiCondensedBlack.ttf||77844:1655828711.0": { + "family_name": "Noto Sans Tamil UI SemiCondensed Black", + "font-family": "Noto Sans Tamil UI SemiCondensed Black", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Tamil UI SemiCondensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTamilUI-SemiCondensedBlack.ttf", + "preferred_family_name": "Noto Sans Tamil UI", + "preferred_subfamily_name": "SemiCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTamilUI-SemiCondensedBold.ttf||77636:1655828711.0": { + "family_name": "Noto Sans Tamil UI SemiCondensed", + "font-family": "Noto Sans Tamil UI SemiCondensed", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Tamil UI SemiCondensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTamilUI-SemiCondensedBold.ttf", + "preferred_family_name": "Noto Sans Tamil UI", + "preferred_subfamily_name": "SemiCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTamilUI-SemiCondensedExtraBold.ttf||77636:1655828711.0": { + "family_name": "Noto Sans Tamil UI SemiCondensed ExtraBold", + "font-family": "Noto Sans Tamil UI SemiCondensed ExtraBold", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Tamil UI SemiCondensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTamilUI-SemiCondensedExtraBold.ttf", + "preferred_family_name": "Noto Sans Tamil UI", + "preferred_subfamily_name": "SemiCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTamilUI-SemiCondensedExtraLight.ttf||66152:1655828711.0": { + "family_name": "Noto Sans Tamil UI SemiCondensed ExtraLight", + "font-family": "Noto Sans Tamil UI SemiCondensed ExtraLight", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Tamil UI SemiCondensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTamilUI-SemiCondensedExtraLight.ttf", + "preferred_family_name": "Noto Sans Tamil UI", + "preferred_subfamily_name": "SemiCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTamilUI-SemiCondensedLight.ttf||66376:1655828711.0": { + "family_name": "Noto Sans Tamil UI SemiCondensed Light", + "font-family": "Noto Sans Tamil UI SemiCondensed Light", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Tamil UI SemiCondensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTamilUI-SemiCondensedLight.ttf", + "preferred_family_name": "Noto Sans Tamil UI", + "preferred_subfamily_name": "SemiCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTamilUI-SemiCondensedMedium.ttf||74728:1655828711.0": { + "family_name": "Noto Sans Tamil UI SemiCondensed Medium", + "font-family": "Noto Sans Tamil UI SemiCondensed Medium", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Tamil UI SemiCondensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTamilUI-SemiCondensedMedium.ttf", + "preferred_family_name": "Noto Sans Tamil UI", + "preferred_subfamily_name": "SemiCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTamilUI-SemiCondensedSemiBold.ttf||77360:1655828711.0": { + "family_name": "Noto Sans Tamil UI SemiCondensed SemiBold", + "font-family": "Noto Sans Tamil UI SemiCondensed SemiBold", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Tamil UI SemiCondensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTamilUI-SemiCondensedSemiBold.ttf", + "preferred_family_name": "Noto Sans Tamil UI", + "preferred_subfamily_name": "SemiCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTamilUI-SemiCondensedThin.ttf||66008:1655828711.0": { + "family_name": "Noto Sans Tamil UI SemiCondensed Thin", + "font-family": "Noto Sans Tamil UI SemiCondensed Thin", + "font-stretch": "ultra-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Tamil UI SemiCondensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTamilUI-SemiCondensedThin.ttf", + "preferred_family_name": "Noto Sans Tamil UI", + "preferred_subfamily_name": "SemiCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 1, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTamilUI-Thin.ttf||66560:1655828711.0": { + "family_name": "Noto Sans Tamil UI Thin", + "font-family": "Noto Sans Tamil UI Thin", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Tamil UI Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTamilUI-Thin.ttf", + "preferred_family_name": "Noto Sans Tamil UI", + "preferred_subfamily_name": "Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTangsa-Bold.ttf||21476:1655828711.0": { + "family_name": "Noto Sans Tangsa", + "font-family": "Noto Sans Tangsa", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Tangsa Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTangsa-Bold.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTangsa-Medium.ttf||23952:1655828711.0": { + "family_name": "Noto Sans Tangsa Medium", + "font-family": "Noto Sans Tangsa Medium", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Tangsa Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTangsa-Medium.ttf", + "preferred_family_name": "Noto Sans Tangsa", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTangsa-Regular.ttf||22992:1655828711.0": { + "family_name": "Noto Sans Tangsa", + "font-family": "Noto Sans Tangsa", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Tangsa Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTangsa-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTangsa-SemiBold.ttf||23900:1655828711.0": { + "family_name": "Noto Sans Tangsa SemiBold", + "font-family": "Noto Sans Tangsa SemiBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Tangsa SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTangsa-SemiBold.ttf", + "preferred_family_name": "Noto Sans Tangsa", + "preferred_subfamily_name": "SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTelugu-Black.ttf||206996:1655828711.0": { + "family_name": "Noto Sans Telugu Black", + "font-family": "Noto Sans Telugu Black", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Telugu Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTelugu-Black.ttf", + "preferred_family_name": "Noto Sans Telugu", + "preferred_subfamily_name": "Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTelugu-Bold.ttf||205304:1655828711.0": { + "family_name": "Noto Sans Telugu", + "font-family": "Noto Sans Telugu", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Telugu Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTelugu-Bold.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTelugu-Condensed.ttf||191412:1655828711.0": { + "family_name": "Noto Sans Telugu Condensed", + "font-family": "Noto Sans Telugu Condensed", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Telugu Condensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTelugu-Condensed.ttf", + "preferred_family_name": "Noto Sans Telugu", + "preferred_subfamily_name": "Condensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTelugu-CondensedBlack.ttf||206608:1655828711.0": { + "family_name": "Noto Sans Telugu Condensed Black", + "font-family": "Noto Sans Telugu Condensed Black", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Telugu Condensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTelugu-CondensedBlack.ttf", + "preferred_family_name": "Noto Sans Telugu", + "preferred_subfamily_name": "Condensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTelugu-CondensedBold.ttf||204080:1655828711.0": { + "family_name": "Noto Sans Telugu Condensed", + "font-family": "Noto Sans Telugu Condensed", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Telugu Condensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTelugu-CondensedBold.ttf", + "preferred_family_name": "Noto Sans Telugu", + "preferred_subfamily_name": "Condensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTelugu-CondensedExtraBold.ttf||204660:1655828711.0": { + "family_name": "Noto Sans Telugu Condensed ExtraBold", + "font-family": "Noto Sans Telugu Condensed ExtraBold", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Telugu Condensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTelugu-CondensedExtraBold.ttf", + "preferred_family_name": "Noto Sans Telugu", + "preferred_subfamily_name": "Condensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTelugu-CondensedExtraLight.ttf||183920:1655828711.0": { + "family_name": "Noto Sans Telugu Condensed ExtraLight", + "font-family": "Noto Sans Telugu Condensed ExtraLight", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Telugu Condensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTelugu-CondensedExtraLight.ttf", + "preferred_family_name": "Noto Sans Telugu", + "preferred_subfamily_name": "Condensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTelugu-CondensedLight.ttf||190740:1655828711.0": { + "family_name": "Noto Sans Telugu Condensed Light", + "font-family": "Noto Sans Telugu Condensed Light", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Telugu Condensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTelugu-CondensedLight.ttf", + "preferred_family_name": "Noto Sans Telugu", + "preferred_subfamily_name": "Condensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTelugu-CondensedMedium.ttf||201244:1655828711.0": { + "family_name": "Noto Sans Telugu Condensed Medium", + "font-family": "Noto Sans Telugu Condensed Medium", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Telugu Condensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTelugu-CondensedMedium.ttf", + "preferred_family_name": "Noto Sans Telugu", + "preferred_subfamily_name": "Condensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTelugu-CondensedSemiBold.ttf||203436:1655828711.0": { + "family_name": "Noto Sans Telugu Condensed SemiBold", + "font-family": "Noto Sans Telugu Condensed SemiBold", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Telugu Condensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTelugu-CondensedSemiBold.ttf", + "preferred_family_name": "Noto Sans Telugu", + "preferred_subfamily_name": "Condensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTelugu-CondensedThin.ttf||192500:1655828711.0": { + "family_name": "Noto Sans Telugu Condensed Thin", + "font-family": "Noto Sans Telugu Condensed Thin", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Telugu Condensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTelugu-CondensedThin.ttf", + "preferred_family_name": "Noto Sans Telugu", + "preferred_subfamily_name": "Condensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTelugu-ExtraBold.ttf||205540:1655828711.0": { + "family_name": "Noto Sans Telugu ExtraBold", + "font-family": "Noto Sans Telugu ExtraBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Telugu ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTelugu-ExtraBold.ttf", + "preferred_family_name": "Noto Sans Telugu", + "preferred_subfamily_name": "ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTelugu-ExtraCondensed.ttf||192636:1655828711.0": { + "family_name": "Noto Sans Telugu ExtraCondensed", + "font-family": "Noto Sans Telugu ExtraCondensed", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Telugu ExtraCondensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTelugu-ExtraCondensed.ttf", + "preferred_family_name": "Noto Sans Telugu", + "preferred_subfamily_name": "ExtraCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTelugu-ExtraCondensedBlack.ttf||206012:1655828711.0": { + "family_name": "Noto Sans Telugu ExtraCondensed Black", + "font-family": "Noto Sans Telugu ExtraCondensed Black", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Telugu ExtraCondensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTelugu-ExtraCondensedBlack.ttf", + "preferred_family_name": "Noto Sans Telugu", + "preferred_subfamily_name": "ExtraCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTelugu-ExtraCondensedBold.ttf||204200:1655828711.0": { + "family_name": "Noto Sans Telugu ExtraCondensed", + "font-family": "Noto Sans Telugu ExtraCondensed", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Telugu ExtraCondensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTelugu-ExtraCondensedBold.ttf", + "preferred_family_name": "Noto Sans Telugu", + "preferred_subfamily_name": "ExtraCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTelugu-ExtraCondensedExtraBold.ttf||203644:1655828711.0": { + "family_name": "Noto Sans Telugu ExtraCondensed ExtraBold", + "font-family": "Noto Sans Telugu ExtraCondensed ExtraBold", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Telugu ExtraCondensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTelugu-ExtraCondensedExtraBold.ttf", + "preferred_family_name": "Noto Sans Telugu", + "preferred_subfamily_name": "ExtraCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTelugu-ExtraCondensedExtraLight.ttf||183992:1655828711.0": { + "family_name": "Noto Sans Telugu ExtraCondensed ExtraLight", + "font-family": "Noto Sans Telugu ExtraCondensed ExtraLight", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Telugu ExtraCondensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTelugu-ExtraCondensedExtraLight.ttf", + "preferred_family_name": "Noto Sans Telugu", + "preferred_subfamily_name": "ExtraCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTelugu-ExtraCondensedLight.ttf||190068:1655828711.0": { + "family_name": "Noto Sans Telugu ExtraCondensed Light", + "font-family": "Noto Sans Telugu ExtraCondensed Light", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Telugu ExtraCondensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTelugu-ExtraCondensedLight.ttf", + "preferred_family_name": "Noto Sans Telugu", + "preferred_subfamily_name": "ExtraCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTelugu-ExtraCondensedMedium.ttf||201124:1655828711.0": { + "family_name": "Noto Sans Telugu ExtraCondensed Medium", + "font-family": "Noto Sans Telugu ExtraCondensed Medium", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Telugu ExtraCondensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTelugu-ExtraCondensedMedium.ttf", + "preferred_family_name": "Noto Sans Telugu", + "preferred_subfamily_name": "ExtraCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTelugu-ExtraCondensedSemiBold.ttf||202504:1655828711.0": { + "family_name": "Noto Sans Telugu ExtraCondensed SemiBold", + "font-family": "Noto Sans Telugu ExtraCondensed SemiBold", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Telugu ExtraCondensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTelugu-ExtraCondensedSemiBold.ttf", + "preferred_family_name": "Noto Sans Telugu", + "preferred_subfamily_name": "ExtraCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTelugu-ExtraCondensedThin.ttf||188288:1655828711.0": { + "family_name": "Noto Sans Telugu ExtraCondensed Thin", + "font-family": "Noto Sans Telugu ExtraCondensed Thin", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Telugu ExtraCondensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTelugu-ExtraCondensedThin.ttf", + "preferred_family_name": "Noto Sans Telugu", + "preferred_subfamily_name": "ExtraCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTelugu-ExtraLight.ttf||186204:1655828711.0": { + "family_name": "Noto Sans Telugu ExtraLight", + "font-family": "Noto Sans Telugu ExtraLight", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Telugu ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTelugu-ExtraLight.ttf", + "preferred_family_name": "Noto Sans Telugu", + "preferred_subfamily_name": "ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTelugu-Light.ttf||191596:1655828711.0": { + "family_name": "Noto Sans Telugu Light", + "font-family": "Noto Sans Telugu Light", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Telugu Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTelugu-Light.ttf", + "preferred_family_name": "Noto Sans Telugu", + "preferred_subfamily_name": "Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTelugu-Medium.ttf||205460:1655828711.0": { + "family_name": "Noto Sans Telugu Medium", + "font-family": "Noto Sans Telugu Medium", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Telugu Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTelugu-Medium.ttf", + "preferred_family_name": "Noto Sans Telugu", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTelugu-Regular.ttf||197228:1655828711.0": { + "family_name": "Noto Sans Telugu", + "font-family": "Noto Sans Telugu", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Telugu Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTelugu-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTelugu-SemiBold.ttf||208712:1655828711.0": { + "family_name": "Noto Sans Telugu SemiBold", + "font-family": "Noto Sans Telugu SemiBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Telugu SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTelugu-SemiBold.ttf", + "preferred_family_name": "Noto Sans Telugu", + "preferred_subfamily_name": "SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTelugu-SemiCondensed.ttf||193476:1655828711.0": { + "family_name": "Noto Sans Telugu SemiCondensed", + "font-family": "Noto Sans Telugu SemiCondensed", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Telugu SemiCondensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTelugu-SemiCondensed.ttf", + "preferred_family_name": "Noto Sans Telugu", + "preferred_subfamily_name": "SemiCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTelugu-SemiCondensedBlack.ttf||208216:1655828711.0": { + "family_name": "Noto Sans Telugu SemiCondensed Black", + "font-family": "Noto Sans Telugu SemiCondensed Black", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Telugu SemiCondensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTelugu-SemiCondensedBlack.ttf", + "preferred_family_name": "Noto Sans Telugu", + "preferred_subfamily_name": "SemiCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTelugu-SemiCondensedBold.ttf||204508:1655828711.0": { + "family_name": "Noto Sans Telugu SemiCondensed", + "font-family": "Noto Sans Telugu SemiCondensed", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Telugu SemiCondensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTelugu-SemiCondensedBold.ttf", + "preferred_family_name": "Noto Sans Telugu", + "preferred_subfamily_name": "SemiCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTelugu-SemiCondensedExtraBold.ttf||204268:1655828711.0": { + "family_name": "Noto Sans Telugu SemiCondensed ExtraBold", + "font-family": "Noto Sans Telugu SemiCondensed ExtraBold", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Telugu SemiCondensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTelugu-SemiCondensedExtraBold.ttf", + "preferred_family_name": "Noto Sans Telugu", + "preferred_subfamily_name": "SemiCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTelugu-SemiCondensedExtraLight.ttf||186484:1655828711.0": { + "family_name": "Noto Sans Telugu SemiCondensed ExtraLight", + "font-family": "Noto Sans Telugu SemiCondensed ExtraLight", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Telugu SemiCondensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTelugu-SemiCondensedExtraLight.ttf", + "preferred_family_name": "Noto Sans Telugu", + "preferred_subfamily_name": "SemiCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTelugu-SemiCondensedLight.ttf||190620:1655828711.0": { + "family_name": "Noto Sans Telugu SemiCondensed Light", + "font-family": "Noto Sans Telugu SemiCondensed Light", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Telugu SemiCondensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTelugu-SemiCondensedLight.ttf", + "preferred_family_name": "Noto Sans Telugu", + "preferred_subfamily_name": "SemiCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTelugu-SemiCondensedMedium.ttf||203436:1655828711.0": { + "family_name": "Noto Sans Telugu SemiCondensed Medium", + "font-family": "Noto Sans Telugu SemiCondensed Medium", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Telugu SemiCondensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTelugu-SemiCondensedMedium.ttf", + "preferred_family_name": "Noto Sans Telugu", + "preferred_subfamily_name": "SemiCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTelugu-SemiCondensedSemiBold.ttf||203108:1655828711.0": { + "family_name": "Noto Sans Telugu SemiCondensed SemiBold", + "font-family": "Noto Sans Telugu SemiCondensed SemiBold", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Telugu SemiCondensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTelugu-SemiCondensedSemiBold.ttf", + "preferred_family_name": "Noto Sans Telugu", + "preferred_subfamily_name": "SemiCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTelugu-SemiCondensedThin.ttf||186236:1655828711.0": { + "family_name": "Noto Sans Telugu SemiCondensed Thin", + "font-family": "Noto Sans Telugu SemiCondensed Thin", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Telugu SemiCondensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTelugu-SemiCondensedThin.ttf", + "preferred_family_name": "Noto Sans Telugu", + "preferred_subfamily_name": "SemiCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTelugu-Thin.ttf||184596:1655828711.0": { + "family_name": "Noto Sans Telugu Thin", + "font-family": "Noto Sans Telugu Thin", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Telugu Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTelugu-Thin.ttf", + "preferred_family_name": "Noto Sans Telugu", + "preferred_subfamily_name": "Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTeluguUI-Black.ttf||220308:1655828711.0": { + "family_name": "Noto Sans Telugu UI Black", + "font-family": "Noto Sans Telugu UI Black", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Telugu UI Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTeluguUI-Black.ttf", + "preferred_family_name": "Noto Sans Telugu UI", + "preferred_subfamily_name": "Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTeluguUI-Bold.ttf||217100:1655828711.0": { + "family_name": "Noto Sans Telugu UI", + "font-family": "Noto Sans Telugu UI", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Telugu UI Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTeluguUI-Bold.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTeluguUI-Condensed.ttf||204880:1655828711.0": { + "family_name": "Noto Sans Telugu UI Condensed", + "font-family": "Noto Sans Telugu UI Condensed", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Telugu UI Condensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTeluguUI-Condensed.ttf", + "preferred_family_name": "Noto Sans Telugu UI", + "preferred_subfamily_name": "Condensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTeluguUI-CondensedBlack.ttf||219248:1655828711.0": { + "family_name": "Noto Sans Telugu UI Condensed Black", + "font-family": "Noto Sans Telugu UI Condensed Black", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Telugu UI Condensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTeluguUI-CondensedBlack.ttf", + "preferred_family_name": "Noto Sans Telugu UI", + "preferred_subfamily_name": "Condensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTeluguUI-CondensedBold.ttf||217524:1655828711.0": { + "family_name": "Noto Sans Telugu UI Condensed", + "font-family": "Noto Sans Telugu UI Condensed", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Telugu UI Condensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTeluguUI-CondensedBold.ttf", + "preferred_family_name": "Noto Sans Telugu UI", + "preferred_subfamily_name": "Condensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTeluguUI-CondensedExtraBold.ttf||217020:1655828711.0": { + "family_name": "Noto Sans Telugu UI Condensed ExtraBold", + "font-family": "Noto Sans Telugu UI Condensed ExtraBold", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Telugu UI Condensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTeluguUI-CondensedExtraBold.ttf", + "preferred_family_name": "Noto Sans Telugu UI", + "preferred_subfamily_name": "Condensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTeluguUI-CondensedExtraLight.ttf||198556:1655828711.0": { + "family_name": "Noto Sans Telugu UI Condensed ExtraLight", + "font-family": "Noto Sans Telugu UI Condensed ExtraLight", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Telugu UI Condensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTeluguUI-CondensedExtraLight.ttf", + "preferred_family_name": "Noto Sans Telugu UI", + "preferred_subfamily_name": "Condensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTeluguUI-CondensedLight.ttf||204096:1655828711.0": { + "family_name": "Noto Sans Telugu UI Condensed Light", + "font-family": "Noto Sans Telugu UI Condensed Light", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Telugu UI Condensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTeluguUI-CondensedLight.ttf", + "preferred_family_name": "Noto Sans Telugu UI", + "preferred_subfamily_name": "Condensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTeluguUI-CondensedMedium.ttf||214584:1655828711.0": { + "family_name": "Noto Sans Telugu UI Condensed Medium", + "font-family": "Noto Sans Telugu UI Condensed Medium", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Telugu UI Condensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTeluguUI-CondensedMedium.ttf", + "preferred_family_name": "Noto Sans Telugu UI", + "preferred_subfamily_name": "Condensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTeluguUI-CondensedSemiBold.ttf||216484:1655828711.0": { + "family_name": "Noto Sans Telugu UI Condensed SemiBold", + "font-family": "Noto Sans Telugu UI Condensed SemiBold", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Telugu UI Condensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTeluguUI-CondensedSemiBold.ttf", + "preferred_family_name": "Noto Sans Telugu UI", + "preferred_subfamily_name": "Condensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTeluguUI-CondensedThin.ttf||205328:1655828711.0": { + "family_name": "Noto Sans Telugu UI Condensed Thin", + "font-family": "Noto Sans Telugu UI Condensed Thin", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Telugu UI Condensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTeluguUI-CondensedThin.ttf", + "preferred_family_name": "Noto Sans Telugu UI", + "preferred_subfamily_name": "Condensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTeluguUI-ExtraBold.ttf||217656:1655828711.0": { + "family_name": "Noto Sans Telugu UI ExtraBold", + "font-family": "Noto Sans Telugu UI ExtraBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Telugu UI ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTeluguUI-ExtraBold.ttf", + "preferred_family_name": "Noto Sans Telugu UI", + "preferred_subfamily_name": "ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTeluguUI-ExtraCondensed.ttf||206728:1655828711.0": { + "family_name": "Noto Sans Telugu UI ExtraCondensed", + "font-family": "Noto Sans Telugu UI ExtraCondensed", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Telugu UI ExtraCondensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTeluguUI-ExtraCondensed.ttf", + "preferred_family_name": "Noto Sans Telugu UI", + "preferred_subfamily_name": "ExtraCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTeluguUI-ExtraCondensedBlack.ttf||219272:1655828711.0": { + "family_name": "Noto Sans Telugu UI ExtraCondensed Black", + "font-family": "Noto Sans Telugu UI ExtraCondensed Black", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Telugu UI ExtraCondensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTeluguUI-ExtraCondensedBlack.ttf", + "preferred_family_name": "Noto Sans Telugu UI", + "preferred_subfamily_name": "ExtraCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTeluguUI-ExtraCondensedBold.ttf||217044:1655828711.0": { + "family_name": "Noto Sans Telugu UI ExtraCondensed", + "font-family": "Noto Sans Telugu UI ExtraCondensed", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Telugu UI ExtraCondensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTeluguUI-ExtraCondensedBold.ttf", + "preferred_family_name": "Noto Sans Telugu UI", + "preferred_subfamily_name": "ExtraCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTeluguUI-ExtraCondensedExtraBold.ttf||217028:1655828711.0": { + "family_name": "Noto Sans Telugu UI ExtraCondensed ExtraBold", + "font-family": "Noto Sans Telugu UI ExtraCondensed ExtraBold", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Telugu UI ExtraCondensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTeluguUI-ExtraCondensedExtraBold.ttf", + "preferred_family_name": "Noto Sans Telugu UI", + "preferred_subfamily_name": "ExtraCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTeluguUI-ExtraCondensedExtraLight.ttf||197872:1655828711.0": { + "family_name": "Noto Sans Telugu UI ExtraCondensed ExtraLight", + "font-family": "Noto Sans Telugu UI ExtraCondensed ExtraLight", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Telugu UI ExtraCondensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTeluguUI-ExtraCondensedExtraLight.ttf", + "preferred_family_name": "Noto Sans Telugu UI", + "preferred_subfamily_name": "ExtraCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTeluguUI-ExtraCondensedLight.ttf||203672:1655828711.0": { + "family_name": "Noto Sans Telugu UI ExtraCondensed Light", + "font-family": "Noto Sans Telugu UI ExtraCondensed Light", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Telugu UI ExtraCondensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTeluguUI-ExtraCondensedLight.ttf", + "preferred_family_name": "Noto Sans Telugu UI", + "preferred_subfamily_name": "ExtraCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTeluguUI-ExtraCondensedMedium.ttf||214552:1655828711.0": { + "family_name": "Noto Sans Telugu UI ExtraCondensed Medium", + "font-family": "Noto Sans Telugu UI ExtraCondensed Medium", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Telugu UI ExtraCondensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTeluguUI-ExtraCondensedMedium.ttf", + "preferred_family_name": "Noto Sans Telugu UI", + "preferred_subfamily_name": "ExtraCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTeluguUI-ExtraCondensedSemiBold.ttf||215028:1655828711.0": { + "family_name": "Noto Sans Telugu UI ExtraCondensed SemiBold", + "font-family": "Noto Sans Telugu UI ExtraCondensed SemiBold", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Telugu UI ExtraCondensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTeluguUI-ExtraCondensedSemiBold.ttf", + "preferred_family_name": "Noto Sans Telugu UI", + "preferred_subfamily_name": "ExtraCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTeluguUI-ExtraCondensedThin.ttf||202048:1655828711.0": { + "family_name": "Noto Sans Telugu UI ExtraCondensed Thin", + "font-family": "Noto Sans Telugu UI ExtraCondensed Thin", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Telugu UI ExtraCondensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTeluguUI-ExtraCondensedThin.ttf", + "preferred_family_name": "Noto Sans Telugu UI", + "preferred_subfamily_name": "ExtraCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTeluguUI-ExtraLight.ttf||200512:1655828711.0": { + "family_name": "Noto Sans Telugu UI ExtraLight", + "font-family": "Noto Sans Telugu UI ExtraLight", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Telugu UI ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTeluguUI-ExtraLight.ttf", + "preferred_family_name": "Noto Sans Telugu UI", + "preferred_subfamily_name": "ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTeluguUI-Light.ttf||205700:1655828711.0": { + "family_name": "Noto Sans Telugu UI Light", + "font-family": "Noto Sans Telugu UI Light", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Telugu UI Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTeluguUI-Light.ttf", + "preferred_family_name": "Noto Sans Telugu UI", + "preferred_subfamily_name": "Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTeluguUI-Medium.ttf||219608:1655828711.0": { + "family_name": "Noto Sans Telugu UI Medium", + "font-family": "Noto Sans Telugu UI Medium", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Telugu UI Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTeluguUI-Medium.ttf", + "preferred_family_name": "Noto Sans Telugu UI", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTeluguUI-Regular.ttf||210656:1655828711.0": { + "family_name": "Noto Sans Telugu UI", + "font-family": "Noto Sans Telugu UI", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Telugu UI Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTeluguUI-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTeluguUI-SemiBold.ttf||221520:1655828711.0": { + "family_name": "Noto Sans Telugu UI SemiBold", + "font-family": "Noto Sans Telugu UI SemiBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Telugu UI SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTeluguUI-SemiBold.ttf", + "preferred_family_name": "Noto Sans Telugu UI", + "preferred_subfamily_name": "SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTeluguUI-SemiCondensed.ttf||206992:1655828711.0": { + "family_name": "Noto Sans Telugu UI SemiCondensed", + "font-family": "Noto Sans Telugu UI SemiCondensed", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Telugu UI SemiCondensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTeluguUI-SemiCondensed.ttf", + "preferred_family_name": "Noto Sans Telugu UI", + "preferred_subfamily_name": "SemiCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTeluguUI-SemiCondensedBlack.ttf||222240:1655828711.0": { + "family_name": "Noto Sans Telugu UI SemiCondensed Black", + "font-family": "Noto Sans Telugu UI SemiCondensed Black", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Telugu UI SemiCondensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTeluguUI-SemiCondensedBlack.ttf", + "preferred_family_name": "Noto Sans Telugu UI", + "preferred_subfamily_name": "SemiCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTeluguUI-SemiCondensedBold.ttf||216544:1655828711.0": { + "family_name": "Noto Sans Telugu UI SemiCondensed", + "font-family": "Noto Sans Telugu UI SemiCondensed", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Telugu UI SemiCondensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTeluguUI-SemiCondensedBold.ttf", + "preferred_family_name": "Noto Sans Telugu UI", + "preferred_subfamily_name": "SemiCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTeluguUI-SemiCondensedExtraBold.ttf||215912:1655828711.0": { + "family_name": "Noto Sans Telugu UI SemiCondensed ExtraBold", + "font-family": "Noto Sans Telugu UI SemiCondensed ExtraBold", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Telugu UI SemiCondensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTeluguUI-SemiCondensedExtraBold.ttf", + "preferred_family_name": "Noto Sans Telugu UI", + "preferred_subfamily_name": "SemiCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTeluguUI-SemiCondensedExtraLight.ttf||200932:1655828711.0": { + "family_name": "Noto Sans Telugu UI SemiCondensed ExtraLight", + "font-family": "Noto Sans Telugu UI SemiCondensed ExtraLight", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Telugu UI SemiCondensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTeluguUI-SemiCondensedExtraLight.ttf", + "preferred_family_name": "Noto Sans Telugu UI", + "preferred_subfamily_name": "SemiCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTeluguUI-SemiCondensedLight.ttf||204432:1655828711.0": { + "family_name": "Noto Sans Telugu UI SemiCondensed Light", + "font-family": "Noto Sans Telugu UI SemiCondensed Light", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Telugu UI SemiCondensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTeluguUI-SemiCondensedLight.ttf", + "preferred_family_name": "Noto Sans Telugu UI", + "preferred_subfamily_name": "SemiCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTeluguUI-SemiCondensedMedium.ttf||216672:1655828711.0": { + "family_name": "Noto Sans Telugu UI SemiCondensed Medium", + "font-family": "Noto Sans Telugu UI SemiCondensed Medium", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Telugu UI SemiCondensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTeluguUI-SemiCondensedMedium.ttf", + "preferred_family_name": "Noto Sans Telugu UI", + "preferred_subfamily_name": "SemiCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTeluguUI-SemiCondensedSemiBold.ttf||215760:1655828711.0": { + "family_name": "Noto Sans Telugu UI SemiCondensed SemiBold", + "font-family": "Noto Sans Telugu UI SemiCondensed SemiBold", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Telugu UI SemiCondensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTeluguUI-SemiCondensedSemiBold.ttf", + "preferred_family_name": "Noto Sans Telugu UI", + "preferred_subfamily_name": "SemiCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTeluguUI-SemiCondensedThin.ttf||200012:1655828711.0": { + "family_name": "Noto Sans Telugu UI SemiCondensed Thin", + "font-family": "Noto Sans Telugu UI SemiCondensed Thin", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Telugu UI SemiCondensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTeluguUI-SemiCondensedThin.ttf", + "preferred_family_name": "Noto Sans Telugu UI", + "preferred_subfamily_name": "SemiCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTeluguUI-Thin.ttf||197736:1655828711.0": { + "family_name": "Noto Sans Telugu UI Thin", + "font-family": "Noto Sans Telugu UI Thin", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Telugu UI Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTeluguUI-Thin.ttf", + "preferred_family_name": "Noto Sans Telugu UI", + "preferred_subfamily_name": "Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansThaana-Black.ttf||18892:1655828711.0": { + "family_name": "Noto Sans Thaana Black", + "font-family": "Noto Sans Thaana Black", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Thaana Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansThaana-Black.ttf", + "preferred_family_name": "Noto Sans Thaana", + "preferred_subfamily_name": "Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansThaana-Bold.ttf||18536:1655828711.0": { + "family_name": "Noto Sans Thaana", + "font-family": "Noto Sans Thaana", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Thaana Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansThaana-Bold.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansThaana-ExtraBold.ttf||18784:1655828711.0": { + "family_name": "Noto Sans Thaana ExtraBold", + "font-family": "Noto Sans Thaana ExtraBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Thaana ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansThaana-ExtraBold.ttf", + "preferred_family_name": "Noto Sans Thaana", + "preferred_subfamily_name": "ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansThaana-ExtraLight.ttf||18464:1655828711.0": { + "family_name": "Noto Sans Thaana ExtraLight", + "font-family": "Noto Sans Thaana ExtraLight", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Thaana ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansThaana-ExtraLight.ttf", + "preferred_family_name": "Noto Sans Thaana", + "preferred_subfamily_name": "ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansThaana-Light.ttf||18560:1655828711.0": { + "family_name": "Noto Sans Thaana Light", + "font-family": "Noto Sans Thaana Light", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Thaana Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansThaana-Light.ttf", + "preferred_family_name": "Noto Sans Thaana", + "preferred_subfamily_name": "Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansThaana-Medium.ttf||18696:1655828711.0": { + "family_name": "Noto Sans Thaana Medium", + "font-family": "Noto Sans Thaana Medium", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Thaana Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansThaana-Medium.ttf", + "preferred_family_name": "Noto Sans Thaana", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansThaana-Regular.ttf||18728:1655828711.0": { + "family_name": "Noto Sans Thaana", + "font-family": "Noto Sans Thaana", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Thaana Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansThaana-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansThaana-SemiBold.ttf||18620:1655828711.0": { + "family_name": "Noto Sans Thaana SemiBold", + "font-family": "Noto Sans Thaana SemiBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Thaana SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansThaana-SemiBold.ttf", + "preferred_family_name": "Noto Sans Thaana", + "preferred_subfamily_name": "SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansThaana-Thin.ttf||18388:1655828711.0": { + "family_name": "Noto Sans Thaana Thin", + "font-family": "Noto Sans Thaana Thin", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Thaana Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansThaana-Thin.ttf", + "preferred_family_name": "Noto Sans Thaana", + "preferred_subfamily_name": "Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansThai-Black.ttf||39100:1655828711.0": { + "family_name": "Noto Sans Thai Blk", + "font-family": "Noto Sans Thai Blk", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Thai Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansThai-Black.ttf", + "preferred_family_name": "Noto Sans Thai", + "preferred_subfamily_name": "Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansThai-Bold.ttf||37796:1655828711.0": { + "family_name": "Noto Sans Thai", + "font-family": "Noto Sans Thai", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Thai Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansThai-Bold.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansThai-Condensed.ttf||37444:1655828711.0": { + "family_name": "Noto Sans Thai Cond", + "font-family": "Noto Sans Thai Cond", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Thai Condensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansThai-Condensed.ttf", + "preferred_family_name": "Noto Sans Thai", + "preferred_subfamily_name": "Condensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansThai-CondensedBlack.ttf||38956:1655828711.0": { + "family_name": "Noto Sans Thai Cond Blk", + "font-family": "Noto Sans Thai Cond Blk", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Thai Condensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansThai-CondensedBlack.ttf", + "preferred_family_name": "Noto Sans Thai", + "preferred_subfamily_name": "Condensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansThai-CondensedBold.ttf||37948:1655828711.0": { + "family_name": "Noto Sans Thai Cond", + "font-family": "Noto Sans Thai Cond", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Thai Condensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansThai-CondensedBold.ttf", + "preferred_family_name": "Noto Sans Thai", + "preferred_subfamily_name": "Condensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansThai-CondensedExtraBold.ttf||38840:1655828711.0": { + "family_name": "Noto Sans Thai Cond ExtBd", + "font-family": "Noto Sans Thai Cond ExtBd", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Thai Condensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansThai-CondensedExtraBold.ttf", + "preferred_family_name": "Noto Sans Thai", + "preferred_subfamily_name": "Condensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansThai-CondensedExtraLight.ttf||35292:1655828711.0": { + "family_name": "Noto Sans Thai Cond ExtLt", + "font-family": "Noto Sans Thai Cond ExtLt", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Thai Condensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansThai-CondensedExtraLight.ttf", + "preferred_family_name": "Noto Sans Thai", + "preferred_subfamily_name": "Condensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansThai-CondensedLight.ttf||35312:1655828711.0": { + "family_name": "Noto Sans Thai Cond Light", + "font-family": "Noto Sans Thai Cond Light", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Thai Condensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansThai-CondensedLight.ttf", + "preferred_family_name": "Noto Sans Thai", + "preferred_subfamily_name": "Condensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansThai-CondensedMedium.ttf||37892:1655828711.0": { + "family_name": "Noto Sans Thai Cond Med", + "font-family": "Noto Sans Thai Cond Med", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Thai Condensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansThai-CondensedMedium.ttf", + "preferred_family_name": "Noto Sans Thai", + "preferred_subfamily_name": "Condensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansThai-CondensedSemiBold.ttf||38340:1655828711.0": { + "family_name": "Noto Sans Thai Cond SemBd", + "font-family": "Noto Sans Thai Cond SemBd", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Thai Condensed SemiBold ", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansThai-CondensedSemiBold.ttf", + "preferred_family_name": "Noto Sans Thai", + "preferred_subfamily_name": "Condensed SemiBold ", + "subfamily_name": "Regular", + "weight": 600, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansThai-CondensedThin.ttf||34588:1655828711.0": { + "family_name": "Noto Sans Thai Cond Thin", + "font-family": "Noto Sans Thai Cond Thin", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Thai Condensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansThai-CondensedThin.ttf", + "preferred_family_name": "Noto Sans Thai", + "preferred_subfamily_name": "Condensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansThai-ExtraBold.ttf||38916:1655828711.0": { + "family_name": "Noto Sans Thai ExtBd", + "font-family": "Noto Sans Thai ExtBd", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Thai ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansThai-ExtraBold.ttf", + "preferred_family_name": "Noto Sans Thai", + "preferred_subfamily_name": "ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansThai-ExtraCondensed.ttf||37296:1655828711.0": { + "family_name": "Noto Sans Thai ExtCond", + "font-family": "Noto Sans Thai ExtCond", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Thai ExtraCondensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansThai-ExtraCondensed.ttf", + "preferred_family_name": "Noto Sans Thai", + "preferred_subfamily_name": "ExtraCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansThai-ExtraCondensedBlack.ttf||38668:1655828711.0": { + "family_name": "Noto Sans Thai ExtCond Blk", + "font-family": "Noto Sans Thai ExtCond Blk", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Thai ExtraCondensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansThai-ExtraCondensedBlack.ttf", + "preferred_family_name": "Noto Sans Thai", + "preferred_subfamily_name": "ExtraCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansThai-ExtraCondensedBold.ttf||37728:1655828711.0": { + "family_name": "Noto Sans Thai ExtCond", + "font-family": "Noto Sans Thai ExtCond", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Thai ExtraCondensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansThai-ExtraCondensedBold.ttf", + "preferred_family_name": "Noto Sans Thai", + "preferred_subfamily_name": "ExtraCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansThai-ExtraCondensedExtraBold.ttf||38232:1655828711.0": { + "family_name": "Noto Sans Thai ExtCond ExtBd", + "font-family": "Noto Sans Thai ExtCond ExtBd", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Thai ExtraCondensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansThai-ExtraCondensedExtraBold.ttf", + "preferred_family_name": "Noto Sans Thai", + "preferred_subfamily_name": "ExtraCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansThai-ExtraCondensedExtraLight.ttf||35388:1655828711.0": { + "family_name": "Noto Sans Thai ExtCond ExtLt", + "font-family": "Noto Sans Thai ExtCond ExtLt", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Thai ExtraCondensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansThai-ExtraCondensedExtraLight.ttf", + "preferred_family_name": "Noto Sans Thai", + "preferred_subfamily_name": "ExtraCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansThai-ExtraCondensedLight.ttf||35292:1655828711.0": { + "family_name": "Noto Sans Thai ExtCond Light", + "font-family": "Noto Sans Thai ExtCond Light", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Thai ExtraCondensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansThai-ExtraCondensedLight.ttf", + "preferred_family_name": "Noto Sans Thai", + "preferred_subfamily_name": "ExtraCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansThai-ExtraCondensedMedium.ttf||37900:1655828711.0": { + "family_name": "Noto Sans Thai ExtCond Med", + "font-family": "Noto Sans Thai ExtCond Med", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Thai ExtraCondensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansThai-ExtraCondensedMedium.ttf", + "preferred_family_name": "Noto Sans Thai", + "preferred_subfamily_name": "ExtraCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansThai-ExtraCondensedSemiBold.ttf||38212:1655828711.0": { + "family_name": "Noto Sans Thai ExtCond SemBd", + "font-family": "Noto Sans Thai ExtCond SemBd", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Thai ExtraCondensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansThai-ExtraCondensedSemiBold.ttf", + "preferred_family_name": "Noto Sans Thai", + "preferred_subfamily_name": "ExtraCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansThai-ExtraCondensedThin.ttf||34560:1655828711.0": { + "family_name": "Noto Sans Thai ExtCond Thin", + "font-family": "Noto Sans Thai ExtCond Thin", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Thai ExtraCondensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansThai-ExtraCondensedThin.ttf", + "preferred_family_name": "Noto Sans Thai", + "preferred_subfamily_name": "ExtraCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansThai-ExtraLight.ttf||34972:1655828711.0": { + "family_name": "Noto Sans Thai ExtLt", + "font-family": "Noto Sans Thai ExtLt", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Thai ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansThai-ExtraLight.ttf", + "preferred_family_name": "Noto Sans Thai", + "preferred_subfamily_name": "ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansThai-Light.ttf||35448:1655828711.0": { + "family_name": "Noto Sans Thai Light", + "font-family": "Noto Sans Thai Light", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Thai Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansThai-Light.ttf", + "preferred_family_name": "Noto Sans Thai", + "preferred_subfamily_name": "Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansThai-Medium.ttf||38268:1655828711.0": { + "family_name": "Noto Sans Thai Med", + "font-family": "Noto Sans Thai Med", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Thai Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansThai-Medium.ttf", + "preferred_family_name": "Noto Sans Thai", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansThai-Regular.ttf||37752:1655828711.0": { + "family_name": "Noto Sans Thai", + "font-family": "Noto Sans Thai", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Thai Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansThai-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansThai-SemiBold.ttf||38496:1655828711.0": { + "family_name": "Noto Sans Thai SemBd", + "font-family": "Noto Sans Thai SemBd", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Thai SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansThai-SemiBold.ttf", + "preferred_family_name": "Noto Sans Thai", + "preferred_subfamily_name": "SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansThai-SemiCondensed.ttf||37496:1655828711.0": { + "family_name": "Noto Sans Thai SemCond", + "font-family": "Noto Sans Thai SemCond", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Thai SemiCondensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansThai-SemiCondensed.ttf", + "preferred_family_name": "Noto Sans Thai", + "preferred_subfamily_name": "SemiCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansThai-SemiCondensedBlack.ttf||39432:1655828711.0": { + "family_name": "Noto Sans Thai SemCond Blk", + "font-family": "Noto Sans Thai SemCond Blk", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Thai SemiCondensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansThai-SemiCondensedBlack.ttf", + "preferred_family_name": "Noto Sans Thai", + "preferred_subfamily_name": "SemiCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansThai-SemiCondensedBold.ttf||37688:1655828711.0": { + "family_name": "Noto Sans Thai SemCond", + "font-family": "Noto Sans Thai SemCond", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Thai SemiCondensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansThai-SemiCondensedBold.ttf", + "preferred_family_name": "Noto Sans Thai", + "preferred_subfamily_name": "SemiCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansThai-SemiCondensedExtraBold.ttf||38816:1655828711.0": { + "family_name": "Noto Sans Thai SemCond ExtBd", + "font-family": "Noto Sans Thai SemCond ExtBd", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Thai SemiCondensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansThai-SemiCondensedExtraBold.ttf", + "preferred_family_name": "Noto Sans Thai", + "preferred_subfamily_name": "SemiCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansThai-SemiCondensedExtraLight.ttf||35580:1655828711.0": { + "family_name": "Noto Sans Thai SemCond ExtLt", + "font-family": "Noto Sans Thai SemCond ExtLt", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Thai SemiCondensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansThai-SemiCondensedExtraLight.ttf", + "preferred_family_name": "Noto Sans Thai", + "preferred_subfamily_name": "SemiCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansThai-SemiCondensedLight.ttf||35588:1655828711.0": { + "family_name": "Noto Sans Thai SemCond Light", + "font-family": "Noto Sans Thai SemCond Light", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Thai SemiCondensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansThai-SemiCondensedLight.ttf", + "preferred_family_name": "Noto Sans Thai", + "preferred_subfamily_name": "SemiCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansThai-SemiCondensedMedium.ttf||38248:1655828711.0": { + "family_name": "Noto Sans Thai SemCond Med", + "font-family": "Noto Sans Thai SemCond Med", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Thai SemiCondensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansThai-SemiCondensedMedium.ttf", + "preferred_family_name": "Noto Sans Thai", + "preferred_subfamily_name": "SemiCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansThai-SemiCondensedSemiBold.ttf||38276:1655828711.0": { + "family_name": "Noto Sans Thai SemCond SemBd", + "font-family": "Noto Sans Thai SemCond SemBd", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Thai SemiCondensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansThai-SemiCondensedSemiBold.ttf", + "preferred_family_name": "Noto Sans Thai", + "preferred_subfamily_name": "SemiCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansThai-SemiCondensedThin.ttf||34644:1655828711.0": { + "family_name": "Noto Sans Thai SemCond Thin", + "font-family": "Noto Sans Thai SemCond Thin", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Thai SemiCondensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansThai-SemiCondensedThin.ttf", + "preferred_family_name": "Noto Sans Thai", + "preferred_subfamily_name": "SemiCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansThai-Thin.ttf||34756:1655828711.0": { + "family_name": "Noto Sans Thai Thin", + "font-family": "Noto Sans Thai Thin", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Thai Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansThai-Thin.ttf", + "preferred_family_name": "Noto Sans Thai", + "preferred_subfamily_name": "Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansThaiUI-Black.ttf||42460:1655828711.0": { + "family_name": "Noto Sans Thai UI Blk", + "font-family": "Noto Sans Thai UI Blk", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Thai UI Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansThaiUI-Black.ttf", + "preferred_family_name": "Noto Sans Thai UI", + "preferred_subfamily_name": "Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansThaiUI-Bold.ttf||38808:1655828711.0": { + "family_name": "Noto Sans Thai UI", + "font-family": "Noto Sans Thai UI", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Thai UI Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansThaiUI-Bold.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansThaiUI-Condensed.ttf||37916:1655828711.0": { + "family_name": "Noto Sans Thai UI Cond", + "font-family": "Noto Sans Thai UI Cond", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Thai UI Condensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansThaiUI-Condensed.ttf", + "preferred_family_name": "Noto Sans Thai UI", + "preferred_subfamily_name": "Condensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansThaiUI-CondensedBlack.ttf||39192:1655828711.0": { + "family_name": "Noto Sans Thai UI Cond Blk", + "font-family": "Noto Sans Thai UI Cond Blk", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Thai UI Condensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansThaiUI-CondensedBlack.ttf", + "preferred_family_name": "Noto Sans Thai UI", + "preferred_subfamily_name": "Condensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansThaiUI-CondensedBold.ttf||38360:1655828711.0": { + "family_name": "Noto Sans Thai UI Cond", + "font-family": "Noto Sans Thai UI Cond", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Thai UI Condensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansThaiUI-CondensedBold.ttf", + "preferred_family_name": "Noto Sans Thai UI", + "preferred_subfamily_name": "Condensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansThaiUI-CondensedExtraBold.ttf||39112:1655828711.0": { + "family_name": "Noto Sans Thai UI Cond ExtBd", + "font-family": "Noto Sans Thai UI Cond ExtBd", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Thai UI Condensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansThaiUI-CondensedExtraBold.ttf", + "preferred_family_name": "Noto Sans Thai UI", + "preferred_subfamily_name": "Condensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansThaiUI-CondensedExtraLight.ttf||33832:1655828711.0": { + "family_name": "Noto Sans Thai UI Cond ExtLt", + "font-family": "Noto Sans Thai UI Cond ExtLt", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Thai UI Condensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansThaiUI-CondensedExtraLight.ttf", + "preferred_family_name": "Noto Sans Thai UI", + "preferred_subfamily_name": "Condensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansThaiUI-CondensedLight.ttf||36580:1655828711.0": { + "family_name": "Noto Sans Thai UI Cond Light", + "font-family": "Noto Sans Thai UI Cond Light", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Thai UI Condensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansThaiUI-CondensedLight.ttf", + "preferred_family_name": "Noto Sans Thai UI", + "preferred_subfamily_name": "Condensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansThaiUI-CondensedMedium.ttf||38432:1655828711.0": { + "family_name": "Noto Sans Thai UI Cond Med", + "font-family": "Noto Sans Thai UI Cond Med", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Thai UI Condensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansThaiUI-CondensedMedium.ttf", + "preferred_family_name": "Noto Sans Thai UI", + "preferred_subfamily_name": "Condensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansThaiUI-CondensedSemiBold.ttf||38584:1655828711.0": { + "family_name": "Noto Sans Thai UI Cond SemBd", + "font-family": "Noto Sans Thai UI Cond SemBd", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Thai UI Condensed SemiBold ", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansThaiUI-CondensedSemiBold.ttf", + "preferred_family_name": "Noto Sans Thai UI", + "preferred_subfamily_name": "Condensed SemiBold ", + "subfamily_name": "Regular", + "weight": 600, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansThaiUI-CondensedThin.ttf||32780:1655828711.0": { + "family_name": "Noto Sans Thai UI Cond Thin", + "font-family": "Noto Sans Thai UI Cond Thin", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Thai UI Condensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansThaiUI-CondensedThin.ttf", + "preferred_family_name": "Noto Sans Thai UI", + "preferred_subfamily_name": "Condensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansThaiUI-ExtraBold.ttf||39312:1655828711.0": { + "family_name": "Noto Sans Thai UI ExtBd", + "font-family": "Noto Sans Thai UI ExtBd", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Thai UI ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansThaiUI-ExtraBold.ttf", + "preferred_family_name": "Noto Sans Thai UI", + "preferred_subfamily_name": "ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansThaiUI-ExtraCondensed.ttf||37716:1655828711.0": { + "family_name": "Noto Sans Thai UI ExtCond", + "font-family": "Noto Sans Thai UI ExtCond", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Thai UI ExtraCondensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansThaiUI-ExtraCondensed.ttf", + "preferred_family_name": "Noto Sans Thai UI", + "preferred_subfamily_name": "ExtraCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansThaiUI-ExtraCondensedBlack.ttf||39084:1655828711.0": { + "family_name": "Noto Sans Thai UI ExtCond Blk", + "font-family": "Noto Sans Thai UI ExtCond Blk", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Thai UI ExtraCondensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansThaiUI-ExtraCondensedBlack.ttf", + "preferred_family_name": "Noto Sans Thai UI", + "preferred_subfamily_name": "ExtraCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansThaiUI-ExtraCondensedBold.ttf||38036:1655828711.0": { + "family_name": "Noto Sans Thai UI ExtCond", + "font-family": "Noto Sans Thai UI ExtCond", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Thai UI ExtraCondensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansThaiUI-ExtraCondensedBold.ttf", + "preferred_family_name": "Noto Sans Thai UI", + "preferred_subfamily_name": "ExtraCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansThaiUI-ExtraCondensedExtraBold.ttf||38728:1655828711.0": { + "family_name": "Noto Sans Thai UI ExtCond ExtBd", + "font-family": "Noto Sans Thai UI ExtCond ExtBd", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Thai UI ExtraCondensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansThaiUI-ExtraCondensedExtraBold.ttf", + "preferred_family_name": "Noto Sans Thai UI", + "preferred_subfamily_name": "ExtraCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansThaiUI-ExtraCondensedExtraLight.ttf||34080:1655828711.0": { + "family_name": "Noto Sans Thai UI ExtCond ExtLt", + "font-family": "Noto Sans Thai UI ExtCond ExtLt", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Thai UI ExtraCondensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansThaiUI-ExtraCondensedExtraLight.ttf", + "preferred_family_name": "Noto Sans Thai UI", + "preferred_subfamily_name": "ExtraCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansThaiUI-ExtraCondensedLight.ttf||36076:1655828711.0": { + "family_name": "Noto Sans Thai UI ExtCond Light", + "font-family": "Noto Sans Thai UI ExtCond Light", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Thai UI ExtraCondensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansThaiUI-ExtraCondensedLight.ttf", + "preferred_family_name": "Noto Sans Thai UI", + "preferred_subfamily_name": "ExtraCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansThaiUI-ExtraCondensedMedium.ttf||38456:1655828711.0": { + "family_name": "Noto Sans Thai UI ExtCond Med", + "font-family": "Noto Sans Thai UI ExtCond Med", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Thai UI ExtraCondensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansThaiUI-ExtraCondensedMedium.ttf", + "preferred_family_name": "Noto Sans Thai UI", + "preferred_subfamily_name": "ExtraCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansThaiUI-ExtraCondensedSemiBold.ttf||38924:1655828711.0": { + "family_name": "Noto Sans Thai UI ExtCond SemBd", + "font-family": "Noto Sans Thai UI ExtCond SemBd", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Thai UI ExtraCondensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansThaiUI-ExtraCondensedSemiBold.ttf", + "preferred_family_name": "Noto Sans Thai UI", + "preferred_subfamily_name": "ExtraCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansThaiUI-ExtraCondensedThin.ttf||32644:1655828711.0": { + "family_name": "Noto Sans Thai UI ExtCond Thin", + "font-family": "Noto Sans Thai UI ExtCond Thin", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Thai UI ExtraCondensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 6, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansThaiUI-ExtraCondensedThin.ttf", + "preferred_family_name": "Noto Sans Thai UI", + "preferred_subfamily_name": "ExtraCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansThaiUI-ExtraLight.ttf||33732:1655828711.0": { + "family_name": "Noto Sans Thai UI ExtLt", + "font-family": "Noto Sans Thai UI ExtLt", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Thai UI ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansThaiUI-ExtraLight.ttf", + "preferred_family_name": "Noto Sans Thai UI", + "preferred_subfamily_name": "ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansThaiUI-Light.ttf||36732:1655828711.0": { + "family_name": "Noto Sans Thai UI Light", + "font-family": "Noto Sans Thai UI Light", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Thai UI Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansThaiUI-Light.ttf", + "preferred_family_name": "Noto Sans Thai UI", + "preferred_subfamily_name": "Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansThaiUI-Medium.ttf||38568:1655828711.0": { + "family_name": "Noto Sans Thai UI Med", + "font-family": "Noto Sans Thai UI Med", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Thai UI Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansThaiUI-Medium.ttf", + "preferred_family_name": "Noto Sans Thai UI", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansThaiUI-Regular.ttf||37880:1655828711.0": { + "family_name": "Noto Sans Thai UI", + "font-family": "Noto Sans Thai UI", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Thai UI Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansThaiUI-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansThaiUI-SemiBold.ttf||39184:1655828711.0": { + "family_name": "Noto Sans Thai UI SemBd", + "font-family": "Noto Sans Thai UI SemBd", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Thai UI SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansThaiUI-SemiBold.ttf", + "preferred_family_name": "Noto Sans Thai UI", + "preferred_subfamily_name": "SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansThaiUI-SemiCondensed.ttf||37996:1655828711.0": { + "family_name": "Noto Sans Thai UI SemCond", + "font-family": "Noto Sans Thai UI SemCond", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Thai UI SemiCondensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansThaiUI-SemiCondensed.ttf", + "preferred_family_name": "Noto Sans Thai UI", + "preferred_subfamily_name": "SemiCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansThaiUI-SemiCondensedBlack.ttf||42572:1655828711.0": { + "family_name": "Noto Sans Thai UI SemCond Blk", + "font-family": "Noto Sans Thai UI SemCond Blk", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Sans Thai UI SemiCondensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 10, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansThaiUI-SemiCondensedBlack.ttf", + "preferred_family_name": "Noto Sans Thai UI", + "preferred_subfamily_name": "SemiCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansThaiUI-SemiCondensedBold.ttf||38752:1655828711.0": { + "family_name": "Noto Sans Thai UI SemCond", + "font-family": "Noto Sans Thai UI SemCond", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Thai UI SemiCondensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansThaiUI-SemiCondensedBold.ttf", + "preferred_family_name": "Noto Sans Thai UI", + "preferred_subfamily_name": "SemiCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansThaiUI-SemiCondensedExtraBold.ttf||39316:1655828711.0": { + "family_name": "Noto Sans Thai UI SemCond ExtBd", + "font-family": "Noto Sans Thai UI SemCond ExtBd", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Sans Thai UI SemiCondensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 9, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansThaiUI-SemiCondensedExtraBold.ttf", + "preferred_family_name": "Noto Sans Thai UI", + "preferred_subfamily_name": "SemiCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansThaiUI-SemiCondensedExtraLight.ttf||34208:1655828711.0": { + "family_name": "Noto Sans Thai UI SemCond ExtLt", + "font-family": "Noto Sans Thai UI SemCond ExtLt", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Sans Thai UI SemiCondensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 3, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansThaiUI-SemiCondensedExtraLight.ttf", + "preferred_family_name": "Noto Sans Thai UI", + "preferred_subfamily_name": "SemiCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansThaiUI-SemiCondensedLight.ttf||36528:1655828711.0": { + "family_name": "Noto Sans Thai UI SemCond Light", + "font-family": "Noto Sans Thai UI SemCond Light", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Sans Thai UI SemiCondensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 4, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansThaiUI-SemiCondensedLight.ttf", + "preferred_family_name": "Noto Sans Thai UI", + "preferred_subfamily_name": "SemiCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansThaiUI-SemiCondensedMedium.ttf||38788:1655828711.0": { + "family_name": "Noto Sans Thai UI SemCond Med", + "font-family": "Noto Sans Thai UI SemCond Med", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Thai UI SemiCondensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansThaiUI-SemiCondensedMedium.ttf", + "preferred_family_name": "Noto Sans Thai UI", + "preferred_subfamily_name": "SemiCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansThaiUI-SemiCondensedSemiBold.ttf||38732:1655828711.0": { + "family_name": "Noto Sans Thai UI SemCond SemBd", + "font-family": "Noto Sans Thai UI SemCond SemBd", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Thai UI SemiCondensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansThaiUI-SemiCondensedSemiBold.ttf", + "preferred_family_name": "Noto Sans Thai UI", + "preferred_subfamily_name": "SemiCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansThaiUI-SemiCondensedThin.ttf||32868:1655828711.0": { + "family_name": "Noto Sans Thai UI SemCond Thin", + "font-family": "Noto Sans Thai UI SemCond Thin", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Thai UI SemiCondensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansThaiUI-SemiCondensedThin.ttf", + "preferred_family_name": "Noto Sans Thai UI", + "preferred_subfamily_name": "SemiCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansThaiUI-Thin.ttf||32848:1655828711.0": { + "family_name": "Noto Sans Thai UI Thin", + "font-family": "Noto Sans Thai UI Thin", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Sans Thai UI Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 2, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansThaiUI-Thin.ttf", + "preferred_family_name": "Noto Sans Thai UI", + "preferred_subfamily_name": "Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTifinagh-Regular.ttf||39216:1655828711.0": { + "family_name": "Noto Sans Tifinagh", + "font-family": "Noto Sans Tifinagh", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Tifinagh Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/noto/NotoSansTifinagh-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTifinaghAPT-Regular.ttf||39540:1655828711.0": { + "family_name": "Noto Sans Tifinagh APT", + "font-family": "Noto Sans Tifinagh APT", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Tifinagh APT Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/noto/NotoSansTifinaghAPT-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTifinaghAdrar-Regular.ttf||38928:1655828711.0": { + "family_name": "Noto Sans Tifinagh Adrar", + "font-family": "Noto Sans Tifinagh Adrar", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Tifinagh Adrar Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/noto/NotoSansTifinaghAdrar-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTifinaghAgrawImazighen-Regular.ttf||40056:1655828711.0": { + "family_name": "Noto Sans Tifinagh Agraw Imazighen", + "font-family": "Noto Sans Tifinagh Agraw Imazighen", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Tifinagh Agraw Imazighen Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/noto/NotoSansTifinaghAgrawImazighen-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTifinaghAhaggar-Regular.ttf||39516:1655828711.0": { + "family_name": "Noto Sans Tifinagh Ahaggar", + "font-family": "Noto Sans Tifinagh Ahaggar", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Tifinagh Ahaggar Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/noto/NotoSansTifinaghAhaggar-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTifinaghAir-Regular.ttf||39484:1655828711.0": { + "family_name": "Noto Sans Tifinagh Air", + "font-family": "Noto Sans Tifinagh Air", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Tifinagh Air Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/noto/NotoSansTifinaghAir-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTifinaghAzawagh-Regular.ttf||39516:1655828711.0": { + "family_name": "Noto Sans Tifinagh Azawagh", + "font-family": "Noto Sans Tifinagh Azawagh", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Tifinagh Azawagh Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/noto/NotoSansTifinaghAzawagh-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTifinaghGhat-Regular.ttf||39320:1655828711.0": { + "family_name": "Noto Sans Tifinagh Ghat", + "font-family": "Noto Sans Tifinagh Ghat", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Tifinagh Ghat Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/noto/NotoSansTifinaghGhat-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTifinaghHawad-Regular.ttf||39324:1655828711.0": { + "family_name": "Noto Sans Tifinagh Hawad", + "font-family": "Noto Sans Tifinagh Hawad", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Tifinagh Hawad Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/noto/NotoSansTifinaghHawad-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTifinaghRhissaIxa-Regular.ttf||39768:1655828711.0": { + "family_name": "Noto Sans Tifinagh Rhissa Ixa", + "font-family": "Noto Sans Tifinagh Rhissa Ixa", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Tifinagh Rhissa Ixa Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/noto/NotoSansTifinaghRhissaIxa-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTifinaghSIL-Regular.ttf||39764:1655828711.0": { + "family_name": "Noto Sans Tifinagh SIL", + "font-family": "Noto Sans Tifinagh SIL", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Tifinagh SIL Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/noto/NotoSansTifinaghSIL-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTifinaghTawellemmet-Regular.ttf||39752:1655828711.0": { + "family_name": "Noto Sans Tifinagh Tawellemmet", + "font-family": "Noto Sans Tifinagh Tawellemmet", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Tifinagh Tawellemmet Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/noto/NotoSansTifinaghTawellemmet-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansTirhuta-Regular.ttf||97008:1655828711.0": { + "family_name": "Noto Sans Tirhuta", + "font-family": "Noto Sans Tirhuta", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Tirhuta Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansTirhuta-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansUgaritic-Regular.ttf||7300:1655828711.0": { + "family_name": "Noto Sans Ugaritic", + "font-family": "Noto Sans Ugaritic", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Ugaritic Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansUgaritic-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansVai-Regular.ttf||91692:1655828711.0": { + "family_name": "Noto Sans Vai", + "font-family": "Noto Sans Vai", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Vai Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansVai-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansVithkuqi-Bold.ttf||18508:1655828711.0": { + "family_name": "Noto Sans Vithkuqi", + "font-family": "Noto Sans Vithkuqi", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Sans Vithkuqi Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 2, + 8, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansVithkuqi-Bold.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansVithkuqi-Medium.ttf||18628:1655828711.0": { + "family_name": "Noto Sans Vithkuqi Medium", + "font-family": "Noto Sans Vithkuqi Medium", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Sans Vithkuqi Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 2, + 6, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansVithkuqi-Medium.ttf", + "preferred_family_name": "Noto Sans Vithkuqi", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansVithkuqi-Regular.ttf||18832:1655828711.0": { + "family_name": "Noto Sans Vithkuqi", + "font-family": "Noto Sans Vithkuqi", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Vithkuqi Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 2, + 5, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansVithkuqi-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansVithkuqi-SemiBold.ttf||18580:1655828711.0": { + "family_name": "Noto Sans Vithkuqi SemiBold", + "font-family": "Noto Sans Vithkuqi SemiBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Sans Vithkuqi SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 2, + 7, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansVithkuqi-SemiBold.ttf", + "preferred_family_name": "Noto Sans Vithkuqi", + "preferred_subfamily_name": "SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansWancho-Regular.ttf||18940:1655828711.0": { + "family_name": "Noto Sans Wancho", + "font-family": "Noto Sans Wancho", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Wancho Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansWancho-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansWarangCiti-Regular.ttf||25328:1655828711.0": { + "family_name": "Noto Sans WarangCiti", + "font-family": "Noto Sans WarangCiti", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Warang Citi Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansWarangCiti-Regular.ttf", + "preferred_family_name": "Noto Sans Warang Citi", + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansYi-Regular.ttf||182808:1655828711.0": { + "family_name": "Noto Sans Yi", + "font-family": "Noto Sans Yi", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Yi Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansYi-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSansZanabazarSquare-Regular.ttf||19896:1655828711.0": { + "family_name": "Noto Sans Zanabazar", + "font-family": "Noto Sans Zanabazar", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Sans Zanabazar Square Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSansZanabazarSquare-Regular.ttf", + "preferred_family_name": "Noto Sans Zanabazar Square", + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerif-Black.ttf||691476:1655828711.0": { + "family_name": "Noto Serif Black", + "font-family": "Noto Serif Black", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Serif Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 10, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerif-Black.ttf", + "preferred_family_name": "Noto Serif", + "preferred_subfamily_name": "Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerif-BlackItalic.ttf||697992:1655828711.0": { + "family_name": "Noto Serif Black", + "font-family": "Noto Serif Black", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Serif Black Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 10, + 2, + 6, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerif-BlackItalic.ttf", + "preferred_family_name": "Noto Serif", + "preferred_subfamily_name": "Black Italic", + "subfamily_name": "Italic", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerif-Bold.ttf||638164:1655828711.0": { + "family_name": "Noto Serif Bold", + "font-family": "Noto Serif Bold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Serif Bold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 8, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerif-Bold.ttf", + "preferred_family_name": "Noto Serif", + "preferred_subfamily_name": "Bold", + "subfamily_name": "Regular", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerif-BoldItalic.ttf||675428:1655828711.0": { + "family_name": "Noto Serif Bold Italic", + "font-family": "Noto Serif Bold Italic", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Serif Bold Italic", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 8, + 2, + 6, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerif-BoldItalic.ttf", + "preferred_family_name": "Noto Serif", + "preferred_subfamily_name": "Bold Italic", + "subfamily_name": "Regular", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerif-Condensed.ttf||626612:1655828711.0": { + "family_name": "Noto Serif Condensed", + "font-family": "Noto Serif Condensed", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif Condensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 5, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerif-Condensed.ttf", + "preferred_family_name": "Noto Serif", + "preferred_subfamily_name": "Condensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerif-CondensedBlack.ttf||658224:1655828711.0": { + "family_name": "Noto Serif Condensed Black", + "font-family": "Noto Serif Condensed Black", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Serif Condensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 10, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerif-CondensedBlack.ttf", + "preferred_family_name": "Noto Serif", + "preferred_subfamily_name": "Condensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerif-CondensedBlackItalic.ttf||681224:1655828711.0": { + "family_name": "Noto Serif Condensed Black", + "font-family": "Noto Serif Condensed Black", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Serif Condensed Black Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 10, + 6, + 6, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerif-CondensedBlackItalic.ttf", + "preferred_family_name": "Noto Serif", + "preferred_subfamily_name": "Condensed Black Italic", + "subfamily_name": "Italic", + "weight": 900, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerif-CondensedBold.ttf||649356:1655828711.0": { + "family_name": "Noto Serif Condensed", + "font-family": "Noto Serif Condensed", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Serif Condensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 8, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerif-CondensedBold.ttf", + "preferred_family_name": "Noto Serif", + "preferred_subfamily_name": "Condensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerif-CondensedBoldItalic.ttf||677724:1655828711.0": { + "family_name": "Noto Serif Condensed", + "font-family": "Noto Serif Condensed", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Serif Condensed Bold Italic", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 8, + 6, + 6, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerif-CondensedBoldItalic.ttf", + "preferred_family_name": "Noto Serif", + "preferred_subfamily_name": "Condensed Bold Italic", + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerif-CondensedExtraBold.ttf||652112:1655828711.0": { + "family_name": "Noto Serif Condensed ExtraBold", + "font-family": "Noto Serif Condensed ExtraBold", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Serif Condensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 9, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerif-CondensedExtraBold.ttf", + "preferred_family_name": "Noto Serif", + "preferred_subfamily_name": "Condensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerif-CondensedExtraBoldItalic.ttf||683288:1655828711.0": { + "family_name": "Noto Serif Condensed ExtraBold", + "font-family": "Noto Serif Condensed ExtraBold", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Serif Condensed ExtraBold Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 9, + 6, + 6, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerif-CondensedExtraBoldItalic.ttf", + "preferred_family_name": "Noto Serif", + "preferred_subfamily_name": "Condensed ExtraBold Italic", + "subfamily_name": "Italic", + "weight": 800, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerif-CondensedExtraLight.ttf||622764:1655828711.0": { + "family_name": "Noto Serif Condensed ExtraLight", + "font-family": "Noto Serif Condensed ExtraLight", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Serif Condensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 3, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerif-CondensedExtraLight.ttf", + "preferred_family_name": "Noto Serif", + "preferred_subfamily_name": "Condensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerif-CondensedExtraLightItalic.ttf||639400:1655828711.0": { + "family_name": "Noto Serif Condensed ExtraLight", + "font-family": "Noto Serif Condensed ExtraLight", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Serif Condensed ExtraLight Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 3, + 6, + 6, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerif-CondensedExtraLightItalic.ttf", + "preferred_family_name": "Noto Serif", + "preferred_subfamily_name": "Condensed ExtraLight Italic", + "subfamily_name": "Italic", + "weight": 200, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerif-CondensedItalic.ttf||652452:1655828711.0": { + "family_name": "Noto Serif Condensed", + "font-family": "Noto Serif Condensed", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif Condensed Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 5, + 6, + 6, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerif-CondensedItalic.ttf", + "preferred_family_name": "Noto Serif", + "preferred_subfamily_name": "Condensed Italic", + "subfamily_name": "Italic", + "weight": 400, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerif-CondensedLight.ttf||614796:1655828711.0": { + "family_name": "Noto Serif Condensed Light", + "font-family": "Noto Serif Condensed Light", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Serif Condensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 4, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerif-CondensedLight.ttf", + "preferred_family_name": "Noto Serif", + "preferred_subfamily_name": "Condensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerif-CondensedLightItalic.ttf||643036:1655828711.0": { + "family_name": "Noto Serif Condensed Light", + "font-family": "Noto Serif Condensed Light", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Serif Condensed Light Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 4, + 6, + 6, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerif-CondensedLightItalic.ttf", + "preferred_family_name": "Noto Serif", + "preferred_subfamily_name": "Condensed Light Italic", + "subfamily_name": "Italic", + "weight": 300, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerif-CondensedMedium.ttf||627112:1655828711.0": { + "family_name": "Noto Serif Condensed Medium", + "font-family": "Noto Serif Condensed Medium", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Serif Condensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 6, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerif-CondensedMedium.ttf", + "preferred_family_name": "Noto Serif", + "preferred_subfamily_name": "Condensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerif-CondensedMediumItalic.ttf||659016:1655828711.0": { + "family_name": "Noto Serif Condensed Medium", + "font-family": "Noto Serif Condensed Medium", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Serif Condensed Medium Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 6, + 6, + 6, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerif-CondensedMediumItalic.ttf", + "preferred_family_name": "Noto Serif", + "preferred_subfamily_name": "Condensed Medium Italic", + "subfamily_name": "Italic", + "weight": 500, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerif-CondensedSemiBold.ttf||643536:1655828711.0": { + "family_name": "Noto Serif Condensed SemiBold", + "font-family": "Noto Serif Condensed SemiBold", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Serif Condensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 7, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerif-CondensedSemiBold.ttf", + "preferred_family_name": "Noto Serif", + "preferred_subfamily_name": "Condensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerif-CondensedSemiBoldItalic.ttf||677040:1655828711.0": { + "family_name": "Noto Serif Condensed SemiBold", + "font-family": "Noto Serif Condensed SemiBold", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Serif Condensed SemiBold Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 7, + 6, + 6, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerif-CondensedSemiBoldItalic.ttf", + "preferred_family_name": "Noto Serif", + "preferred_subfamily_name": "Condensed SemiBold Italic", + "subfamily_name": "Italic", + "weight": 600, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerif-CondensedThin.ttf||646440:1655828711.0": { + "family_name": "Noto Serif Condensed Thin", + "font-family": "Noto Serif Condensed Thin", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Serif Condensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 2, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerif-CondensedThin.ttf", + "preferred_family_name": "Noto Serif", + "preferred_subfamily_name": "Condensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerif-CondensedThinItalic.ttf||646816:1655828711.0": { + "family_name": "Noto Serif Condensed Thin", + "font-family": "Noto Serif Condensed Thin", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Serif Condensed Thin Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 2, + 6, + 6, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerif-CondensedThinItalic.ttf", + "preferred_family_name": "Noto Serif", + "preferred_subfamily_name": "Condensed Thin Italic", + "subfamily_name": "Italic", + "weight": 100, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerif-ExtraBold.ttf||655652:1655828711.0": { + "family_name": "Noto Serif ExtraBold", + "font-family": "Noto Serif ExtraBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Serif ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 9, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerif-ExtraBold.ttf", + "preferred_family_name": "Noto Serif", + "preferred_subfamily_name": "ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerif-ExtraBoldItalic.ttf||682248:1655828711.0": { + "family_name": "Noto Serif ExtraBold", + "font-family": "Noto Serif ExtraBold", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Serif ExtraBold Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 9, + 2, + 6, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerif-ExtraBoldItalic.ttf", + "preferred_family_name": "Noto Serif", + "preferred_subfamily_name": "ExtraBold Italic", + "subfamily_name": "Italic", + "weight": 800, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerif-ExtraCondensed.ttf||621144:1655828711.0": { + "family_name": "Noto Serif ExtraCondensed", + "font-family": "Noto Serif ExtraCondensed", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif ExtraCondensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 5, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerif-ExtraCondensed.ttf", + "preferred_family_name": "Noto Serif", + "preferred_subfamily_name": "ExtraCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerif-ExtraCondensedBlack.ttf||653568:1655828711.0": { + "family_name": "Noto Serif ExtraCondensed Black", + "font-family": "Noto Serif ExtraCondensed Black", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Serif ExtraCondensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 10, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerif-ExtraCondensedBlack.ttf", + "preferred_family_name": "Noto Serif", + "preferred_subfamily_name": "ExtraCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerif-ExtraCondensedBlackItalic.ttf||679864:1655828711.0": { + "family_name": "Noto Serif ExtraCondensed Black", + "font-family": "Noto Serif ExtraCondensed Black", + "font-stretch": "extra-condensed", + "font-style": "italic", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Serif ExtraCondensed Black Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 10, + 6, + 6, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerif-ExtraCondensedBlackItalic.ttf", + "preferred_family_name": "Noto Serif", + "preferred_subfamily_name": "ExtraCondensed Black Italic", + "subfamily_name": "Italic", + "weight": 900, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerif-ExtraCondensedBold.ttf||651076:1655828711.0": { + "family_name": "Noto Serif ExtraCondensed", + "font-family": "Noto Serif ExtraCondensed", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Serif ExtraCondensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 8, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerif-ExtraCondensedBold.ttf", + "preferred_family_name": "Noto Serif", + "preferred_subfamily_name": "ExtraCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerif-ExtraCondensedBoldItalic.ttf||680652:1655828711.0": { + "family_name": "Noto Serif ExtraCondensed", + "font-family": "Noto Serif ExtraCondensed", + "font-stretch": "extra-condensed", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Serif ExtraCondensed Bold Italic", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 8, + 6, + 6, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerif-ExtraCondensedBoldItalic.ttf", + "preferred_family_name": "Noto Serif", + "preferred_subfamily_name": "ExtraCondensed Bold Italic", + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerif-ExtraCondensedExtraBold.ttf||652120:1655828711.0": { + "family_name": "Noto Serif ExtraCondensed ExtraBold", + "font-family": "Noto Serif ExtraCondensed ExtraBold", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Serif ExtraCondensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 9, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerif-ExtraCondensedExtraBold.ttf", + "preferred_family_name": "Noto Serif", + "preferred_subfamily_name": "ExtraCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerif-ExtraCondensedExtraBoldItalic.ttf||679408:1655828711.0": { + "family_name": "Noto Serif ExtraCondensed ExtraBold", + "font-family": "Noto Serif ExtraCondensed ExtraBold", + "font-stretch": "extra-condensed", + "font-style": "italic", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Serif ExtraCondensed ExtraBold Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 9, + 6, + 6, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerif-ExtraCondensedExtraBoldItalic.ttf", + "preferred_family_name": "Noto Serif", + "preferred_subfamily_name": "ExtraCondensed ExtraBold Italic", + "subfamily_name": "Italic", + "weight": 800, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerif-ExtraCondensedExtraLight.ttf||621004:1655828711.0": { + "family_name": "Noto Serif ExtraCondensed ExtraLight", + "font-family": "Noto Serif ExtraCondensed ExtraLight", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Serif ExtraCondensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 3, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerif-ExtraCondensedExtraLight.ttf", + "preferred_family_name": "Noto Serif", + "preferred_subfamily_name": "ExtraCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerif-ExtraCondensedExtraLightItalic.ttf||642328:1655828711.0": { + "family_name": "Noto Serif ExtraCondensed ExtraLight", + "font-family": "Noto Serif ExtraCondensed ExtraLight", + "font-stretch": "extra-condensed", + "font-style": "italic", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Serif ExtraCondensed ExtraLight Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 3, + 6, + 6, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerif-ExtraCondensedExtraLightItalic.ttf", + "preferred_family_name": "Noto Serif", + "preferred_subfamily_name": "ExtraCondensed ExtraLight Italic", + "subfamily_name": "Italic", + "weight": 200, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerif-ExtraCondensedItalic.ttf||650476:1655828711.0": { + "family_name": "Noto Serif ExtraCondensed", + "font-family": "Noto Serif ExtraCondensed", + "font-stretch": "extra-condensed", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif ExtraCondensed Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 5, + 6, + 6, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerif-ExtraCondensedItalic.ttf", + "preferred_family_name": "Noto Serif", + "preferred_subfamily_name": "ExtraCondensed Italic", + "subfamily_name": "Italic", + "weight": 400, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerif-ExtraCondensedLight.ttf||611324:1655828711.0": { + "family_name": "Noto Serif ExtraCondensed Light", + "font-family": "Noto Serif ExtraCondensed Light", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Serif ExtraCondensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 4, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerif-ExtraCondensedLight.ttf", + "preferred_family_name": "Noto Serif", + "preferred_subfamily_name": "ExtraCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerif-ExtraCondensedLightItalic.ttf||639836:1655828711.0": { + "family_name": "Noto Serif ExtraCondensed Light", + "font-family": "Noto Serif ExtraCondensed Light", + "font-stretch": "extra-condensed", + "font-style": "italic", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Serif ExtraCondensed Light Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 4, + 6, + 6, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerif-ExtraCondensedLightItalic.ttf", + "preferred_family_name": "Noto Serif", + "preferred_subfamily_name": "ExtraCondensed Light Italic", + "subfamily_name": "Italic", + "weight": 300, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerif-ExtraCondensedMedium.ttf||631756:1655828711.0": { + "family_name": "Noto Serif ExtraCondensed Medium", + "font-family": "Noto Serif ExtraCondensed Medium", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Serif ExtraCondensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 6, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerif-ExtraCondensedMedium.ttf", + "preferred_family_name": "Noto Serif", + "preferred_subfamily_name": "ExtraCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerif-ExtraCondensedMediumItalic.ttf||658984:1655828711.0": { + "family_name": "Noto Serif ExtraCondensed Medium", + "font-family": "Noto Serif ExtraCondensed Medium", + "font-stretch": "extra-condensed", + "font-style": "italic", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Serif ExtraCondensed Medium Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 6, + 6, + 6, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerif-ExtraCondensedMediumItalic.ttf", + "preferred_family_name": "Noto Serif", + "preferred_subfamily_name": "ExtraCondensed Medium Italic", + "subfamily_name": "Italic", + "weight": 500, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerif-ExtraCondensedSemiBold.ttf||645424:1655828711.0": { + "family_name": "Noto Serif ExtraCondensed SemiBold", + "font-family": "Noto Serif ExtraCondensed SemiBold", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Serif ExtraCondensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 7, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerif-ExtraCondensedSemiBold.ttf", + "preferred_family_name": "Noto Serif", + "preferred_subfamily_name": "ExtraCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerif-ExtraCondensedSemiBoldItalic.ttf||676468:1655828711.0": { + "family_name": "Noto Serif ExtraCondensed SemiBold", + "font-family": "Noto Serif ExtraCondensed SemiBold", + "font-stretch": "extra-condensed", + "font-style": "italic", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Serif ExtraCondensed SemiBold Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 7, + 6, + 6, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerif-ExtraCondensedSemiBoldItalic.ttf", + "preferred_family_name": "Noto Serif", + "preferred_subfamily_name": "ExtraCondensed SemiBold Italic", + "subfamily_name": "Italic", + "weight": 600, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerif-ExtraCondensedThin.ttf||644344:1655828711.0": { + "family_name": "Noto Serif ExtraCondensed Thin", + "font-family": "Noto Serif ExtraCondensed Thin", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Serif ExtraCondensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 2, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerif-ExtraCondensedThin.ttf", + "preferred_family_name": "Noto Serif", + "preferred_subfamily_name": "ExtraCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerif-ExtraCondensedThinItalic.ttf||654520:1655828711.0": { + "family_name": "Noto Serif ExtraCondensed Thin", + "font-family": "Noto Serif ExtraCondensed Thin", + "font-stretch": "extra-condensed", + "font-style": "italic", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Serif ExtraCondensed Thin Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 2, + 6, + 6, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerif-ExtraCondensedThinItalic.ttf", + "preferred_family_name": "Noto Serif", + "preferred_subfamily_name": "ExtraCondensed Thin Italic", + "subfamily_name": "Italic", + "weight": 100, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerif-ExtraLight.ttf||614336:1655828711.0": { + "family_name": "Noto Serif ExtraLight", + "font-family": "Noto Serif ExtraLight", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Serif ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 3, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerif-ExtraLight.ttf", + "preferred_family_name": "Noto Serif", + "preferred_subfamily_name": "ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerif-ExtraLightItalic.ttf||634980:1655828711.0": { + "family_name": "Noto Serif ExtraLight", + "font-family": "Noto Serif ExtraLight", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Serif ExtraLight Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 3, + 2, + 6, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerif-ExtraLightItalic.ttf", + "preferred_family_name": "Noto Serif", + "preferred_subfamily_name": "ExtraLight Italic", + "subfamily_name": "Italic", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerif-Italic.ttf||657092:1655828711.0": { + "family_name": "Noto Serif Italic", + "font-family": "Noto Serif Italic", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif Italic", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 5, + 2, + 6, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerif-Italic.ttf", + "preferred_family_name": "Noto Serif", + "preferred_subfamily_name": "Italic", + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerif-Light.ttf||627220:1655828711.0": { + "family_name": "Noto Serif Light", + "font-family": "Noto Serif Light", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Serif Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 4, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerif-Light.ttf", + "preferred_family_name": "Noto Serif", + "preferred_subfamily_name": "Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerif-LightItalic.ttf||641384:1655828711.0": { + "family_name": "Noto Serif Light", + "font-family": "Noto Serif Light", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Serif Light Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 4, + 2, + 6, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerif-LightItalic.ttf", + "preferred_family_name": "Noto Serif", + "preferred_subfamily_name": "Light Italic", + "subfamily_name": "Italic", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerif-Medium.ttf||640104:1655828711.0": { + "family_name": "Noto Serif Medium", + "font-family": "Noto Serif Medium", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Serif Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 6, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerif-Medium.ttf", + "preferred_family_name": "Noto Serif", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerif-MediumItalic.ttf||678428:1655828711.0": { + "family_name": "Noto Serif Medium", + "font-family": "Noto Serif Medium", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Serif Medium Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 6, + 2, + 6, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerif-MediumItalic.ttf", + "preferred_family_name": "Noto Serif", + "preferred_subfamily_name": "Medium Italic", + "subfamily_name": "Italic", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerif-Regular.ttf||616196:1655828711.0": { + "family_name": "Noto Serif", + "font-family": "Noto Serif", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 5, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerif-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerif-SemiBold.ttf||640852:1655828711.0": { + "family_name": "Noto Serif SemiBold", + "font-family": "Noto Serif SemiBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Serif SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 7, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerif-SemiBold.ttf", + "preferred_family_name": "Noto Serif", + "preferred_subfamily_name": "SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerif-SemiBoldItalic.ttf||678712:1655828711.0": { + "family_name": "Noto Serif SemiBold", + "font-family": "Noto Serif SemiBold", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Serif SemiBold Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 7, + 2, + 6, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerif-SemiBoldItalic.ttf", + "preferred_family_name": "Noto Serif", + "preferred_subfamily_name": "SemiBold Italic", + "subfamily_name": "Italic", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerif-SemiCondensed.ttf||627412:1655828711.0": { + "family_name": "Noto Serif SemiCondensed", + "font-family": "Noto Serif SemiCondensed", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif SemiCondensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 5, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerif-SemiCondensed.ttf", + "preferred_family_name": "Noto Serif", + "preferred_subfamily_name": "SemiCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerif-SemiCondensedBlack.ttf||690888:1655828711.0": { + "family_name": "Noto Serif SemiCondensed Black", + "font-family": "Noto Serif SemiCondensed Black", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Serif SemiCondensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 10, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerif-SemiCondensedBlack.ttf", + "preferred_family_name": "Noto Serif", + "preferred_subfamily_name": "SemiCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerif-SemiCondensedBlackItalic.ttf||696236:1655828711.0": { + "family_name": "Noto Serif SemiCondensed Black", + "font-family": "Noto Serif SemiCondensed Black", + "font-stretch": "semi-condensed", + "font-style": "italic", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Serif SemiCondensed Black Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 10, + 2, + 6, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerif-SemiCondensedBlackItalic.ttf", + "preferred_family_name": "Noto Serif", + "preferred_subfamily_name": "SemiCondensed Black Italic", + "subfamily_name": "Italic", + "weight": 900, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerif-SemiCondensedBold.ttf||644832:1655828711.0": { + "family_name": "Noto Serif SemiCondensed", + "font-family": "Noto Serif SemiCondensed", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Serif SemiCondensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 8, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerif-SemiCondensedBold.ttf", + "preferred_family_name": "Noto Serif", + "preferred_subfamily_name": "SemiCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerif-SemiCondensedBoldItalic.ttf||676668:1655828711.0": { + "family_name": "Noto Serif SemiCondensed", + "font-family": "Noto Serif SemiCondensed", + "font-stretch": "semi-condensed", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Serif SemiCondensed Bold Italic", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 8, + 2, + 6, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerif-SemiCondensedBoldItalic.ttf", + "preferred_family_name": "Noto Serif", + "preferred_subfamily_name": "SemiCondensed Bold Italic", + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerif-SemiCondensedExtraBold.ttf||655104:1655828711.0": { + "family_name": "Noto Serif SemiCondensed ExtraBold", + "font-family": "Noto Serif SemiCondensed ExtraBold", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Serif SemiCondensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 9, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerif-SemiCondensedExtraBold.ttf", + "preferred_family_name": "Noto Serif", + "preferred_subfamily_name": "SemiCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerif-SemiCondensedExtraBoldItalic.ttf||681724:1655828711.0": { + "family_name": "Noto Serif SemiCondensed ExtraBold", + "font-family": "Noto Serif SemiCondensed ExtraBold", + "font-stretch": "semi-condensed", + "font-style": "italic", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Serif SemiCondensed ExtraBold Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 9, + 2, + 6, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerif-SemiCondensedExtraBoldItalic.ttf", + "preferred_family_name": "Noto Serif", + "preferred_subfamily_name": "SemiCondensed ExtraBold Italic", + "subfamily_name": "Italic", + "weight": 800, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerif-SemiCondensedExtraLight.ttf||617372:1655828711.0": { + "family_name": "Noto Serif SemiCondensed ExtraLight", + "font-family": "Noto Serif SemiCondensed ExtraLight", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Serif SemiCondensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 3, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerif-SemiCondensedExtraLight.ttf", + "preferred_family_name": "Noto Serif", + "preferred_subfamily_name": "SemiCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerif-SemiCondensedExtraLightItalic.ttf||637760:1655828711.0": { + "family_name": "Noto Serif SemiCondensed ExtraLight", + "font-family": "Noto Serif SemiCondensed ExtraLight", + "font-stretch": "semi-condensed", + "font-style": "italic", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Serif SemiCondensed ExtraLight Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 3, + 2, + 6, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerif-SemiCondensedExtraLightItalic.ttf", + "preferred_family_name": "Noto Serif", + "preferred_subfamily_name": "SemiCondensed ExtraLight Italic", + "subfamily_name": "Italic", + "weight": 200, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerif-SemiCondensedItalic.ttf||658324:1655828711.0": { + "family_name": "Noto Serif SemiCondensed", + "font-family": "Noto Serif SemiCondensed", + "font-stretch": "semi-condensed", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif SemiCondensed Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 5, + 2, + 6, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerif-SemiCondensedItalic.ttf", + "preferred_family_name": "Noto Serif", + "preferred_subfamily_name": "SemiCondensed Italic", + "subfamily_name": "Italic", + "weight": 400, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerif-SemiCondensedLight.ttf||630456:1655828711.0": { + "family_name": "Noto Serif SemiCondensed Light", + "font-family": "Noto Serif SemiCondensed Light", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Serif SemiCondensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 4, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerif-SemiCondensedLight.ttf", + "preferred_family_name": "Noto Serif", + "preferred_subfamily_name": "SemiCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerif-SemiCondensedLightItalic.ttf||644148:1655828711.0": { + "family_name": "Noto Serif SemiCondensed Light", + "font-family": "Noto Serif SemiCondensed Light", + "font-stretch": "semi-condensed", + "font-style": "italic", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Serif SemiCondensed Light Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 4, + 2, + 6, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerif-SemiCondensedLightItalic.ttf", + "preferred_family_name": "Noto Serif", + "preferred_subfamily_name": "SemiCondensed Light Italic", + "subfamily_name": "Italic", + "weight": 300, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerif-SemiCondensedMedium.ttf||650048:1655828711.0": { + "family_name": "Noto Serif SemiCondensed Medium", + "font-family": "Noto Serif SemiCondensed Medium", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Serif SemiCondensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 6, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerif-SemiCondensedMedium.ttf", + "preferred_family_name": "Noto Serif", + "preferred_subfamily_name": "SemiCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerif-SemiCondensedMediumItalic.ttf||658892:1655828711.0": { + "family_name": "Noto Serif SemiCondensed Medium", + "font-family": "Noto Serif SemiCondensed Medium", + "font-stretch": "semi-condensed", + "font-style": "italic", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Serif SemiCondensed Medium Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 6, + 2, + 6, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerif-SemiCondensedMediumItalic.ttf", + "preferred_family_name": "Noto Serif", + "preferred_subfamily_name": "SemiCondensed Medium Italic", + "subfamily_name": "Italic", + "weight": 500, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerif-SemiCondensedSemiBold.ttf||647048:1655828711.0": { + "family_name": "Noto Serif SemiCondensed SemiBold", + "font-family": "Noto Serif SemiCondensed SemiBold", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Serif SemiCondensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 7, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerif-SemiCondensedSemiBold.ttf", + "preferred_family_name": "Noto Serif", + "preferred_subfamily_name": "SemiCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerif-SemiCondensedSemiBoldItalic.ttf||679468:1655828711.0": { + "family_name": "Noto Serif SemiCondensed SemiBold", + "font-family": "Noto Serif SemiCondensed SemiBold", + "font-stretch": "semi-condensed", + "font-style": "italic", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Serif SemiCondensed SemiBold Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 7, + 2, + 6, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerif-SemiCondensedSemiBoldItalic.ttf", + "preferred_family_name": "Noto Serif", + "preferred_subfamily_name": "SemiCondensed SemiBold Italic", + "subfamily_name": "Italic", + "weight": 600, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerif-SemiCondensedThin.ttf||646032:1655828711.0": { + "family_name": "Noto Serif SemiCondensed Thin", + "font-family": "Noto Serif SemiCondensed Thin", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Serif SemiCondensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 2, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerif-SemiCondensedThin.ttf", + "preferred_family_name": "Noto Serif", + "preferred_subfamily_name": "SemiCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerif-SemiCondensedThinItalic.ttf||646532:1655828711.0": { + "family_name": "Noto Serif SemiCondensed Thin", + "font-family": "Noto Serif SemiCondensed Thin", + "font-stretch": "semi-condensed", + "font-style": "italic", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Serif SemiCondensed Thin Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 2, + 2, + 6, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerif-SemiCondensedThinItalic.ttf", + "preferred_family_name": "Noto Serif", + "preferred_subfamily_name": "SemiCondensed Thin Italic", + "subfamily_name": "Italic", + "weight": 100, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerif-Thin.ttf||652132:1655828711.0": { + "family_name": "Noto Serif Thin", + "font-family": "Noto Serif Thin", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Serif Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 2, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerif-Thin.ttf", + "preferred_family_name": "Noto Serif", + "preferred_subfamily_name": "Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerif-ThinItalic.ttf||653328:1655828711.0": { + "family_name": "Noto Serif Thin", + "font-family": "Noto Serif Thin", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Serif Thin Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 2, + 2, + 6, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerif-ThinItalic.ttf", + "preferred_family_name": "Noto Serif", + "preferred_subfamily_name": "Thin Italic", + "subfamily_name": "Italic", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifAhom-Regular.ttf||19536:1655828711.0": { + "family_name": "Noto Serif Ahom", + "font-family": "Noto Serif Ahom", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif Ahom Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 5, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifAhom-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifArmenian-Black.ttf||32492:1655828711.0": { + "family_name": "Noto Serif Armenian Black", + "font-family": "Noto Serif Armenian Black", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Serif Armenian Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 10, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifArmenian-Black.ttf", + "preferred_family_name": "Noto Serif Armenian", + "preferred_subfamily_name": "Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifArmenian-Bold.ttf||30412:1655828711.0": { + "family_name": "Noto Serif Armenian", + "font-family": "Noto Serif Armenian", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Serif Armenian Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 8, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifArmenian-Bold.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifArmenian-Condensed.ttf||33796:1655828711.0": { + "family_name": "Noto Serif Armenian Condensed", + "font-family": "Noto Serif Armenian Condensed", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif Armenian Condensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 5, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifArmenian-Condensed.ttf", + "preferred_family_name": "Noto Serif Armenian", + "preferred_subfamily_name": "Condensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifArmenian-CondensedBlack.ttf||35004:1655828711.0": { + "family_name": "Noto Serif Armenian Condensed Black", + "font-family": "Noto Serif Armenian Condensed Black", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Serif Armenian Condensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 10, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifArmenian-CondensedBlack.ttf", + "preferred_family_name": "Noto Serif Armenian", + "preferred_subfamily_name": "Condensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifArmenian-CondensedBold.ttf||29956:1655828711.0": { + "family_name": "Noto Serif Armenian Condensed", + "font-family": "Noto Serif Armenian Condensed", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Serif Armenian Condensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 8, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifArmenian-CondensedBold.ttf", + "preferred_family_name": "Noto Serif Armenian", + "preferred_subfamily_name": "Condensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifArmenian-CondensedExtraBold.ttf||31012:1655828711.0": { + "family_name": "Noto Serif Armenian Condensed ExtraBold", + "font-family": "Noto Serif Armenian Condensed ExtraBold", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Serif Armenian Condensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 9, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifArmenian-CondensedExtraBold.ttf", + "preferred_family_name": "Noto Serif Armenian", + "preferred_subfamily_name": "Condensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifArmenian-CondensedExtraLight.ttf||31088:1655828711.0": { + "family_name": "Noto Serif Armenian Condensed ExtraLight", + "font-family": "Noto Serif Armenian Condensed ExtraLight", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Serif Armenian Condensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 3, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifArmenian-CondensedExtraLight.ttf", + "preferred_family_name": "Noto Serif Armenian", + "preferred_subfamily_name": "Condensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifArmenian-CondensedLight.ttf||30624:1655828711.0": { + "family_name": "Noto Serif Armenian Condensed Light", + "font-family": "Noto Serif Armenian Condensed Light", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Serif Armenian Condensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 4, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifArmenian-CondensedLight.ttf", + "preferred_family_name": "Noto Serif Armenian", + "preferred_subfamily_name": "Condensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifArmenian-CondensedMedium.ttf||31400:1655828711.0": { + "family_name": "Noto Serif Armenian Condensed Medium", + "font-family": "Noto Serif Armenian Condensed Medium", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Serif Armenian Condensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 6, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifArmenian-CondensedMedium.ttf", + "preferred_family_name": "Noto Serif Armenian", + "preferred_subfamily_name": "Condensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifArmenian-CondensedSemiBold.ttf||30820:1655828711.0": { + "family_name": "Noto Serif Armenian Condensed SemiBold", + "font-family": "Noto Serif Armenian Condensed SemiBold", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Serif Armenian Condensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 7, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifArmenian-CondensedSemiBold.ttf", + "preferred_family_name": "Noto Serif Armenian", + "preferred_subfamily_name": "Condensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifArmenian-CondensedThin.ttf||32336:1655828711.0": { + "family_name": "Noto Serif Armenian Condensed Thin", + "font-family": "Noto Serif Armenian Condensed Thin", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Serif Armenian Condensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 2, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifArmenian-CondensedThin.ttf", + "preferred_family_name": "Noto Serif Armenian", + "preferred_subfamily_name": "Condensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifArmenian-ExtraBold.ttf||34668:1655828711.0": { + "family_name": "Noto Serif Armenian ExtraBold", + "font-family": "Noto Serif Armenian ExtraBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Serif Armenian ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 9, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifArmenian-ExtraBold.ttf", + "preferred_family_name": "Noto Serif Armenian", + "preferred_subfamily_name": "ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifArmenian-ExtraCondensed.ttf||32908:1655828711.0": { + "family_name": "Noto Serif Armenian ExtraCondensed", + "font-family": "Noto Serif Armenian ExtraCondensed", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif Armenian ExtraCondensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 5, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifArmenian-ExtraCondensed.ttf", + "preferred_family_name": "Noto Serif Armenian", + "preferred_subfamily_name": "ExtraCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifArmenian-ExtraCondensedBlack.ttf||34940:1655828711.0": { + "family_name": "Noto Serif Armenian ExtraCondensed Black", + "font-family": "Noto Serif Armenian ExtraCondensed Black", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Serif Armenian ExtraCondensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 10, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifArmenian-ExtraCondensedBlack.ttf", + "preferred_family_name": "Noto Serif Armenian", + "preferred_subfamily_name": "ExtraCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifArmenian-ExtraCondensedBold.ttf||29956:1655828711.0": { + "family_name": "Noto Serif Armenian ExtraCondensed", + "font-family": "Noto Serif Armenian ExtraCondensed", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Serif Armenian ExtraCondensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 8, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifArmenian-ExtraCondensedBold.ttf", + "preferred_family_name": "Noto Serif Armenian", + "preferred_subfamily_name": "ExtraCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifArmenian-ExtraCondensedExtraBold.ttf||30800:1655828711.0": { + "family_name": "Noto Serif Armenian ExtraCondensed ExtraBold", + "font-family": "Noto Serif Armenian ExtraCondensed ExtraBold", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Serif Armenian ExtraCondensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 9, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifArmenian-ExtraCondensedExtraBold.ttf", + "preferred_family_name": "Noto Serif Armenian", + "preferred_subfamily_name": "ExtraCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifArmenian-ExtraCondensedExtraLight.ttf||31092:1655828711.0": { + "family_name": "Noto Serif Armenian ExtraCondensed ExtraLight", + "font-family": "Noto Serif Armenian ExtraCondensed ExtraLight", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Serif Armenian ExtraCondensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 3, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifArmenian-ExtraCondensedExtraLight.ttf", + "preferred_family_name": "Noto Serif Armenian", + "preferred_subfamily_name": "ExtraCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifArmenian-ExtraCondensedLight.ttf||30724:1655828711.0": { + "family_name": "Noto Serif Armenian ExtraCondensed Light", + "font-family": "Noto Serif Armenian ExtraCondensed Light", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Serif Armenian ExtraCondensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 4, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifArmenian-ExtraCondensedLight.ttf", + "preferred_family_name": "Noto Serif Armenian", + "preferred_subfamily_name": "ExtraCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifArmenian-ExtraCondensedMedium.ttf||30332:1655828711.0": { + "family_name": "Noto Serif Armenian ExtraCondensed Medium", + "font-family": "Noto Serif Armenian ExtraCondensed Medium", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Serif Armenian ExtraCondensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 6, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifArmenian-ExtraCondensedMedium.ttf", + "preferred_family_name": "Noto Serif Armenian", + "preferred_subfamily_name": "ExtraCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifArmenian-ExtraCondensedSemiBold.ttf||29892:1655828711.0": { + "family_name": "Noto Serif Armenian ExtraCondensed SemiBold", + "font-family": "Noto Serif Armenian ExtraCondensed SemiBold", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Serif Armenian ExtraCondensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 7, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifArmenian-ExtraCondensedSemiBold.ttf", + "preferred_family_name": "Noto Serif Armenian", + "preferred_subfamily_name": "ExtraCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifArmenian-ExtraCondensedThin.ttf||29212:1655828711.0": { + "family_name": "Noto Serif Armenian ExtraCondensed Thin", + "font-family": "Noto Serif Armenian ExtraCondensed Thin", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Serif Armenian ExtraCondensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 2, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifArmenian-ExtraCondensedThin.ttf", + "preferred_family_name": "Noto Serif Armenian", + "preferred_subfamily_name": "ExtraCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifArmenian-ExtraLight.ttf||30872:1655828711.0": { + "family_name": "Noto Serif Armenian ExtraLight", + "font-family": "Noto Serif Armenian ExtraLight", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Serif Armenian ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 3, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifArmenian-ExtraLight.ttf", + "preferred_family_name": "Noto Serif Armenian", + "preferred_subfamily_name": "ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifArmenian-Light.ttf||30904:1655828711.0": { + "family_name": "Noto Serif Armenian Light", + "font-family": "Noto Serif Armenian Light", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Serif Armenian Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 4, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifArmenian-Light.ttf", + "preferred_family_name": "Noto Serif Armenian", + "preferred_subfamily_name": "Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifArmenian-Medium.ttf||31808:1655828711.0": { + "family_name": "Noto Serif Armenian Medium", + "font-family": "Noto Serif Armenian Medium", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Serif Armenian Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 6, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifArmenian-Medium.ttf", + "preferred_family_name": "Noto Serif Armenian", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifArmenian-Regular.ttf||31192:1655828711.0": { + "family_name": "Noto Serif Armenian", + "font-family": "Noto Serif Armenian", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif Armenian Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 5, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifArmenian-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifArmenian-SemiBold.ttf||31032:1655828711.0": { + "family_name": "Noto Serif Armenian SemiBold", + "font-family": "Noto Serif Armenian SemiBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Serif Armenian SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 7, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifArmenian-SemiBold.ttf", + "preferred_family_name": "Noto Serif Armenian", + "preferred_subfamily_name": "SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifArmenian-SemiCondensed.ttf||33544:1655828711.0": { + "family_name": "Noto Serif Armenian SemiCondensed", + "font-family": "Noto Serif Armenian SemiCondensed", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif Armenian SemiCondensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 5, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifArmenian-SemiCondensed.ttf", + "preferred_family_name": "Noto Serif Armenian", + "preferred_subfamily_name": "SemiCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifArmenian-SemiCondensedBlack.ttf||32460:1655828711.0": { + "family_name": "Noto Serif Armenian SemiCondensed Black", + "font-family": "Noto Serif Armenian SemiCondensed Black", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Serif Armenian SemiCondensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 10, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifArmenian-SemiCondensedBlack.ttf", + "preferred_family_name": "Noto Serif Armenian", + "preferred_subfamily_name": "SemiCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifArmenian-SemiCondensedBold.ttf||30224:1655828711.0": { + "family_name": "Noto Serif Armenian SemiCondensed", + "font-family": "Noto Serif Armenian SemiCondensed", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Serif Armenian SemiCondensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 8, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifArmenian-SemiCondensedBold.ttf", + "preferred_family_name": "Noto Serif Armenian", + "preferred_subfamily_name": "SemiCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifArmenian-SemiCondensedExtraBold.ttf||34912:1655828711.0": { + "family_name": "Noto Serif Armenian SemiCondensed ExtraBold", + "font-family": "Noto Serif Armenian SemiCondensed ExtraBold", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Serif Armenian SemiCondensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 9, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifArmenian-SemiCondensedExtraBold.ttf", + "preferred_family_name": "Noto Serif Armenian", + "preferred_subfamily_name": "SemiCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifArmenian-SemiCondensedExtraLight.ttf||30876:1655828711.0": { + "family_name": "Noto Serif Armenian SemiCondensed ExtraLight", + "font-family": "Noto Serif Armenian SemiCondensed ExtraLight", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Serif Armenian SemiCondensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 3, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifArmenian-SemiCondensedExtraLight.ttf", + "preferred_family_name": "Noto Serif Armenian", + "preferred_subfamily_name": "SemiCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifArmenian-SemiCondensedLight.ttf||31112:1655828711.0": { + "family_name": "Noto Serif Armenian SemiCondensed Light", + "font-family": "Noto Serif Armenian SemiCondensed Light", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Serif Armenian SemiCondensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 4, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifArmenian-SemiCondensedLight.ttf", + "preferred_family_name": "Noto Serif Armenian", + "preferred_subfamily_name": "SemiCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifArmenian-SemiCondensedMedium.ttf||30948:1655828711.0": { + "family_name": "Noto Serif Armenian SemiCondensed Medium", + "font-family": "Noto Serif Armenian SemiCondensed Medium", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Serif Armenian SemiCondensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 6, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifArmenian-SemiCondensedMedium.ttf", + "preferred_family_name": "Noto Serif Armenian", + "preferred_subfamily_name": "SemiCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifArmenian-SemiCondensedSemiBold.ttf||31948:1655828711.0": { + "family_name": "Noto Serif Armenian SemiCondensed SemiBold", + "font-family": "Noto Serif Armenian SemiCondensed SemiBold", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Serif Armenian SemiCondensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 7, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifArmenian-SemiCondensedSemiBold.ttf", + "preferred_family_name": "Noto Serif Armenian", + "preferred_subfamily_name": "SemiCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifArmenian-SemiCondensedThin.ttf||32284:1655828711.0": { + "family_name": "Noto Serif Armenian SemiCondensed Thin", + "font-family": "Noto Serif Armenian SemiCondensed Thin", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Serif Armenian SemiCondensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 2, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifArmenian-SemiCondensedThin.ttf", + "preferred_family_name": "Noto Serif Armenian", + "preferred_subfamily_name": "SemiCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifArmenian-Thin.ttf||30656:1655828711.0": { + "family_name": "Noto Serif Armenian Thin", + "font-family": "Noto Serif Armenian Thin", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Serif Armenian Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 2, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifArmenian-Thin.ttf", + "preferred_family_name": "Noto Serif Armenian", + "preferred_subfamily_name": "Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifBalinese-Regular.ttf||51976:1655828711.0": { + "family_name": "Noto Serif Balinese", + "font-family": "Noto Serif Balinese", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif Balinese Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 5, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifBalinese-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifBengali-Black.ttf||269600:1655828711.0": { + "family_name": "Noto Serif Bengali Black", + "font-family": "Noto Serif Bengali Black", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Serif Bengali Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 10, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifBengali-Black.ttf", + "preferred_family_name": "Noto Serif Bengali", + "preferred_subfamily_name": "Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifBengali-Bold.ttf||258728:1655828711.0": { + "family_name": "Noto Serif Bengali", + "font-family": "Noto Serif Bengali", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Serif Bengali Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 8, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifBengali-Bold.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifBengali-Condensed.ttf||249068:1655828711.0": { + "family_name": "Noto Serif Bengali Condensed", + "font-family": "Noto Serif Bengali Condensed", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif Bengali Condensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 5, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifBengali-Condensed.ttf", + "preferred_family_name": "Noto Serif Bengali", + "preferred_subfamily_name": "Condensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifBengali-CondensedBlack.ttf||260772:1655828711.0": { + "family_name": "Noto Serif Bengali Condensed Black", + "font-family": "Noto Serif Bengali Condensed Black", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Serif Bengali Condensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 10, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifBengali-CondensedBlack.ttf", + "preferred_family_name": "Noto Serif Bengali", + "preferred_subfamily_name": "Condensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifBengali-CondensedBold.ttf||255220:1655828711.0": { + "family_name": "Noto Serif Bengali Condensed", + "font-family": "Noto Serif Bengali Condensed", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Serif Bengali Condensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 8, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifBengali-CondensedBold.ttf", + "preferred_family_name": "Noto Serif Bengali", + "preferred_subfamily_name": "Condensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifBengali-CondensedExtraBold.ttf||261452:1655828711.0": { + "family_name": "Noto Serif Bengali Condensed ExtraBold", + "font-family": "Noto Serif Bengali Condensed ExtraBold", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Serif Bengali Condensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 9, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifBengali-CondensedExtraBold.ttf", + "preferred_family_name": "Noto Serif Bengali", + "preferred_subfamily_name": "Condensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifBengali-CondensedExtraLight.ttf||221508:1655828711.0": { + "family_name": "Noto Serif Bengali Condensed ExtraLight", + "font-family": "Noto Serif Bengali Condensed ExtraLight", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Serif Bengali Condensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 3, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifBengali-CondensedExtraLight.ttf", + "preferred_family_name": "Noto Serif Bengali", + "preferred_subfamily_name": "Condensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifBengali-CondensedLight.ttf||241400:1655828711.0": { + "family_name": "Noto Serif Bengali Condensed Light", + "font-family": "Noto Serif Bengali Condensed Light", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Serif Bengali Condensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 4, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifBengali-CondensedLight.ttf", + "preferred_family_name": "Noto Serif Bengali", + "preferred_subfamily_name": "Condensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifBengali-CondensedMedium.ttf||249244:1655828711.0": { + "family_name": "Noto Serif Bengali Condensed Medium", + "font-family": "Noto Serif Bengali Condensed Medium", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Serif Bengali Condensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 6, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifBengali-CondensedMedium.ttf", + "preferred_family_name": "Noto Serif Bengali", + "preferred_subfamily_name": "Condensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifBengali-CondensedSemiBold.ttf||257840:1655828711.0": { + "family_name": "Noto Serif Bengali Condensed SemiBold", + "font-family": "Noto Serif Bengali Condensed SemiBold", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Serif Bengali Condensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 7, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifBengali-CondensedSemiBold.ttf", + "preferred_family_name": "Noto Serif Bengali", + "preferred_subfamily_name": "Condensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifBengali-CondensedThin.ttf||226644:1655828711.0": { + "family_name": "Noto Serif Bengali Condensed Thin", + "font-family": "Noto Serif Bengali Condensed Thin", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Serif Bengali Condensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 2, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifBengali-CondensedThin.ttf", + "preferred_family_name": "Noto Serif Bengali", + "preferred_subfamily_name": "Condensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifBengali-ExtraBold.ttf||258908:1655828711.0": { + "family_name": "Noto Serif Bengali ExtraBold", + "font-family": "Noto Serif Bengali ExtraBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Serif Bengali ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 9, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifBengali-ExtraBold.ttf", + "preferred_family_name": "Noto Serif Bengali", + "preferred_subfamily_name": "ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifBengali-ExtraCondensed.ttf||247164:1655828711.0": { + "family_name": "Noto Serif Bengali ExtraCondensed", + "font-family": "Noto Serif Bengali ExtraCondensed", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif Bengali ExtraCondensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 5, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifBengali-ExtraCondensed.ttf", + "preferred_family_name": "Noto Serif Bengali", + "preferred_subfamily_name": "ExtraCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifBengali-ExtraCondensedBlack.ttf||253808:1655828711.0": { + "family_name": "Noto Serif Bengali ExtraCondensed Black", + "font-family": "Noto Serif Bengali ExtraCondensed Black", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Serif Bengali ExtraCondensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 10, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifBengali-ExtraCondensedBlack.ttf", + "preferred_family_name": "Noto Serif Bengali", + "preferred_subfamily_name": "ExtraCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifBengali-ExtraCondensedBold.ttf||257752:1655828711.0": { + "family_name": "Noto Serif Bengali ExtraCondensed", + "font-family": "Noto Serif Bengali ExtraCondensed", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Serif Bengali ExtraCondensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 8, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifBengali-ExtraCondensedBold.ttf", + "preferred_family_name": "Noto Serif Bengali", + "preferred_subfamily_name": "ExtraCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifBengali-ExtraCondensedExtraBold.ttf||257184:1655828711.0": { + "family_name": "Noto Serif Bengali ExtraCondensed ExtraBold", + "font-family": "Noto Serif Bengali ExtraCondensed ExtraBold", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Serif Bengali ExtraCondensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 9, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifBengali-ExtraCondensedExtraBold.ttf", + "preferred_family_name": "Noto Serif Bengali", + "preferred_subfamily_name": "ExtraCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifBengali-ExtraCondensedExtraLight.ttf||219160:1655828711.0": { + "family_name": "Noto Serif Bengali ExtraCondensed ExtraLight", + "font-family": "Noto Serif Bengali ExtraCondensed ExtraLight", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Serif Bengali ExtraCondensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 3, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifBengali-ExtraCondensedExtraLight.ttf", + "preferred_family_name": "Noto Serif Bengali", + "preferred_subfamily_name": "ExtraCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifBengali-ExtraCondensedLight.ttf||240620:1655828711.0": { + "family_name": "Noto Serif Bengali ExtraCondensed Light", + "font-family": "Noto Serif Bengali ExtraCondensed Light", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Serif Bengali ExtraCondensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 4, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifBengali-ExtraCondensedLight.ttf", + "preferred_family_name": "Noto Serif Bengali", + "preferred_subfamily_name": "ExtraCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifBengali-ExtraCondensedMedium.ttf||247872:1655828711.0": { + "family_name": "Noto Serif Bengali ExtraCondensed Medium", + "font-family": "Noto Serif Bengali ExtraCondensed Medium", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Serif Bengali ExtraCondensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 6, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifBengali-ExtraCondensedMedium.ttf", + "preferred_family_name": "Noto Serif Bengali", + "preferred_subfamily_name": "ExtraCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifBengali-ExtraCondensedSemiBold.ttf||252944:1655828711.0": { + "family_name": "Noto Serif Bengali ExtraCondensed SemiBold", + "font-family": "Noto Serif Bengali ExtraCondensed SemiBold", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Serif Bengali ExtraCondensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 7, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifBengali-ExtraCondensedSemiBold.ttf", + "preferred_family_name": "Noto Serif Bengali", + "preferred_subfamily_name": "ExtraCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifBengali-ExtraCondensedThin.ttf||225852:1655828711.0": { + "family_name": "Noto Serif Bengali ExtraCondensed Thin", + "font-family": "Noto Serif Bengali ExtraCondensed Thin", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Serif Bengali ExtraCondensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 2, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifBengali-ExtraCondensedThin.ttf", + "preferred_family_name": "Noto Serif Bengali", + "preferred_subfamily_name": "ExtraCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifBengali-ExtraLight.ttf||226220:1655828711.0": { + "family_name": "Noto Serif Bengali ExtraLight", + "font-family": "Noto Serif Bengali ExtraLight", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Serif Bengali ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 3, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifBengali-ExtraLight.ttf", + "preferred_family_name": "Noto Serif Bengali", + "preferred_subfamily_name": "ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifBengali-Light.ttf||233556:1655828711.0": { + "family_name": "Noto Serif Bengali Light", + "font-family": "Noto Serif Bengali Light", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Serif Bengali Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 4, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifBengali-Light.ttf", + "preferred_family_name": "Noto Serif Bengali", + "preferred_subfamily_name": "Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifBengali-Medium.ttf||256256:1655828711.0": { + "family_name": "Noto Serif Bengali Medium", + "font-family": "Noto Serif Bengali Medium", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Serif Bengali Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 6, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifBengali-Medium.ttf", + "preferred_family_name": "Noto Serif Bengali", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifBengali-Regular.ttf||263780:1655828711.0": { + "family_name": "Noto Serif Bengali", + "font-family": "Noto Serif Bengali", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif Bengali Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 5, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifBengali-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifBengali-SemiBold.ttf||255172:1655828711.0": { + "family_name": "Noto Serif Bengali SemiBold", + "font-family": "Noto Serif Bengali SemiBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Serif Bengali SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 7, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifBengali-SemiBold.ttf", + "preferred_family_name": "Noto Serif Bengali", + "preferred_subfamily_name": "SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifBengali-SemiCondensed.ttf||252272:1655828711.0": { + "family_name": "Noto Serif Bengali SemiCondensed", + "font-family": "Noto Serif Bengali SemiCondensed", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif Bengali SemiCondensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 5, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifBengali-SemiCondensed.ttf", + "preferred_family_name": "Noto Serif Bengali", + "preferred_subfamily_name": "SemiCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifBengali-SemiCondensedBlack.ttf||263204:1655828711.0": { + "family_name": "Noto Serif Bengali SemiCondensed Black", + "font-family": "Noto Serif Bengali SemiCondensed Black", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Serif Bengali SemiCondensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 10, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifBengali-SemiCondensedBlack.ttf", + "preferred_family_name": "Noto Serif Bengali", + "preferred_subfamily_name": "SemiCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifBengali-SemiCondensedBold.ttf||257304:1655828711.0": { + "family_name": "Noto Serif Bengali SemiCondensed", + "font-family": "Noto Serif Bengali SemiCondensed", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Serif Bengali SemiCondensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 8, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifBengali-SemiCondensedBold.ttf", + "preferred_family_name": "Noto Serif Bengali", + "preferred_subfamily_name": "SemiCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifBengali-SemiCondensedExtraBold.ttf||259700:1655828711.0": { + "family_name": "Noto Serif Bengali SemiCondensed ExtraBold", + "font-family": "Noto Serif Bengali SemiCondensed ExtraBold", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Serif Bengali SemiCondensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 9, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifBengali-SemiCondensedExtraBold.ttf", + "preferred_family_name": "Noto Serif Bengali", + "preferred_subfamily_name": "SemiCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifBengali-SemiCondensedExtraLight.ttf||223432:1655828711.0": { + "family_name": "Noto Serif Bengali SemiCondensed ExtraLight", + "font-family": "Noto Serif Bengali SemiCondensed ExtraLight", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Serif Bengali SemiCondensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 3, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifBengali-SemiCondensedExtraLight.ttf", + "preferred_family_name": "Noto Serif Bengali", + "preferred_subfamily_name": "SemiCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifBengali-SemiCondensedLight.ttf||240884:1655828711.0": { + "family_name": "Noto Serif Bengali SemiCondensed Light", + "font-family": "Noto Serif Bengali SemiCondensed Light", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Serif Bengali SemiCondensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 4, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifBengali-SemiCondensedLight.ttf", + "preferred_family_name": "Noto Serif Bengali", + "preferred_subfamily_name": "SemiCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifBengali-SemiCondensedMedium.ttf||250864:1655828711.0": { + "family_name": "Noto Serif Bengali SemiCondensed Medium", + "font-family": "Noto Serif Bengali SemiCondensed Medium", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Serif Bengali SemiCondensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 6, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifBengali-SemiCondensedMedium.ttf", + "preferred_family_name": "Noto Serif Bengali", + "preferred_subfamily_name": "SemiCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifBengali-SemiCondensedSemiBold.ttf||257612:1655828711.0": { + "family_name": "Noto Serif Bengali SemiCondensed SemiBold", + "font-family": "Noto Serif Bengali SemiCondensed SemiBold", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Serif Bengali SemiCondensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 7, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifBengali-SemiCondensedSemiBold.ttf", + "preferred_family_name": "Noto Serif Bengali", + "preferred_subfamily_name": "SemiCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifBengali-SemiCondensedThin.ttf||228460:1655828711.0": { + "family_name": "Noto Serif Bengali SemiCondensed Thin", + "font-family": "Noto Serif Bengali SemiCondensed Thin", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Serif Bengali SemiCondensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 2, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifBengali-SemiCondensedThin.ttf", + "preferred_family_name": "Noto Serif Bengali", + "preferred_subfamily_name": "SemiCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifBengali-Thin.ttf||235548:1655828711.0": { + "family_name": "Noto Serif Bengali Thin", + "font-family": "Noto Serif Bengali Thin", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Serif Bengali Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 2, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifBengali-Thin.ttf", + "preferred_family_name": "Noto Serif Bengali", + "preferred_subfamily_name": "Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifDevanagari-Black.ttf||274668:1655828711.0": { + "family_name": "Noto Serif Devanagari Black", + "font-family": "Noto Serif Devanagari Black", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Serif Devanagari Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 10, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifDevanagari-Black.ttf", + "preferred_family_name": "Noto Serif Devanagari", + "preferred_subfamily_name": "Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifDevanagari-Bold.ttf||278024:1655828711.0": { + "family_name": "Noto Serif Devanagari", + "font-family": "Noto Serif Devanagari", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Serif Devanagari Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 8, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifDevanagari-Bold.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifDevanagari-Condensed.ttf||265556:1655828711.0": { + "family_name": "Noto Serif Devanagari Condensed", + "font-family": "Noto Serif Devanagari Condensed", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif Devanagari Condensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 5, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifDevanagari-Condensed.ttf", + "preferred_family_name": "Noto Serif Devanagari", + "preferred_subfamily_name": "Condensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifDevanagari-CondensedBlack.ttf||281912:1655828711.0": { + "family_name": "Noto Serif Devanagari Condensed Black", + "font-family": "Noto Serif Devanagari Condensed Black", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Serif Devanagari Condensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 10, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifDevanagari-CondensedBlack.ttf", + "preferred_family_name": "Noto Serif Devanagari", + "preferred_subfamily_name": "Condensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifDevanagari-CondensedBold.ttf||277208:1655828711.0": { + "family_name": "Noto Serif Devanagari Condensed", + "font-family": "Noto Serif Devanagari Condensed", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Serif Devanagari Condensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 8, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifDevanagari-CondensedBold.ttf", + "preferred_family_name": "Noto Serif Devanagari", + "preferred_subfamily_name": "Condensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifDevanagari-CondensedExtraBold.ttf||279264:1655828711.0": { + "family_name": "Noto Serif Devanagari Condensed ExtraBold", + "font-family": "Noto Serif Devanagari Condensed ExtraBold", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Serif Devanagari Condensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 9, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifDevanagari-CondensedExtraBold.ttf", + "preferred_family_name": "Noto Serif Devanagari", + "preferred_subfamily_name": "Condensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifDevanagari-CondensedExtraLight.ttf||310348:1655828711.0": { + "family_name": "Noto Serif Devanagari Condensed ExtraLight", + "font-family": "Noto Serif Devanagari Condensed ExtraLight", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Serif Devanagari Condensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 3, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifDevanagari-CondensedExtraLight.ttf", + "preferred_family_name": "Noto Serif Devanagari", + "preferred_subfamily_name": "Condensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifDevanagari-CondensedLight.ttf||254952:1655828711.0": { + "family_name": "Noto Serif Devanagari Condensed Light", + "font-family": "Noto Serif Devanagari Condensed Light", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Serif Devanagari Condensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 4, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifDevanagari-CondensedLight.ttf", + "preferred_family_name": "Noto Serif Devanagari", + "preferred_subfamily_name": "Condensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifDevanagari-CondensedMedium.ttf||274912:1655828711.0": { + "family_name": "Noto Serif Devanagari Condensed Medium", + "font-family": "Noto Serif Devanagari Condensed Medium", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Serif Devanagari Condensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 6, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifDevanagari-CondensedMedium.ttf", + "preferred_family_name": "Noto Serif Devanagari", + "preferred_subfamily_name": "Condensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifDevanagari-CondensedSemiBold.ttf||276520:1655828711.0": { + "family_name": "Noto Serif Devanagari Condensed SemiBold", + "font-family": "Noto Serif Devanagari Condensed SemiBold", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Serif Devanagari Condensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 7, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifDevanagari-CondensedSemiBold.ttf", + "preferred_family_name": "Noto Serif Devanagari", + "preferred_subfamily_name": "Condensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifDevanagari-CondensedThin.ttf||319536:1655828711.0": { + "family_name": "Noto Serif Devanagari Condensed Thin", + "font-family": "Noto Serif Devanagari Condensed Thin", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Serif Devanagari Condensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 2, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifDevanagari-CondensedThin.ttf", + "preferred_family_name": "Noto Serif Devanagari", + "preferred_subfamily_name": "Condensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifDevanagari-ExtraBold.ttf||273996:1655828711.0": { + "family_name": "Noto Serif Devanagari ExtraBold", + "font-family": "Noto Serif Devanagari ExtraBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Serif Devanagari ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 9, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifDevanagari-ExtraBold.ttf", + "preferred_family_name": "Noto Serif Devanagari", + "preferred_subfamily_name": "ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifDevanagari-ExtraCondensed.ttf||264076:1655828711.0": { + "family_name": "Noto Serif Devanagari ExtraCondensed", + "font-family": "Noto Serif Devanagari ExtraCondensed", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif Devanagari ExtraCondensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 5, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifDevanagari-ExtraCondensed.ttf", + "preferred_family_name": "Noto Serif Devanagari", + "preferred_subfamily_name": "ExtraCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifDevanagari-ExtraCondensedBlack.ttf||280420:1655828711.0": { + "family_name": "Noto Serif Devanagari ExtraCondensed Black", + "font-family": "Noto Serif Devanagari ExtraCondensed Black", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Serif Devanagari ExtraCondensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 10, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifDevanagari-ExtraCondensedBlack.ttf", + "preferred_family_name": "Noto Serif Devanagari", + "preferred_subfamily_name": "ExtraCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifDevanagari-ExtraCondensedBold.ttf||276084:1655828711.0": { + "family_name": "Noto Serif Devanagari ExtraCondensed", + "font-family": "Noto Serif Devanagari ExtraCondensed", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Serif Devanagari ExtraCondensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 8, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifDevanagari-ExtraCondensedBold.ttf", + "preferred_family_name": "Noto Serif Devanagari", + "preferred_subfamily_name": "ExtraCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifDevanagari-ExtraCondensedExtraBold.ttf||277860:1655828711.0": { + "family_name": "Noto Serif Devanagari ExtraCondensed ExtraBold", + "font-family": "Noto Serif Devanagari ExtraCondensed ExtraBold", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Serif Devanagari ExtraCondensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 9, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifDevanagari-ExtraCondensedExtraBold.ttf", + "preferred_family_name": "Noto Serif Devanagari", + "preferred_subfamily_name": "ExtraCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifDevanagari-ExtraCondensedExtraLight.ttf||308516:1655828711.0": { + "family_name": "Noto Serif Devanagari ExtraCondensed ExtraLight", + "font-family": "Noto Serif Devanagari ExtraCondensed ExtraLight", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Serif Devanagari ExtraCondensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 3, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifDevanagari-ExtraCondensedExtraLight.ttf", + "preferred_family_name": "Noto Serif Devanagari", + "preferred_subfamily_name": "ExtraCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifDevanagari-ExtraCondensedLight.ttf||254620:1655828711.0": { + "family_name": "Noto Serif Devanagari ExtraCondensed Light", + "font-family": "Noto Serif Devanagari ExtraCondensed Light", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Serif Devanagari ExtraCondensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 4, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifDevanagari-ExtraCondensedLight.ttf", + "preferred_family_name": "Noto Serif Devanagari", + "preferred_subfamily_name": "ExtraCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifDevanagari-ExtraCondensedMedium.ttf||274036:1655828711.0": { + "family_name": "Noto Serif Devanagari ExtraCondensed Medium", + "font-family": "Noto Serif Devanagari ExtraCondensed Medium", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Serif Devanagari ExtraCondensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 6, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifDevanagari-ExtraCondensedMedium.ttf", + "preferred_family_name": "Noto Serif Devanagari", + "preferred_subfamily_name": "ExtraCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifDevanagari-ExtraCondensedSemiBold.ttf||272868:1655828711.0": { + "family_name": "Noto Serif Devanagari ExtraCondensed SemiBold", + "font-family": "Noto Serif Devanagari ExtraCondensed SemiBold", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Serif Devanagari ExtraCondensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 7, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifDevanagari-ExtraCondensedSemiBold.ttf", + "preferred_family_name": "Noto Serif Devanagari", + "preferred_subfamily_name": "ExtraCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifDevanagari-ExtraCondensedThin.ttf||318156:1655828711.0": { + "family_name": "Noto Serif Devanagari ExtraCondensed Thin", + "font-family": "Noto Serif Devanagari ExtraCondensed Thin", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Serif Devanagari ExtraCondensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 2, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifDevanagari-ExtraCondensedThin.ttf", + "preferred_family_name": "Noto Serif Devanagari", + "preferred_subfamily_name": "ExtraCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifDevanagari-ExtraLight.ttf||312540:1655828711.0": { + "family_name": "Noto Serif Devanagari ExtraLight", + "font-family": "Noto Serif Devanagari ExtraLight", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Serif Devanagari ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 3, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifDevanagari-ExtraLight.ttf", + "preferred_family_name": "Noto Serif Devanagari", + "preferred_subfamily_name": "ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifDevanagari-Light.ttf||255924:1655828711.0": { + "family_name": "Noto Serif Devanagari Light", + "font-family": "Noto Serif Devanagari Light", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Serif Devanagari Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 4, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifDevanagari-Light.ttf", + "preferred_family_name": "Noto Serif Devanagari", + "preferred_subfamily_name": "Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifDevanagari-Medium.ttf||279532:1655828711.0": { + "family_name": "Noto Serif Devanagari Medium", + "font-family": "Noto Serif Devanagari Medium", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Serif Devanagari Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 6, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifDevanagari-Medium.ttf", + "preferred_family_name": "Noto Serif Devanagari", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifDevanagari-Regular.ttf||262176:1655828711.0": { + "family_name": "Noto Serif Devanagari", + "font-family": "Noto Serif Devanagari", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif Devanagari Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 5, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifDevanagari-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifDevanagari-SemiBold.ttf||278604:1655828711.0": { + "family_name": "Noto Serif Devanagari SemiBold", + "font-family": "Noto Serif Devanagari SemiBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Serif Devanagari SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 7, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifDevanagari-SemiBold.ttf", + "preferred_family_name": "Noto Serif Devanagari", + "preferred_subfamily_name": "SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifDevanagari-SemiCondensed.ttf||265328:1655828711.0": { + "family_name": "Noto Serif Devanagari SemiCondensed", + "font-family": "Noto Serif Devanagari SemiCondensed", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif Devanagari SemiCondensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 5, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifDevanagari-SemiCondensed.ttf", + "preferred_family_name": "Noto Serif Devanagari", + "preferred_subfamily_name": "SemiCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifDevanagari-SemiCondensedBlack.ttf||275056:1655828711.0": { + "family_name": "Noto Serif Devanagari SemiCondensed Black", + "font-family": "Noto Serif Devanagari SemiCondensed Black", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Serif Devanagari SemiCondensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 10, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifDevanagari-SemiCondensedBlack.ttf", + "preferred_family_name": "Noto Serif Devanagari", + "preferred_subfamily_name": "SemiCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifDevanagari-SemiCondensedBold.ttf||276512:1655828711.0": { + "family_name": "Noto Serif Devanagari SemiCondensed", + "font-family": "Noto Serif Devanagari SemiCondensed", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Serif Devanagari SemiCondensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 8, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifDevanagari-SemiCondensedBold.ttf", + "preferred_family_name": "Noto Serif Devanagari", + "preferred_subfamily_name": "SemiCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifDevanagari-SemiCondensedExtraBold.ttf||270744:1655828711.0": { + "family_name": "Noto Serif Devanagari SemiCondensed ExtraBold", + "font-family": "Noto Serif Devanagari SemiCondensed ExtraBold", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Serif Devanagari SemiCondensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 9, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifDevanagari-SemiCondensedExtraBold.ttf", + "preferred_family_name": "Noto Serif Devanagari", + "preferred_subfamily_name": "SemiCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifDevanagari-SemiCondensedExtraLight.ttf||310748:1655828711.0": { + "family_name": "Noto Serif Devanagari SemiCondensed ExtraLight", + "font-family": "Noto Serif Devanagari SemiCondensed ExtraLight", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Serif Devanagari SemiCondensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 3, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifDevanagari-SemiCondensedExtraLight.ttf", + "preferred_family_name": "Noto Serif Devanagari", + "preferred_subfamily_name": "SemiCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifDevanagari-SemiCondensedLight.ttf||255596:1655828711.0": { + "family_name": "Noto Serif Devanagari SemiCondensed Light", + "font-family": "Noto Serif Devanagari SemiCondensed Light", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Serif Devanagari SemiCondensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 4, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifDevanagari-SemiCondensedLight.ttf", + "preferred_family_name": "Noto Serif Devanagari", + "preferred_subfamily_name": "SemiCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifDevanagari-SemiCondensedMedium.ttf||276876:1655828711.0": { + "family_name": "Noto Serif Devanagari SemiCondensed Medium", + "font-family": "Noto Serif Devanagari SemiCondensed Medium", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Serif Devanagari SemiCondensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 6, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifDevanagari-SemiCondensedMedium.ttf", + "preferred_family_name": "Noto Serif Devanagari", + "preferred_subfamily_name": "SemiCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifDevanagari-SemiCondensedSemiBold.ttf||276964:1655828711.0": { + "family_name": "Noto Serif Devanagari SemiCondensed SemiBold", + "font-family": "Noto Serif Devanagari SemiCondensed SemiBold", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Serif Devanagari SemiCondensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 7, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifDevanagari-SemiCondensedSemiBold.ttf", + "preferred_family_name": "Noto Serif Devanagari", + "preferred_subfamily_name": "SemiCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifDevanagari-SemiCondensedThin.ttf||320352:1655828711.0": { + "family_name": "Noto Serif Devanagari SemiCondensed Thin", + "font-family": "Noto Serif Devanagari SemiCondensed Thin", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Serif Devanagari SemiCondensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 2, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifDevanagari-SemiCondensedThin.ttf", + "preferred_family_name": "Noto Serif Devanagari", + "preferred_subfamily_name": "SemiCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifDevanagari-Thin.ttf||318688:1655828711.0": { + "family_name": "Noto Serif Devanagari Thin", + "font-family": "Noto Serif Devanagari Thin", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Serif Devanagari Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 2, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifDevanagari-Thin.ttf", + "preferred_family_name": "Noto Serif Devanagari", + "preferred_subfamily_name": "Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifDisplay-Black.ttf||642092:1655828711.0": { + "family_name": "Noto Serif Display Black", + "font-family": "Noto Serif Display Black", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Serif Display Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 10, + 2, + 8, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifDisplay-Black.ttf", + "preferred_family_name": "Noto Serif", + "preferred_subfamily_name": "Display Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifDisplay-BlackItalic.ttf||630392:1655828711.0": { + "family_name": "Noto Serif Display Black", + "font-family": "Noto Serif Display Black", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Serif Display Black Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 10, + 2, + 8, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifDisplay-BlackItalic.ttf", + "preferred_family_name": "Noto Serif Display", + "preferred_subfamily_name": "Black Italic", + "subfamily_name": "Italic", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifDisplay-Bold.ttf||596352:1655828711.0": { + "family_name": "Noto Serif Display Bold", + "font-family": "Noto Serif Display Bold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Serif Display Bold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 8, + 2, + 8, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifDisplay-Bold.ttf", + "preferred_family_name": "Noto Serif", + "preferred_subfamily_name": "Display Bold", + "subfamily_name": "Regular", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifDisplay-BoldItalic.ttf||614148:1655828711.0": { + "family_name": "Noto Serif Display Bold Italic", + "font-family": "Noto Serif Display Bold Italic", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Serif Display Bold Italic", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 8, + 2, + 8, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifDisplay-BoldItalic.ttf", + "preferred_family_name": "Noto Serif Display", + "preferred_subfamily_name": "Bold Italic", + "subfamily_name": "Regular", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifDisplay-Condensed.ttf||598668:1655828711.0": { + "family_name": "Noto Serif Display Condensed", + "font-family": "Noto Serif Display Condensed", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif Display Condensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 5, + 6, + 8, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifDisplay-Condensed.ttf", + "preferred_family_name": "Noto Serif", + "preferred_subfamily_name": "Display Condensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifDisplay-CondensedBlack.ttf||604416:1655828711.0": { + "family_name": "Noto Serif Display Condensed Black", + "font-family": "Noto Serif Display Condensed Black", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Serif Display Condensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 10, + 6, + 8, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifDisplay-CondensedBlack.ttf", + "preferred_family_name": "Noto Serif", + "preferred_subfamily_name": "Display Condensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifDisplay-CondensedBlackItalic.ttf||619968:1655828711.0": { + "family_name": "Noto Serif Display Condensed Black", + "font-family": "Noto Serif Display Condensed Black", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Serif Display Condensed Black Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 10, + 6, + 8, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifDisplay-CondensedBlackItalic.ttf", + "preferred_family_name": "Noto Serif Display", + "preferred_subfamily_name": "Condensed Black Italic", + "subfamily_name": "Italic", + "weight": 900, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifDisplay-CondensedBold.ttf||604956:1655828711.0": { + "family_name": "Noto Serif Condensed", + "font-family": "Noto Serif Condensed", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Serif Display Condensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 8, + 6, + 8, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifDisplay-CondensedBold.ttf", + "preferred_family_name": "Noto Serif", + "preferred_subfamily_name": "Display Condensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifDisplay-CondensedBoldItalic.ttf||619624:1655828711.0": { + "family_name": "Noto Serif Display Condensed", + "font-family": "Noto Serif Display Condensed", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Serif Display Condensed Bold Italic", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 8, + 6, + 8, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifDisplay-CondensedBoldItalic.ttf", + "preferred_family_name": "Noto Serif Display", + "preferred_subfamily_name": "Condensed Bold Italic", + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifDisplay-CondensedExtraBold.ttf||610612:1655828711.0": { + "family_name": "Noto Serif Display Condensed ExtraBold", + "font-family": "Noto Serif Display Condensed ExtraBold", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Serif Display Condensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 9, + 6, + 8, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifDisplay-CondensedExtraBold.ttf", + "preferred_family_name": "Noto Serif", + "preferred_subfamily_name": "Display Condensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifDisplay-CondensedExtraBoldItalic.ttf||619540:1655828711.0": { + "family_name": "Noto Serif Display Condensed ExtraBold", + "font-family": "Noto Serif Display Condensed ExtraBold", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Serif Display Condensed ExtraBold Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 9, + 6, + 8, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifDisplay-CondensedExtraBoldItalic.ttf", + "preferred_family_name": "Noto Serif Display", + "preferred_subfamily_name": "Condensed ExtraBold Italic", + "subfamily_name": "Italic", + "weight": 800, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifDisplay-CondensedExtraLight.ttf||614580:1655828711.0": { + "family_name": "Noto Serif Display Condensed ExtraLight", + "font-family": "Noto Serif Display Condensed ExtraLight", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Serif Display Condensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 3, + 6, + 8, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifDisplay-CondensedExtraLight.ttf", + "preferred_family_name": "Noto Serif", + "preferred_subfamily_name": "Display Condensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifDisplay-CondensedExtraLightItalic.ttf||618728:1655828711.0": { + "family_name": "Noto Serif Display Condensed ExtraLight", + "font-family": "Noto Serif Display Condensed ExtraLight", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Serif Display Condensed ExtraLight Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 3, + 6, + 8, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifDisplay-CondensedExtraLightItalic.ttf", + "preferred_family_name": "Noto Serif Display", + "preferred_subfamily_name": "Condensed ExtraLight Italic", + "subfamily_name": "Italic", + "weight": 200, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifDisplay-CondensedItalic.ttf||615188:1655828711.0": { + "family_name": "Noto Serif Display Condensed", + "font-family": "Noto Serif Display Condensed", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif Display Condensed Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 5, + 6, + 8, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifDisplay-CondensedItalic.ttf", + "preferred_family_name": "Noto Serif Display", + "preferred_subfamily_name": "Condensed Italic", + "subfamily_name": "Italic", + "weight": 400, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifDisplay-CondensedLight.ttf||610720:1655828711.0": { + "family_name": "Noto Serif Display Condensed Light", + "font-family": "Noto Serif Display Condensed Light", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Serif Display Condensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 4, + 6, + 8, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifDisplay-CondensedLight.ttf", + "preferred_family_name": "Noto Serif", + "preferred_subfamily_name": "Display Condensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifDisplay-CondensedLightItalic.ttf||619540:1655828711.0": { + "family_name": "Noto Serif Display Condensed Light", + "font-family": "Noto Serif Display Condensed Light", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Serif Display Condensed Light Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 4, + 6, + 8, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifDisplay-CondensedLightItalic.ttf", + "preferred_family_name": "Noto Serif Display", + "preferred_subfamily_name": "Condensed Light Italic", + "subfamily_name": "Italic", + "weight": 300, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifDisplay-CondensedMedium.ttf||597628:1655828711.0": { + "family_name": "Noto Serif Display Condensed Medium", + "font-family": "Noto Serif Display Condensed Medium", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Serif Display Condensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 6, + 6, + 8, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifDisplay-CondensedMedium.ttf", + "preferred_family_name": "Noto Serif", + "preferred_subfamily_name": "Display Condensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifDisplay-CondensedMediumItalic.ttf||616408:1655828711.0": { + "family_name": "Noto Serif Display Condensed Medium", + "font-family": "Noto Serif Display Condensed Medium", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Serif Display Condensed Medium Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 6, + 6, + 8, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifDisplay-CondensedMediumItalic.ttf", + "preferred_family_name": "Noto Serif Display", + "preferred_subfamily_name": "Condensed Medium Italic", + "subfamily_name": "Italic", + "weight": 500, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifDisplay-CondensedSemiBold.ttf||609608:1655828711.0": { + "family_name": "Noto Serif Display Condensed SemiBold", + "font-family": "Noto Serif Display Condensed SemiBold", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Serif Display Condensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 7, + 6, + 8, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifDisplay-CondensedSemiBold.ttf", + "preferred_family_name": "Noto Serif", + "preferred_subfamily_name": "Display Condensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifDisplay-CondensedSemiBoldItalic.ttf||617584:1655828711.0": { + "family_name": "Noto Serif Display Condensed SemiBold", + "font-family": "Noto Serif Display Condensed SemiBold", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Serif Display Condensed SemiBold Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 7, + 6, + 8, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifDisplay-CondensedSemiBoldItalic.ttf", + "preferred_family_name": "Noto Serif Display", + "preferred_subfamily_name": "Condensed SemiBold Italic", + "subfamily_name": "Italic", + "weight": 600, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifDisplay-CondensedThin.ttf||613648:1655828711.0": { + "family_name": "Noto Serif Display Condensed Thin", + "font-family": "Noto Serif Display Condensed Thin", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Serif Display Condensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 2, + 6, + 8, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifDisplay-CondensedThin.ttf", + "preferred_family_name": "Noto Serif", + "preferred_subfamily_name": "Display Condensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifDisplay-CondensedThinItalic.ttf||617088:1655828711.0": { + "family_name": "Noto Serif Display Condensed Thin", + "font-family": "Noto Serif Display Condensed Thin", + "font-stretch": "condensed", + "font-style": "italic", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Serif Display Condensed Thin Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 2, + 6, + 8, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifDisplay-CondensedThinItalic.ttf", + "preferred_family_name": "Noto Serif Display", + "preferred_subfamily_name": "Condensed Thin Italic", + "subfamily_name": "Italic", + "weight": 100, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifDisplay-ExtraBold.ttf||597780:1655828711.0": { + "family_name": "Noto Serif Display ExtraBold", + "font-family": "Noto Serif Display ExtraBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Serif Display ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 9, + 2, + 8, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifDisplay-ExtraBold.ttf", + "preferred_family_name": "Noto Serif", + "preferred_subfamily_name": "Display ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifDisplay-ExtraBoldItalic.ttf||618564:1655828711.0": { + "family_name": "Noto Serif Display ExtraBold", + "font-family": "Noto Serif Display ExtraBold", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Serif Display ExtraBold Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 9, + 2, + 8, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifDisplay-ExtraBoldItalic.ttf", + "preferred_family_name": "Noto Serif Display", + "preferred_subfamily_name": "ExtraBold Italic", + "subfamily_name": "Italic", + "weight": 800, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifDisplay-ExtraCondensed.ttf||605260:1655828711.0": { + "family_name": "Noto Serif Display ExtraCondensed", + "font-family": "Noto Serif Display ExtraCondensed", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif Display ExtraCondensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 5, + 6, + 8, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifDisplay-ExtraCondensed.ttf", + "preferred_family_name": "Noto Serif", + "preferred_subfamily_name": "Display ExtraCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifDisplay-ExtraCondensedBlack.ttf||605900:1655828711.0": { + "family_name": "Noto Serif Display ExtraCondensed Black", + "font-family": "Noto Serif Display ExtraCondensed Black", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Serif Display ExtraCondensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 10, + 6, + 8, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifDisplay-ExtraCondensedBlack.ttf", + "preferred_family_name": "Noto Serif", + "preferred_subfamily_name": "Display ExtraCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifDisplay-ExtraCondensedBlackItalic.ttf||618552:1655828711.0": { + "family_name": "Noto Serif Display ExtraCondensed Black", + "font-family": "Noto Serif Display ExtraCondensed Black", + "font-stretch": "extra-condensed", + "font-style": "italic", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Serif Display ExtraCondensed Black Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 10, + 6, + 8, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifDisplay-ExtraCondensedBlackItalic.ttf", + "preferred_family_name": "Noto Serif Display", + "preferred_subfamily_name": "ExtraCondensed Black Italic", + "subfamily_name": "Italic", + "weight": 900, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifDisplay-ExtraCondensedBold.ttf||606592:1655828711.0": { + "family_name": "Noto Serif ExtraCondensed", + "font-family": "Noto Serif ExtraCondensed", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Serif Display ExtraCondensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 8, + 6, + 8, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifDisplay-ExtraCondensedBold.ttf", + "preferred_family_name": "Noto Serif", + "preferred_subfamily_name": "Display ExtraCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifDisplay-ExtraCondensedBoldItalic.ttf||615832:1655828711.0": { + "family_name": "Noto Serif Display ExtraCondensed", + "font-family": "Noto Serif Display ExtraCondensed", + "font-stretch": "extra-condensed", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Serif Display ExtraCondensed Bold Italic", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 8, + 6, + 8, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifDisplay-ExtraCondensedBoldItalic.ttf", + "preferred_family_name": "Noto Serif Display", + "preferred_subfamily_name": "ExtraCondensed Bold Italic", + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifDisplay-ExtraCondensedExtraBold.ttf||606148:1655828711.0": { + "family_name": "Noto Serif Display ExtraCondensed ExtraBold", + "font-family": "Noto Serif Display ExtraCondensed ExtraBold", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Serif Display ExtraCondensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 9, + 6, + 8, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifDisplay-ExtraCondensedExtraBold.ttf", + "preferred_family_name": "Noto Serif", + "preferred_subfamily_name": "Display ExtraCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifDisplay-ExtraCondensedExtraBoldItalic.ttf||617432:1655828711.0": { + "family_name": "Noto Serif Display ExtraCondensed ExtraBold", + "font-family": "Noto Serif Display ExtraCondensed ExtraBold", + "font-stretch": "extra-condensed", + "font-style": "italic", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Serif Display ExtraCondensed ExtraBold Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 9, + 6, + 8, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifDisplay-ExtraCondensedExtraBoldItalic.ttf", + "preferred_family_name": "Noto Serif Display", + "preferred_subfamily_name": "ExtraCondensed ExtraBold Italic", + "subfamily_name": "Italic", + "weight": 800, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifDisplay-ExtraCondensedExtraLight.ttf||606668:1655828711.0": { + "family_name": "Noto Serif Display ExtraCondensed ExtraLight", + "font-family": "Noto Serif Display ExtraCondensed ExtraLight", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Serif Display ExtraCondensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 3, + 6, + 8, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifDisplay-ExtraCondensedExtraLight.ttf", + "preferred_family_name": "Noto Serif", + "preferred_subfamily_name": "Display ExtraCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifDisplay-ExtraCondensedExtraLightItalic.ttf||616880:1655828711.0": { + "family_name": "Noto Serif Display ExtraCondensed ExtraLight", + "font-family": "Noto Serif Display ExtraCondensed ExtraLight", + "font-stretch": "extra-condensed", + "font-style": "italic", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Serif Display ExtraCondensed ExtraLight Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 3, + 6, + 8, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifDisplay-ExtraCondensedExtraLightItalic.ttf", + "preferred_family_name": "Noto Serif Display", + "preferred_subfamily_name": "ExtraCondensed ExtraLight Italic", + "subfamily_name": "Italic", + "weight": 200, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifDisplay-ExtraCondensedItalic.ttf||613668:1655828711.0": { + "family_name": "Noto Serif Display ExtraCondensed", + "font-family": "Noto Serif Display ExtraCondensed", + "font-stretch": "extra-condensed", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif Display ExtraCondensed Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 5, + 6, + 8, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifDisplay-ExtraCondensedItalic.ttf", + "preferred_family_name": "Noto Serif Display", + "preferred_subfamily_name": "ExtraCondensed Italic", + "subfamily_name": "Italic", + "weight": 400, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifDisplay-ExtraCondensedLight.ttf||602652:1655828711.0": { + "family_name": "Noto Serif Display ExtraCondensed Light", + "font-family": "Noto Serif Display ExtraCondensed Light", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Serif Display ExtraCondensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 4, + 6, + 8, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifDisplay-ExtraCondensedLight.ttf", + "preferred_family_name": "Noto Serif", + "preferred_subfamily_name": "Display ExtraCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifDisplay-ExtraCondensedLightItalic.ttf||612968:1655828711.0": { + "family_name": "Noto Serif Display ExtraCondensed Light", + "font-family": "Noto Serif Display ExtraCondensed Light", + "font-stretch": "extra-condensed", + "font-style": "italic", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Serif Display ExtraCondensed Light Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 4, + 6, + 8, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifDisplay-ExtraCondensedLightItalic.ttf", + "preferred_family_name": "Noto Serif Display", + "preferred_subfamily_name": "ExtraCondensed Light Italic", + "subfamily_name": "Italic", + "weight": 300, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifDisplay-ExtraCondensedMedium.ttf||599608:1655828711.0": { + "family_name": "Noto Serif Display ExtraCondensed Medium", + "font-family": "Noto Serif Display ExtraCondensed Medium", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Serif Display ExtraCondensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 6, + 6, + 8, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifDisplay-ExtraCondensedMedium.ttf", + "preferred_family_name": "Noto Serif", + "preferred_subfamily_name": "Display ExtraCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifDisplay-ExtraCondensedMediumItalic.ttf||612620:1655828711.0": { + "family_name": "Noto Serif Display ExtraCondensed Medium", + "font-family": "Noto Serif Display ExtraCondensed Medium", + "font-stretch": "extra-condensed", + "font-style": "italic", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Serif Display ExtraCondensed Medium Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 6, + 6, + 8, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifDisplay-ExtraCondensedMediumItalic.ttf", + "preferred_family_name": "Noto Serif Display", + "preferred_subfamily_name": "ExtraCondensed Medium Italic", + "subfamily_name": "Italic", + "weight": 500, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifDisplay-ExtraCondensedSemiBold.ttf||603624:1655828711.0": { + "family_name": "Noto Serif Display ExtraCondensed SemiBold", + "font-family": "Noto Serif Display ExtraCondensed SemiBold", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Serif Display ExtraCondensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 7, + 6, + 8, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifDisplay-ExtraCondensedSemiBold.ttf", + "preferred_family_name": "Noto Serif", + "preferred_subfamily_name": "Display ExtraCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifDisplay-ExtraCondensedSemiBoldItalic.ttf||613104:1655828711.0": { + "family_name": "Noto Serif Display ExtraCondensed SemiBold", + "font-family": "Noto Serif Display ExtraCondensed SemiBold", + "font-stretch": "extra-condensed", + "font-style": "italic", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Serif Display ExtraCondensed SemiBold Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 7, + 6, + 8, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifDisplay-ExtraCondensedSemiBoldItalic.ttf", + "preferred_family_name": "Noto Serif Display", + "preferred_subfamily_name": "ExtraCondensed SemiBold Italic", + "subfamily_name": "Italic", + "weight": 600, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifDisplay-ExtraCondensedThin.ttf||604720:1655828711.0": { + "family_name": "Noto Serif Display ExtraCondensed Thin", + "font-family": "Noto Serif Display ExtraCondensed Thin", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Serif Display ExtraCondensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 2, + 6, + 8, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifDisplay-ExtraCondensedThin.ttf", + "preferred_family_name": "Noto Serif", + "preferred_subfamily_name": "Display ExtraCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifDisplay-ExtraCondensedThinItalic.ttf||614932:1655828711.0": { + "family_name": "Noto Serif Display ExtraCondensed Thin", + "font-family": "Noto Serif Display ExtraCondensed Thin", + "font-stretch": "extra-condensed", + "font-style": "italic", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Serif Display ExtraCondensed Thin Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 2, + 6, + 8, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifDisplay-ExtraCondensedThinItalic.ttf", + "preferred_family_name": "Noto Serif Display", + "preferred_subfamily_name": "ExtraCondensed Thin Italic", + "subfamily_name": "Italic", + "weight": 100, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifDisplay-ExtraLight.ttf||608652:1655828711.0": { + "family_name": "Noto Serif Display ExtraLight", + "font-family": "Noto Serif Display ExtraLight", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Serif Display ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 3, + 2, + 8, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifDisplay-ExtraLight.ttf", + "preferred_family_name": "Noto Serif", + "preferred_subfamily_name": "Display ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifDisplay-ExtraLightItalic.ttf||618508:1655828711.0": { + "family_name": "Noto Serif Display ExtraLight", + "font-family": "Noto Serif Display ExtraLight", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Serif Display ExtraLight Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 3, + 2, + 8, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifDisplay-ExtraLightItalic.ttf", + "preferred_family_name": "Noto Serif Display", + "preferred_subfamily_name": "ExtraLight Italic", + "subfamily_name": "Italic", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifDisplay-Italic.ttf||611472:1655828711.0": { + "family_name": "Noto Serif Display Italic", + "font-family": "Noto Serif Display Italic", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif Display Italic", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 5, + 2, + 8, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifDisplay-Italic.ttf", + "preferred_family_name": "Noto Serif Display", + "preferred_subfamily_name": "Italic", + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifDisplay-Light.ttf||596456:1655828711.0": { + "family_name": "Noto Serif Display Light", + "font-family": "Noto Serif Display Light", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Serif Display Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 4, + 2, + 8, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifDisplay-Light.ttf", + "preferred_family_name": "Noto Serif", + "preferred_subfamily_name": "Display Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifDisplay-LightItalic.ttf||611728:1655828711.0": { + "family_name": "Noto Serif Display Light", + "font-family": "Noto Serif Display Light", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Serif Display Light Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 4, + 2, + 8, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifDisplay-LightItalic.ttf", + "preferred_family_name": "Noto Serif Display", + "preferred_subfamily_name": "Light Italic", + "subfamily_name": "Italic", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifDisplay-Medium.ttf||595196:1655828711.0": { + "family_name": "Noto Serif Display Medium", + "font-family": "Noto Serif Display Medium", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Serif Display Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 6, + 2, + 8, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifDisplay-Medium.ttf", + "preferred_family_name": "Noto Serif", + "preferred_subfamily_name": "Display Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifDisplay-MediumItalic.ttf||614588:1655828711.0": { + "family_name": "Noto Serif Display Medium", + "font-family": "Noto Serif Display Medium", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Serif Display Medium Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 6, + 2, + 8, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifDisplay-MediumItalic.ttf", + "preferred_family_name": "Noto Serif Display", + "preferred_subfamily_name": "Medium Italic", + "subfamily_name": "Italic", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifDisplay-Regular.ttf||586068:1655828711.0": { + "family_name": "Noto Serif Display", + "font-family": "Noto Serif Display", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif Display Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 5, + 2, + 8, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifDisplay-Regular.ttf", + "preferred_family_name": "Noto Serif", + "preferred_subfamily_name": "Display Regular", + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifDisplay-SemiBold.ttf||594140:1655828711.0": { + "family_name": "Noto Serif Display SemiBold", + "font-family": "Noto Serif Display SemiBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Serif Display SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 7, + 2, + 8, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifDisplay-SemiBold.ttf", + "preferred_family_name": "Noto Serif", + "preferred_subfamily_name": "Display SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifDisplay-SemiBoldItalic.ttf||616008:1655828711.0": { + "family_name": "Noto Serif Display SemiBold", + "font-family": "Noto Serif Display SemiBold", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Serif Display SemiBold Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 7, + 2, + 8, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifDisplay-SemiBoldItalic.ttf", + "preferred_family_name": "Noto Serif Display", + "preferred_subfamily_name": "SemiBold Italic", + "subfamily_name": "Italic", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifDisplay-SemiCondensed.ttf||602852:1655828711.0": { + "family_name": "Noto Serif Display SemiCondensed", + "font-family": "Noto Serif Display SemiCondensed", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif Display SemiCondensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 5, + 2, + 8, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifDisplay-SemiCondensed.ttf", + "preferred_family_name": "Noto Serif", + "preferred_subfamily_name": "Display SemiCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifDisplay-SemiCondensedBlack.ttf||642040:1655828711.0": { + "family_name": "Noto Serif Display SemiCondensed Black", + "font-family": "Noto Serif Display SemiCondensed Black", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Serif Display SemiCondensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 10, + 2, + 8, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifDisplay-SemiCondensedBlack.ttf", + "preferred_family_name": "Noto Serif", + "preferred_subfamily_name": "Display SemiCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifDisplay-SemiCondensedBlackItalic.ttf||633764:1655828711.0": { + "family_name": "Noto Serif Display SemiCondensed Black", + "font-family": "Noto Serif Display SemiCondensed Black", + "font-stretch": "semi-condensed", + "font-style": "italic", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Serif Display SemiCondensed Black Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 10, + 2, + 8, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifDisplay-SemiCondensedBlackItalic.ttf", + "preferred_family_name": "Noto Serif Display", + "preferred_subfamily_name": "SemiCondensed Black Italic", + "subfamily_name": "Italic", + "weight": 900, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifDisplay-SemiCondensedBold.ttf||597032:1655828711.0": { + "family_name": "Noto Serif SemiCondensed", + "font-family": "Noto Serif SemiCondensed", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Serif Display SemiCondensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 8, + 2, + 8, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifDisplay-SemiCondensedBold.ttf", + "preferred_family_name": "Noto Serif", + "preferred_subfamily_name": "Display SemiCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifDisplay-SemiCondensedBoldItalic.ttf||619656:1655828711.0": { + "family_name": "Noto Serif Display SemiCondensed", + "font-family": "Noto Serif Display SemiCondensed", + "font-stretch": "semi-condensed", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Serif Display SemiCondensed Bold Italic", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 8, + 2, + 8, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifDisplay-SemiCondensedBoldItalic.ttf", + "preferred_family_name": "Noto Serif Display", + "preferred_subfamily_name": "SemiCondensed Bold Italic", + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifDisplay-SemiCondensedExtraBold.ttf||604600:1655828711.0": { + "family_name": "Noto Serif Display SemiCondensed ExtraBold", + "font-family": "Noto Serif Display SemiCondensed ExtraBold", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Serif Display SemiCondensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 9, + 2, + 8, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifDisplay-SemiCondensedExtraBold.ttf", + "preferred_family_name": "Noto Serif", + "preferred_subfamily_name": "Display SemiCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifDisplay-SemiCondensedExtraBoldItalic.ttf||622876:1655828711.0": { + "family_name": "Noto Serif Display SemiCondensed ExtraBold", + "font-family": "Noto Serif Display SemiCondensed ExtraBold", + "font-stretch": "semi-condensed", + "font-style": "italic", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Serif Display SemiCondensed ExtraBold Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 9, + 2, + 8, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifDisplay-SemiCondensedExtraBoldItalic.ttf", + "preferred_family_name": "Noto Serif Display", + "preferred_subfamily_name": "SemiCondensed ExtraBold Italic", + "subfamily_name": "Italic", + "weight": 800, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifDisplay-SemiCondensedExtraLight.ttf||612792:1655828711.0": { + "family_name": "Noto Serif Display SemiCondensed ExtraLight", + "font-family": "Noto Serif Display SemiCondensed ExtraLight", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Serif Display SemiCondensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 3, + 2, + 8, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifDisplay-SemiCondensedExtraLight.ttf", + "preferred_family_name": "Noto Serif", + "preferred_subfamily_name": "Display SemiCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifDisplay-SemiCondensedExtraLightItalic.ttf||621188:1655828711.0": { + "family_name": "Noto Serif Display SemiCondensed ExtraLight", + "font-family": "Noto Serif Display SemiCondensed ExtraLight", + "font-stretch": "semi-condensed", + "font-style": "italic", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Serif Display SemiCondensed ExtraLight Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 3, + 2, + 8, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifDisplay-SemiCondensedExtraLightItalic.ttf", + "preferred_family_name": "Noto Serif Display", + "preferred_subfamily_name": "SemiCondensed ExtraLight Italic", + "subfamily_name": "Italic", + "weight": 200, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifDisplay-SemiCondensedItalic.ttf||618480:1655828711.0": { + "family_name": "Noto Serif Display SemiCondensed", + "font-family": "Noto Serif Display SemiCondensed", + "font-stretch": "semi-condensed", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif Display SemiCondensed Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 5, + 2, + 8, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifDisplay-SemiCondensedItalic.ttf", + "preferred_family_name": "Noto Serif Display", + "preferred_subfamily_name": "SemiCondensed Italic", + "subfamily_name": "Italic", + "weight": 400, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifDisplay-SemiCondensedLight.ttf||605056:1655828711.0": { + "family_name": "Noto Serif Display SemiCondensed Light", + "font-family": "Noto Serif Display SemiCondensed Light", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Serif Display SemiCondensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 4, + 2, + 8, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifDisplay-SemiCondensedLight.ttf", + "preferred_family_name": "Noto Serif", + "preferred_subfamily_name": "Display SemiCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifDisplay-SemiCondensedLightItalic.ttf||619232:1655828711.0": { + "family_name": "Noto Serif Display SemiCondensed Light", + "font-family": "Noto Serif Display SemiCondensed Light", + "font-stretch": "semi-condensed", + "font-style": "italic", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Serif Display SemiCondensed Light Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 4, + 2, + 8, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifDisplay-SemiCondensedLightItalic.ttf", + "preferred_family_name": "Noto Serif Display", + "preferred_subfamily_name": "SemiCondensed Light Italic", + "subfamily_name": "Italic", + "weight": 300, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifDisplay-SemiCondensedMedium.ttf||601304:1655828711.0": { + "family_name": "Noto Serif Display SemiCondensed Medium", + "font-family": "Noto Serif Display SemiCondensed Medium", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Serif Display SemiCondensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 6, + 2, + 8, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifDisplay-SemiCondensedMedium.ttf", + "preferred_family_name": "Noto Serif", + "preferred_subfamily_name": "Display SemiCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifDisplay-SemiCondensedMediumItalic.ttf||616908:1655828711.0": { + "family_name": "Noto Serif Display SemiCondensed Medium", + "font-family": "Noto Serif Display SemiCondensed Medium", + "font-stretch": "semi-condensed", + "font-style": "italic", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Serif Display SemiCondensed Medium Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 6, + 2, + 8, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifDisplay-SemiCondensedMediumItalic.ttf", + "preferred_family_name": "Noto Serif Display", + "preferred_subfamily_name": "SemiCondensed Medium Italic", + "subfamily_name": "Italic", + "weight": 500, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifDisplay-SemiCondensedSemiBold.ttf||602816:1655828711.0": { + "family_name": "Noto Serif Display SemiCondensed SemiBold", + "font-family": "Noto Serif Display SemiCondensed SemiBold", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Serif Display SemiCondensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 7, + 2, + 8, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifDisplay-SemiCondensedSemiBold.ttf", + "preferred_family_name": "Noto Serif", + "preferred_subfamily_name": "Display SemiCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifDisplay-SemiCondensedSemiBoldItalic.ttf||617824:1655828711.0": { + "family_name": "Noto Serif Display SemiCondensed SemiBold", + "font-family": "Noto Serif Display SemiCondensed SemiBold", + "font-stretch": "semi-condensed", + "font-style": "italic", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Serif Display SemiCondensed SemiBold Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 7, + 2, + 8, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifDisplay-SemiCondensedSemiBoldItalic.ttf", + "preferred_family_name": "Noto Serif Display", + "preferred_subfamily_name": "SemiCondensed SemiBold Italic", + "subfamily_name": "Italic", + "weight": 600, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifDisplay-SemiCondensedThin.ttf||611752:1655828711.0": { + "family_name": "Noto Serif Display SemiCondensed Thin", + "font-family": "Noto Serif Display SemiCondensed Thin", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Serif Display SemiCondensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 2, + 2, + 8, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifDisplay-SemiCondensedThin.ttf", + "preferred_family_name": "Noto Serif", + "preferred_subfamily_name": "Display SemiCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifDisplay-SemiCondensedThinItalic.ttf||617760:1655828711.0": { + "family_name": "Noto Serif Display SemiCondensed Thin", + "font-family": "Noto Serif Display SemiCondensed Thin", + "font-stretch": "semi-condensed", + "font-style": "italic", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Serif Display SemiCondensed Thin Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 2, + 2, + 8, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifDisplay-SemiCondensedThinItalic.ttf", + "preferred_family_name": "Noto Serif Display", + "preferred_subfamily_name": "SemiCondensed Thin Italic", + "subfamily_name": "Italic", + "weight": 100, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifDisplay-Thin.ttf||606976:1655828711.0": { + "family_name": "Noto Serif Display Thin", + "font-family": "Noto Serif Display Thin", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Serif Display Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 2, + 2, + 8, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifDisplay-Thin.ttf", + "preferred_family_name": "Noto Serif", + "preferred_subfamily_name": "Display Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifDisplay-ThinItalic.ttf||619420:1655828711.0": { + "family_name": "Noto Serif Display Thin", + "font-family": "Noto Serif Display Thin", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Serif Display Thin Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 2, + 2, + 8, + 5, + 5, + 9, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifDisplay-ThinItalic.ttf", + "preferred_family_name": "Noto Serif Display", + "preferred_subfamily_name": "Thin Italic", + "subfamily_name": "Italic", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifDivesAkuru-Regular.ttf||48324:1655828711.0": { + "family_name": "Noto Serif Dives Akuru", + "font-family": "Noto Serif Dives Akuru", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif Dives Akuru Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/noto/NotoSerifDivesAkuru-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifDogra-Bold.ttf||27024:1655828711.0": { + "family_name": "Noto Serif Dogra", + "font-family": "Noto Serif Dogra", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Serif Dogra Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/noto/NotoSerifDogra-Bold.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifDogra-Medium.ttf||27512:1655828711.0": { + "family_name": "Noto Serif Dogra", + "font-family": "Noto Serif Dogra", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Serif Dogra Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/noto/NotoSerifDogra-Medium.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifDogra-Regular.ttf||27504:1655828711.0": { + "family_name": "Noto Serif Dogra", + "font-family": "Noto Serif Dogra", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif Dogra Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/noto/NotoSerifDogra-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifDogra-Semibold.ttf||27352:1655828711.0": { + "family_name": "Noto Serif Dogra", + "font-family": "Noto Serif Dogra", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Serif Dogra Semibold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/noto/NotoSerifDogra-Semibold.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": "Semibold", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifEthiopic-Black.ttf||291348:1655828711.0": { + "family_name": "Noto Serif Ethiopic Bk", + "font-family": "Noto Serif Ethiopic Bk", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Serif Ethiopic Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 10, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifEthiopic-Black.ttf", + "preferred_family_name": "Noto Serif Ethiopic", + "preferred_subfamily_name": "Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifEthiopic-Bold.ttf||283060:1655828711.0": { + "family_name": "Noto Serif Ethiopic", + "font-family": "Noto Serif Ethiopic", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Serif Ethiopic Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 8, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifEthiopic-Bold.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifEthiopic-Condensed.ttf||285360:1655828711.0": { + "family_name": "Noto Serif Ethiopic Cn", + "font-family": "Noto Serif Ethiopic Cn", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif Ethiopic Condensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 5, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifEthiopic-Condensed.ttf", + "preferred_family_name": "Noto Serif Ethiopic", + "preferred_subfamily_name": "Condensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifEthiopic-CondensedBlack.ttf||285732:1655828711.0": { + "family_name": "Noto Serif Ethiopic Cn Bk", + "font-family": "Noto Serif Ethiopic Cn Bk", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Serif Ethiopic Condensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 10, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifEthiopic-CondensedBlack.ttf", + "preferred_family_name": "Noto Serif Ethiopic", + "preferred_subfamily_name": "Condensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifEthiopic-CondensedBold.ttf||281712:1655828711.0": { + "family_name": "Noto Serif Ethiopic Cn", + "font-family": "Noto Serif Ethiopic Cn", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Serif Ethiopic Condensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 8, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifEthiopic-CondensedBold.ttf", + "preferred_family_name": "Noto Serif Ethiopic", + "preferred_subfamily_name": "Condensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifEthiopic-CondensedExtraBold.ttf||282700:1655828711.0": { + "family_name": "Noto Serif Ethiopic Cn XBd", + "font-family": "Noto Serif Ethiopic Cn XBd", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Serif Ethiopic Condensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 9, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifEthiopic-CondensedExtraBold.ttf", + "preferred_family_name": "Noto Serif Ethiopic", + "preferred_subfamily_name": "Condensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifEthiopic-CondensedExtraLight.ttf||293096:1655828711.0": { + "family_name": "Noto Serif Ethiopic Cn XLt", + "font-family": "Noto Serif Ethiopic Cn XLt", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Serif Ethiopic Condensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 3, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifEthiopic-CondensedExtraLight.ttf", + "preferred_family_name": "Noto Serif Ethiopic", + "preferred_subfamily_name": "Condensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifEthiopic-CondensedLight.ttf||293060:1655828711.0": { + "family_name": "Noto Serif Ethiopic Cn Lt", + "font-family": "Noto Serif Ethiopic Cn Lt", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Serif Ethiopic Condensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 4, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifEthiopic-CondensedLight.ttf", + "preferred_family_name": "Noto Serif Ethiopic", + "preferred_subfamily_name": "Condensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifEthiopic-CondensedMedium.ttf||284140:1655828711.0": { + "family_name": "Noto Serif Ethiopic Cn Md", + "font-family": "Noto Serif Ethiopic Cn Md", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Serif Ethiopic Condensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 6, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifEthiopic-CondensedMedium.ttf", + "preferred_family_name": "Noto Serif Ethiopic", + "preferred_subfamily_name": "Condensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifEthiopic-CondensedSemiBold.ttf||286144:1655828711.0": { + "family_name": "Noto Serif Ethiopic Cn SmBd", + "font-family": "Noto Serif Ethiopic Cn SmBd", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Serif Ethiopic Condensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 7, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifEthiopic-CondensedSemiBold.ttf", + "preferred_family_name": "Noto Serif Ethiopic", + "preferred_subfamily_name": "Condensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifEthiopic-CondensedThin.ttf||285524:1655828711.0": { + "family_name": "Noto Serif Ethiopic Cn Th", + "font-family": "Noto Serif Ethiopic Cn Th", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Serif Ethiopic Condensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 2, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifEthiopic-CondensedThin.ttf", + "preferred_family_name": "Noto Serif Ethiopic", + "preferred_subfamily_name": "Condensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifEthiopic-ExtraBold.ttf||288380:1655828711.0": { + "family_name": "Noto Serif Ethiopic XBd", + "font-family": "Noto Serif Ethiopic XBd", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Serif Ethiopic ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 9, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifEthiopic-ExtraBold.ttf", + "preferred_family_name": "Noto Serif Ethiopic", + "preferred_subfamily_name": "ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifEthiopic-ExtraCondensed.ttf||285100:1655828711.0": { + "family_name": "Noto Serif Ethiopic XCn", + "font-family": "Noto Serif Ethiopic XCn", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif Ethiopic ExtraCondensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 5, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifEthiopic-ExtraCondensed.ttf", + "preferred_family_name": "Noto Serif Ethiopic", + "preferred_subfamily_name": "ExtraCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifEthiopic-ExtraCondensedBlack.ttf||283816:1655828711.0": { + "family_name": "Noto Serif Ethiopic XCn Bk", + "font-family": "Noto Serif Ethiopic XCn Bk", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Serif Ethiopic ExtraCondensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 10, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifEthiopic-ExtraCondensedBlack.ttf", + "preferred_family_name": "Noto Serif Ethiopic", + "preferred_subfamily_name": "ExtraCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifEthiopic-ExtraCondensedBold.ttf||280540:1655828711.0": { + "family_name": "Noto Serif Ethiopic XCn", + "font-family": "Noto Serif Ethiopic XCn", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Serif Ethiopic ExtraCondensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 8, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifEthiopic-ExtraCondensedBold.ttf", + "preferred_family_name": "Noto Serif Ethiopic", + "preferred_subfamily_name": "ExtraCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifEthiopic-ExtraCondensedExtraBold.ttf||281116:1655828711.0": { + "family_name": "Noto Serif Ethiopic XCn XBd", + "font-family": "Noto Serif Ethiopic XCn XBd", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Serif Ethiopic ExtraCondensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 9, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifEthiopic-ExtraCondensedExtraBold.ttf", + "preferred_family_name": "Noto Serif Ethiopic", + "preferred_subfamily_name": "ExtraCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifEthiopic-ExtraCondensedExtraLight.ttf||293152:1655828711.0": { + "family_name": "Noto Serif Ethiopic XCn XLt", + "font-family": "Noto Serif Ethiopic XCn XLt", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Serif Ethiopic ExtraCondensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 3, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifEthiopic-ExtraCondensedExtraLight.ttf", + "preferred_family_name": "Noto Serif Ethiopic", + "preferred_subfamily_name": "ExtraCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifEthiopic-ExtraCondensedLight.ttf||292368:1655828711.0": { + "family_name": "Noto Serif Ethiopic XCn Lt", + "font-family": "Noto Serif Ethiopic XCn Lt", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Serif Ethiopic ExtraCondensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 4, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifEthiopic-ExtraCondensedLight.ttf", + "preferred_family_name": "Noto Serif Ethiopic", + "preferred_subfamily_name": "ExtraCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifEthiopic-ExtraCondensedMedium.ttf||281400:1655828711.0": { + "family_name": "Noto Serif Ethiopic XCn Md", + "font-family": "Noto Serif Ethiopic XCn Md", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Serif Ethiopic ExtraCondensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 6, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifEthiopic-ExtraCondensedMedium.ttf", + "preferred_family_name": "Noto Serif Ethiopic", + "preferred_subfamily_name": "ExtraCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifEthiopic-ExtraCondensedSemiBold.ttf||288060:1655828711.0": { + "family_name": "Noto Serif Ethiopic XCn SmBd", + "font-family": "Noto Serif Ethiopic XCn SmBd", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Serif Ethiopic ExtraCondensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 7, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifEthiopic-ExtraCondensedSemiBold.ttf", + "preferred_family_name": "Noto Serif Ethiopic", + "preferred_subfamily_name": "ExtraCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifEthiopic-ExtraCondensedThin.ttf||283572:1655828711.0": { + "family_name": "Noto Serif Ethiopic XCn Th", + "font-family": "Noto Serif Ethiopic XCn Th", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Serif Ethiopic ExtraCondensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 2, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifEthiopic-ExtraCondensedThin.ttf", + "preferred_family_name": "Noto Serif Ethiopic", + "preferred_subfamily_name": "ExtraCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifEthiopic-ExtraLight.ttf||295304:1655828711.0": { + "family_name": "Noto Serif Ethiopic XLt", + "font-family": "Noto Serif Ethiopic XLt", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Serif Ethiopic ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 3, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifEthiopic-ExtraLight.ttf", + "preferred_family_name": "Noto Serif Ethiopic", + "preferred_subfamily_name": "ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifEthiopic-Light.ttf||295248:1655828711.0": { + "family_name": "Noto Serif Ethiopic Lt", + "font-family": "Noto Serif Ethiopic Lt", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Serif Ethiopic Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 4, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifEthiopic-Light.ttf", + "preferred_family_name": "Noto Serif Ethiopic", + "preferred_subfamily_name": "Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifEthiopic-Medium.ttf||284588:1655828711.0": { + "family_name": "Noto Serif Ethiopic Md", + "font-family": "Noto Serif Ethiopic Md", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Serif Ethiopic Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 6, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifEthiopic-Medium.ttf", + "preferred_family_name": "Noto Serif Ethiopic", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifEthiopic-Regular.ttf||289588:1655828711.0": { + "family_name": "Noto Serif Ethiopic", + "font-family": "Noto Serif Ethiopic", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif Ethiopic Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 5, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifEthiopic-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifEthiopic-SemiBold.ttf||288216:1655828711.0": { + "family_name": "Noto Serif Ethiopic SmBd", + "font-family": "Noto Serif Ethiopic SmBd", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Serif Ethiopic SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 7, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifEthiopic-SemiBold.ttf", + "preferred_family_name": "Noto Serif Ethiopic", + "preferred_subfamily_name": "SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifEthiopic-SemiCondensed.ttf||286768:1655828711.0": { + "family_name": "Noto Serif Ethiopic SmCn", + "font-family": "Noto Serif Ethiopic SmCn", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif Ethiopic SemiCondensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 5, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifEthiopic-SemiCondensed.ttf", + "preferred_family_name": "Noto Serif Ethiopic", + "preferred_subfamily_name": "SemiCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifEthiopic-SemiCondensedBlack.ttf||289772:1655828711.0": { + "family_name": "Noto Serif Ethiopic SmCn Bk", + "font-family": "Noto Serif Ethiopic SmCn Bk", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Serif Ethiopic SemiCondensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 10, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifEthiopic-SemiCondensedBlack.ttf", + "preferred_family_name": "Noto Serif Ethiopic", + "preferred_subfamily_name": "SemiCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifEthiopic-SemiCondensedBold.ttf||282968:1655828711.0": { + "family_name": "Noto Serif Ethiopic SmCn", + "font-family": "Noto Serif Ethiopic SmCn", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Serif Ethiopic SemiCondensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 8, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifEthiopic-SemiCondensedBold.ttf", + "preferred_family_name": "Noto Serif Ethiopic", + "preferred_subfamily_name": "SemiCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifEthiopic-SemiCondensedExtraBold.ttf||287368:1655828711.0": { + "family_name": "Noto Serif Ethiopic SmCn XBd", + "font-family": "Noto Serif Ethiopic SmCn XBd", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Serif Ethiopic SemiCondensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 9, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifEthiopic-SemiCondensedExtraBold.ttf", + "preferred_family_name": "Noto Serif Ethiopic", + "preferred_subfamily_name": "SemiCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifEthiopic-SemiCondensedExtraLight.ttf||295076:1655828711.0": { + "family_name": "Noto Serif Ethiopic SmCn XLt", + "font-family": "Noto Serif Ethiopic SmCn XLt", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Serif Ethiopic SemiCondensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 3, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifEthiopic-SemiCondensedExtraLight.ttf", + "preferred_family_name": "Noto Serif Ethiopic", + "preferred_subfamily_name": "SemiCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifEthiopic-SemiCondensedLight.ttf||293860:1655828711.0": { + "family_name": "Noto Serif Ethiopic SmCn Lt", + "font-family": "Noto Serif Ethiopic SmCn Lt", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Serif Ethiopic SemiCondensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 4, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifEthiopic-SemiCondensedLight.ttf", + "preferred_family_name": "Noto Serif Ethiopic", + "preferred_subfamily_name": "SemiCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifEthiopic-SemiCondensedMedium.ttf||285336:1655828711.0": { + "family_name": "Noto Serif Ethiopic SmCn Md", + "font-family": "Noto Serif Ethiopic SmCn Md", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Serif Ethiopic SemiCondensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 6, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifEthiopic-SemiCondensedMedium.ttf", + "preferred_family_name": "Noto Serif Ethiopic", + "preferred_subfamily_name": "SemiCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifEthiopic-SemiCondensedSemiBold.ttf||288308:1655828711.0": { + "family_name": "Noto Serif Ethiopic SmCn SmBd", + "font-family": "Noto Serif Ethiopic SmCn SmBd", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Serif Ethiopic SemiCondensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 7, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifEthiopic-SemiCondensedSemiBold.ttf", + "preferred_family_name": "Noto Serif Ethiopic", + "preferred_subfamily_name": "SemiCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifEthiopic-SemiCondensedThin.ttf||285016:1655828711.0": { + "family_name": "Noto Serif Ethiopic SmCn Th", + "font-family": "Noto Serif Ethiopic SmCn Th", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Serif Ethiopic SemiCondensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 2, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifEthiopic-SemiCondensedThin.ttf", + "preferred_family_name": "Noto Serif Ethiopic", + "preferred_subfamily_name": "SemiCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifEthiopic-Thin.ttf||285724:1655828711.0": { + "family_name": "Noto Serif Ethiopic Th", + "font-family": "Noto Serif Ethiopic Th", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Serif Ethiopic Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 2, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifEthiopic-Thin.ttf", + "preferred_family_name": "Noto Serif Ethiopic", + "preferred_subfamily_name": "Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifGeorgian-Black.ttf||64504:1655828711.0": { + "family_name": "Noto Serif Georgian Bk", + "font-family": "Noto Serif Georgian Bk", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Serif Georgian Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 10, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifGeorgian-Black.ttf", + "preferred_family_name": "Noto Serif Georgian", + "preferred_subfamily_name": "Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifGeorgian-Bold.ttf||63768:1655828711.0": { + "family_name": "Noto Serif Georgian", + "font-family": "Noto Serif Georgian", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Serif Georgian Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 8, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifGeorgian-Bold.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifGeorgian-Condensed.ttf||63524:1655828711.0": { + "family_name": "Noto Serif Georgian Cn", + "font-family": "Noto Serif Georgian Cn", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif Georgian Condensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 5, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifGeorgian-Condensed.ttf", + "preferred_family_name": "Noto Serif Georgian", + "preferred_subfamily_name": "Condensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifGeorgian-CondensedBlack.ttf||65444:1655828711.0": { + "family_name": "Noto Serif Georgian Cn Bk", + "font-family": "Noto Serif Georgian Cn Bk", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Serif Georgian Condensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 10, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifGeorgian-CondensedBlack.ttf", + "preferred_family_name": "Noto Serif Georgian", + "preferred_subfamily_name": "Condensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifGeorgian-CondensedBold.ttf||65196:1655828711.0": { + "family_name": "Noto Serif Georgian Cn", + "font-family": "Noto Serif Georgian Cn", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Serif Georgian Condensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 8, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifGeorgian-CondensedBold.ttf", + "preferred_family_name": "Noto Serif Georgian", + "preferred_subfamily_name": "Condensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifGeorgian-CondensedExtraBold.ttf||67036:1655828711.0": { + "family_name": "Noto Serif Georgian Cn XBd", + "font-family": "Noto Serif Georgian Cn XBd", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Serif Georgian Condensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 9, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifGeorgian-CondensedExtraBold.ttf", + "preferred_family_name": "Noto Serif Georgian", + "preferred_subfamily_name": "Condensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifGeorgian-CondensedExtraLight.ttf||62468:1655828711.0": { + "family_name": "Noto Serif Georgian Cn XLt", + "font-family": "Noto Serif Georgian Cn XLt", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Serif Georgian Condensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 3, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifGeorgian-CondensedExtraLight.ttf", + "preferred_family_name": "Noto Serif Georgian", + "preferred_subfamily_name": "Condensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifGeorgian-CondensedLight.ttf||62028:1655828711.0": { + "family_name": "Noto Serif Georgian Cn Lt", + "font-family": "Noto Serif Georgian Cn Lt", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Serif Georgian Condensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 4, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifGeorgian-CondensedLight.ttf", + "preferred_family_name": "Noto Serif Georgian", + "preferred_subfamily_name": "Condensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifGeorgian-CondensedMedium.ttf||63448:1655828711.0": { + "family_name": "Noto Serif Georgian Cn Md", + "font-family": "Noto Serif Georgian Cn Md", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Serif Georgian Condensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 6, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifGeorgian-CondensedMedium.ttf", + "preferred_family_name": "Noto Serif Georgian", + "preferred_subfamily_name": "Condensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifGeorgian-CondensedSemiBold.ttf||63548:1655828711.0": { + "family_name": "Noto Serif Georgian Cn SmBd", + "font-family": "Noto Serif Georgian Cn SmBd", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Serif Georgian Condensed SemiBold ", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 7, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifGeorgian-CondensedSemiBold.ttf", + "preferred_family_name": "Noto Serif Georgian", + "preferred_subfamily_name": "Condensed SemiBold ", + "subfamily_name": "Regular", + "weight": 600, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifGeorgian-CondensedThin.ttf||61588:1655828711.0": { + "family_name": "Noto Serif Georgian Cn Th", + "font-family": "Noto Serif Georgian Cn Th", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Serif Georgian Condensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 2, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifGeorgian-CondensedThin.ttf", + "preferred_family_name": "Noto Serif Georgian", + "preferred_subfamily_name": "Condensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifGeorgian-ExtraBold.ttf||64876:1655828711.0": { + "family_name": "Noto Serif Georgian XBd", + "font-family": "Noto Serif Georgian XBd", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Serif Georgian ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 9, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifGeorgian-ExtraBold.ttf", + "preferred_family_name": "Noto Serif Georgian", + "preferred_subfamily_name": "ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifGeorgian-ExtraCondensed.ttf||63144:1655828711.0": { + "family_name": "Noto Serif Georgian XCn", + "font-family": "Noto Serif Georgian XCn", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif Georgian ExtraCondensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 5, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifGeorgian-ExtraCondensed.ttf", + "preferred_family_name": "Noto Serif Georgian", + "preferred_subfamily_name": "ExtraCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifGeorgian-ExtraCondensedBlack.ttf||64932:1655828711.0": { + "family_name": "Noto Serif Georgian XCn Bk", + "font-family": "Noto Serif Georgian XCn Bk", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Serif Georgian ExtraCondensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 10, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifGeorgian-ExtraCondensedBlack.ttf", + "preferred_family_name": "Noto Serif Georgian", + "preferred_subfamily_name": "ExtraCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifGeorgian-ExtraCondensedBold.ttf||63736:1655828711.0": { + "family_name": "Noto Serif Georgian XCn", + "font-family": "Noto Serif Georgian XCn", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Serif Georgian ExtraCondensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 8, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifGeorgian-ExtraCondensedBold.ttf", + "preferred_family_name": "Noto Serif Georgian", + "preferred_subfamily_name": "ExtraCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifGeorgian-ExtraCondensedExtraBold.ttf||64656:1655828711.0": { + "family_name": "Noto Serif Georgian XCn XBd", + "font-family": "Noto Serif Georgian XCn XBd", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Serif Georgian ExtraCondensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 9, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifGeorgian-ExtraCondensedExtraBold.ttf", + "preferred_family_name": "Noto Serif Georgian", + "preferred_subfamily_name": "ExtraCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifGeorgian-ExtraCondensedExtraLight.ttf||61776:1655828711.0": { + "family_name": "Noto Serif Georgian XCn XLt", + "font-family": "Noto Serif Georgian XCn XLt", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Serif Georgian ExtraCondensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 3, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifGeorgian-ExtraCondensedExtraLight.ttf", + "preferred_family_name": "Noto Serif Georgian", + "preferred_subfamily_name": "ExtraCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifGeorgian-ExtraCondensedLight.ttf||61348:1655828711.0": { + "family_name": "Noto Serif Georgian XCn Lt", + "font-family": "Noto Serif Georgian XCn Lt", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Serif Georgian ExtraCondensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 4, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifGeorgian-ExtraCondensedLight.ttf", + "preferred_family_name": "Noto Serif Georgian", + "preferred_subfamily_name": "ExtraCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifGeorgian-ExtraCondensedMedium.ttf||62988:1655828711.0": { + "family_name": "Noto Serif Georgian XCn Md", + "font-family": "Noto Serif Georgian XCn Md", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Serif Georgian ExtraCondensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 6, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifGeorgian-ExtraCondensedMedium.ttf", + "preferred_family_name": "Noto Serif Georgian", + "preferred_subfamily_name": "ExtraCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifGeorgian-ExtraCondensedSemiBold.ttf||63192:1655828711.0": { + "family_name": "Noto Serif Georgian XCn SmBd", + "font-family": "Noto Serif Georgian XCn SmBd", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Serif Georgian ExtraCondensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 7, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifGeorgian-ExtraCondensedSemiBold.ttf", + "preferred_family_name": "Noto Serif Georgian", + "preferred_subfamily_name": "ExtraCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifGeorgian-ExtraCondensedThin.ttf||60892:1655828711.0": { + "family_name": "Noto Serif Georgian XCn Th", + "font-family": "Noto Serif Georgian XCn Th", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Serif Georgian ExtraCondensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 2, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifGeorgian-ExtraCondensedThin.ttf", + "preferred_family_name": "Noto Serif Georgian", + "preferred_subfamily_name": "ExtraCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifGeorgian-ExtraLight.ttf||62024:1655828711.0": { + "family_name": "Noto Serif Georgian XLt", + "font-family": "Noto Serif Georgian XLt", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Serif Georgian ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 3, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifGeorgian-ExtraLight.ttf", + "preferred_family_name": "Noto Serif Georgian", + "preferred_subfamily_name": "ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifGeorgian-Light.ttf||61500:1655828711.0": { + "family_name": "Noto Serif Georgian Lt", + "font-family": "Noto Serif Georgian Lt", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Serif Georgian Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 4, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifGeorgian-Light.ttf", + "preferred_family_name": "Noto Serif Georgian", + "preferred_subfamily_name": "Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifGeorgian-Medium.ttf||62480:1655828711.0": { + "family_name": "Noto Serif Georgian Md", + "font-family": "Noto Serif Georgian Md", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Serif Georgian Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 6, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifGeorgian-Medium.ttf", + "preferred_family_name": "Noto Serif Georgian", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifGeorgian-Regular.ttf||61176:1655828711.0": { + "family_name": "Noto Serif Georgian", + "font-family": "Noto Serif Georgian", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif Georgian Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 5, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifGeorgian-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifGeorgian-SemiBold.ttf||63076:1655828711.0": { + "family_name": "Noto Serif Georgian SmBd", + "font-family": "Noto Serif Georgian SmBd", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Serif Georgian SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 7, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifGeorgian-SemiBold.ttf", + "preferred_family_name": "Noto Serif Georgian", + "preferred_subfamily_name": "SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifGeorgian-SemiCondensed.ttf||62384:1655828711.0": { + "family_name": "Noto Serif Georgian SmCn", + "font-family": "Noto Serif Georgian SmCn", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif Georgian SemiCondensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 5, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifGeorgian-SemiCondensed.ttf", + "preferred_family_name": "Noto Serif Georgian", + "preferred_subfamily_name": "SemiCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifGeorgian-SemiCondensedBlack.ttf||65168:1655828711.0": { + "family_name": "Noto Serif Georgian SmCn Bk", + "font-family": "Noto Serif Georgian SmCn Bk", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Serif Georgian SemiCondensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 10, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifGeorgian-SemiCondensedBlack.ttf", + "preferred_family_name": "Noto Serif Georgian", + "preferred_subfamily_name": "SemiCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifGeorgian-SemiCondensedBold.ttf||64892:1655828711.0": { + "family_name": "Noto Serif Georgian SmCn", + "font-family": "Noto Serif Georgian SmCn", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Serif Georgian SemiCondensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 8, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifGeorgian-SemiCondensedBold.ttf", + "preferred_family_name": "Noto Serif Georgian", + "preferred_subfamily_name": "SemiCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifGeorgian-SemiCondensedExtraBold.ttf||66040:1655828711.0": { + "family_name": "Noto Serif Georgian SmCn XBd", + "font-family": "Noto Serif Georgian SmCn XBd", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Serif Georgian SemiCondensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 9, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifGeorgian-SemiCondensedExtraBold.ttf", + "preferred_family_name": "Noto Serif Georgian", + "preferred_subfamily_name": "SemiCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifGeorgian-SemiCondensedExtraLight.ttf||62816:1655828711.0": { + "family_name": "Noto Serif Georgian SmCn XLt", + "font-family": "Noto Serif Georgian SmCn XLt", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Serif Georgian SemiCondensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 3, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifGeorgian-SemiCondensedExtraLight.ttf", + "preferred_family_name": "Noto Serif Georgian", + "preferred_subfamily_name": "SemiCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifGeorgian-SemiCondensedLight.ttf||62096:1655828711.0": { + "family_name": "Noto Serif Georgian SmCn Lt", + "font-family": "Noto Serif Georgian SmCn Lt", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Serif Georgian SemiCondensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 4, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifGeorgian-SemiCondensedLight.ttf", + "preferred_family_name": "Noto Serif Georgian", + "preferred_subfamily_name": "SemiCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifGeorgian-SemiCondensedMedium.ttf||63032:1655828711.0": { + "family_name": "Noto Serif Georgian SmCn Md", + "font-family": "Noto Serif Georgian SmCn Md", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Serif Georgian SemiCondensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 6, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifGeorgian-SemiCondensedMedium.ttf", + "preferred_family_name": "Noto Serif Georgian", + "preferred_subfamily_name": "SemiCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifGeorgian-SemiCondensedSemiBold.ttf||63736:1655828711.0": { + "family_name": "Noto Serif Georgian SmCn SmBd", + "font-family": "Noto Serif Georgian SmCn SmBd", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Serif Georgian SemiCondensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 7, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifGeorgian-SemiCondensedSemiBold.ttf", + "preferred_family_name": "Noto Serif Georgian", + "preferred_subfamily_name": "SemiCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifGeorgian-SemiCondensedThin.ttf||61960:1655828711.0": { + "family_name": "Noto Serif Georgian SmCn Th", + "font-family": "Noto Serif Georgian SmCn Th", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Serif Georgian SemiCondensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 2, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifGeorgian-SemiCondensedThin.ttf", + "preferred_family_name": "Noto Serif Georgian", + "preferred_subfamily_name": "SemiCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifGeorgian-Thin.ttf||61284:1655828711.0": { + "family_name": "Noto Serif Georgian Th", + "font-family": "Noto Serif Georgian Th", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Serif Georgian Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 2, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifGeorgian-Thin.ttf", + "preferred_family_name": "Noto Serif Georgian", + "preferred_subfamily_name": "Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifGrantha-Regular.ttf||379364:1655828711.0": { + "family_name": "Noto Serif Grantha", + "font-family": "Noto Serif Grantha", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif Grantha Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 5, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifGrantha-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifGujarati-Black.ttf||143736:1655828711.0": { + "family_name": "Noto Serif Gujarati Black", + "font-family": "Noto Serif Gujarati Black", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Serif Gujarati Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 10, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifGujarati-Black.ttf", + "preferred_family_name": "Noto Serif Gujarati", + "preferred_subfamily_name": "Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifGujarati-Bold.ttf||147448:1655828711.0": { + "family_name": "Noto Serif Gujarati", + "font-family": "Noto Serif Gujarati", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Serif Gujarati Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 8, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifGujarati-Bold.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifGujarati-ExtraBold.ttf||144948:1655828711.0": { + "family_name": "Noto Serif Gujarati ExtraBold", + "font-family": "Noto Serif Gujarati ExtraBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Serif Gujarati ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 9, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifGujarati-ExtraBold.ttf", + "preferred_family_name": "Noto Serif Gujarati", + "preferred_subfamily_name": "ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifGujarati-ExtraLight.ttf||140788:1655828711.0": { + "family_name": "Noto Serif Gujarati ExtraLight", + "font-family": "Noto Serif Gujarati ExtraLight", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Serif Gujarati ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 3, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifGujarati-ExtraLight.ttf", + "preferred_family_name": "Noto Serif Gujarati", + "preferred_subfamily_name": "ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifGujarati-Light.ttf||143780:1655828711.0": { + "family_name": "Noto Serif Gujarati Light", + "font-family": "Noto Serif Gujarati Light", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Serif Gujarati Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 4, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifGujarati-Light.ttf", + "preferred_family_name": "Noto Serif Gujarati", + "preferred_subfamily_name": "Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifGujarati-Medium.ttf||144676:1655828711.0": { + "family_name": "Noto Serif Gujarati Medium", + "font-family": "Noto Serif Gujarati Medium", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Serif Gujarati Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 6, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifGujarati-Medium.ttf", + "preferred_family_name": "Noto Serif Gujarati", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifGujarati-Regular.ttf||144736:1655828711.0": { + "family_name": "Noto Serif Gujarati", + "font-family": "Noto Serif Gujarati", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif Gujarati Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 5, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifGujarati-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifGujarati-SemiBold.ttf||146520:1655828711.0": { + "family_name": "Noto Serif Gujarati SemiBold", + "font-family": "Noto Serif Gujarati SemiBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Serif Gujarati SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 7, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifGujarati-SemiBold.ttf", + "preferred_family_name": "Noto Serif Gujarati", + "preferred_subfamily_name": "SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifGujarati-Thin.ttf||139500:1655828711.0": { + "family_name": "Noto Serif Gujarati Thin", + "font-family": "Noto Serif Gujarati Thin", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Serif Gujarati Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 2, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifGujarati-Thin.ttf", + "preferred_family_name": "Noto Serif Gujarati", + "preferred_subfamily_name": "Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifGurmukhi-Black.ttf||54536:1655828711.0": { + "family_name": "Noto Serif Gurmukhi Black", + "font-family": "Noto Serif Gurmukhi Black", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Serif Gurmukhi Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 10, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifGurmukhi-Black.ttf", + "preferred_family_name": "Noto Serif Gurmukhi", + "preferred_subfamily_name": "Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifGurmukhi-Bold.ttf||53624:1655828711.0": { + "family_name": "Noto Serif Gurmukhi", + "font-family": "Noto Serif Gurmukhi", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Serif Gurmukhi Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 8, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifGurmukhi-Bold.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifGurmukhi-ExtraBold.ttf||54240:1655828711.0": { + "family_name": "Noto Serif Gurmukhi ExtraBold", + "font-family": "Noto Serif Gurmukhi ExtraBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Serif Gurmukhi ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 9, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifGurmukhi-ExtraBold.ttf", + "preferred_family_name": "Noto Serif Gurmukhi", + "preferred_subfamily_name": "ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifGurmukhi-ExtraLight.ttf||52400:1655828711.0": { + "family_name": "Noto Serif Gurmukhi ExtraLight", + "font-family": "Noto Serif Gurmukhi ExtraLight", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Serif Gurmukhi ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 3, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifGurmukhi-ExtraLight.ttf", + "preferred_family_name": "Noto Serif Gurmukhi", + "preferred_subfamily_name": "ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifGurmukhi-Light.ttf||52628:1655828711.0": { + "family_name": "Noto Serif Gurmukhi Light", + "font-family": "Noto Serif Gurmukhi Light", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Serif Gurmukhi Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 4, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifGurmukhi-Light.ttf", + "preferred_family_name": "Noto Serif Gurmukhi", + "preferred_subfamily_name": "Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifGurmukhi-Medium.ttf||53296:1655828711.0": { + "family_name": "Noto Serif Gurmukhi Medium", + "font-family": "Noto Serif Gurmukhi Medium", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Serif Gurmukhi Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 6, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifGurmukhi-Medium.ttf", + "preferred_family_name": "Noto Serif Gurmukhi", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifGurmukhi-Regular.ttf||52688:1655828711.0": { + "family_name": "Noto Serif Gurmukhi", + "font-family": "Noto Serif Gurmukhi", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif Gurmukhi Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 5, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifGurmukhi-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifGurmukhi-SemiBold.ttf||54020:1655828711.0": { + "family_name": "Noto Serif Gurmukhi SemiBold", + "font-family": "Noto Serif Gurmukhi SemiBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Serif Gurmukhi SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 7, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifGurmukhi-SemiBold.ttf", + "preferred_family_name": "Noto Serif Gurmukhi", + "preferred_subfamily_name": "SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifGurmukhi-Thin.ttf||50996:1655828711.0": { + "family_name": "Noto Serif Gurmukhi Thin", + "font-family": "Noto Serif Gurmukhi Thin", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Serif Gurmukhi Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 2, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifGurmukhi-Thin.ttf", + "preferred_family_name": "Noto Serif Gurmukhi", + "preferred_subfamily_name": "Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifHebrew-Black.ttf||31536:1655828711.0": { + "family_name": "Noto Serif Hebrew Black", + "font-family": "Noto Serif Hebrew Black", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Serif Hebrew Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 10, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifHebrew-Black.ttf", + "preferred_family_name": "Noto Serif Hebrew", + "preferred_subfamily_name": "Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifHebrew-Bold.ttf||32324:1655828711.0": { + "family_name": "Noto Serif Hebrew", + "font-family": "Noto Serif Hebrew", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Serif Hebrew Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 8, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifHebrew-Bold.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifHebrew-Condensed.ttf||31236:1655828711.0": { + "family_name": "Noto Serif Hebrew Condensed", + "font-family": "Noto Serif Hebrew Condensed", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif Hebrew Condensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 5, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifHebrew-Condensed.ttf", + "preferred_family_name": "Noto Serif Hebrew", + "preferred_subfamily_name": "Condensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifHebrew-CondensedBlack.ttf||32380:1655828711.0": { + "family_name": "Noto Serif Hebrew Condensed Black", + "font-family": "Noto Serif Hebrew Condensed Black", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Serif Hebrew Condensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 10, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifHebrew-CondensedBlack.ttf", + "preferred_family_name": "Noto Serif Hebrew", + "preferred_subfamily_name": "Condensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifHebrew-CondensedBold.ttf||32176:1655828711.0": { + "family_name": "Noto Serif Hebrew Condensed", + "font-family": "Noto Serif Hebrew Condensed", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Serif Hebrew Condensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 8, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifHebrew-CondensedBold.ttf", + "preferred_family_name": "Noto Serif Hebrew", + "preferred_subfamily_name": "Condensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifHebrew-CondensedExtraBold.ttf||32112:1655828711.0": { + "family_name": "Noto Serif Hebrew Condensed ExtraBold", + "font-family": "Noto Serif Hebrew Condensed ExtraBold", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Serif Hebrew Condensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 9, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifHebrew-CondensedExtraBold.ttf", + "preferred_family_name": "Noto Serif Hebrew", + "preferred_subfamily_name": "Condensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifHebrew-CondensedExtraLight.ttf||30780:1655828711.0": { + "family_name": "Noto Serif Hebrew Condensed ExtraLight", + "font-family": "Noto Serif Hebrew Condensed ExtraLight", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Serif Hebrew Condensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 3, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifHebrew-CondensedExtraLight.ttf", + "preferred_family_name": "Noto Serif Hebrew", + "preferred_subfamily_name": "Condensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifHebrew-CondensedLight.ttf||30568:1655828711.0": { + "family_name": "Noto Serif Hebrew Condensed Light", + "font-family": "Noto Serif Hebrew Condensed Light", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Serif Hebrew Condensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 4, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifHebrew-CondensedLight.ttf", + "preferred_family_name": "Noto Serif Hebrew", + "preferred_subfamily_name": "Condensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifHebrew-CondensedMedium.ttf||31628:1655828711.0": { + "family_name": "Noto Serif Hebrew Condensed Medium", + "font-family": "Noto Serif Hebrew Condensed Medium", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Serif Hebrew Condensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 6, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifHebrew-CondensedMedium.ttf", + "preferred_family_name": "Noto Serif Hebrew", + "preferred_subfamily_name": "Condensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifHebrew-CondensedSemiBold.ttf||32296:1655828711.0": { + "family_name": "Noto Serif Hebrew Condensed SemiBold", + "font-family": "Noto Serif Hebrew Condensed SemiBold", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Serif Hebrew Condensed SemiBold ", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 7, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifHebrew-CondensedSemiBold.ttf", + "preferred_family_name": "Noto Serif Hebrew", + "preferred_subfamily_name": "Condensed SemiBold ", + "subfamily_name": "Regular", + "weight": 600, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifHebrew-CondensedThin.ttf||30272:1655828711.0": { + "family_name": "Noto Serif Hebrew Condensed Thin", + "font-family": "Noto Serif Hebrew Condensed Thin", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Serif Hebrew Condensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 2, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifHebrew-CondensedThin.ttf", + "preferred_family_name": "Noto Serif Hebrew", + "preferred_subfamily_name": "Condensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifHebrew-ExtraBold.ttf||32364:1655828711.0": { + "family_name": "Noto Serif Hebrew ExtraBold", + "font-family": "Noto Serif Hebrew ExtraBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Serif Hebrew ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 9, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifHebrew-ExtraBold.ttf", + "preferred_family_name": "Noto Serif Hebrew", + "preferred_subfamily_name": "ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifHebrew-ExtraCondensed.ttf||31712:1655828711.0": { + "family_name": "Noto Serif Hebrew ExtraCondensed", + "font-family": "Noto Serif Hebrew ExtraCondensed", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif Hebrew ExtraCondensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 5, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifHebrew-ExtraCondensed.ttf", + "preferred_family_name": "Noto Serif Hebrew", + "preferred_subfamily_name": "ExtraCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifHebrew-ExtraCondensedBlack.ttf||32296:1655828711.0": { + "family_name": "Noto Serif Hebrew ExtraCondensed Black", + "font-family": "Noto Serif Hebrew ExtraCondensed Black", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Serif Hebrew ExtraCondensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 10, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifHebrew-ExtraCondensedBlack.ttf", + "preferred_family_name": "Noto Serif Hebrew", + "preferred_subfamily_name": "ExtraCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifHebrew-ExtraCondensedBold.ttf||31532:1655828711.0": { + "family_name": "Noto Serif Hebrew ExtraCondensed", + "font-family": "Noto Serif Hebrew ExtraCondensed", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Serif Hebrew ExtraCondensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 8, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifHebrew-ExtraCondensedBold.ttf", + "preferred_family_name": "Noto Serif Hebrew", + "preferred_subfamily_name": "ExtraCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifHebrew-ExtraCondensedExtraBold.ttf||32104:1655828711.0": { + "family_name": "Noto Serif Hebrew ExtraCondensed ExtraBold", + "font-family": "Noto Serif Hebrew ExtraCondensed ExtraBold", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Serif Hebrew ExtraCondensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 9, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifHebrew-ExtraCondensedExtraBold.ttf", + "preferred_family_name": "Noto Serif Hebrew", + "preferred_subfamily_name": "ExtraCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifHebrew-ExtraCondensedExtraLight.ttf||30748:1655828711.0": { + "family_name": "Noto Serif Hebrew ExtraCondensed ExtraLight", + "font-family": "Noto Serif Hebrew ExtraCondensed ExtraLight", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Serif Hebrew ExtraCondensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 3, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifHebrew-ExtraCondensedExtraLight.ttf", + "preferred_family_name": "Noto Serif Hebrew", + "preferred_subfamily_name": "ExtraCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifHebrew-ExtraCondensedLight.ttf||30500:1655828711.0": { + "family_name": "Noto Serif Hebrew ExtraCondensed Light", + "font-family": "Noto Serif Hebrew ExtraCondensed Light", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Serif Hebrew ExtraCondensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 4, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifHebrew-ExtraCondensedLight.ttf", + "preferred_family_name": "Noto Serif Hebrew", + "preferred_subfamily_name": "ExtraCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifHebrew-ExtraCondensedMedium.ttf||31448:1655828711.0": { + "family_name": "Noto Serif Hebrew ExtraCondensed Medium", + "font-family": "Noto Serif Hebrew ExtraCondensed Medium", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Serif Hebrew ExtraCondensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 6, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifHebrew-ExtraCondensedMedium.ttf", + "preferred_family_name": "Noto Serif Hebrew", + "preferred_subfamily_name": "ExtraCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifHebrew-ExtraCondensedSemiBold.ttf||31512:1655828711.0": { + "family_name": "Noto Serif Hebrew ExtraCondensed SemiBold", + "font-family": "Noto Serif Hebrew ExtraCondensed SemiBold", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Serif Hebrew ExtraCondensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 7, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifHebrew-ExtraCondensedSemiBold.ttf", + "preferred_family_name": "Noto Serif Hebrew", + "preferred_subfamily_name": "ExtraCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifHebrew-ExtraCondensedThin.ttf||30344:1655828711.0": { + "family_name": "Noto Serif Hebrew ExtraCondensed Thin", + "font-family": "Noto Serif Hebrew ExtraCondensed Thin", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Serif Hebrew ExtraCondensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 2, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifHebrew-ExtraCondensedThin.ttf", + "preferred_family_name": "Noto Serif Hebrew", + "preferred_subfamily_name": "ExtraCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifHebrew-ExtraLight.ttf||30580:1655828711.0": { + "family_name": "Noto Serif Hebrew ExtraLight", + "font-family": "Noto Serif Hebrew ExtraLight", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Serif Hebrew ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 3, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifHebrew-ExtraLight.ttf", + "preferred_family_name": "Noto Serif Hebrew", + "preferred_subfamily_name": "ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifHebrew-Light.ttf||30676:1655828711.0": { + "family_name": "Noto Serif Hebrew Light", + "font-family": "Noto Serif Hebrew Light", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Serif Hebrew Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 4, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifHebrew-Light.ttf", + "preferred_family_name": "Noto Serif Hebrew", + "preferred_subfamily_name": "Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifHebrew-Medium.ttf||32196:1655828711.0": { + "family_name": "Noto Serif Hebrew Medium", + "font-family": "Noto Serif Hebrew Medium", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Serif Hebrew Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 6, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifHebrew-Medium.ttf", + "preferred_family_name": "Noto Serif Hebrew", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifHebrew-Regular.ttf||31584:1655828711.0": { + "family_name": "Noto Serif Hebrew", + "font-family": "Noto Serif Hebrew", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif Hebrew Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 5, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifHebrew-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifHebrew-SemiBold.ttf||32496:1655828711.0": { + "family_name": "Noto Serif Hebrew SemiBold", + "font-family": "Noto Serif Hebrew SemiBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Serif Hebrew SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 7, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifHebrew-SemiBold.ttf", + "preferred_family_name": "Noto Serif Hebrew", + "preferred_subfamily_name": "SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifHebrew-SemiCondensed.ttf||32436:1655828711.0": { + "family_name": "Noto Serif Hebrew SemiCondensed", + "font-family": "Noto Serif Hebrew SemiCondensed", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif Hebrew SemiCondensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 5, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifHebrew-SemiCondensed.ttf", + "preferred_family_name": "Noto Serif Hebrew", + "preferred_subfamily_name": "SemiCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifHebrew-SemiCondensedBlack.ttf||32564:1655828711.0": { + "family_name": "Noto Serif Hebrew SemiCondensed Black", + "font-family": "Noto Serif Hebrew SemiCondensed Black", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Serif Hebrew SemiCondensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 10, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifHebrew-SemiCondensedBlack.ttf", + "preferred_family_name": "Noto Serif Hebrew", + "preferred_subfamily_name": "SemiCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifHebrew-SemiCondensedBold.ttf||32408:1655828711.0": { + "family_name": "Noto Serif Hebrew SemiCondensed", + "font-family": "Noto Serif Hebrew SemiCondensed", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Serif Hebrew SemiCondensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 8, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifHebrew-SemiCondensedBold.ttf", + "preferred_family_name": "Noto Serif Hebrew", + "preferred_subfamily_name": "SemiCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifHebrew-SemiCondensedExtraBold.ttf||32316:1655828711.0": { + "family_name": "Noto Serif Hebrew SemiCondensed ExtraBold", + "font-family": "Noto Serif Hebrew SemiCondensed ExtraBold", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Serif Hebrew SemiCondensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 9, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifHebrew-SemiCondensedExtraBold.ttf", + "preferred_family_name": "Noto Serif Hebrew", + "preferred_subfamily_name": "SemiCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifHebrew-SemiCondensedExtraLight.ttf||30836:1655828711.0": { + "family_name": "Noto Serif Hebrew SemiCondensed ExtraLight", + "font-family": "Noto Serif Hebrew SemiCondensed ExtraLight", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Serif Hebrew SemiCondensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 3, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifHebrew-SemiCondensedExtraLight.ttf", + "preferred_family_name": "Noto Serif Hebrew", + "preferred_subfamily_name": "SemiCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifHebrew-SemiCondensedLight.ttf||30828:1655828711.0": { + "family_name": "Noto Serif Hebrew SemiCondensed Light", + "font-family": "Noto Serif Hebrew SemiCondensed Light", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Serif Hebrew SemiCondensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 4, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifHebrew-SemiCondensedLight.ttf", + "preferred_family_name": "Noto Serif Hebrew", + "preferred_subfamily_name": "SemiCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifHebrew-SemiCondensedMedium.ttf||31660:1655828711.0": { + "family_name": "Noto Serif Hebrew SemiCondensed Medium", + "font-family": "Noto Serif Hebrew SemiCondensed Medium", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Serif Hebrew SemiCondensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 6, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifHebrew-SemiCondensedMedium.ttf", + "preferred_family_name": "Noto Serif Hebrew", + "preferred_subfamily_name": "SemiCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifHebrew-SemiCondensedSemiBold.ttf||32120:1655828711.0": { + "family_name": "Noto Serif Hebrew SemiCondensed SemiBold", + "font-family": "Noto Serif Hebrew SemiCondensed SemiBold", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Serif Hebrew SemiCondensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 7, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifHebrew-SemiCondensedSemiBold.ttf", + "preferred_family_name": "Noto Serif Hebrew", + "preferred_subfamily_name": "SemiCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifHebrew-SemiCondensedThin.ttf||30412:1655828711.0": { + "family_name": "Noto Serif Hebrew SemiCondensed Thin", + "font-family": "Noto Serif Hebrew SemiCondensed Thin", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Serif Hebrew SemiCondensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 2, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifHebrew-SemiCondensedThin.ttf", + "preferred_family_name": "Noto Serif Hebrew", + "preferred_subfamily_name": "SemiCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifHebrew-Thin.ttf||30328:1655828711.0": { + "family_name": "Noto Serif Hebrew Thin", + "font-family": "Noto Serif Hebrew Thin", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Serif Hebrew Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 2, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifHebrew-Thin.ttf", + "preferred_family_name": "Noto Serif Hebrew", + "preferred_subfamily_name": "Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifKannada-Black.ttf||223272:1655828711.0": { + "family_name": "Noto Serif Kannada Black", + "font-family": "Noto Serif Kannada Black", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Serif Kannada Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 10, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifKannada-Black.ttf", + "preferred_family_name": "Noto Serif Kannada", + "preferred_subfamily_name": "Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifKannada-Bold.ttf||214044:1655828711.0": { + "family_name": "Noto Serif Kannada", + "font-family": "Noto Serif Kannada", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Serif Kannada Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 8, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifKannada-Bold.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifKannada-ExtraBold.ttf||222628:1655828711.0": { + "family_name": "Noto Serif Kannada ExtraBold", + "font-family": "Noto Serif Kannada ExtraBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Serif Kannada ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 9, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifKannada-ExtraBold.ttf", + "preferred_family_name": "Noto Serif Kannada", + "preferred_subfamily_name": "ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifKannada-ExtraLight.ttf||185356:1655828711.0": { + "family_name": "Noto Serif Kannada ExtraLight", + "font-family": "Noto Serif Kannada ExtraLight", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Serif Kannada ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 3, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifKannada-ExtraLight.ttf", + "preferred_family_name": "Noto Serif Kannada", + "preferred_subfamily_name": "ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifKannada-Light.ttf||198760:1655828711.0": { + "family_name": "Noto Serif Kannada Light", + "font-family": "Noto Serif Kannada Light", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Serif Kannada Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 4, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifKannada-Light.ttf", + "preferred_family_name": "Noto Serif Kannada", + "preferred_subfamily_name": "Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifKannada-Medium.ttf||194800:1655828711.0": { + "family_name": "Noto Serif Kannada Medium", + "font-family": "Noto Serif Kannada Medium", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Serif Kannada Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 6, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifKannada-Medium.ttf", + "preferred_family_name": "Noto Serif Kannada", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifKannada-Regular.ttf||194492:1655828711.0": { + "family_name": "Noto Serif Kannada", + "font-family": "Noto Serif Kannada", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif Kannada Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 5, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifKannada-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifKannada-SemiBold.ttf||203608:1655828711.0": { + "family_name": "Noto Serif Kannada SemiBold", + "font-family": "Noto Serif Kannada SemiBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Serif Kannada SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 7, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifKannada-SemiBold.ttf", + "preferred_family_name": "Noto Serif Kannada", + "preferred_subfamily_name": "SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifKannada-Thin.ttf||182488:1655828711.0": { + "family_name": "Noto Serif Kannada Thin", + "font-family": "Noto Serif Kannada Thin", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Serif Kannada Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 2, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifKannada-Thin.ttf", + "preferred_family_name": "Noto Serif Kannada", + "preferred_subfamily_name": "Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifKhmer-Black.ttf||151972:1655828711.0": { + "family_name": "Noto Serif Khmer Black", + "font-family": "Noto Serif Khmer Black", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Serif Khmer Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 10, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifKhmer-Black.ttf", + "preferred_family_name": "Noto Serif Khmer", + "preferred_subfamily_name": "Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifKhmer-Bold.ttf||151828:1655828711.0": { + "family_name": "Noto Serif Khmer", + "font-family": "Noto Serif Khmer", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Serif Khmer Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 8, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifKhmer-Bold.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifKhmer-Condensed.ttf||149384:1655828711.0": { + "family_name": "Noto Serif Khmer Condensed", + "font-family": "Noto Serif Khmer Condensed", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif Khmer Condensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 5, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifKhmer-Condensed.ttf", + "preferred_family_name": "Noto Serif Khmer", + "preferred_subfamily_name": "Condensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifKhmer-CondensedBlack.ttf||149476:1655828711.0": { + "family_name": "Noto Serif Khmer Condensed Black", + "font-family": "Noto Serif Khmer Condensed Black", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Serif Khmer Condensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 10, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifKhmer-CondensedBlack.ttf", + "preferred_family_name": "Noto Serif Khmer", + "preferred_subfamily_name": "Condensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifKhmer-CondensedBold.ttf||148240:1655828711.0": { + "family_name": "Noto Serif Khmer Condensed", + "font-family": "Noto Serif Khmer Condensed", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Serif Khmer Condensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 8, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifKhmer-CondensedBold.ttf", + "preferred_family_name": "Noto Serif Khmer", + "preferred_subfamily_name": "Condensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifKhmer-CondensedExtraBold.ttf||147760:1655828711.0": { + "family_name": "Noto Serif Khmer Condensed ExtraBold", + "font-family": "Noto Serif Khmer Condensed ExtraBold", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Serif Khmer Condensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 9, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifKhmer-CondensedExtraBold.ttf", + "preferred_family_name": "Noto Serif Khmer", + "preferred_subfamily_name": "Condensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifKhmer-CondensedExtraLight.ttf||145572:1655828711.0": { + "family_name": "Noto Serif Khmer Condensed ExtraLight", + "font-family": "Noto Serif Khmer Condensed ExtraLight", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Serif Khmer Condensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 3, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifKhmer-CondensedExtraLight.ttf", + "preferred_family_name": "Noto Serif Khmer", + "preferred_subfamily_name": "Condensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifKhmer-CondensedLight.ttf||145576:1655828711.0": { + "family_name": "Noto Serif Khmer Condensed Light", + "font-family": "Noto Serif Khmer Condensed Light", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Serif Khmer Condensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 4, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifKhmer-CondensedLight.ttf", + "preferred_family_name": "Noto Serif Khmer", + "preferred_subfamily_name": "Condensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifKhmer-CondensedMedium.ttf||145872:1655828711.0": { + "family_name": "Noto Serif Khmer Condensed Medium", + "font-family": "Noto Serif Khmer Condensed Medium", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Serif Khmer Condensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 6, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifKhmer-CondensedMedium.ttf", + "preferred_family_name": "Noto Serif Khmer", + "preferred_subfamily_name": "Condensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifKhmer-CondensedSemiBold.ttf||146452:1655828711.0": { + "family_name": "Noto Serif Khmer Condensed SemiBold", + "font-family": "Noto Serif Khmer Condensed SemiBold", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Serif Khmer Condensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 7, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifKhmer-CondensedSemiBold.ttf", + "preferred_family_name": "Noto Serif Khmer", + "preferred_subfamily_name": "Condensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifKhmer-CondensedThin.ttf||140756:1655828711.0": { + "family_name": "Noto Serif Khmer Condensed Thin", + "font-family": "Noto Serif Khmer Condensed Thin", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Serif Khmer Condensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 2, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifKhmer-CondensedThin.ttf", + "preferred_family_name": "Noto Serif Khmer", + "preferred_subfamily_name": "Condensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifKhmer-ExtraBold.ttf||150088:1655828711.0": { + "family_name": "Noto Serif Khmer ExtraBold", + "font-family": "Noto Serif Khmer ExtraBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Serif Khmer ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 9, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifKhmer-ExtraBold.ttf", + "preferred_family_name": "Noto Serif Khmer", + "preferred_subfamily_name": "ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifKhmer-ExtraCondensed.ttf||150152:1655828711.0": { + "family_name": "Noto Serif Khmer ExtraCondensed", + "font-family": "Noto Serif Khmer ExtraCondensed", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif Khmer ExtraCondensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 5, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifKhmer-ExtraCondensed.ttf", + "preferred_family_name": "Noto Serif Khmer", + "preferred_subfamily_name": "ExtraCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifKhmer-ExtraCondensedBlack.ttf||147856:1655828711.0": { + "family_name": "Noto Serif Khmer ExtraCondensed Black", + "font-family": "Noto Serif Khmer ExtraCondensed Black", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Serif Khmer ExtraCondensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 10, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifKhmer-ExtraCondensedBlack.ttf", + "preferred_family_name": "Noto Serif Khmer", + "preferred_subfamily_name": "ExtraCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifKhmer-ExtraCondensedBold.ttf||147644:1655828711.0": { + "family_name": "Noto Serif Khmer ExtraCondensed", + "font-family": "Noto Serif Khmer ExtraCondensed", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Serif Khmer ExtraCondensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 8, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifKhmer-ExtraCondensedBold.ttf", + "preferred_family_name": "Noto Serif Khmer", + "preferred_subfamily_name": "ExtraCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifKhmer-ExtraCondensedExtraBold.ttf||147584:1655828711.0": { + "family_name": "Noto Serif Khmer ExtraCondensed ExtraBold", + "font-family": "Noto Serif Khmer ExtraCondensed ExtraBold", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Serif Khmer ExtraCondensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 9, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifKhmer-ExtraCondensedExtraBold.ttf", + "preferred_family_name": "Noto Serif Khmer", + "preferred_subfamily_name": "ExtraCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifKhmer-ExtraCondensedExtraLight.ttf||142776:1655828711.0": { + "family_name": "Noto Serif Khmer ExtraCondensed ExtraLight", + "font-family": "Noto Serif Khmer ExtraCondensed ExtraLight", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Serif Khmer ExtraCondensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 3, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifKhmer-ExtraCondensedExtraLight.ttf", + "preferred_family_name": "Noto Serif Khmer", + "preferred_subfamily_name": "ExtraCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifKhmer-ExtraCondensedLight.ttf||146392:1655828711.0": { + "family_name": "Noto Serif Khmer ExtraCondensed Light", + "font-family": "Noto Serif Khmer ExtraCondensed Light", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Serif Khmer ExtraCondensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 4, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifKhmer-ExtraCondensedLight.ttf", + "preferred_family_name": "Noto Serif Khmer", + "preferred_subfamily_name": "ExtraCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifKhmer-ExtraCondensedMedium.ttf||144888:1655828711.0": { + "family_name": "Noto Serif Khmer ExtraCondensed Medium", + "font-family": "Noto Serif Khmer ExtraCondensed Medium", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Serif Khmer ExtraCondensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 6, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifKhmer-ExtraCondensedMedium.ttf", + "preferred_family_name": "Noto Serif Khmer", + "preferred_subfamily_name": "ExtraCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifKhmer-ExtraCondensedSemiBold.ttf||146296:1655828711.0": { + "family_name": "Noto Serif Khmer ExtraCondensed SemiBold", + "font-family": "Noto Serif Khmer ExtraCondensed SemiBold", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Serif Khmer ExtraCondensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 7, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifKhmer-ExtraCondensedSemiBold.ttf", + "preferred_family_name": "Noto Serif Khmer", + "preferred_subfamily_name": "ExtraCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifKhmer-ExtraCondensedThin.ttf||141524:1655828711.0": { + "family_name": "Noto Serif Khmer ExtraCondensed Thin", + "font-family": "Noto Serif Khmer ExtraCondensed Thin", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Serif Khmer ExtraCondensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 2, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifKhmer-ExtraCondensedThin.ttf", + "preferred_family_name": "Noto Serif Khmer", + "preferred_subfamily_name": "ExtraCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifKhmer-ExtraLight.ttf||143608:1655828711.0": { + "family_name": "Noto Serif Khmer ExtraLight", + "font-family": "Noto Serif Khmer ExtraLight", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Serif Khmer ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 3, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifKhmer-ExtraLight.ttf", + "preferred_family_name": "Noto Serif Khmer", + "preferred_subfamily_name": "ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifKhmer-Light.ttf||150440:1655828711.0": { + "family_name": "Noto Serif Khmer Light", + "font-family": "Noto Serif Khmer Light", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Serif Khmer Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 4, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifKhmer-Light.ttf", + "preferred_family_name": "Noto Serif Khmer", + "preferred_subfamily_name": "Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifKhmer-Medium.ttf||150372:1655828711.0": { + "family_name": "Noto Serif Khmer Medium", + "font-family": "Noto Serif Khmer Medium", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Serif Khmer Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 6, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifKhmer-Medium.ttf", + "preferred_family_name": "Noto Serif Khmer", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifKhmer-Regular.ttf||154040:1655828711.0": { + "family_name": "Noto Serif Khmer", + "font-family": "Noto Serif Khmer", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif Khmer Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 5, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifKhmer-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifKhmer-SemiBold.ttf||153276:1655828711.0": { + "family_name": "Noto Serif Khmer SemiBold", + "font-family": "Noto Serif Khmer SemiBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Serif Khmer SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 7, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifKhmer-SemiBold.ttf", + "preferred_family_name": "Noto Serif Khmer", + "preferred_subfamily_name": "SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifKhmer-SemiCondensed.ttf||151692:1655828711.0": { + "family_name": "Noto Serif Khmer SemiCondensed", + "font-family": "Noto Serif Khmer SemiCondensed", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif Khmer SemiCondensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 5, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifKhmer-SemiCondensed.ttf", + "preferred_family_name": "Noto Serif Khmer", + "preferred_subfamily_name": "SemiCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifKhmer-SemiCondensedBlack.ttf||151636:1655828711.0": { + "family_name": "Noto Serif Khmer SemiCondensed Black", + "font-family": "Noto Serif Khmer SemiCondensed Black", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Serif Khmer SemiCondensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 10, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifKhmer-SemiCondensedBlack.ttf", + "preferred_family_name": "Noto Serif Khmer", + "preferred_subfamily_name": "SemiCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifKhmer-SemiCondensedBold.ttf||150236:1655828711.0": { + "family_name": "Noto Serif Khmer SemiCondensed", + "font-family": "Noto Serif Khmer SemiCondensed", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Serif Khmer SemiCondensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 8, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifKhmer-SemiCondensedBold.ttf", + "preferred_family_name": "Noto Serif Khmer", + "preferred_subfamily_name": "SemiCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifKhmer-SemiCondensedExtraBold.ttf||148820:1655828711.0": { + "family_name": "Noto Serif Khmer SemiCondensed ExtraBold", + "font-family": "Noto Serif Khmer SemiCondensed ExtraBold", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Serif Khmer SemiCondensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 9, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifKhmer-SemiCondensedExtraBold.ttf", + "preferred_family_name": "Noto Serif Khmer", + "preferred_subfamily_name": "SemiCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifKhmer-SemiCondensedExtraLight.ttf||143504:1655828711.0": { + "family_name": "Noto Serif Khmer SemiCondensed ExtraLight", + "font-family": "Noto Serif Khmer SemiCondensed ExtraLight", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Serif Khmer SemiCondensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 3, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifKhmer-SemiCondensedExtraLight.ttf", + "preferred_family_name": "Noto Serif Khmer", + "preferred_subfamily_name": "SemiCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifKhmer-SemiCondensedLight.ttf||146028:1655828711.0": { + "family_name": "Noto Serif Khmer SemiCondensed Light", + "font-family": "Noto Serif Khmer SemiCondensed Light", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Serif Khmer SemiCondensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 4, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifKhmer-SemiCondensedLight.ttf", + "preferred_family_name": "Noto Serif Khmer", + "preferred_subfamily_name": "SemiCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifKhmer-SemiCondensedMedium.ttf||150492:1655828711.0": { + "family_name": "Noto Serif Khmer SemiCondensed Medium", + "font-family": "Noto Serif Khmer SemiCondensed Medium", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Serif Khmer SemiCondensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 6, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifKhmer-SemiCondensedMedium.ttf", + "preferred_family_name": "Noto Serif Khmer", + "preferred_subfamily_name": "SemiCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifKhmer-SemiCondensedSemiBold.ttf||148232:1655828711.0": { + "family_name": "Noto Serif Khmer SemiCondensed SemiBold", + "font-family": "Noto Serif Khmer SemiCondensed SemiBold", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Serif Khmer SemiCondensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 7, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifKhmer-SemiCondensedSemiBold.ttf", + "preferred_family_name": "Noto Serif Khmer", + "preferred_subfamily_name": "SemiCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifKhmer-SemiCondensedThin.ttf||142228:1655828711.0": { + "family_name": "Noto Serif Khmer SemiCondensed Thin", + "font-family": "Noto Serif Khmer SemiCondensed Thin", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Serif Khmer SemiCondensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 2, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifKhmer-SemiCondensedThin.ttf", + "preferred_family_name": "Noto Serif Khmer", + "preferred_subfamily_name": "SemiCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifKhmer-Thin.ttf||142996:1655828711.0": { + "family_name": "Noto Serif Khmer Thin", + "font-family": "Noto Serif Khmer Thin", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Serif Khmer Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 2, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifKhmer-Thin.ttf", + "preferred_family_name": "Noto Serif Khmer", + "preferred_subfamily_name": "Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifKhojki-Bold.ttf||145036:1655828711.0": { + "family_name": "Noto Serif Khojki", + "font-family": "Noto Serif Khojki", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Serif Khojki Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/noto/NotoSerifKhojki-Bold.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifKhojki-Regular.ttf||143888:1655828711.0": { + "family_name": "Noto Serif Khojki", + "font-family": "Noto Serif Khojki", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif Khojki Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 0, + 5, + 2, + 4, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifKhojki-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifLao-Black.ttf||41544:1655828711.0": { + "family_name": "Noto Serif Lao Blk", + "font-family": "Noto Serif Lao Blk", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Serif Lao Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 10, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifLao-Black.ttf", + "preferred_family_name": "Noto Serif Lao", + "preferred_subfamily_name": "Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifLao-Bold.ttf||40352:1655828711.0": { + "family_name": "Noto Serif Lao", + "font-family": "Noto Serif Lao", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Serif Lao Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 8, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifLao-Bold.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifLao-Condensed.ttf||38508:1655828711.0": { + "family_name": "Noto Serif Lao Cond", + "font-family": "Noto Serif Lao Cond", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif Lao Condensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 5, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifLao-Condensed.ttf", + "preferred_family_name": "Noto Serif Lao", + "preferred_subfamily_name": "Condensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifLao-CondensedBlack.ttf||40868:1655828711.0": { + "family_name": "Noto Serif Lao Cond Blk", + "font-family": "Noto Serif Lao Cond Blk", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Serif Lao Condensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 10, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifLao-CondensedBlack.ttf", + "preferred_family_name": "Noto Serif Lao", + "preferred_subfamily_name": "Condensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifLao-CondensedBold.ttf||39976:1655828711.0": { + "family_name": "Noto Serif Lao Cond", + "font-family": "Noto Serif Lao Cond", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Serif Lao Condensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 8, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifLao-CondensedBold.ttf", + "preferred_family_name": "Noto Serif Lao", + "preferred_subfamily_name": "Condensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifLao-CondensedExtraBold.ttf||40764:1655828711.0": { + "family_name": "Noto Serif Lao Cond ExtBd", + "font-family": "Noto Serif Lao Cond ExtBd", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Serif Lao Condensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 9, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifLao-CondensedExtraBold.ttf", + "preferred_family_name": "Noto Serif Lao", + "preferred_subfamily_name": "Condensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifLao-CondensedExtraLight.ttf||38688:1655828711.0": { + "family_name": "Noto Serif Lao Cond ExtLt", + "font-family": "Noto Serif Lao Cond ExtLt", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Serif Lao Condensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 3, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifLao-CondensedExtraLight.ttf", + "preferred_family_name": "Noto Serif Lao", + "preferred_subfamily_name": "Condensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifLao-CondensedLight.ttf||38880:1655828711.0": { + "family_name": "Noto Serif Lao Cond Light", + "font-family": "Noto Serif Lao Cond Light", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Serif Lao Condensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 4, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifLao-CondensedLight.ttf", + "preferred_family_name": "Noto Serif Lao", + "preferred_subfamily_name": "Condensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifLao-CondensedMedium.ttf||38780:1655828711.0": { + "family_name": "Noto Serif Lao Cond Med", + "font-family": "Noto Serif Lao Cond Med", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Serif Lao Condensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 6, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifLao-CondensedMedium.ttf", + "preferred_family_name": "Noto Serif Lao", + "preferred_subfamily_name": "Condensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifLao-CondensedSemiBold.ttf||39916:1655828711.0": { + "family_name": "Noto Serif Lao Cond SemBd", + "font-family": "Noto Serif Lao Cond SemBd", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Serif Lao Condensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 7, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifLao-CondensedSemiBold.ttf", + "preferred_family_name": "Noto Serif Lao", + "preferred_subfamily_name": "Condensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifLao-CondensedThin.ttf||38696:1655828711.0": { + "family_name": "Noto Serif Lao Cond Thin", + "font-family": "Noto Serif Lao Cond Thin", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Serif Lao Condensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 2, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifLao-CondensedThin.ttf", + "preferred_family_name": "Noto Serif Lao", + "preferred_subfamily_name": "Condensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifLao-ExtraBold.ttf||40752:1655828711.0": { + "family_name": "Noto Serif Lao ExtBd", + "font-family": "Noto Serif Lao ExtBd", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Serif Lao ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 9, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifLao-ExtraBold.ttf", + "preferred_family_name": "Noto Serif Lao", + "preferred_subfamily_name": "ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifLao-ExtraCondensed.ttf||38332:1655828711.0": { + "family_name": "Noto Serif Lao ExtCond", + "font-family": "Noto Serif Lao ExtCond", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif Lao ExtraCondensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 5, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifLao-ExtraCondensed.ttf", + "preferred_family_name": "Noto Serif Lao", + "preferred_subfamily_name": "ExtraCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifLao-ExtraCondensedBlack.ttf||40768:1655828711.0": { + "family_name": "Noto Serif Lao ExtCond Blk", + "font-family": "Noto Serif Lao ExtCond Blk", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Serif Lao ExtraCondensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 10, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifLao-ExtraCondensedBlack.ttf", + "preferred_family_name": "Noto Serif Lao", + "preferred_subfamily_name": "ExtraCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifLao-ExtraCondensedBold.ttf||39608:1655828711.0": { + "family_name": "Noto Serif Lao ExtCond", + "font-family": "Noto Serif Lao ExtCond", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Serif Lao ExtraCondensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 8, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifLao-ExtraCondensedBold.ttf", + "preferred_family_name": "Noto Serif Lao", + "preferred_subfamily_name": "ExtraCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifLao-ExtraCondensedExtraBold.ttf||40404:1655828711.0": { + "family_name": "Noto Serif Lao ExtCond ExtBd", + "font-family": "Noto Serif Lao ExtCond ExtBd", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Serif Lao ExtraCondensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 9, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifLao-ExtraCondensedExtraBold.ttf", + "preferred_family_name": "Noto Serif Lao", + "preferred_subfamily_name": "ExtraCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifLao-ExtraCondensedExtraLight.ttf||38676:1655828711.0": { + "family_name": "Noto Serif Lao ExtCond ExtLt", + "font-family": "Noto Serif Lao ExtCond ExtLt", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Serif Lao ExtraCondensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 3, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifLao-ExtraCondensedExtraLight.ttf", + "preferred_family_name": "Noto Serif Lao", + "preferred_subfamily_name": "ExtraCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifLao-ExtraCondensedLight.ttf||38828:1655828711.0": { + "family_name": "Noto Serif Lao ExtCond Light", + "font-family": "Noto Serif Lao ExtCond Light", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Serif Lao ExtraCondensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 4, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifLao-ExtraCondensedLight.ttf", + "preferred_family_name": "Noto Serif Lao", + "preferred_subfamily_name": "ExtraCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifLao-ExtraCondensedMedium.ttf||38608:1655828711.0": { + "family_name": "Noto Serif Lao ExtCond Med", + "font-family": "Noto Serif Lao ExtCond Med", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Serif Lao ExtraCondensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 6, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifLao-ExtraCondensedMedium.ttf", + "preferred_family_name": "Noto Serif Lao", + "preferred_subfamily_name": "ExtraCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifLao-ExtraCondensedSemiBold.ttf||39740:1655828711.0": { + "family_name": "Noto Serif Lao ExtCond SemBd", + "font-family": "Noto Serif Lao ExtCond SemBd", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Serif Lao ExtraCondensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 7, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifLao-ExtraCondensedSemiBold.ttf", + "preferred_family_name": "Noto Serif Lao", + "preferred_subfamily_name": "ExtraCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifLao-ExtraCondensedThin.ttf||38628:1655828711.0": { + "family_name": "Noto Serif Lao ExtCond Thin", + "font-family": "Noto Serif Lao ExtCond Thin", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Serif Lao ExtraCondensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 2, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifLao-ExtraCondensedThin.ttf", + "preferred_family_name": "Noto Serif Lao", + "preferred_subfamily_name": "ExtraCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifLao-ExtraLight.ttf||38912:1655828711.0": { + "family_name": "Noto Serif Lao ExtLt", + "font-family": "Noto Serif Lao ExtLt", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Serif Lao ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 3, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifLao-ExtraLight.ttf", + "preferred_family_name": "Noto Serif Lao", + "preferred_subfamily_name": "ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifLao-Light.ttf||38620:1655828711.0": { + "family_name": "Noto Serif Lao Light", + "font-family": "Noto Serif Lao Light", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Serif Lao Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 4, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifLao-Light.ttf", + "preferred_family_name": "Noto Serif Lao", + "preferred_subfamily_name": "Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifLao-Medium.ttf||38948:1655828711.0": { + "family_name": "Noto Serif Lao Med", + "font-family": "Noto Serif Lao Med", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Serif Lao Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 6, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifLao-Medium.ttf", + "preferred_family_name": "Noto Serif Lao", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifLao-Regular.ttf||38516:1655828711.0": { + "family_name": "Noto Serif Lao", + "font-family": "Noto Serif Lao", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif Lao Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 5, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifLao-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifLao-SemiBold.ttf||39788:1655828711.0": { + "family_name": "Noto Serif Lao SemBd", + "font-family": "Noto Serif Lao SemBd", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Serif Lao SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 7, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifLao-SemiBold.ttf", + "preferred_family_name": "Noto Serif Lao", + "preferred_subfamily_name": "SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifLao-SemiCondensed.ttf||38712:1655828711.0": { + "family_name": "Noto Serif Lao SemCond", + "font-family": "Noto Serif Lao SemCond", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif Lao SemiCondensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 5, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifLao-SemiCondensed.ttf", + "preferred_family_name": "Noto Serif Lao", + "preferred_subfamily_name": "SemiCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifLao-SemiCondensedBlack.ttf||41320:1655828711.0": { + "family_name": "Noto Serif Lao SemCond Blk", + "font-family": "Noto Serif Lao SemCond Blk", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Serif Lao SemiCondensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 10, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifLao-SemiCondensedBlack.ttf", + "preferred_family_name": "Noto Serif Lao", + "preferred_subfamily_name": "SemiCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifLao-SemiCondensedBold.ttf||40524:1655828711.0": { + "family_name": "Noto Serif Lao SemCond", + "font-family": "Noto Serif Lao SemCond", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Serif Lao SemiCondensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 8, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifLao-SemiCondensedBold.ttf", + "preferred_family_name": "Noto Serif Lao", + "preferred_subfamily_name": "SemiCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifLao-SemiCondensedExtraBold.ttf||40608:1655828711.0": { + "family_name": "Noto Serif Lao SemCond ExtBd", + "font-family": "Noto Serif Lao SemCond ExtBd", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Serif Lao SemiCondensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 9, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifLao-SemiCondensedExtraBold.ttf", + "preferred_family_name": "Noto Serif Lao", + "preferred_subfamily_name": "SemiCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifLao-SemiCondensedExtraLight.ttf||38956:1655828711.0": { + "family_name": "Noto Serif Lao SemCond ExtLt", + "font-family": "Noto Serif Lao SemCond ExtLt", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Serif Lao SemiCondensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 3, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifLao-SemiCondensedExtraLight.ttf", + "preferred_family_name": "Noto Serif Lao", + "preferred_subfamily_name": "SemiCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifLao-SemiCondensedLight.ttf||38400:1655828711.0": { + "family_name": "Noto Serif Lao SemCond Light", + "font-family": "Noto Serif Lao SemCond Light", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Serif Lao SemiCondensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 4, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifLao-SemiCondensedLight.ttf", + "preferred_family_name": "Noto Serif Lao", + "preferred_subfamily_name": "SemiCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifLao-SemiCondensedMedium.ttf||38852:1655828711.0": { + "family_name": "Noto Serif Lao SemCond Med", + "font-family": "Noto Serif Lao SemCond Med", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Serif Lao SemiCondensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 6, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifLao-SemiCondensedMedium.ttf", + "preferred_family_name": "Noto Serif Lao", + "preferred_subfamily_name": "SemiCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifLao-SemiCondensedSemiBold.ttf||40096:1655828711.0": { + "family_name": "Noto Serif Lao SemCond SemBd", + "font-family": "Noto Serif Lao SemCond SemBd", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Serif Lao SemiCondensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 7, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifLao-SemiCondensedSemiBold.ttf", + "preferred_family_name": "Noto Serif Lao", + "preferred_subfamily_name": "SemiCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifLao-SemiCondensedThin.ttf||38832:1655828711.0": { + "family_name": "Noto Serif Lao SemCond Thin", + "font-family": "Noto Serif Lao SemCond Thin", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Serif Lao SemiCondensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 2, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifLao-SemiCondensedThin.ttf", + "preferred_family_name": "Noto Serif Lao", + "preferred_subfamily_name": "SemiCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifLao-Thin.ttf||38448:1655828711.0": { + "family_name": "Noto Serif Lao Thin", + "font-family": "Noto Serif Lao Thin", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Serif Lao Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 2, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifLao-Thin.ttf", + "preferred_family_name": "Noto Serif Lao", + "preferred_subfamily_name": "Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifMakasar-Regular.ttf||7244:1655828711.0": { + "family_name": "Noto Serif Makasar", + "font-family": "Noto Serif Makasar", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif Makasar Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 2, + 5, + 2, + 6, + 5, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifMakasar-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifMalayalam-Black.ttf||115476:1655828711.0": { + "family_name": "Noto Serif Malayalam Black", + "font-family": "Noto Serif Malayalam Black", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Serif Malayalam Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 10, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifMalayalam-Black.ttf", + "preferred_family_name": "Noto Serif Malayalam", + "preferred_subfamily_name": "Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifMalayalam-Bold.ttf||112256:1655828711.0": { + "family_name": "Noto Serif Malayalam", + "font-family": "Noto Serif Malayalam", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Serif Malayalam Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 8, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifMalayalam-Bold.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifMalayalam-ExtraBold.ttf||113384:1655828711.0": { + "family_name": "Noto Serif Malayalam ExtraBold", + "font-family": "Noto Serif Malayalam ExtraBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Serif Malayalam ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 9, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifMalayalam-ExtraBold.ttf", + "preferred_family_name": "Noto Serif Malayalam", + "preferred_subfamily_name": "ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifMalayalam-ExtraLight.ttf||115480:1655828711.0": { + "family_name": "Noto Serif Malayalam ExtraLight", + "font-family": "Noto Serif Malayalam ExtraLight", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Serif Malayalam ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 3, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifMalayalam-ExtraLight.ttf", + "preferred_family_name": "Noto Serif Malayalam", + "preferred_subfamily_name": "ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifMalayalam-Light.ttf||108292:1655828711.0": { + "family_name": "Noto Serif Malayalam Light", + "font-family": "Noto Serif Malayalam Light", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Serif Malayalam Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 4, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifMalayalam-Light.ttf", + "preferred_family_name": "Noto Serif Malayalam", + "preferred_subfamily_name": "Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifMalayalam-Medium.ttf||111548:1655828711.0": { + "family_name": "Noto Serif Malayalam Medium", + "font-family": "Noto Serif Malayalam Medium", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Serif Malayalam Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 6, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifMalayalam-Medium.ttf", + "preferred_family_name": "Noto Serif Malayalam", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifMalayalam-Regular.ttf||111052:1655828711.0": { + "family_name": "Noto Serif Malayalam", + "font-family": "Noto Serif Malayalam", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif Malayalam Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 5, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifMalayalam-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifMalayalam-SemiBold.ttf||112480:1655828711.0": { + "family_name": "Noto Serif Malayalam SemiBold", + "font-family": "Noto Serif Malayalam SemiBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Serif Malayalam SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 7, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifMalayalam-SemiBold.ttf", + "preferred_family_name": "Noto Serif Malayalam", + "preferred_subfamily_name": "SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifMalayalam-Thin.ttf||106036:1655828711.0": { + "family_name": "Noto Serif Malayalam Thin", + "font-family": "Noto Serif Malayalam Thin", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Serif Malayalam Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 2, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifMalayalam-Thin.ttf", + "preferred_family_name": "Noto Serif Malayalam", + "preferred_subfamily_name": "Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifMyanmar-Black.ttf||258792:1655828711.0": { + "family_name": "Noto Serif Myanmar Blk", + "font-family": "Noto Serif Myanmar Blk", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Serif Myanmar Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 10, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifMyanmar-Black.ttf", + "preferred_family_name": "Noto Serif Myanmar", + "preferred_subfamily_name": "Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifMyanmar-Bold.ttf||271328:1655828711.0": { + "family_name": "Noto Serif Myanmar", + "font-family": "Noto Serif Myanmar", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif Myanmar Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 10, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifMyanmar-Bold.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifMyanmar-Condensed.ttf||253172:1655828711.0": { + "family_name": "Noto Serif Myanmar Condensed", + "font-family": "Noto Serif Myanmar Condensed", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif Myanmar Condensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 7, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifMyanmar-Condensed.ttf", + "preferred_family_name": "Noto Serif Myanmar", + "preferred_subfamily_name": "Condensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifMyanmar-CondensedBlack.ttf||251024:1655828711.0": { + "family_name": "Noto Serif Myanmar Cond Blk", + "font-family": "Noto Serif Myanmar Cond Blk", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Serif Myanmar Condensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 10, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifMyanmar-CondensedBlack.ttf", + "preferred_family_name": "Noto Serif Myanmar", + "preferred_subfamily_name": "Condensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifMyanmar-CondensedBold.ttf||261112:1655828711.0": { + "family_name": "Noto Serif Myanmar Condensed Bold", + "font-family": "Noto Serif Myanmar Condensed Bold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif Myanmar Condensed Bold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 10, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifMyanmar-CondensedBold.ttf", + "preferred_family_name": "Noto Serif Myanmar", + "preferred_subfamily_name": "Condensed Bold", + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifMyanmar-CondensedExtraBold.ttf||248916:1655828711.0": { + "family_name": "Noto Serif Myanmar Cond ExtBd", + "font-family": "Noto Serif Myanmar Cond ExtBd", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Serif Myanmar Condensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 9, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifMyanmar-CondensedExtraBold.ttf", + "preferred_family_name": "Noto Serif Myanmar", + "preferred_subfamily_name": "Condensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifMyanmar-CondensedExtraLight.ttf||233388:1655828711.0": { + "family_name": "Noto Serif Myanmar Cond ExtLt", + "font-family": "Noto Serif Myanmar Cond ExtLt", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Serif Myanmar Condensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 3, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifMyanmar-CondensedExtraLight.ttf", + "preferred_family_name": "Noto Serif Myanmar", + "preferred_subfamily_name": "Condensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifMyanmar-CondensedLight.ttf||239744:1655828711.0": { + "family_name": "Noto Serif Myanmar Condensed Light", + "font-family": "Noto Serif Myanmar Condensed Light", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif Myanmar Condensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 2, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifMyanmar-CondensedLight.ttf", + "preferred_family_name": "Noto Serif Myanmar", + "preferred_subfamily_name": "Condensed Light", + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifMyanmar-CondensedMedium.ttf||241120:1655828711.0": { + "family_name": "Noto Serif Myanmar Cond Med", + "font-family": "Noto Serif Myanmar Cond Med", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Serif Myanmar Condensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 6, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifMyanmar-CondensedMedium.ttf", + "preferred_family_name": "Noto Serif Myanmar", + "preferred_subfamily_name": "Condensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifMyanmar-CondensedSemiBold.ttf||244520:1655828711.0": { + "family_name": "Noto Serif Myanmar Cond SemBd", + "font-family": "Noto Serif Myanmar Cond SemBd", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Serif Myanmar Condensed SemiBold ", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 7, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifMyanmar-CondensedSemiBold.ttf", + "preferred_family_name": "Noto Serif Myanmar", + "preferred_subfamily_name": "Condensed SemiBold ", + "subfamily_name": "Regular", + "weight": 600, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifMyanmar-CondensedThin.ttf||231312:1655828711.0": { + "family_name": "Noto Serif Myanmar Cond Thin", + "font-family": "Noto Serif Myanmar Cond Thin", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Serif Myanmar Condensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 2, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifMyanmar-CondensedThin.ttf", + "preferred_family_name": "Noto Serif Myanmar", + "preferred_subfamily_name": "Condensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifMyanmar-ExtraBold.ttf||255936:1655828711.0": { + "family_name": "Noto Serif Myanmar ExtBd", + "font-family": "Noto Serif Myanmar ExtBd", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Serif Myanmar ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 9, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifMyanmar-ExtraBold.ttf", + "preferred_family_name": "Noto Serif Myanmar", + "preferred_subfamily_name": "ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifMyanmar-ExtraCondensed.ttf||239976:1655828711.0": { + "family_name": "Noto Serif Myanmar ExtCond", + "font-family": "Noto Serif Myanmar ExtCond", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif Myanmar ExtraCondensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 5, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifMyanmar-ExtraCondensed.ttf", + "preferred_family_name": "Noto Serif Myanmar", + "preferred_subfamily_name": "ExtraCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifMyanmar-ExtraCondensedBlack.ttf||249768:1655828711.0": { + "family_name": "Noto Serif Myanmar ExtCond Blk", + "font-family": "Noto Serif Myanmar ExtCond Blk", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Serif Myanmar ExtraCondensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 10, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifMyanmar-ExtraCondensedBlack.ttf", + "preferred_family_name": "Noto Serif Myanmar", + "preferred_subfamily_name": "ExtraCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifMyanmar-ExtraCondensedBold.ttf||242812:1655828711.0": { + "family_name": "Noto Serif Myanmar ExtCond", + "font-family": "Noto Serif Myanmar ExtCond", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Serif Myanmar ExtraCondensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 8, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifMyanmar-ExtraCondensedBold.ttf", + "preferred_family_name": "Noto Serif Myanmar", + "preferred_subfamily_name": "ExtraCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifMyanmar-ExtraCondensedExtraBold.ttf||248532:1655828711.0": { + "family_name": "Noto Serif Myanmar ExtCond ExtBd", + "font-family": "Noto Serif Myanmar ExtCond ExtBd", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Serif Myanmar ExtraCondensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 9, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifMyanmar-ExtraCondensedExtraBold.ttf", + "preferred_family_name": "Noto Serif Myanmar", + "preferred_subfamily_name": "ExtraCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifMyanmar-ExtraCondensedExtraLight.ttf||231744:1655828711.0": { + "family_name": "Noto Serif Myanmar ExtCond ExtLt", + "font-family": "Noto Serif Myanmar ExtCond ExtLt", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Serif Myanmar ExtraCondensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 3, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifMyanmar-ExtraCondensedExtraLight.ttf", + "preferred_family_name": "Noto Serif Myanmar", + "preferred_subfamily_name": "ExtraCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifMyanmar-ExtraCondensedLight.ttf||240224:1655828711.0": { + "family_name": "Noto Serif Myanmar ExtCond Light", + "font-family": "Noto Serif Myanmar ExtCond Light", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Serif Myanmar ExtraCondensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 4, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifMyanmar-ExtraCondensedLight.ttf", + "preferred_family_name": "Noto Serif Myanmar", + "preferred_subfamily_name": "ExtraCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifMyanmar-ExtraCondensedMedium.ttf||241804:1655828711.0": { + "family_name": "Noto Serif Myanmar ExtCond Med", + "font-family": "Noto Serif Myanmar ExtCond Med", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Serif Myanmar ExtraCondensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 6, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifMyanmar-ExtraCondensedMedium.ttf", + "preferred_family_name": "Noto Serif Myanmar", + "preferred_subfamily_name": "ExtraCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifMyanmar-ExtraCondensedSemiBold.ttf||242248:1655828711.0": { + "family_name": "Noto Serif Myanmar ExtCond SemBd", + "font-family": "Noto Serif Myanmar ExtCond SemBd", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Serif Myanmar ExtraCondensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 7, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifMyanmar-ExtraCondensedSemiBold.ttf", + "preferred_family_name": "Noto Serif Myanmar", + "preferred_subfamily_name": "ExtraCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifMyanmar-ExtraCondensedThin.ttf||229920:1655828711.0": { + "family_name": "Noto Serif Myanmar ExtCond Thin", + "font-family": "Noto Serif Myanmar ExtCond Thin", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Serif Myanmar ExtraCondensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 2, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifMyanmar-ExtraCondensedThin.ttf", + "preferred_family_name": "Noto Serif Myanmar", + "preferred_subfamily_name": "ExtraCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifMyanmar-ExtraLight.ttf||235972:1655828711.0": { + "family_name": "Noto Serif Myanmar ExtLt", + "font-family": "Noto Serif Myanmar ExtLt", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Serif Myanmar ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 3, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifMyanmar-ExtraLight.ttf", + "preferred_family_name": "Noto Serif Myanmar", + "preferred_subfamily_name": "ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifMyanmar-Light.ttf||245452:1655828711.0": { + "family_name": "Noto Serif Myanmar Light", + "font-family": "Noto Serif Myanmar Light", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif Myanmar Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 2, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifMyanmar-Light.ttf", + "preferred_family_name": "Noto Serif Myanmar", + "preferred_subfamily_name": "Light", + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifMyanmar-Medium.ttf||246880:1655828711.0": { + "family_name": "Noto Serif Myanmar Med", + "font-family": "Noto Serif Myanmar Med", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Serif Myanmar Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 6, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifMyanmar-Medium.ttf", + "preferred_family_name": "Noto Serif Myanmar", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifMyanmar-Regular.ttf||260404:1655828711.0": { + "family_name": "Noto Serif Myanmar", + "font-family": "Noto Serif Myanmar", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif Myanmar Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 7, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifMyanmar-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifMyanmar-SemiBold.ttf||247708:1655828711.0": { + "family_name": "Noto Serif Myanmar SemBd", + "font-family": "Noto Serif Myanmar SemBd", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Serif Myanmar SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 7, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifMyanmar-SemiBold.ttf", + "preferred_family_name": "Noto Serif Myanmar", + "preferred_subfamily_name": "SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifMyanmar-SemiCondensed.ttf||245312:1655828711.0": { + "family_name": "Noto Serif Myanmar SemCond", + "font-family": "Noto Serif Myanmar SemCond", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif Myanmar SemiCondensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 5, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifMyanmar-SemiCondensed.ttf", + "preferred_family_name": "Noto Serif Myanmar", + "preferred_subfamily_name": "SemiCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifMyanmar-SemiCondensedBlack.ttf||254840:1655828711.0": { + "family_name": "Noto Serif Myanmar SemCond Blk", + "font-family": "Noto Serif Myanmar SemCond Blk", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Serif Myanmar SemiCondensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 10, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifMyanmar-SemiCondensedBlack.ttf", + "preferred_family_name": "Noto Serif Myanmar", + "preferred_subfamily_name": "SemiCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifMyanmar-SemiCondensedBold.ttf||245856:1655828711.0": { + "family_name": "Noto Serif Myanmar SemCond", + "font-family": "Noto Serif Myanmar SemCond", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Serif Myanmar SemiCondensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 8, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifMyanmar-SemiCondensedBold.ttf", + "preferred_family_name": "Noto Serif Myanmar", + "preferred_subfamily_name": "SemiCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifMyanmar-SemiCondensedExtraBold.ttf||251504:1655828711.0": { + "family_name": "Noto Serif Myanmar SemCond ExtBd", + "font-family": "Noto Serif Myanmar SemCond ExtBd", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Serif Myanmar SemiCondensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 9, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifMyanmar-SemiCondensedExtraBold.ttf", + "preferred_family_name": "Noto Serif Myanmar", + "preferred_subfamily_name": "SemiCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifMyanmar-SemiCondensedExtraLight.ttf||233648:1655828711.0": { + "family_name": "Noto Serif Myanmar SemCond ExtLt", + "font-family": "Noto Serif Myanmar SemCond ExtLt", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Serif Myanmar SemiCondensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 3, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifMyanmar-SemiCondensedExtraLight.ttf", + "preferred_family_name": "Noto Serif Myanmar", + "preferred_subfamily_name": "SemiCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifMyanmar-SemiCondensedLight.ttf||240328:1655828711.0": { + "family_name": "Noto Serif Myanmar SemCond Light", + "font-family": "Noto Serif Myanmar SemCond Light", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Serif Myanmar SemiCondensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 4, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifMyanmar-SemiCondensedLight.ttf", + "preferred_family_name": "Noto Serif Myanmar", + "preferred_subfamily_name": "SemiCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifMyanmar-SemiCondensedMedium.ttf||242444:1655828711.0": { + "family_name": "Noto Serif Myanmar SemCond Med", + "font-family": "Noto Serif Myanmar SemCond Med", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Serif Myanmar SemiCondensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 6, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifMyanmar-SemiCondensedMedium.ttf", + "preferred_family_name": "Noto Serif Myanmar", + "preferred_subfamily_name": "SemiCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifMyanmar-SemiCondensedSemiBold.ttf||245940:1655828711.0": { + "family_name": "Noto Serif Myanmar SemCond SemBd", + "font-family": "Noto Serif Myanmar SemCond SemBd", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Serif Myanmar SemiCondensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 7, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifMyanmar-SemiCondensedSemiBold.ttf", + "preferred_family_name": "Noto Serif Myanmar", + "preferred_subfamily_name": "SemiCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifMyanmar-SemiCondensedThin.ttf||233400:1655828711.0": { + "family_name": "Noto Serif Myanmar SemCond Thin", + "font-family": "Noto Serif Myanmar SemCond Thin", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Serif Myanmar SemiCondensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 2, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifMyanmar-SemiCondensedThin.ttf", + "preferred_family_name": "Noto Serif Myanmar", + "preferred_subfamily_name": "SemiCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifMyanmar-Thin.ttf||235492:1655828711.0": { + "family_name": "Noto Serif Myanmar Thin", + "font-family": "Noto Serif Myanmar Thin", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Serif Myanmar Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 2, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifMyanmar-Thin.ttf", + "preferred_family_name": "Noto Serif Myanmar", + "preferred_subfamily_name": "Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifNyiakengPuachueHmong-Bold.ttf||15152:1655828711.0": { + "family_name": "Noto Serif Hmong Nyiakeng", + "font-family": "Noto Serif Hmong Nyiakeng", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Serif Hmong Nyiakeng Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 8, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifNyiakengPuachueHmong-Bold.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifNyiakengPuachueHmong-Medium.ttf||15104:1655828711.0": { + "family_name": "Noto Serif Hmong Nyiakeng Medium", + "font-family": "Noto Serif Hmong Nyiakeng Medium", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Serif Hmong Nyiakeng Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 6, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifNyiakengPuachueHmong-Medium.ttf", + "preferred_family_name": "Noto Serif Hmong Nyiakeng", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifNyiakengPuachueHmong-Regular.ttf||14912:1655828711.0": { + "family_name": "Noto Serif Hmong Nyiakeng", + "font-family": "Noto Serif Hmong Nyiakeng", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif Hmong Nyiakeng Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 5, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifNyiakengPuachueHmong-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifNyiakengPuachueHmong-SemiBold.ttf||15144:1655828711.0": { + "family_name": "Noto Serif Hmong Nyiakeng SemiBold", + "font-family": "Noto Serif Hmong Nyiakeng SemiBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Serif Hmong Nyiakeng SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 7, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifNyiakengPuachueHmong-SemiBold.ttf", + "preferred_family_name": "Noto Serif Hmong Nyiakeng", + "preferred_subfamily_name": "SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifOldUyghur-Regular.ttf||31420:1655828711.0": { + "family_name": "Noto Serif Old Uyghur", + "font-family": "Noto Serif Old Uyghur", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif Old Uyghur Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/noto/NotoSerifOldUyghur-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifOriya-Bold.ttf||111212:1655828711.0": { + "family_name": "Noto Serif Oriya", + "font-family": "Noto Serif Oriya", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Serif Oriya Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 8, + 4, + 6, + 8, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifOriya-Bold.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifOriya-Medium.ttf||113296:1655828711.0": { + "family_name": "Noto Serif Oriya Medium", + "font-family": "Noto Serif Oriya Medium", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Serif Oriya Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 6, + 4, + 6, + 8, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifOriya-Medium.ttf", + "preferred_family_name": "Noto Serif Oriya", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifOriya-Regular.ttf||113568:1655828711.0": { + "family_name": "Noto Serif Oriya", + "font-family": "Noto Serif Oriya", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif Oriya Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 5, + 4, + 6, + 8, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifOriya-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifOriya-SemiBold.ttf||112736:1655828711.0": { + "family_name": "Noto Serif Oriya SemiBold", + "font-family": "Noto Serif Oriya SemiBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Serif Oriya SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 11, + 7, + 4, + 6, + 8, + 4, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifOriya-SemiBold.ttf", + "preferred_family_name": "Noto Serif Oriya", + "preferred_subfamily_name": "SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifSinhala-Black.ttf||340372:1655828711.0": { + "family_name": "Noto Serif Sinhala Black", + "font-family": "Noto Serif Sinhala Black", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Serif Sinhala Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 10, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifSinhala-Black.ttf", + "preferred_family_name": "Noto Serif Sinhala", + "preferred_subfamily_name": "Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifSinhala-Bold.ttf||334568:1655828711.0": { + "family_name": "Noto Serif Sinhala", + "font-family": "Noto Serif Sinhala", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Serif Sinhala Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 8, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifSinhala-Bold.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifSinhala-Condensed.ttf||311324:1655828711.0": { + "family_name": "Noto Serif Sinhala Condensed", + "font-family": "Noto Serif Sinhala Condensed", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif Sinhala Condensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 5, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifSinhala-Condensed.ttf", + "preferred_family_name": "Noto Serif Sinhala", + "preferred_subfamily_name": "Condensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifSinhala-CondensedBlack.ttf||338036:1655828711.0": { + "family_name": "Noto Serif Sinhala Condensed Black", + "font-family": "Noto Serif Sinhala Condensed Black", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Serif Sinhala Condensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 10, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifSinhala-CondensedBlack.ttf", + "preferred_family_name": "Noto Serif Sinhala", + "preferred_subfamily_name": "Condensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifSinhala-CondensedBold.ttf||345688:1655828711.0": { + "family_name": "Noto Serif Sinhala Condensed", + "font-family": "Noto Serif Sinhala Condensed", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Serif Sinhala Condensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 8, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifSinhala-CondensedBold.ttf", + "preferred_family_name": "Noto Serif Sinhala", + "preferred_subfamily_name": "Condensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifSinhala-CondensedExtraBold.ttf||337972:1655828711.0": { + "family_name": "Noto Serif Sinhala Condensed ExtraBold", + "font-family": "Noto Serif Sinhala Condensed ExtraBold", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Serif Sinhala Condensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 9, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifSinhala-CondensedExtraBold.ttf", + "preferred_family_name": "Noto Serif Sinhala", + "preferred_subfamily_name": "Condensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifSinhala-CondensedExtraLight.ttf||310532:1655828711.0": { + "family_name": "Noto Serif Sinhala Condensed ExtraLight", + "font-family": "Noto Serif Sinhala Condensed ExtraLight", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Serif Sinhala Condensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 3, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifSinhala-CondensedExtraLight.ttf", + "preferred_family_name": "Noto Serif Sinhala", + "preferred_subfamily_name": "Condensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifSinhala-CondensedLight.ttf||323020:1655828711.0": { + "family_name": "Noto Serif Sinhala Condensed Light", + "font-family": "Noto Serif Sinhala Condensed Light", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Serif Sinhala Condensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 4, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifSinhala-CondensedLight.ttf", + "preferred_family_name": "Noto Serif Sinhala", + "preferred_subfamily_name": "Condensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifSinhala-CondensedMedium.ttf||315324:1655828711.0": { + "family_name": "Noto Serif Sinhala Condensed Medium", + "font-family": "Noto Serif Sinhala Condensed Medium", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Serif Sinhala Condensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 6, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifSinhala-CondensedMedium.ttf", + "preferred_family_name": "Noto Serif Sinhala", + "preferred_subfamily_name": "Condensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifSinhala-CondensedSemiBold.ttf||316844:1655828711.0": { + "family_name": "Noto Serif Sinhala Condensed SemiBold", + "font-family": "Noto Serif Sinhala Condensed SemiBold", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Serif Sinhala Condensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 7, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifSinhala-CondensedSemiBold.ttf", + "preferred_family_name": "Noto Serif Sinhala", + "preferred_subfamily_name": "Condensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifSinhala-CondensedThin.ttf||319488:1655828711.0": { + "family_name": "Noto Serif Sinhala Condensed Thin", + "font-family": "Noto Serif Sinhala Condensed Thin", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Serif Sinhala Condensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 2, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifSinhala-CondensedThin.ttf", + "preferred_family_name": "Noto Serif Sinhala", + "preferred_subfamily_name": "Condensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifSinhala-ExtraBold.ttf||344716:1655828711.0": { + "family_name": "Noto Serif Sinhala ExtraBold", + "font-family": "Noto Serif Sinhala ExtraBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Serif Sinhala ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 9, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifSinhala-ExtraBold.ttf", + "preferred_family_name": "Noto Serif Sinhala", + "preferred_subfamily_name": "ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifSinhala-ExtraCondensed.ttf||312212:1655828711.0": { + "family_name": "Noto Serif Sinhala ExtraCondensed", + "font-family": "Noto Serif Sinhala ExtraCondensed", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif Sinhala ExtraCondensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 5, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifSinhala-ExtraCondensed.ttf", + "preferred_family_name": "Noto Serif Sinhala", + "preferred_subfamily_name": "ExtraCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifSinhala-ExtraCondensedBlack.ttf||333412:1655828711.0": { + "family_name": "Noto Serif Sinhala ExtraCondensed Black", + "font-family": "Noto Serif Sinhala ExtraCondensed Black", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Serif Sinhala ExtraCondensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 10, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifSinhala-ExtraCondensedBlack.ttf", + "preferred_family_name": "Noto Serif Sinhala", + "preferred_subfamily_name": "ExtraCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifSinhala-ExtraCondensedBold.ttf||329912:1655828711.0": { + "family_name": "Noto Serif Sinhala ExtraCondensed", + "font-family": "Noto Serif Sinhala ExtraCondensed", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Serif Sinhala ExtraCondensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 8, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifSinhala-ExtraCondensedBold.ttf", + "preferred_family_name": "Noto Serif Sinhala", + "preferred_subfamily_name": "ExtraCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifSinhala-ExtraCondensedExtraBold.ttf||325652:1655828711.0": { + "family_name": "Noto Serif Sinhala ExtraCondensed ExtraBold", + "font-family": "Noto Serif Sinhala ExtraCondensed ExtraBold", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Serif Sinhala ExtraCondensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 9, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifSinhala-ExtraCondensedExtraBold.ttf", + "preferred_family_name": "Noto Serif Sinhala", + "preferred_subfamily_name": "ExtraCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifSinhala-ExtraCondensedExtraLight.ttf||307168:1655828711.0": { + "family_name": "Noto Serif Sinhala ExtraCondensed ExtraLight", + "font-family": "Noto Serif Sinhala ExtraCondensed ExtraLight", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Serif Sinhala ExtraCondensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 3, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifSinhala-ExtraCondensedExtraLight.ttf", + "preferred_family_name": "Noto Serif Sinhala", + "preferred_subfamily_name": "ExtraCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifSinhala-ExtraCondensedLight.ttf||324276:1655828711.0": { + "family_name": "Noto Serif Sinhala ExtraCondensed Light", + "font-family": "Noto Serif Sinhala ExtraCondensed Light", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Serif Sinhala ExtraCondensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 4, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifSinhala-ExtraCondensedLight.ttf", + "preferred_family_name": "Noto Serif Sinhala", + "preferred_subfamily_name": "ExtraCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifSinhala-ExtraCondensedMedium.ttf||316092:1655828711.0": { + "family_name": "Noto Serif Sinhala ExtraCondensed Medium", + "font-family": "Noto Serif Sinhala ExtraCondensed Medium", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Serif Sinhala ExtraCondensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 6, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifSinhala-ExtraCondensedMedium.ttf", + "preferred_family_name": "Noto Serif Sinhala", + "preferred_subfamily_name": "ExtraCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifSinhala-ExtraCondensedSemiBold.ttf||306920:1655828711.0": { + "family_name": "Noto Serif Sinhala ExtraCondensed SemiBold", + "font-family": "Noto Serif Sinhala ExtraCondensed SemiBold", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Serif Sinhala ExtraCondensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 7, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifSinhala-ExtraCondensedSemiBold.ttf", + "preferred_family_name": "Noto Serif Sinhala", + "preferred_subfamily_name": "ExtraCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifSinhala-ExtraCondensedThin.ttf||315068:1655828711.0": { + "family_name": "Noto Serif Sinhala ExtraCondensed Thin", + "font-family": "Noto Serif Sinhala ExtraCondensed Thin", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Serif Sinhala ExtraCondensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 2, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifSinhala-ExtraCondensedThin.ttf", + "preferred_family_name": "Noto Serif Sinhala", + "preferred_subfamily_name": "ExtraCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifSinhala-ExtraLight.ttf||324356:1655828711.0": { + "family_name": "Noto Serif Sinhala ExtraLight", + "font-family": "Noto Serif Sinhala ExtraLight", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Serif Sinhala ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 3, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifSinhala-ExtraLight.ttf", + "preferred_family_name": "Noto Serif Sinhala", + "preferred_subfamily_name": "ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifSinhala-Light.ttf||335496:1655828711.0": { + "family_name": "Noto Serif Sinhala Light", + "font-family": "Noto Serif Sinhala Light", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Serif Sinhala Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 4, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifSinhala-Light.ttf", + "preferred_family_name": "Noto Serif Sinhala", + "preferred_subfamily_name": "Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifSinhala-Medium.ttf||322468:1655828711.0": { + "family_name": "Noto Serif Sinhala Medium", + "font-family": "Noto Serif Sinhala Medium", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Serif Sinhala Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 6, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifSinhala-Medium.ttf", + "preferred_family_name": "Noto Serif Sinhala", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifSinhala-Regular.ttf||322840:1655828711.0": { + "family_name": "Noto Serif Sinhala", + "font-family": "Noto Serif Sinhala", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif Sinhala Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 5, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifSinhala-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifSinhala-SemiBold.ttf||331864:1655828711.0": { + "family_name": "Noto Serif Sinhala SemiBold", + "font-family": "Noto Serif Sinhala SemiBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Serif Sinhala SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 7, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifSinhala-SemiBold.ttf", + "preferred_family_name": "Noto Serif Sinhala", + "preferred_subfamily_name": "SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifSinhala-SemiCondensed.ttf||328616:1655828711.0": { + "family_name": "Noto Serif Sinhala SemiCondensed", + "font-family": "Noto Serif Sinhala SemiCondensed", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif Sinhala SemiCondensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 5, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifSinhala-SemiCondensed.ttf", + "preferred_family_name": "Noto Serif Sinhala", + "preferred_subfamily_name": "SemiCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifSinhala-SemiCondensedBlack.ttf||339060:1655828711.0": { + "family_name": "Noto Serif Sinhala SemiCondensed Black", + "font-family": "Noto Serif Sinhala SemiCondensed Black", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Serif Sinhala SemiCondensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 10, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifSinhala-SemiCondensedBlack.ttf", + "preferred_family_name": "Noto Serif Sinhala", + "preferred_subfamily_name": "SemiCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifSinhala-SemiCondensedBold.ttf||341296:1655828711.0": { + "family_name": "Noto Serif Sinhala SemiCondensed", + "font-family": "Noto Serif Sinhala SemiCondensed", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Serif Sinhala SemiCondensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 8, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifSinhala-SemiCondensedBold.ttf", + "preferred_family_name": "Noto Serif Sinhala", + "preferred_subfamily_name": "SemiCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifSinhala-SemiCondensedExtraBold.ttf||345252:1655828711.0": { + "family_name": "Noto Serif Sinhala SemiCondensed ExtraBold", + "font-family": "Noto Serif Sinhala SemiCondensed ExtraBold", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Serif Sinhala SemiCondensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 9, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifSinhala-SemiCondensedExtraBold.ttf", + "preferred_family_name": "Noto Serif Sinhala", + "preferred_subfamily_name": "SemiCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifSinhala-SemiCondensedExtraLight.ttf||319816:1655828711.0": { + "family_name": "Noto Serif Sinhala SemiCondensed ExtraLight", + "font-family": "Noto Serif Sinhala SemiCondensed ExtraLight", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Serif Sinhala SemiCondensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 3, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifSinhala-SemiCondensedExtraLight.ttf", + "preferred_family_name": "Noto Serif Sinhala", + "preferred_subfamily_name": "SemiCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifSinhala-SemiCondensedLight.ttf||337448:1655828711.0": { + "family_name": "Noto Serif Sinhala SemiCondensed Light", + "font-family": "Noto Serif Sinhala SemiCondensed Light", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Serif Sinhala SemiCondensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 4, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifSinhala-SemiCondensedLight.ttf", + "preferred_family_name": "Noto Serif Sinhala", + "preferred_subfamily_name": "SemiCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifSinhala-SemiCondensedMedium.ttf||313912:1655828711.0": { + "family_name": "Noto Serif Sinhala SemiCondensed Medium", + "font-family": "Noto Serif Sinhala SemiCondensed Medium", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Serif Sinhala SemiCondensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 6, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifSinhala-SemiCondensedMedium.ttf", + "preferred_family_name": "Noto Serif Sinhala", + "preferred_subfamily_name": "SemiCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifSinhala-SemiCondensedSemiBold.ttf||324464:1655828711.0": { + "family_name": "Noto Serif Sinhala SemiCondensed SemiBold", + "font-family": "Noto Serif Sinhala SemiCondensed SemiBold", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Serif Sinhala SemiCondensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 7, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifSinhala-SemiCondensedSemiBold.ttf", + "preferred_family_name": "Noto Serif Sinhala", + "preferred_subfamily_name": "SemiCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifSinhala-SemiCondensedThin.ttf||333524:1655828711.0": { + "family_name": "Noto Serif Sinhala SemiCondensed Thin", + "font-family": "Noto Serif Sinhala SemiCondensed Thin", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Serif Sinhala SemiCondensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 2, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifSinhala-SemiCondensedThin.ttf", + "preferred_family_name": "Noto Serif Sinhala", + "preferred_subfamily_name": "SemiCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifSinhala-Thin.ttf||319844:1655828711.0": { + "family_name": "Noto Serif Sinhala Thin", + "font-family": "Noto Serif Sinhala Thin", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Serif Sinhala Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 2, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifSinhala-Thin.ttf", + "preferred_family_name": "Noto Serif Sinhala", + "preferred_subfamily_name": "Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifTamil-Black.ttf||83128:1655828711.0": { + "family_name": "Noto Serif Tamil Black", + "font-family": "Noto Serif Tamil Black", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Serif Tamil Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 10, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifTamil-Black.ttf", + "preferred_family_name": "Noto Serif Tamil", + "preferred_subfamily_name": "Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifTamil-Bold.ttf||78460:1655828711.0": { + "family_name": "Noto Serif Tamil", + "font-family": "Noto Serif Tamil", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Serif Tamil Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 8, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifTamil-Bold.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifTamil-Condensed.ttf||77568:1655828711.0": { + "family_name": "Noto Serif Tamil Condensed", + "font-family": "Noto Serif Tamil Condensed", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif Tamil Condensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 5, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifTamil-Condensed.ttf", + "preferred_family_name": "Noto Serif Tamil", + "preferred_subfamily_name": "Condensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifTamil-CondensedBlack.ttf||79888:1655828711.0": { + "family_name": "Noto Serif Tamil Condensed Black", + "font-family": "Noto Serif Tamil Condensed Black", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Serif Tamil Condensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 10, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifTamil-CondensedBlack.ttf", + "preferred_family_name": "Noto Serif Tamil", + "preferred_subfamily_name": "Condensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifTamil-CondensedBold.ttf||78964:1655828711.0": { + "family_name": "Noto Serif Tamil Condensed", + "font-family": "Noto Serif Tamil Condensed", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Serif Tamil Condensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 8, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifTamil-CondensedBold.ttf", + "preferred_family_name": "Noto Serif Tamil", + "preferred_subfamily_name": "Condensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifTamil-CondensedExtraBold.ttf||81072:1655828711.0": { + "family_name": "Noto Serif Tamil Condensed ExtraBold", + "font-family": "Noto Serif Tamil Condensed ExtraBold", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Serif Tamil Condensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 9, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifTamil-CondensedExtraBold.ttf", + "preferred_family_name": "Noto Serif Tamil", + "preferred_subfamily_name": "Condensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifTamil-CondensedExtraLight.ttf||79868:1655828711.0": { + "family_name": "Noto Serif Tamil Condensed ExtraLight", + "font-family": "Noto Serif Tamil Condensed ExtraLight", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Serif Tamil Condensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 3, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifTamil-CondensedExtraLight.ttf", + "preferred_family_name": "Noto Serif Tamil", + "preferred_subfamily_name": "Condensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifTamil-CondensedLight.ttf||77708:1655828711.0": { + "family_name": "Noto Serif Tamil Condensed Light", + "font-family": "Noto Serif Tamil Condensed Light", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Serif Tamil Condensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 4, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifTamil-CondensedLight.ttf", + "preferred_family_name": "Noto Serif Tamil", + "preferred_subfamily_name": "Condensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifTamil-CondensedMedium.ttf||79572:1655828711.0": { + "family_name": "Noto Serif Tamil Condensed Medium", + "font-family": "Noto Serif Tamil Condensed Medium", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Serif Tamil Condensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 6, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifTamil-CondensedMedium.ttf", + "preferred_family_name": "Noto Serif Tamil", + "preferred_subfamily_name": "Condensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifTamil-CondensedSemiBold.ttf||79588:1655828711.0": { + "family_name": "Noto Serif Tamil Condensed SemiBold", + "font-family": "Noto Serif Tamil Condensed SemiBold", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Serif Tamil Condensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 7, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifTamil-CondensedSemiBold.ttf", + "preferred_family_name": "Noto Serif Tamil", + "preferred_subfamily_name": "Condensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifTamil-CondensedThin.ttf||79364:1655828711.0": { + "family_name": "Noto Serif Tamil Condensed Thin", + "font-family": "Noto Serif Tamil Condensed Thin", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Serif Tamil Condensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 2, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifTamil-CondensedThin.ttf", + "preferred_family_name": "Noto Serif Tamil", + "preferred_subfamily_name": "Condensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifTamil-ExtraBold.ttf||81560:1655828711.0": { + "family_name": "Noto Serif Tamil ExtraBold", + "font-family": "Noto Serif Tamil ExtraBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Serif Tamil ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 9, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifTamil-ExtraBold.ttf", + "preferred_family_name": "Noto Serif Tamil", + "preferred_subfamily_name": "ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifTamil-ExtraCondensed.ttf||76020:1655828711.0": { + "family_name": "Noto Serif Tamil ExtraCondensed", + "font-family": "Noto Serif Tamil ExtraCondensed", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif Tamil ExtraCondensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 5, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifTamil-ExtraCondensed.ttf", + "preferred_family_name": "Noto Serif Tamil", + "preferred_subfamily_name": "ExtraCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifTamil-ExtraCondensedBlack.ttf||78776:1655828711.0": { + "family_name": "Noto Serif Tamil ExtraCondensed Black", + "font-family": "Noto Serif Tamil ExtraCondensed Black", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Serif Tamil ExtraCondensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 10, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifTamil-ExtraCondensedBlack.ttf", + "preferred_family_name": "Noto Serif Tamil", + "preferred_subfamily_name": "ExtraCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifTamil-ExtraCondensedBold.ttf||78112:1655828711.0": { + "family_name": "Noto Serif Tamil ExtraCondensed", + "font-family": "Noto Serif Tamil ExtraCondensed", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Serif Tamil ExtraCondensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 8, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifTamil-ExtraCondensedBold.ttf", + "preferred_family_name": "Noto Serif Tamil", + "preferred_subfamily_name": "ExtraCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifTamil-ExtraCondensedExtraBold.ttf||78116:1655828711.0": { + "family_name": "Noto Serif Tamil ExtraCondensed ExtraBold", + "font-family": "Noto Serif Tamil ExtraCondensed ExtraBold", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Serif Tamil ExtraCondensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 9, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifTamil-ExtraCondensedExtraBold.ttf", + "preferred_family_name": "Noto Serif Tamil", + "preferred_subfamily_name": "ExtraCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifTamil-ExtraCondensedExtraLight.ttf||78628:1655828711.0": { + "family_name": "Noto Serif Tamil ExtraCondensed ExtraLight", + "font-family": "Noto Serif Tamil ExtraCondensed ExtraLight", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Serif Tamil ExtraCondensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 3, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifTamil-ExtraCondensedExtraLight.ttf", + "preferred_family_name": "Noto Serif Tamil", + "preferred_subfamily_name": "ExtraCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifTamil-ExtraCondensedLight.ttf||77052:1655828711.0": { + "family_name": "Noto Serif Tamil ExtraCondensed Light", + "font-family": "Noto Serif Tamil ExtraCondensed Light", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Serif Tamil ExtraCondensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 4, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifTamil-ExtraCondensedLight.ttf", + "preferred_family_name": "Noto Serif Tamil", + "preferred_subfamily_name": "ExtraCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifTamil-ExtraCondensedMedium.ttf||80152:1655828711.0": { + "family_name": "Noto Serif Tamil ExtraCondensed Medium", + "font-family": "Noto Serif Tamil ExtraCondensed Medium", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Serif Tamil ExtraCondensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 6, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifTamil-ExtraCondensedMedium.ttf", + "preferred_family_name": "Noto Serif Tamil", + "preferred_subfamily_name": "ExtraCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifTamil-ExtraCondensedSemiBold.ttf||77976:1655828711.0": { + "family_name": "Noto Serif Tamil ExtraCondensed SemiBold", + "font-family": "Noto Serif Tamil ExtraCondensed SemiBold", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Serif Tamil ExtraCondensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 7, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifTamil-ExtraCondensedSemiBold.ttf", + "preferred_family_name": "Noto Serif Tamil", + "preferred_subfamily_name": "ExtraCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifTamil-ExtraCondensedThin.ttf||78432:1655828711.0": { + "family_name": "Noto Serif Tamil ExtraCondensed Thin", + "font-family": "Noto Serif Tamil ExtraCondensed Thin", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Serif Tamil ExtraCondensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 2, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifTamil-ExtraCondensedThin.ttf", + "preferred_family_name": "Noto Serif Tamil", + "preferred_subfamily_name": "ExtraCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifTamil-ExtraLight.ttf||80380:1655828711.0": { + "family_name": "Noto Serif Tamil ExtraLight", + "font-family": "Noto Serif Tamil ExtraLight", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Serif Tamil ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 3, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifTamil-ExtraLight.ttf", + "preferred_family_name": "Noto Serif Tamil", + "preferred_subfamily_name": "ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifTamil-Light.ttf||78632:1655828711.0": { + "family_name": "Noto Serif Tamil Light", + "font-family": "Noto Serif Tamil Light", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Serif Tamil Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 4, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifTamil-Light.ttf", + "preferred_family_name": "Noto Serif Tamil", + "preferred_subfamily_name": "Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifTamil-Medium.ttf||80588:1655828711.0": { + "family_name": "Noto Serif Tamil Medium", + "font-family": "Noto Serif Tamil Medium", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Serif Tamil Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 6, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifTamil-Medium.ttf", + "preferred_family_name": "Noto Serif Tamil", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifTamil-Regular.ttf||79636:1655828711.0": { + "family_name": "Noto Serif Tamil", + "font-family": "Noto Serif Tamil", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif Tamil Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 5, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifTamil-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifTamil-SemiBold.ttf||78148:1655828711.0": { + "family_name": "Noto Serif Tamil SemiBold", + "font-family": "Noto Serif Tamil SemiBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Serif Tamil SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 7, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifTamil-SemiBold.ttf", + "preferred_family_name": "Noto Serif Tamil", + "preferred_subfamily_name": "SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifTamil-SemiCondensed.ttf||80080:1655828711.0": { + "family_name": "Noto Serif Tamil SemiCondensed", + "font-family": "Noto Serif Tamil SemiCondensed", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif Tamil SemiCondensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 5, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifTamil-SemiCondensed.ttf", + "preferred_family_name": "Noto Serif Tamil", + "preferred_subfamily_name": "SemiCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifTamil-SemiCondensedBlack.ttf||82960:1655828711.0": { + "family_name": "Noto Serif Tamil SemiCondensed Black", + "font-family": "Noto Serif Tamil SemiCondensed Black", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Serif Tamil SemiCondensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 10, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifTamil-SemiCondensedBlack.ttf", + "preferred_family_name": "Noto Serif Tamil", + "preferred_subfamily_name": "SemiCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifTamil-SemiCondensedBold.ttf||79776:1655828711.0": { + "family_name": "Noto Serif Tamil SemiCondensed", + "font-family": "Noto Serif Tamil SemiCondensed", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Serif Tamil SemiCondensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 8, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifTamil-SemiCondensedBold.ttf", + "preferred_family_name": "Noto Serif Tamil", + "preferred_subfamily_name": "SemiCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifTamil-SemiCondensedExtraBold.ttf||80636:1655828711.0": { + "family_name": "Noto Serif Tamil SemiCondensed ExtraBold", + "font-family": "Noto Serif Tamil SemiCondensed ExtraBold", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Serif Tamil SemiCondensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 9, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifTamil-SemiCondensedExtraBold.ttf", + "preferred_family_name": "Noto Serif Tamil", + "preferred_subfamily_name": "SemiCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifTamil-SemiCondensedExtraLight.ttf||80564:1655828711.0": { + "family_name": "Noto Serif Tamil SemiCondensed ExtraLight", + "font-family": "Noto Serif Tamil SemiCondensed ExtraLight", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Serif Tamil SemiCondensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 3, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifTamil-SemiCondensedExtraLight.ttf", + "preferred_family_name": "Noto Serif Tamil", + "preferred_subfamily_name": "SemiCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifTamil-SemiCondensedLight.ttf||78908:1655828711.0": { + "family_name": "Noto Serif Tamil SemiCondensed Light", + "font-family": "Noto Serif Tamil SemiCondensed Light", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Serif Tamil SemiCondensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 4, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifTamil-SemiCondensedLight.ttf", + "preferred_family_name": "Noto Serif Tamil", + "preferred_subfamily_name": "SemiCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifTamil-SemiCondensedMedium.ttf||80744:1655828711.0": { + "family_name": "Noto Serif Tamil SemiCondensed Medium", + "font-family": "Noto Serif Tamil SemiCondensed Medium", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Serif Tamil SemiCondensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 6, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifTamil-SemiCondensedMedium.ttf", + "preferred_family_name": "Noto Serif Tamil", + "preferred_subfamily_name": "SemiCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifTamil-SemiCondensedSemiBold.ttf||79508:1655828711.0": { + "family_name": "Noto Serif Tamil SemiCondensed SemiBold", + "font-family": "Noto Serif Tamil SemiCondensed SemiBold", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Serif Tamil SemiCondensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 7, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifTamil-SemiCondensedSemiBold.ttf", + "preferred_family_name": "Noto Serif Tamil", + "preferred_subfamily_name": "SemiCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifTamil-SemiCondensedThin.ttf||80580:1655828711.0": { + "family_name": "Noto Serif Tamil SemiCondensed Thin", + "font-family": "Noto Serif Tamil SemiCondensed Thin", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Serif Tamil SemiCondensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 2, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifTamil-SemiCondensedThin.ttf", + "preferred_family_name": "Noto Serif Tamil", + "preferred_subfamily_name": "SemiCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifTamil-Thin.ttf||80876:1655828711.0": { + "family_name": "Noto Serif Tamil Thin", + "font-family": "Noto Serif Tamil Thin", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Serif Tamil Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 2, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifTamil-Thin.ttf", + "preferred_family_name": "Noto Serif Tamil", + "preferred_subfamily_name": "Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifTamilSlanted-Black.ttf||83828:1655828711.0": { + "family_name": "NotoSerifTamilSlanted Black", + "font-family": "NotoSerifTamilSlanted Black", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Serif Tamil Slanted Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 10, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifTamilSlanted-Black.ttf", + "preferred_family_name": "Noto Serif Tamil Slanted", + "preferred_subfamily_name": "Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifTamilSlanted-Bold.ttf||80280:1655828711.0": { + "family_name": "NotoSerifTamilSlanted", + "font-family": "NotoSerifTamilSlanted", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Serif Tamil Slanted Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 8, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifTamilSlanted-Bold.ttf", + "preferred_family_name": "Noto Serif Tamil Slanted", + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifTamilSlanted-Condensed.ttf||78944:1655828711.0": { + "family_name": "NotoSerifTamilSlanted Condensed", + "font-family": "NotoSerifTamilSlanted Condensed", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif Tamil Slanted Condensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 5, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifTamilSlanted-Condensed.ttf", + "preferred_family_name": "Noto Serif Tamil Slanted", + "preferred_subfamily_name": "Condensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifTamilSlanted-CondensedBlack.ttf||80832:1655828711.0": { + "family_name": "NotoSerifTamilSlanted Condensed Black", + "font-family": "NotoSerifTamilSlanted Condensed Black", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Serif Tamil Slanted Condensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 10, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifTamilSlanted-CondensedBlack.ttf", + "preferred_family_name": "Noto Serif Tamil Slanted", + "preferred_subfamily_name": "Condensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifTamilSlanted-CondensedBold.ttf||80028:1655828711.0": { + "family_name": "NotoSerifTamilSlanted Condensed", + "font-family": "NotoSerifTamilSlanted Condensed", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Serif Tamil Slanted Condensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 8, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifTamilSlanted-CondensedBold.ttf", + "preferred_family_name": "Noto Serif Tamil Slanted", + "preferred_subfamily_name": "Condensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifTamilSlanted-CondensedExtraBold.ttf||82644:1655828711.0": { + "family_name": "NotoSerifTamilSlanted Condensed ExtraBold", + "font-family": "NotoSerifTamilSlanted Condensed ExtraBold", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Serif Tamil Slanted Condensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 9, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifTamilSlanted-CondensedExtraBold.ttf", + "preferred_family_name": "Noto Serif Tamil Slanted", + "preferred_subfamily_name": "Condensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifTamilSlanted-CondensedExtraLight.ttf||80928:1655828711.0": { + "family_name": "NotoSerifTamilSlanted Condensed ExtraLight", + "font-family": "NotoSerifTamilSlanted Condensed ExtraLight", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Serif Tamil Slanted Condensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 3, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifTamilSlanted-CondensedExtraLight.ttf", + "preferred_family_name": "Noto Serif Tamil Slanted", + "preferred_subfamily_name": "Condensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifTamilSlanted-CondensedLight.ttf||78872:1655828711.0": { + "family_name": "NotoSerifTamilSlanted Condensed Light", + "font-family": "NotoSerifTamilSlanted Condensed Light", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Serif Tamil Slanted Condensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 4, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifTamilSlanted-CondensedLight.ttf", + "preferred_family_name": "Noto Serif Tamil Slanted", + "preferred_subfamily_name": "Condensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifTamilSlanted-CondensedMedium.ttf||80944:1655828711.0": { + "family_name": "NotoSerifTamilSlanted Condensed Medium", + "font-family": "NotoSerifTamilSlanted Condensed Medium", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Serif Tamil Slanted Condensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 6, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifTamilSlanted-CondensedMedium.ttf", + "preferred_family_name": "Noto Serif Tamil Slanted", + "preferred_subfamily_name": "Condensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifTamilSlanted-CondensedSemiBold.ttf||80292:1655828711.0": { + "family_name": "NotoSerifTamilSlanted Condensed SemiBold", + "font-family": "NotoSerifTamilSlanted Condensed SemiBold", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Serif Tamil Slanted Condensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 7, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifTamilSlanted-CondensedSemiBold.ttf", + "preferred_family_name": "Noto Serif Tamil Slanted", + "preferred_subfamily_name": "Condensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifTamilSlanted-CondensedThin.ttf||80556:1655828711.0": { + "family_name": "NotoSerifTamilSlanted Condensed Thin", + "font-family": "NotoSerifTamilSlanted Condensed Thin", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Serif Tamil Slanted Condensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 2, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifTamilSlanted-CondensedThin.ttf", + "preferred_family_name": "Noto Serif Tamil Slanted", + "preferred_subfamily_name": "Condensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifTamilSlanted-ExtraBold.ttf||81424:1655828711.0": { + "family_name": "NotoSerifTamilSlanted ExtraBold", + "font-family": "NotoSerifTamilSlanted ExtraBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Serif Tamil Slanted ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 9, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifTamilSlanted-ExtraBold.ttf", + "preferred_family_name": "Noto Serif Tamil Slanted", + "preferred_subfamily_name": "ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifTamilSlanted-ExtraCondensed.ttf||77844:1655828711.0": { + "family_name": "NotoSerifTamilSlanted ExtraCondensed", + "font-family": "NotoSerifTamilSlanted ExtraCondensed", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif Tamil Slanted ExtraCondensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 5, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifTamilSlanted-ExtraCondensed.ttf", + "preferred_family_name": "Noto Serif Tamil Slanted", + "preferred_subfamily_name": "ExtraCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifTamilSlanted-ExtraCondensedBlack.ttf||80892:1655828711.0": { + "family_name": "NotoSerifTamilSlanted ExtraCondensed Black", + "font-family": "NotoSerifTamilSlanted ExtraCondensed Black", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Serif Tamil Slanted ExtraCondensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 10, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifTamilSlanted-ExtraCondensedBlack.ttf", + "preferred_family_name": "Noto Serif Tamil Slanted", + "preferred_subfamily_name": "ExtraCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifTamilSlanted-ExtraCondensedBold.ttf||80528:1655828711.0": { + "family_name": "NotoSerifTamilSlanted ExtraCondensed", + "font-family": "NotoSerifTamilSlanted ExtraCondensed", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Serif Tamil Slanted ExtraCondensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 8, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifTamilSlanted-ExtraCondensedBold.ttf", + "preferred_family_name": "Noto Serif Tamil Slanted", + "preferred_subfamily_name": "ExtraCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifTamilSlanted-ExtraCondensedExtraBold.ttf||79712:1655828711.0": { + "family_name": "NotoSerifTamilSlanted ExtraCondensed ExtraBold", + "font-family": "NotoSerifTamilSlanted ExtraCondensed ExtraBold", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Serif Tamil Slanted ExtraCondensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 9, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifTamilSlanted-ExtraCondensedExtraBold.ttf", + "preferred_family_name": "Noto Serif Tamil Slanted", + "preferred_subfamily_name": "ExtraCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifTamilSlanted-ExtraCondensedExtraLight.ttf||79904:1655828711.0": { + "family_name": "NotoSerifTamilSlanted ExtraCondensed ExtraLight", + "font-family": "NotoSerifTamilSlanted ExtraCondensed ExtraLight", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Serif Tamil Slanted ExtraCondensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 3, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifTamilSlanted-ExtraCondensedExtraLight.ttf", + "preferred_family_name": "Noto Serif Tamil Slanted", + "preferred_subfamily_name": "ExtraCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifTamilSlanted-ExtraCondensedLight.ttf||78780:1655828711.0": { + "family_name": "NotoSerifTamilSlanted ExtraCondensed Light", + "font-family": "NotoSerifTamilSlanted ExtraCondensed Light", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Serif Tamil Slanted ExtraCondensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 4, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifTamilSlanted-ExtraCondensedLight.ttf", + "preferred_family_name": "Noto Serif Tamil Slanted", + "preferred_subfamily_name": "ExtraCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifTamilSlanted-ExtraCondensedMedium.ttf||81096:1655828711.0": { + "family_name": "NotoSerifTamilSlanted ExtraCondensed Medium", + "font-family": "NotoSerifTamilSlanted ExtraCondensed Medium", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Serif Tamil Slanted ExtraCondensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 6, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifTamilSlanted-ExtraCondensedMedium.ttf", + "preferred_family_name": "Noto Serif Tamil Slanted", + "preferred_subfamily_name": "ExtraCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifTamilSlanted-ExtraCondensedSemiBold.ttf||79804:1655828711.0": { + "family_name": "NotoSerifTamilSlanted ExtraCondensed SemiBold", + "font-family": "NotoSerifTamilSlanted ExtraCondensed SemiBold", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Serif Tamil Slanted ExtraCondensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 7, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifTamilSlanted-ExtraCondensedSemiBold.ttf", + "preferred_family_name": "Noto Serif Tamil Slanted", + "preferred_subfamily_name": "ExtraCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifTamilSlanted-ExtraCondensedThin.ttf||80296:1655828711.0": { + "family_name": "NotoSerifTamilSlanted ExtraCondensed Thin", + "font-family": "NotoSerifTamilSlanted ExtraCondensed Thin", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Serif Tamil Slanted ExtraCondensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 2, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifTamilSlanted-ExtraCondensedThin.ttf", + "preferred_family_name": "Noto Serif Tamil Slanted", + "preferred_subfamily_name": "ExtraCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifTamilSlanted-ExtraLight.ttf||81984:1655828711.0": { + "family_name": "NotoSerifTamilSlanted ExtraLight", + "font-family": "NotoSerifTamilSlanted ExtraLight", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Serif Tamil Slanted ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 3, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifTamilSlanted-ExtraLight.ttf", + "preferred_family_name": "Noto Serif Tamil Slanted", + "preferred_subfamily_name": "ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifTamilSlanted-Light.ttf||79480:1655828711.0": { + "family_name": "NotoSerifTamilSlanted Light", + "font-family": "NotoSerifTamilSlanted Light", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Serif Tamil Slanted Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 4, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifTamilSlanted-Light.ttf", + "preferred_family_name": "Noto Serif Tamil Slanted", + "preferred_subfamily_name": "Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifTamilSlanted-Medium.ttf||82272:1655828711.0": { + "family_name": "NotoSerifTamilSlanted Medium", + "font-family": "NotoSerifTamilSlanted Medium", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Serif Tamil Slanted Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 6, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifTamilSlanted-Medium.ttf", + "preferred_family_name": "Noto Serif Tamil Slanted", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifTamilSlanted-Regular.ttf||79468:1655828711.0": { + "family_name": "NotoSerifTamilSlanted", + "font-family": "NotoSerifTamilSlanted", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif Tamil Slanted Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 5, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifTamilSlanted-Regular.ttf", + "preferred_family_name": "Noto Serif Tamil Slanted", + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifTamilSlanted-SemiBold.ttf||79256:1655828711.0": { + "family_name": "NotoSerifTamilSlanted SemiBold", + "font-family": "NotoSerifTamilSlanted SemiBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Serif Tamil Slanted SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 7, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifTamilSlanted-SemiBold.ttf", + "preferred_family_name": "Noto Serif Tamil Slanted", + "preferred_subfamily_name": "SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifTamilSlanted-SemiCondensed.ttf||79160:1655828711.0": { + "family_name": "NotoSerifTamilSlanted SemiCondensed", + "font-family": "NotoSerifTamilSlanted SemiCondensed", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif Tamil Slanted SemiCondensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 5, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifTamilSlanted-SemiCondensed.ttf", + "preferred_family_name": "Noto Serif Tamil Slanted", + "preferred_subfamily_name": "SemiCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifTamilSlanted-SemiCondensedBlack.ttf||81900:1655828711.0": { + "family_name": "NotoSerifTamilSlanted SemiCondensed Black", + "font-family": "NotoSerifTamilSlanted SemiCondensed Black", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Serif Tamil Slanted SemiCondensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 10, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifTamilSlanted-SemiCondensedBlack.ttf", + "preferred_family_name": "Noto Serif Tamil Slanted", + "preferred_subfamily_name": "SemiCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifTamilSlanted-SemiCondensedBold.ttf||81408:1655828711.0": { + "family_name": "NotoSerifTamilSlanted SemiCondensed", + "font-family": "NotoSerifTamilSlanted SemiCondensed", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Serif Tamil Slanted SemiCondensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 8, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifTamilSlanted-SemiCondensedBold.ttf", + "preferred_family_name": "Noto Serif Tamil Slanted", + "preferred_subfamily_name": "SemiCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifTamilSlanted-SemiCondensedExtraBold.ttf||81848:1655828711.0": { + "family_name": "NotoSerifTamilSlanted SemiCondensed ExtraBold", + "font-family": "NotoSerifTamilSlanted SemiCondensed ExtraBold", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Serif Tamil Slanted SemiCondensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 9, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifTamilSlanted-SemiCondensedExtraBold.ttf", + "preferred_family_name": "Noto Serif Tamil Slanted", + "preferred_subfamily_name": "SemiCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifTamilSlanted-SemiCondensedExtraLight.ttf||81788:1655828711.0": { + "family_name": "NotoSerifTamilSlanted SemiCondensed ExtraLight", + "font-family": "NotoSerifTamilSlanted SemiCondensed ExtraLight", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Serif Tamil Slanted SemiCondensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 3, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifTamilSlanted-SemiCondensedExtraLight.ttf", + "preferred_family_name": "Noto Serif Tamil Slanted", + "preferred_subfamily_name": "SemiCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifTamilSlanted-SemiCondensedLight.ttf||79916:1655828711.0": { + "family_name": "NotoSerifTamilSlanted SemiCondensed Light", + "font-family": "NotoSerifTamilSlanted SemiCondensed Light", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Serif Tamil Slanted SemiCondensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 4, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifTamilSlanted-SemiCondensedLight.ttf", + "preferred_family_name": "Noto Serif Tamil Slanted", + "preferred_subfamily_name": "SemiCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifTamilSlanted-SemiCondensedMedium.ttf||81848:1655828711.0": { + "family_name": "NotoSerifTamilSlanted SemiCondensed Medium", + "font-family": "NotoSerifTamilSlanted SemiCondensed Medium", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Serif Tamil Slanted SemiCondensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 6, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifTamilSlanted-SemiCondensedMedium.ttf", + "preferred_family_name": "Noto Serif Tamil Slanted", + "preferred_subfamily_name": "SemiCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifTamilSlanted-SemiCondensedSemiBold.ttf||81488:1655828711.0": { + "family_name": "NotoSerifTamilSlanted SemiCondensed SemiBold", + "font-family": "NotoSerifTamilSlanted SemiCondensed SemiBold", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Serif Tamil Slanted SemiCondensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 7, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifTamilSlanted-SemiCondensedSemiBold.ttf", + "preferred_family_name": "Noto Serif Tamil Slanted", + "preferred_subfamily_name": "SemiCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifTamilSlanted-SemiCondensedThin.ttf||81620:1655828711.0": { + "family_name": "NotoSerifTamilSlanted SemiCondensed Thin", + "font-family": "NotoSerifTamilSlanted SemiCondensed Thin", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Serif Tamil Slanted SemiCondensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 2, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifTamilSlanted-SemiCondensedThin.ttf", + "preferred_family_name": "Noto Serif Tamil Slanted", + "preferred_subfamily_name": "SemiCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifTamilSlanted-Thin.ttf||81832:1655828711.0": { + "family_name": "NotoSerifTamilSlanted Thin", + "font-family": "NotoSerifTamilSlanted Thin", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Serif Tamil Slanted Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 2, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifTamilSlanted-Thin.ttf", + "preferred_family_name": "Noto Serif Tamil Slanted", + "preferred_subfamily_name": "Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifTangut-Regular.ttf||5692876:1655828711.0": { + "family_name": "Noto Serif Tangut", + "font-family": "Noto Serif Tangut", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif Tangut Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 5, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/noto/NotoSerifTangut-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifTelugu-Black.ttf||372576:1655828711.0": { + "family_name": "Noto Serif Telugu Black", + "font-family": "Noto Serif Telugu Black", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Serif Telugu Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 10, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifTelugu-Black.ttf", + "preferred_family_name": "Noto Serif Telugu", + "preferred_subfamily_name": "Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifTelugu-Bold.ttf||332592:1655828711.0": { + "family_name": "Noto Serif Telugu", + "font-family": "Noto Serif Telugu", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Serif Telugu Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 8, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifTelugu-Bold.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifTelugu-ExtraBold.ttf||381036:1655828711.0": { + "family_name": "Noto Serif Telugu ExtraBold", + "font-family": "Noto Serif Telugu ExtraBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Serif Telugu ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 9, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifTelugu-ExtraBold.ttf", + "preferred_family_name": "Noto Serif Telugu", + "preferred_subfamily_name": "ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifTelugu-ExtraLight.ttf||321100:1655828711.0": { + "family_name": "Noto Serif Telugu ExtraLight", + "font-family": "Noto Serif Telugu ExtraLight", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Serif Telugu ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 3, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifTelugu-ExtraLight.ttf", + "preferred_family_name": "Noto Serif Telugu", + "preferred_subfamily_name": "ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifTelugu-Light.ttf||289448:1655828711.0": { + "family_name": "Noto Serif Telugu Light", + "font-family": "Noto Serif Telugu Light", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Serif Telugu Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 4, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifTelugu-Light.ttf", + "preferred_family_name": "Noto Serif Telugu", + "preferred_subfamily_name": "Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifTelugu-Medium.ttf||305024:1655828711.0": { + "family_name": "Noto Serif Telugu Medium", + "font-family": "Noto Serif Telugu Medium", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Serif Telugu Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 6, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifTelugu-Medium.ttf", + "preferred_family_name": "Noto Serif Telugu", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifTelugu-Regular.ttf||312332:1655828711.0": { + "family_name": "Noto Serif Telugu", + "font-family": "Noto Serif Telugu", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif Telugu Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 5, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifTelugu-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifTelugu-SemiBold.ttf||311096:1655828711.0": { + "family_name": "Noto Serif Telugu SemiBold", + "font-family": "Noto Serif Telugu SemiBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Serif Telugu SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 7, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifTelugu-SemiBold.ttf", + "preferred_family_name": "Noto Serif Telugu", + "preferred_subfamily_name": "SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifTelugu-Thin.ttf||290540:1655828711.0": { + "family_name": "Noto Serif Telugu Thin", + "font-family": "Noto Serif Telugu Thin", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Serif Telugu Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 2, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifTelugu-Thin.ttf", + "preferred_family_name": "Noto Serif Telugu", + "preferred_subfamily_name": "Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifThai-Black.ttf||48876:1655828711.0": { + "family_name": "Noto Serif Thai Blk", + "font-family": "Noto Serif Thai Blk", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Serif Thai Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 10, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifThai-Black.ttf", + "preferred_family_name": "Noto Serif Thai", + "preferred_subfamily_name": "Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifThai-Bold.ttf||47000:1655828711.0": { + "family_name": "Noto Serif Thai", + "font-family": "Noto Serif Thai", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Serif Thai Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 8, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifThai-Bold.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifThai-Condensed.ttf||45724:1655828711.0": { + "family_name": "Noto Serif Thai Cond", + "font-family": "Noto Serif Thai Cond", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif Thai Condensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 5, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifThai-Condensed.ttf", + "preferred_family_name": "Noto Serif Thai", + "preferred_subfamily_name": "Condensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifThai-CondensedBlack.ttf||48800:1655828711.0": { + "family_name": "Noto Serif Thai Cond Blk", + "font-family": "Noto Serif Thai Cond Blk", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Serif Thai Condensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 10, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifThai-CondensedBlack.ttf", + "preferred_family_name": "Noto Serif Thai", + "preferred_subfamily_name": "Condensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifThai-CondensedBold.ttf||45980:1655828711.0": { + "family_name": "Noto Serif Thai Cond", + "font-family": "Noto Serif Thai Cond", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Serif Thai Condensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 8, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifThai-CondensedBold.ttf", + "preferred_family_name": "Noto Serif Thai", + "preferred_subfamily_name": "Condensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifThai-CondensedExtraBold.ttf||48176:1655828711.0": { + "family_name": "Noto Serif Thai Cond ExtBd", + "font-family": "Noto Serif Thai Cond ExtBd", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Serif Thai Condensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 9, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifThai-CondensedExtraBold.ttf", + "preferred_family_name": "Noto Serif Thai", + "preferred_subfamily_name": "Condensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifThai-CondensedExtraLight.ttf||46572:1655828711.0": { + "family_name": "Noto Serif Thai Cond ExtLt", + "font-family": "Noto Serif Thai Cond ExtLt", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Serif Thai Condensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 3, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifThai-CondensedExtraLight.ttf", + "preferred_family_name": "Noto Serif Thai", + "preferred_subfamily_name": "Condensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifThai-CondensedLight.ttf||46708:1655828711.0": { + "family_name": "Noto Serif Thai Cond Light", + "font-family": "Noto Serif Thai Cond Light", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Serif Thai Condensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 4, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifThai-CondensedLight.ttf", + "preferred_family_name": "Noto Serif Thai", + "preferred_subfamily_name": "Condensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifThai-CondensedMedium.ttf||45908:1655828711.0": { + "family_name": "Noto Serif Thai Cond Med", + "font-family": "Noto Serif Thai Cond Med", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Serif Thai Condensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 6, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifThai-CondensedMedium.ttf", + "preferred_family_name": "Noto Serif Thai", + "preferred_subfamily_name": "Condensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifThai-CondensedSemiBold.ttf||46412:1655828711.0": { + "family_name": "Noto Serif Thai Cond SemBd", + "font-family": "Noto Serif Thai Cond SemBd", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Serif Thai Condensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 7, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifThai-CondensedSemiBold.ttf", + "preferred_family_name": "Noto Serif Thai", + "preferred_subfamily_name": "Condensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifThai-CondensedThin.ttf||47036:1655828711.0": { + "family_name": "Noto Serif Thai Cond Thin", + "font-family": "Noto Serif Thai Cond Thin", + "font-stretch": "condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Serif Thai Condensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 2, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifThai-CondensedThin.ttf", + "preferred_family_name": "Noto Serif Thai", + "preferred_subfamily_name": "Condensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 3, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifThai-ExtraBold.ttf||47996:1655828711.0": { + "family_name": "Noto Serif Thai ExtBd", + "font-family": "Noto Serif Thai ExtBd", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Serif Thai ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 9, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifThai-ExtraBold.ttf", + "preferred_family_name": "Noto Serif Thai", + "preferred_subfamily_name": "ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifThai-ExtraCondensed.ttf||45840:1655828711.0": { + "family_name": "Noto Serif Thai ExtCond", + "font-family": "Noto Serif Thai ExtCond", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif Thai ExtraCondensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 5, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifThai-ExtraCondensed.ttf", + "preferred_family_name": "Noto Serif Thai", + "preferred_subfamily_name": "ExtraCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifThai-ExtraCondensedBlack.ttf||48720:1655828711.0": { + "family_name": "Noto Serif Thai ExtCond Blk", + "font-family": "Noto Serif Thai ExtCond Blk", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Serif Thai ExtraCondensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 10, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifThai-ExtraCondensedBlack.ttf", + "preferred_family_name": "Noto Serif Thai", + "preferred_subfamily_name": "ExtraCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifThai-ExtraCondensedBold.ttf||45616:1655828711.0": { + "family_name": "Noto Serif Thai ExtCond", + "font-family": "Noto Serif Thai ExtCond", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Serif Thai ExtraCondensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 8, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifThai-ExtraCondensedBold.ttf", + "preferred_family_name": "Noto Serif Thai", + "preferred_subfamily_name": "ExtraCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifThai-ExtraCondensedExtraBold.ttf||48348:1655828711.0": { + "family_name": "Noto Serif Thai ExtCond ExtBd", + "font-family": "Noto Serif Thai ExtCond ExtBd", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Serif Thai ExtraCondensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 9, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifThai-ExtraCondensedExtraBold.ttf", + "preferred_family_name": "Noto Serif Thai", + "preferred_subfamily_name": "ExtraCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifThai-ExtraCondensedExtraLight.ttf||46320:1655828711.0": { + "family_name": "Noto Serif Thai ExtCond ExtLt", + "font-family": "Noto Serif Thai ExtCond ExtLt", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Serif Thai ExtraCondensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 3, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifThai-ExtraCondensedExtraLight.ttf", + "preferred_family_name": "Noto Serif Thai", + "preferred_subfamily_name": "ExtraCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifThai-ExtraCondensedLight.ttf||46452:1655828711.0": { + "family_name": "Noto Serif Thai ExtCond Light", + "font-family": "Noto Serif Thai ExtCond Light", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Serif Thai ExtraCondensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 4, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifThai-ExtraCondensedLight.ttf", + "preferred_family_name": "Noto Serif Thai", + "preferred_subfamily_name": "ExtraCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifThai-ExtraCondensedMedium.ttf||45616:1655828711.0": { + "family_name": "Noto Serif Thai ExtCond Med", + "font-family": "Noto Serif Thai ExtCond Med", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Serif Thai ExtraCondensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 6, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifThai-ExtraCondensedMedium.ttf", + "preferred_family_name": "Noto Serif Thai", + "preferred_subfamily_name": "ExtraCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifThai-ExtraCondensedSemiBold.ttf||46596:1655828711.0": { + "family_name": "Noto Serif Thai ExtCond SemBd", + "font-family": "Noto Serif Thai ExtCond SemBd", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Serif Thai ExtraCondensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 7, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifThai-ExtraCondensedSemiBold.ttf", + "preferred_family_name": "Noto Serif Thai", + "preferred_subfamily_name": "ExtraCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifThai-ExtraCondensedThin.ttf||47716:1655828711.0": { + "family_name": "Noto Serif Thai ExtCond Thin", + "font-family": "Noto Serif Thai ExtCond Thin", + "font-stretch": "extra-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Serif Thai ExtraCondensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 2, + 6, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifThai-ExtraCondensedThin.ttf", + "preferred_family_name": "Noto Serif Thai", + "preferred_subfamily_name": "ExtraCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 2, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifThai-ExtraLight.ttf||47236:1655828711.0": { + "family_name": "Noto Serif Thai ExtLt", + "font-family": "Noto Serif Thai ExtLt", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Serif Thai ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 3, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifThai-ExtraLight.ttf", + "preferred_family_name": "Noto Serif Thai", + "preferred_subfamily_name": "ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifThai-Light.ttf||46960:1655828711.0": { + "family_name": "Noto Serif Thai Light", + "font-family": "Noto Serif Thai Light", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Serif Thai Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 4, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifThai-Light.ttf", + "preferred_family_name": "Noto Serif Thai", + "preferred_subfamily_name": "Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifThai-Medium.ttf||46052:1655828711.0": { + "family_name": "Noto Serif Thai Med", + "font-family": "Noto Serif Thai Med", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Serif Thai Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 6, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifThai-Medium.ttf", + "preferred_family_name": "Noto Serif Thai", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifThai-Regular.ttf||46000:1655828711.0": { + "family_name": "Noto Serif Thai", + "font-family": "Noto Serif Thai", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif Thai Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 5, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifThai-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifThai-SemiBold.ttf||47320:1655828711.0": { + "family_name": "Noto Serif Thai SemBd", + "font-family": "Noto Serif Thai SemBd", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Serif Thai SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 7, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifThai-SemiBold.ttf", + "preferred_family_name": "Noto Serif Thai", + "preferred_subfamily_name": "SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifThai-SemiCondensed.ttf||45980:1655828711.0": { + "family_name": "Noto Serif Thai SemCond", + "font-family": "Noto Serif Thai SemCond", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif Thai SemiCondensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 5, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifThai-SemiCondensed.ttf", + "preferred_family_name": "Noto Serif Thai", + "preferred_subfamily_name": "SemiCondensed", + "subfamily_name": "Regular", + "weight": 400, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifThai-SemiCondensedBlack.ttf||48688:1655828711.0": { + "family_name": "Noto Serif Thai SemCond Blk", + "font-family": "Noto Serif Thai SemCond Blk", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Serif Thai SemiCondensed Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 10, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifThai-SemiCondensedBlack.ttf", + "preferred_family_name": "Noto Serif Thai", + "preferred_subfamily_name": "SemiCondensed Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifThai-SemiCondensedBold.ttf||46816:1655828711.0": { + "family_name": "Noto Serif Thai SemCond", + "font-family": "Noto Serif Thai SemCond", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Serif Thai SemiCondensed Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 8, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifThai-SemiCondensedBold.ttf", + "preferred_family_name": "Noto Serif Thai", + "preferred_subfamily_name": "SemiCondensed Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifThai-SemiCondensedExtraBold.ttf||48548:1655828711.0": { + "family_name": "Noto Serif Thai SemCond ExtBd", + "font-family": "Noto Serif Thai SemCond ExtBd", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Serif Thai SemiCondensed ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 9, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifThai-SemiCondensedExtraBold.ttf", + "preferred_family_name": "Noto Serif Thai", + "preferred_subfamily_name": "SemiCondensed ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifThai-SemiCondensedExtraLight.ttf||47060:1655828711.0": { + "family_name": "Noto Serif Thai SemCond ExtLt", + "font-family": "Noto Serif Thai SemCond ExtLt", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Serif Thai SemiCondensed ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 3, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifThai-SemiCondensedExtraLight.ttf", + "preferred_family_name": "Noto Serif Thai", + "preferred_subfamily_name": "SemiCondensed ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifThai-SemiCondensedLight.ttf||46540:1655828711.0": { + "family_name": "Noto Serif Thai SemCond Light", + "font-family": "Noto Serif Thai SemCond Light", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Serif Thai SemiCondensed Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 4, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifThai-SemiCondensedLight.ttf", + "preferred_family_name": "Noto Serif Thai", + "preferred_subfamily_name": "SemiCondensed Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifThai-SemiCondensedMedium.ttf||46004:1655828711.0": { + "family_name": "Noto Serif Thai SemCond Med", + "font-family": "Noto Serif Thai SemCond Med", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Serif Thai SemiCondensed Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 6, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifThai-SemiCondensedMedium.ttf", + "preferred_family_name": "Noto Serif Thai", + "preferred_subfamily_name": "SemiCondensed Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifThai-SemiCondensedSemiBold.ttf||46864:1655828711.0": { + "family_name": "Noto Serif Thai SemCond SemBd", + "font-family": "Noto Serif Thai SemCond SemBd", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Serif Thai SemiCondensed SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 7, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifThai-SemiCondensedSemiBold.ttf", + "preferred_family_name": "Noto Serif Thai", + "preferred_subfamily_name": "SemiCondensed SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifThai-SemiCondensedThin.ttf||46384:1655828711.0": { + "family_name": "Noto Serif Thai SemCond Thin", + "font-family": "Noto Serif Thai SemCond Thin", + "font-stretch": "semi-condensed", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Serif Thai SemiCondensed Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 2, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifThai-SemiCondensedThin.ttf", + "preferred_family_name": "Noto Serif Thai", + "preferred_subfamily_name": "SemiCondensed Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 4, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifThai-Thin.ttf||45688:1655828711.0": { + "family_name": "Noto Serif Thai Thin", + "font-family": "Noto Serif Thai Thin", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Serif Thai Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 2, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifThai-Thin.ttf", + "preferred_family_name": "Noto Serif Thai", + "preferred_subfamily_name": "Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifTibetan-Black.ttf||594640:1655828711.0": { + "family_name": "Noto Serif Tibetan Black", + "font-family": "Noto Serif Tibetan Black", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "900", + "fs_type": 0, + "full_name": "Noto Serif Tibetan Black", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 2, + 10, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifTibetan-Black.ttf", + "preferred_family_name": "Noto Serif Tibetan", + "preferred_subfamily_name": "Black", + "subfamily_name": "Regular", + "weight": 900, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifTibetan-Bold.ttf||606276:1655828711.0": { + "family_name": "Noto Serif Tibetan Bold", + "font-family": "Noto Serif Tibetan Bold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Serif Tibetan Bold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 2, + 8, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifTibetan-Bold.ttf", + "preferred_family_name": "Noto Serif Tibetan", + "preferred_subfamily_name": "Bold", + "subfamily_name": "Regular", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifTibetan-ExtraBold.ttf||601576:1655828711.0": { + "family_name": "Noto Serif Tibetan ExtraBold", + "font-family": "Noto Serif Tibetan ExtraBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "800", + "fs_type": 0, + "full_name": "Noto Serif Tibetan ExtraBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 2, + 9, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifTibetan-ExtraBold.ttf", + "preferred_family_name": "Noto Serif Tibetan", + "preferred_subfamily_name": "ExtraBold", + "subfamily_name": "Regular", + "weight": 800, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifTibetan-ExtraLight.ttf||620508:1655828711.0": { + "family_name": "Noto Serif Tibetan ExtraLight", + "font-family": "Noto Serif Tibetan ExtraLight", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "200", + "fs_type": 0, + "full_name": "Noto Serif Tibetan ExtraLight", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 2, + 3, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifTibetan-ExtraLight.ttf", + "preferred_family_name": "Noto Serif Tibetan", + "preferred_subfamily_name": "ExtraLight", + "subfamily_name": "Regular", + "weight": 200, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifTibetan-Light.ttf||616452:1655828711.0": { + "family_name": "Noto Serif Tibetan Light", + "font-family": "Noto Serif Tibetan Light", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Serif Tibetan Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 2, + 4, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifTibetan-Light.ttf", + "preferred_family_name": "Noto Serif Tibetan", + "preferred_subfamily_name": "Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifTibetan-Medium.ttf||612140:1655828711.0": { + "family_name": "Noto Serif Tibetan Medium", + "font-family": "Noto Serif Tibetan Medium", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Serif Tibetan Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 2, + 6, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifTibetan-Medium.ttf", + "preferred_family_name": "Noto Serif Tibetan", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifTibetan-Regular.ttf||613292:1655828711.0": { + "family_name": "Noto Serif Tibetan", + "font-family": "Noto Serif Tibetan", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif Tibetan Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 2, + 5, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifTibetan-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifTibetan-SemiBold.ttf||609596:1655828711.0": { + "family_name": "Noto Serif Tibetan SemiBold", + "font-family": "Noto Serif Tibetan SemiBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Serif Tibetan SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 2, + 7, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifTibetan-SemiBold.ttf", + "preferred_family_name": "Noto Serif Tibetan", + "preferred_subfamily_name": "SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifTibetan-Thin.ttf||627024:1655828711.0": { + "family_name": "Noto Serif Tibetan Thin", + "font-family": "Noto Serif Tibetan Thin", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "100", + "fs_type": 0, + "full_name": "Noto Serif Tibetan Thin", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 2, + 2, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifTibetan-Thin.ttf", + "preferred_family_name": "Noto Serif Tibetan", + "preferred_subfamily_name": "Thin", + "subfamily_name": "Regular", + "weight": 100, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifToto-Bold.ttf||7132:1655828711.0": { + "family_name": "Noto Serif Toto", + "font-family": "Noto Serif Toto", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Serif Toto Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 8, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifToto-Bold.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifToto-Medium.ttf||7228:1655828711.0": { + "family_name": "Noto Serif Toto Medium", + "font-family": "Noto Serif Toto Medium", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Serif Toto Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 6, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifToto-Medium.ttf", + "preferred_family_name": "Noto Serif Toto", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifToto-Regular.ttf||7200:1655828711.0": { + "family_name": "Noto Serif Toto", + "font-family": "Noto Serif Toto", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif Toto Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 5, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifToto-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifToto-SemiBold.ttf||7236:1655828711.0": { + "family_name": "Noto Serif Toto SemiBold", + "font-family": "Noto Serif Toto SemiBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Serif Toto SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 7, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifToto-SemiBold.ttf", + "preferred_family_name": "Noto Serif Toto", + "preferred_subfamily_name": "SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifVithkuqi-Bold.ttf||19340:1655828711.0": { + "family_name": "Noto Serif Vithkuqi", + "font-family": "Noto Serif Vithkuqi", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Serif Vithkuqi Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 2, + 8, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifVithkuqi-Bold.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifVithkuqi-Medium.ttf||19332:1655828711.0": { + "family_name": "Noto Serif Vithkuqi Medium", + "font-family": "Noto Serif Vithkuqi Medium", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Serif Vithkuqi Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 2, + 6, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifVithkuqi-Medium.ttf", + "preferred_family_name": "Noto Serif Vithkuqi", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifVithkuqi-Regular.ttf||19376:1655828711.0": { + "family_name": "Noto Serif Vithkuqi", + "font-family": "Noto Serif Vithkuqi", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif Vithkuqi Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 2, + 5, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifVithkuqi-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifVithkuqi-SemiBold.ttf||19284:1655828711.0": { + "family_name": "Noto Serif Vithkuqi SemiBold", + "font-family": "Noto Serif Vithkuqi SemiBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Serif Vithkuqi SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 2, + 7, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifVithkuqi-SemiBold.ttf", + "preferred_family_name": "Noto Serif Vithkuqi", + "preferred_subfamily_name": "SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifYezidi-Bold.ttf||11776:1655828711.0": { + "family_name": "Noto Serif Yezidi", + "font-family": "Noto Serif Yezidi", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Serif Yezidi Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 8, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifYezidi-Bold.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifYezidi-Medium.ttf||11992:1655828711.0": { + "family_name": "Noto Serif Yezidi Medium", + "font-family": "Noto Serif Yezidi Medium", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Noto Serif Yezidi Medium", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 6, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifYezidi-Medium.ttf", + "preferred_family_name": "Noto Serif Yezidi", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Regular", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifYezidi-Regular.ttf||11956:1655828711.0": { + "family_name": "Noto Serif Yezidi", + "font-family": "Noto Serif Yezidi", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Serif Yezidi Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 5, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifYezidi-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoSerifYezidi-SemiBold.ttf||11992:1655828711.0": { + "family_name": "Noto Serif Yezidi SemiBold", + "font-family": "Noto Serif Yezidi SemiBold", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "600", + "fs_type": 0, + "full_name": "Noto Serif Yezidi SemiBold", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": true, + "os2_version": 4, + "panose": [ + 2, + 2, + 7, + 2, + 6, + 5, + 5, + 2, + 2, + 4 + ], + "path": "/usr/share/fonts/noto/NotoSerifYezidi-SemiBold.ttf", + "preferred_family_name": "Noto Serif Yezidi", + "preferred_subfamily_name": "SemiBold", + "subfamily_name": "Regular", + "weight": 600, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoTraditionalNushu-Bold.ttf||151200:1655828711.0": { + "family_name": "Noto Traditional Nushu", + "font-family": "Noto Traditional Nushu", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Noto Traditional Nushu Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/noto/NotoTraditionalNushu-Bold.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoTraditionalNushu-Light.ttf||153356:1655828711.0": { + "family_name": "Noto Traditional Nushu Light", + "font-family": "Noto Traditional Nushu Light", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Noto Traditional Nushu Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/noto/NotoTraditionalNushu-Light.ttf", + "preferred_family_name": "Noto Traditional Nushu", + "preferred_subfamily_name": "Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/noto/NotoTraditionalNushu-Regular.ttf||151380:1655828711.0": { + "family_name": "Noto Traditional Nushu", + "font-family": "Noto Traditional Nushu", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Noto Traditional Nushu Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/noto/NotoTraditionalNushu-Regular.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/ubuntu/Ubuntu-B.ttf||333612:1646061603.0": { + "family_name": "Ubuntu", + "font-family": "Ubuntu", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Ubuntu Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 8, + 4, + 3, + 6, + 2, + 3, + 2, + 4 + ], + "path": "/usr/share/fonts/ubuntu/Ubuntu-B.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/ubuntu/Ubuntu-BI.ttf||356980:1646061603.0": { + "family_name": "Ubuntu", + "font-family": "Ubuntu", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Ubuntu Bold Italic", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 8, + 4, + 3, + 6, + 2, + 10, + 2, + 4 + ], + "path": "/usr/share/fonts/ubuntu/Ubuntu-BI.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/ubuntu/Ubuntu-C.ttf||350444:1646061603.0": { + "family_name": "Ubuntu Condensed", + "font-family": "Ubuntu Condensed", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Ubuntu Condensed", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 5, + 6, + 3, + 6, + 2, + 3, + 2, + 4 + ], + "path": "/usr/share/fonts/ubuntu/Ubuntu-C.ttf", + "preferred_family_name": "Ubuntu Condensed", + "preferred_subfamily_name": "Regular", + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/ubuntu/Ubuntu-L.ttf||415552:1646061603.0": { + "family_name": "Ubuntu Light", + "font-family": "Ubuntu Light", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "300", + "fs_type": 0, + "full_name": "Ubuntu Light", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 3, + 4, + 3, + 6, + 2, + 3, + 2, + 4 + ], + "path": "/usr/share/fonts/ubuntu/Ubuntu-L.ttf", + "preferred_family_name": "Ubuntu", + "preferred_subfamily_name": "Light", + "subfamily_name": "Regular", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/ubuntu/Ubuntu-LI.ttf||409608:1646061603.0": { + "family_name": "Ubuntu Light", + "font-family": "Ubuntu Light", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "300", + "fs_type": 0, + "full_name": "Ubuntu Light Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 3, + 4, + 3, + 6, + 2, + 10, + 2, + 4 + ], + "path": "/usr/share/fonts/ubuntu/Ubuntu-LI.ttf", + "preferred_family_name": "Ubuntu", + "preferred_subfamily_name": "Light Italic", + "subfamily_name": "Italic", + "weight": 300, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/ubuntu/Ubuntu-M.ttf||341324:1646061603.0": { + "family_name": "Ubuntu Light", + "font-family": "Ubuntu Light", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "500", + "fs_type": 0, + "full_name": "Ubuntu Medium", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 6, + 4, + 3, + 6, + 2, + 3, + 2, + 4 + ], + "path": "/usr/share/fonts/ubuntu/Ubuntu-M.ttf", + "preferred_family_name": "Ubuntu", + "preferred_subfamily_name": "Medium", + "subfamily_name": "Bold", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/ubuntu/Ubuntu-MI.ttf||366992:1646061603.0": { + "family_name": "Ubuntu Light", + "font-family": "Ubuntu Light", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "500", + "fs_type": 0, + "full_name": "Ubuntu Medium Italic", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 5, + 4, + 3, + 6, + 2, + 10, + 2, + 4 + ], + "path": "/usr/share/fonts/ubuntu/Ubuntu-MI.ttf", + "preferred_family_name": "Ubuntu", + "preferred_subfamily_name": "Medium Italic", + "subfamily_name": "Bold Italic", + "weight": 500, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/ubuntu/Ubuntu-R.ttf||353824:1646061603.0": { + "family_name": "Ubuntu", + "font-family": "Ubuntu", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Ubuntu", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 5, + 4, + 3, + 6, + 2, + 3, + 2, + 4 + ], + "path": "/usr/share/fonts/ubuntu/Ubuntu-R.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/ubuntu/Ubuntu-RI.ttf||386440:1646061603.0": { + "family_name": "Ubuntu", + "font-family": "Ubuntu", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Ubuntu Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 5, + 4, + 3, + 6, + 2, + 10, + 2, + 4 + ], + "path": "/usr/share/fonts/ubuntu/Ubuntu-RI.ttf", + "preferred_family_name": null, + "preferred_subfamily_name": null, + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/ubuntu/UbuntuMono-B.ttf||191400:1646061603.0": { + "family_name": "Ubuntu Mono", + "font-family": "Ubuntu Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Ubuntu Mono Bold", + "is_bold": true, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 8, + 9, + 3, + 6, + 2, + 3, + 2, + 4 + ], + "path": "/usr/share/fonts/ubuntu/UbuntuMono-B.ttf", + "preferred_family_name": "Ubuntu Mono", + "preferred_subfamily_name": "Bold", + "subfamily_name": "Bold", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/ubuntu/UbuntuMono-BI.ttf||216208:1646061603.0": { + "family_name": "Ubuntu Mono", + "font-family": "Ubuntu Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "bold", + "fs_type": 0, + "full_name": "Ubuntu Mono Bold Italic", + "is_bold": true, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 8, + 9, + 3, + 6, + 2, + 10, + 2, + 4 + ], + "path": "/usr/share/fonts/ubuntu/UbuntuMono-BI.ttf", + "preferred_family_name": "Ubuntu Mono", + "preferred_subfamily_name": "Bold Italic", + "subfamily_name": "Bold Italic", + "weight": 700, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/ubuntu/UbuntuMono-R.ttf||205748:1646061603.0": { + "family_name": "Ubuntu Mono", + "font-family": "Ubuntu Mono", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Ubuntu Mono", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 5, + 9, + 3, + 6, + 2, + 3, + 2, + 4 + ], + "path": "/usr/share/fonts/ubuntu/UbuntuMono-R.ttf", + "preferred_family_name": "Ubuntu Mono", + "preferred_subfamily_name": "Regular", + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/ubuntu/UbuntuMono-RI.ttf||210216:1646061603.0": { + "family_name": "Ubuntu Mono", + "font-family": "Ubuntu Mono", + "font-stretch": "normal", + "font-style": "italic", + "font-weight": "normal", + "fs_type": 0, + "full_name": "Ubuntu Mono Italic", + "is_bold": false, + "is_italic": true, + "is_oblique": false, + "is_otf": false, + "is_regular": false, + "is_wws": false, + "os2_version": 3, + "panose": [ + 2, + 11, + 5, + 9, + 3, + 6, + 2, + 10, + 2, + 4 + ], + "path": "/usr/share/fonts/ubuntu/UbuntuMono-RI.ttf", + "preferred_family_name": "Ubuntu Mono", + "preferred_subfamily_name": "Italic", + "subfamily_name": "Italic", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + }, + "/usr/share/fonts/wps-office/DejaVuMathTeXGyre.ttf||577708:1654753421.0": { + "family_name": "DejaVu Math TeX Gyre", + "font-family": "DejaVu Math TeX Gyre", + "font-stretch": "normal", + "font-style": "normal", + "font-weight": "normal", + "fs_type": 12, + "full_name": "DejaVuMathTeXGyre-Regular", + "is_bold": false, + "is_italic": false, + "is_oblique": false, + "is_otf": false, + "is_regular": true, + "is_wws": false, + "os2_version": 4, + "panose": [ + 2, + 0, + 5, + 3, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "path": "/usr/share/fonts/wps-office/DejaVuMathTeXGyre.ttf", + "preferred_family_name": "DejaVu Math TeX Gyre", + "preferred_subfamily_name": "Regular", + "subfamily_name": "Regular", + "weight": 400, + "width": 5, + "wws_family_name": null, + "wws_subfamily_name": null + } + }, + "version": 2 +} \ No newline at end of file diff --git a/arch-config/.config/calibre/global.py.json b/arch-config/.config/calibre/global.py.json new file mode 100644 index 00000000..6f2077f8 --- /dev/null +++ b/arch-config/.config/calibre/global.py.json @@ -0,0 +1,51 @@ +{ + "add_formats_to_existing": false, + "case_sensitive": false, + "check_for_dupes_on_ctl": false, + "database_path": "/home/marc/library1.db", + "filename_pattern": "(?P.+) - (?P<author>[^_]+)", + "input_format_order": [ + "EPUB", + "AZW3", + "MOBI", + "LIT", + "PRC", + "FB2", + "HTML", + "HTM", + "XHTM", + "SHTML", + "XHTML", + "ZIP", + "DOCX", + "ODT", + "RTF", + "PDF", + "TXT" + ], + "installation_uuid": "95258752-0a69-416a-90ff-c20df0267b24", + "isbndb_com_key": "", + "language": "de", + "library_path": "/home/marc/Calibre-Bibliothek", + "limit_search_columns": false, + "limit_search_columns_to": [ + "title", + "authors", + "tags", + "series", + "publisher" + ], + "manage_device_metadata": "manual", + "mark_new_books": false, + "migrated": false, + "network_timeout": 5, + "new_book_tags": [], + "numeric_collation": false, + "output_format": "epub", + "read_file_metadata": true, + "saved_searches": {}, + "swap_author_names": false, + "use_primary_find_in_search": true, + "user_categories": {}, + "worker_process_priority": "normal" +} \ No newline at end of file diff --git a/arch-config/.config/calibre/gui.json b/arch-config/.config/calibre/gui.json new file mode 100644 index 00000000..04cbcb23 --- /dev/null +++ b/arch-config/.config/calibre/gui.json @@ -0,0 +1,274 @@ +{ + "Plugin Updater plugin:plugin updater dialog": { + "__class__": "bytearray", + "__value__": "AdnQywADAAAAAAHDAAABFQAABdUAAAMKAAABxQAAARcAAAXTAAADCAAAAAAAAAAAB4AAAAHFAAABFwAABdMAAAMI" + }, + "action-layout-toolbar": [ + "Add Books", + "Edit Metadata", + null, + "Convert Books", + "View", + null, + "Store", + "Donate", + "Fetch News", + "Help", + null, + "Remove Books", + "Choose Library", + "Save To Disk", + "Connect Share", + "Tweak ePub", + "Preferences", + "Obok DeDRM" + ], + "action-layout-toolbar-device": [ + "Add Books", + "Edit Metadata", + null, + "Convert Books", + "View", + "Send To Device", + null, + null, + "Location Manager", + null, + null, + "Fetch News", + "Save To Disk", + "Store", + "Connect Share", + null, + "Remove Books", + null, + "Help", + "Preferences", + "Obok DeDRM" + ], + "advanced search dialog current tab": 3, + "advanced_search_template_tab_program_field": "", + "advanced_search_template_tab_test_field": "0", + "advanced_search_template_tab_value_field": "", + "ask_to_manage_device": [ + "9d273cd5" + ], + "basic_metadata_widget_splitter_state": { + "__class__": "bytearray", + "__value__": "AAAA/wAAAAEAAAADAAAA6wAAAZwAAAEKAf////8BAAAAAQA=" + }, + "book_details_splitter_horizontal_state": [ + true, + 200 + ], + "book_info_dialog_layout": [ + { + "__class__": "bytearray", + "__value__": "AdnQywADAAAAAAH3AAAAJAAABYgAAAP7AAAB+QAAACYAAAWGAAAD+QAAAAAAAAAAB4AAAAH5AAAAJgAABYYAAAP5" + }, + { + "__class__": "bytearray", + "__value__": "AAAA/wAAAAEAAAACAAABXgAAAV4B/////wEAAAABAA==" + } + ], + "book_list_pin_splitter_state": { + "__class__": "bytearray", + "__value__": "AAAA/wAAAAEAAAACAAABAAAAAEYA/////wEAAAABAA==" + }, + "bulk_metadata_window_geometry": { + "__class__": "bytearray", + "__value__": "AdnQywADAAAAAAAbAAAAEgAAB1gAAAQbAAAAHQAAABQAAAdWAAAEGQAAAAAAAAAAB4AAAAAdAAAAFAAAB1YAAAQZ" + }, + "bulk_metadata_window_tab": 0, + "convert_bulk_dialog_geom": { + "__class__": "bytearray", + "__value__": "AdnQywADAAAAAAASAAAAJAAAB08AAAP7AAAAFAAAACYAAAdNAAAD+QAAAAAAAAAAB4AAAAAUAAAAJgAAB00AAAP5" + }, + "convert_single_dialog_geom": { + "__class__": "bytearray", + "__value__": "AdnQywADAAAAAAAsAAAAEgAAB2kAAAPpAAAALgAAABQAAAdnAAAD5wAAAAAAAAAAB4AAAAAuAAAAFAAAB2cAAAPn" + }, + "cover_browser_splitter_vertical_state": [ + false, + 300 + ], + "custom_colors_for_color_dialog": [ + [ + 255, + 255, + 255, + 255 + ], + [ + 255, + 255, + 255, + 255 + ], + [ + 255, + 255, + 255, + 255 + ], + [ + 255, + 255, + 255, + 255 + ], + [ + 255, + 255, + 255, + 255 + ], + [ + 255, + 255, + 255, + 255 + ], + [ + 255, + 255, + 255, + 255 + ], + [ + 255, + 255, + 255, + 255 + ], + [ + 255, + 255, + 255, + 255 + ], + [ + 255, + 255, + 255, + 255 + ], + [ + 255, + 255, + 255, + 255 + ], + [ + 255, + 255, + 255, + 255 + ], + [ + 255, + 255, + 255, + 255 + ], + [ + 255, + 255, + 255, + 255 + ], + [ + 255, + 255, + 255, + 255 + ], + [ + 255, + 255, + 255, + 255 + ] + ], + "diff_dialog_geom": { + "__class__": "bytearray", + "__value__": "AdnQywADAAAAAAJnAAAAJgAABv8AAAP9AAACaQAAACgAAAb9AAAD+wAAAAAAAAAAB4AAAAJpAAAAKAAABv0AAAP7" + }, + "duplicates-question-dialog-geometry": { + "__class__": "bytearray", + "__value__": "AdnQywADAAAAAACGAAABTAAAA2AAAALPAAAAiAAAAU4AAANeAAACzQAAAAAAAAAAB4AAAACIAAABTgAAA14AAALN" + }, + "grid view visible": false, + "jobs view column layout3": { + "__class__": "bytearray", + "__value__": "AAAA/wAAAAAAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA04AAAAFAQEBAAAAAAAAAAAAAAAAAGT/////AAAAhAAAAAAAAAAFAAABRAAAAAEAAAAAAAAAtgAAAAEAAAAAAAAAjAAAAAEAAAAAAAAAZAAAAAEAAAAAAAAAZAAAAAEAAAAAAAAD6AAAAAAA" + }, + "jobs_dialog_geometry": { + "__class__": "bytearray", + "__value__": "AdnQywADAAAAAAGYAAABEQAABQ4AAAMyAAABmgAAARMAAAUMAAADMAAAAAAAAAAAB4AAAAGaAAABEwAABQwAAAMw" + }, + "library_usage_stats": { + "/home/marc/Calibre-Bibliothek": 184 + }, + "metadata-download-identify-widget-splitter-state": { + "__class__": "bytearray", + "__value__": "AAAA/wAAAAEAAAACAAACAAAAAQAA/////wEAAAABAA==" + }, + "metadata_single_gui_geom": { + "__class__": "bytearray", + "__value__": "AdnQywADAAAAAAIiAAAA6QAABXcAAANEAAACJAAAAOsAAAV1AAADQgAAAAAAAAAAB4AAAAIkAAAA6wAABXUAAANC" + }, + "metasingle_window_geometry3": { + "__class__": "bytearray", + "__value__": "AdnQywADAAAAAAA8AAAAEgAAB3kAAAQbAAAAPgAAABQAAAd3AAAEGQAAAAAAAAAAB4AAAAA+AAAAFAAAB3cAAAQZ" + }, + "plugin config dialog:Dateityp:DeACSM": { + "__class__": "bytearray", + "__value__": "AdnQywADAAAAAAMiAAABRAAABKAAAAL9AAADJAAAAUYAAASeAAAC+wAAAAAAAAAAB4AAAAMkAAABRgAABJ4AAAL7" + }, + "plugin config dialog:Dateityp:DeDRM": { + "__class__": "bytearray", + "__value__": "AdnQywADAAAAAAP8AAAApAAABRYAAAKaAAAD/gAAAKYAAAUUAAACmAAAAAAAAAAAB4AAAAP+AAAApgAABRQAAAKY" + }, + "preferences dialog geometry": { + "__class__": "bytearray", + "__value__": "AdnQywADAAAAAAHtAAAApgAABZIAAAN5AAAB7wAAAKgAAAWQAAADdwAAAAAAAAAAB4AAAAHvAAAAqAAABZAAAAN3" + }, + "previous_sort_order_BooksView": { + "authors": true, + "rating": true, + "series": true, + "title": true + }, + "quick_start_guide_added": true, + "quickview visible": false, + "recently_used_languages": [ + "Englisch" + ], + "replace_scene_breaks_history": [ + "", + "<hr />", + "∗ ∗ ∗", + "• • •", + "♦ ♦ ♦", + "† †", + "‡ ‡ ‡", + "∞ ∞ ∞", + "¤ ¤ ¤" + ], + "search bar visible": true, + "single-cover-fetch-dialog-geometry": { + "__class__": "bytearray", + "__value__": "AdnQywADAAAAAAIhAAAA5wAABXYAAANCAAACIwAAAOkAAAV0AAADQAAAAAAAAAAAB4AAAAIjAAAA6QAABXQAAANA" + }, + "tag browser search box visible": false, + "tag_browser_splitter_horizontal_state": [ + true, + 200 + ], + "tag_editor_geometry": { + "__class__": "bytearray", + "__value__": "AdnQywADAAAAAAKTAAAAyAAABRYAAANlAAAClQAAAMoAAAUUAAADYwAAAAAAAAAAB4AAAAKVAAAAygAABRQAAANj" + }, + "tag_editor_last_filter": "add_tag_input" +} \ No newline at end of file diff --git a/arch-config/.config/calibre/gui.py.json b/arch-config/.config/calibre/gui.py.json new file mode 100644 index 00000000..b7a61032 --- /dev/null +++ b/arch-config/.config/calibre/gui.py.json @@ -0,0 +1,78 @@ +{ + "LRF_conversion_defaults": [], + "LRF_ebook_viewer_options": null, + "asked_library_thing_password": false, + "auto_download_cover": false, + "autolaunch_server": false, + "column_map": [ + "title", + "ondevice", + "authors", + "size", + "timestamp", + "rating", + "publisher", + "tags", + "series", + "pubdate" + ], + "confirm_delete": false, + "cover_flow_queue_length": 6, + "default_send_to_device_action": "DeviceAction:main::False:False", + "delete_news_from_library_on_upload": false, + "disable_animations": false, + "disable_tray_notification": false, + "enforce_cpu_limit": true, + "get_social_metadata": true, + "gui_layout": "wide", + "highlight_search_matches": false, + "internally_viewed_formats": [ + "LRF", + "EPUB", + "LIT", + "MOBI", + "PRC", + "POBI", + "AZW", + "AZW3", + "HTML", + "FB2", + "PDB", + "RB", + "SNB", + "HTMLZ", + "KEPUB" + ], + "jobs_search_history": [], + "lrf_viewer_search_history": [], + "main_search_history": [], + "main_window_geometry": { + "__class__": "bytearray", + "__value__": "AdnQywADAAAAAAAAAAAAAAAAB38AAAQjAAAAAgAAAAIAAAd9AAAEIQAAAAAAAAAAB4AAAAACAAAAAgAAB30AAAQh" + }, + "match_tags_type": "any", + "new_version_notification": true, + "oldest_news": 60, + "overwrite_author_title_metadata": true, + "plugin_search_history": [], + "save_to_disk_template_history": [], + "scheduler_search_history": [], + "search_as_you_type": false, + "send_to_device_template_history": [], + "send_to_storage_card_by_default": false, + "separate_cover_flow": false, + "shortcuts_search_history": [], + "show_avg_rating": true, + "sort_tags_by": "name", + "systray_icon": false, + "tag_browser_hidden_categories": { + "__class__": "set", + "__value__": [] + }, + "tweaks_search_history": [], + "upload_news_to_device": true, + "use_roman_numerals_for_series_number": true, + "viewer_search_history": [], + "viewer_toc_search_history": [], + "worker_limit": 6 +} \ No newline at end of file diff --git a/arch-config/.config/calibre/metadata-sources-cache.json b/arch-config/.config/calibre/metadata-sources-cache.json new file mode 100644 index 00000000..f83301a3 --- /dev/null +++ b/arch-config/.config/calibre/metadata-sources-cache.json @@ -0,0 +1,18 @@ +{ + "amazon": "#!/usr/bin/env python\n# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai\n# License: GPLv3 Copyright: 2011, Kovid Goyal <kovid at kovidgoyal.net>\nfrom __future__ import absolute_import, division, print_function, unicode_literals\n\nimport re\nimport string\nimport socket\nimport time\nfrom functools import partial\ntry:\n from queue import Empty, Queue\nexcept ImportError:\n from Queue import Empty, Queue\nfrom threading import Thread\ntry:\n from urllib.parse import urlparse\nexcept ImportError:\n from urlparse import urlparse\n\nfrom mechanize import HTTPError\n\nfrom calibre import as_unicode, browser, random_user_agent, xml_replace_entities\nfrom calibre.ebooks.metadata import check_isbn\nfrom calibre.ebooks.metadata.book.base import Metadata\nfrom calibre.ebooks.metadata.sources.base import Option, Source, fixauthors, fixcase\nfrom calibre.utils.localization import canonicalize_lang\nfrom calibre.utils.random_ua import accept_header_for_ua\nfrom calibre.ebooks.oeb.base import urlquote\n\n\ndef sort_matches_preferring_kindle_editions(matches):\n upos_map = {url:i for i, url in enumerate(matches)}\n\n def skey(url):\n opos = upos_map[url]\n parts = url.split('/')\n try:\n idx = parts.index('dp')\n except Exception:\n idx = -1\n if idx < 0 or idx + 1 >= len(parts) or not parts[idx+1].startswith('B'):\n return 1, opos\n return 0, opos\n matches.sort(key=skey)\n return matches\n\n\ndef iri_quote_plus(url):\n ans = urlquote(url)\n if isinstance(ans, bytes):\n ans = ans.decode('utf-8')\n return ans.replace('%20', '+')\n\n\ndef user_agent_is_ok(ua):\n return 'Mobile/' not in ua and 'Mobile ' not in ua\n\n\nclass CaptchaError(Exception):\n pass\n\n\nclass SearchFailed(ValueError):\n pass\n\n\ndef parse_html(raw):\n try:\n from html5_parser import parse\n except ImportError:\n # Old versions of calibre\n import html5lib\n return html5lib.parse(raw, treebuilder='lxml', namespaceHTMLElements=False)\n else:\n return parse(raw)\n\n\ndef parse_details_page(url, log, timeout, browser, domain):\n from calibre.utils.cleantext import clean_ascii_chars\n from calibre.ebooks.chardet import xml_to_unicode\n from lxml.html import tostring\n try:\n from calibre.ebooks.metadata.sources.update import search_engines_module\n get_data_for_cached_url = search_engines_module().get_data_for_cached_url\n except Exception:\n get_data_for_cached_url = lambda *a: None\n raw = get_data_for_cached_url(url)\n if raw:\n log('Using cached details for url:', url)\n else:\n log('Downloading details from:', url)\n try:\n raw = browser.open_novisit(url, timeout=timeout).read().strip()\n except Exception as e:\n if callable(getattr(e, 'getcode', None)) and \\\n e.getcode() == 404:\n log.error('URL malformed: %r' % url)\n return\n attr = getattr(e, 'args', [None])\n attr = attr if attr else [None]\n if isinstance(attr[0], socket.timeout):\n msg = 'Details page timed out. Try again later.'\n log.error(msg)\n else:\n msg = 'Failed to make details query: %r' % url\n log.exception(msg)\n return\n\n oraw = raw\n if 'amazon.com.br' in url:\n # amazon.com.br serves utf-8 but has an incorrect latin1 <meta> tag\n raw = raw.decode('utf-8')\n raw = xml_to_unicode(raw, strip_encoding_pats=True,\n resolve_entities=True)[0]\n if '<title>404 - ' in raw:\n raise ValueError('URL malformed: %r' % url)\n if '>Could not find the requested document in the cache.<' in raw:\n raise ValueError('No cached entry for %s found' % url)\n\n try:\n root = parse_html(clean_ascii_chars(raw))\n except Exception:\n msg = 'Failed to parse amazon details page: %r' % url\n log.exception(msg)\n return\n if domain == 'jp':\n for a in root.xpath('//a[@href]'):\n if ('black-curtain-redirect.html' in a.get('href')) or ('/black-curtain/save-eligibility/black-curtain' in a.get('href')):\n url = a.get('href')\n if url:\n if url.startswith('/'):\n url = 'https://amazon.co.jp' + a.get('href')\n log('Black curtain redirect found, following')\n return parse_details_page(url, log, timeout, browser, domain)\n\n errmsg = root.xpath('//*[@id=\"errorMessage\"]')\n if errmsg:\n msg = 'Failed to parse amazon details page: %r' % url\n msg += tostring(errmsg, method='text', encoding='unicode').strip()\n log.error(msg)\n return\n\n from css_selectors import Select\n selector = Select(root)\n return oraw, root, selector\n\n\ndef parse_asin(root, log, url):\n try:\n link = root.xpath('//link[@rel=\"canonical\" and @href]')\n for l in link:\n return l.get('href').rpartition('/')[-1]\n except Exception:\n log.exception('Error parsing ASIN for url: %r' % url)\n\n\nclass Worker(Thread): # Get details {{{\n\n '''\n Get book details from amazons book page in a separate thread\n '''\n\n def __init__(self, url, result_queue, browser, log, relevance, domain,\n plugin, timeout=20, testing=False, preparsed_root=None,\n cover_url_processor=None, filter_result=None):\n Thread.__init__(self)\n self.cover_url_processor = cover_url_processor\n self.preparsed_root = preparsed_root\n self.daemon = True\n self.testing = testing\n self.url, self.result_queue = url, result_queue\n self.log, self.timeout = log, timeout\n self.filter_result = filter_result or (lambda x, log: True)\n self.relevance, self.plugin = relevance, plugin\n self.browser = browser\n self.cover_url = self.amazon_id = self.isbn = None\n self.domain = domain\n from lxml.html import tostring\n self.tostring = tostring\n\n months = { # {{{\n 'de': {\n 1: ['jän', 'januar'],\n 2: ['februar'],\n 3: ['märz'],\n 5: ['mai'],\n 6: ['juni'],\n 7: ['juli'],\n 10: ['okt', 'oktober'],\n 12: ['dez', 'dezember']\n },\n 'it': {\n 1: ['gennaio', 'enn'],\n 2: ['febbraio', 'febbr'],\n 3: ['marzo'],\n 4: ['aprile'],\n 5: ['maggio', 'magg'],\n 6: ['giugno'],\n 7: ['luglio'],\n 8: ['agosto', 'ag'],\n 9: ['settembre', 'sett'],\n 10: ['ottobre', 'ott'],\n 11: ['novembre'],\n 12: ['dicembre', 'dic'],\n },\n 'fr': {\n 1: ['janv'],\n 2: ['févr'],\n 3: ['mars'],\n 4: ['avril'],\n 5: ['mai'],\n 6: ['juin'],\n 7: ['juil'],\n 8: ['août'],\n 9: ['sept'],\n 12: ['déc'],\n },\n 'br': {\n 1: ['janeiro'],\n 2: ['fevereiro'],\n 3: ['março'],\n 4: ['abril'],\n 5: ['maio'],\n 6: ['junho'],\n 7: ['julho'],\n 8: ['agosto'],\n 9: ['setembro'],\n 10: ['outubro'],\n 11: ['novembro'],\n 12: ['dezembro'],\n },\n 'es': {\n 1: ['enero'],\n 2: ['febrero'],\n 3: ['marzo'],\n 4: ['abril'],\n 5: ['mayo'],\n 6: ['junio'],\n 7: ['julio'],\n 8: ['agosto'],\n 9: ['septiembre', 'setiembre'],\n 10: ['octubre'],\n 11: ['noviembre'],\n 12: ['diciembre'],\n },\n 'se': {\n 1: ['januari'],\n 2: ['februari'],\n 3: ['mars'],\n 4: ['april'],\n 5: ['maj'],\n 6: ['juni'],\n 7: ['juli'],\n 8: ['augusti'],\n 9: ['september'],\n 10: ['oktober'],\n 11: ['november'],\n 12: ['december'],\n },\n 'jp': {\n 1: ['1月'],\n 2: ['2月'],\n 3: ['3月'],\n 4: ['4月'],\n 5: ['5月'],\n 6: ['6月'],\n 7: ['7月'],\n 8: ['8月'],\n 9: ['9月'],\n 10: ['10月'],\n 11: ['11月'],\n 12: ['12月'],\n },\n 'nl': {\n 1: ['januari'], 2: ['februari'], 3: ['maart'], 5: ['mei'], 6: ['juni'], 7: ['juli'], 8: ['augustus'], 10: ['oktober'],\n }\n\n } # }}}\n\n self.english_months = [None, 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',\n 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']\n self.months = months.get(self.domain, {})\n\n self.pd_xpath = '''\n //h2[text()=\"Product Details\" or \\\n text()=\"Produktinformation\" or \\\n text()=\"Dettagli prodotto\" or \\\n text()=\"Product details\" or \\\n text()=\"Détails sur le produit\" or \\\n text()=\"Detalles del producto\" or \\\n text()=\"Detalhes do produto\" or \\\n text()=\"Productgegevens\" or \\\n text()=\"基本信息\" or \\\n starts-with(text(), \"登録情報\")]/../div[@class=\"content\"]\n '''\n # Editor: is for Spanish\n self.publisher_xpath = '''\n descendant::*[starts-with(text(), \"Publisher:\") or \\\n starts-with(text(), \"Verlag:\") or \\\n starts-with(text(), \"Editore:\") or \\\n starts-with(text(), \"Editeur\") or \\\n starts-with(text(), \"Editor:\") or \\\n starts-with(text(), \"Editora:\") or \\\n starts-with(text(), \"Uitgever:\") or \\\n starts-with(text(), \"Utgivare:\") or \\\n starts-with(text(), \"出版社:\")]\n '''\n self.pubdate_xpath = '''\n descendant::*[starts-with(text(), \"Publication Date:\") or \\\n starts-with(text(), \"Audible.com Release Date:\")]\n '''\n self.publisher_names = {'Publisher', 'Uitgever', 'Verlag', 'Utgivare', 'Herausgeber',\n 'Editore', 'Editeur', 'Editor', 'Editora', '出版社'}\n\n self.language_xpath = '''\n descendant::*[\n starts-with(text(), \"Language:\") \\\n or text() = \"Language\" \\\n or text() = \"Sprache:\" \\\n or text() = \"Lingua:\" \\\n or text() = \"Idioma:\" \\\n or starts-with(text(), \"Langue\") \\\n or starts-with(text(), \"言語\") \\\n or starts-with(text(), \"Språk\") \\\n or starts-with(text(), \"语种\")\n ]\n '''\n self.language_names = {'Language', 'Sprache', 'Språk',\n 'Lingua', 'Idioma', 'Langue', '言語', 'Taal', '语种'}\n\n self.tags_xpath = '''\n descendant::h2[\n text() = \"Look for Similar Items by Category\" or\n text() = \"Ähnliche Artikel finden\" or\n text() = \"Buscar productos similares por categoría\" or\n text() = \"Ricerca articoli simili per categoria\" or\n text() = \"Rechercher des articles similaires par rubrique\" or\n text() = \"Procure por items similares por categoria\" or\n text() = \"関連商品を探す\"\n ]/../descendant::ul/li\n '''\n\n self.ratings_pat = re.compile(\n r'([0-9.,]+) ?(out of|von|van|su|étoiles sur|つ星のうち|de un máximo de|de|av) '\n r'([\\d\\.]+)( (stars|Sternen|stelle|estrellas|estrelas|sterren|stjärnor)){0,1}'\n )\n self.ratings_pat_cn = re.compile('([0-9.]+) 颗星,最多 5 颗星')\n self.ratings_pat_jp = re.compile(r'\\d+つ星のうち([\\d\\.]+)')\n\n lm = {\n 'eng': ('English', 'Englisch', 'Engels', 'Engelska'),\n 'fra': ('French', 'Français'),\n 'ita': ('Italian', 'Italiano'),\n 'deu': ('German', 'Deutsch'),\n 'spa': ('Spanish', 'Espa\\xf1ol', 'Espaniol'),\n 'jpn': ('Japanese', '日本語'),\n 'por': ('Portuguese', 'Português'),\n 'nld': ('Dutch', 'Nederlands',),\n 'chs': ('Chinese', '中文', '简体中文'),\n 'swe': ('Swedish', 'Svenska'),\n }\n self.lang_map = {}\n for code, names in lm.items():\n for name in names:\n self.lang_map[name] = code\n\n self.series_pat = re.compile(\n r'''\n \\|\\s* # Prefix\n (Series)\\s*:\\s* # Series declaration\n (?P<series>.+?)\\s+ # The series name\n \\((Book)\\s* # Book declaration\n (?P<index>[0-9.]+) # Series index\n \\s*\\)\n ''', re.X)\n\n def delocalize_datestr(self, raw):\n if self.domain == 'cn':\n return raw.replace('年', '-').replace('月', '-').replace('日', '')\n if not self.months:\n return raw\n ans = raw.lower()\n for i, vals in self.months.items():\n for x in vals:\n ans = ans.replace(x, self.english_months[i])\n ans = ans.replace(' de ', ' ')\n return ans\n\n def run(self):\n try:\n self.get_details()\n except:\n self.log.exception('get_details failed for url: %r' % self.url)\n\n def get_details(self):\n if self.preparsed_root is None:\n raw, root, selector = parse_details_page(\n self.url, self.log, self.timeout, self.browser, self.domain)\n else:\n raw, root, selector = self.preparsed_root\n\n from css_selectors import Select\n self.selector = Select(root)\n self.parse_details(raw, root)\n\n def parse_details(self, raw, root):\n asin = parse_asin(root, self.log, self.url)\n if not asin and root.xpath('//form[@action=\"/errors/validateCaptcha\"]'):\n raise CaptchaError(\n 'Amazon returned a CAPTCHA page, probably because you downloaded too many books. Wait for some time and try again.')\n if self.testing:\n import tempfile\n import uuid\n with tempfile.NamedTemporaryFile(prefix=(asin or type('')(uuid.uuid4())) + '_',\n suffix='.html', delete=False) as f:\n f.write(raw)\n print('Downloaded HTML for', asin, 'saved in', f.name)\n\n try:\n title = self.parse_title(root)\n except:\n self.log.exception('Error parsing title for url: %r' % self.url)\n title = None\n\n try:\n authors = self.parse_authors(root)\n except:\n self.log.exception('Error parsing authors for url: %r' % self.url)\n authors = []\n\n if not title or not authors or not asin:\n self.log.error(\n 'Could not find title/authors/asin for %r' % self.url)\n self.log.error('ASIN: %r Title: %r Authors: %r' % (asin, title,\n authors))\n return\n\n mi = Metadata(title, authors)\n idtype = 'amazon' if self.domain == 'com' else 'amazon_' + self.domain\n mi.set_identifier(idtype, asin)\n self.amazon_id = asin\n\n try:\n mi.rating = self.parse_rating(root)\n except:\n self.log.exception('Error parsing ratings for url: %r' % self.url)\n\n try:\n mi.comments = self.parse_comments(root, raw)\n except:\n self.log.exception('Error parsing comments for url: %r' % self.url)\n\n try:\n series, series_index = self.parse_series(root)\n if series:\n mi.series, mi.series_index = series, series_index\n elif self.testing:\n mi.series, mi.series_index = 'Dummy series for testing', 1\n except:\n self.log.exception('Error parsing series for url: %r' % self.url)\n\n try:\n mi.tags = self.parse_tags(root)\n except:\n self.log.exception('Error parsing tags for url: %r' % self.url)\n\n try:\n self.cover_url = self.parse_cover(root, raw)\n except:\n self.log.exception('Error parsing cover for url: %r' % self.url)\n if self.cover_url_processor is not None and self.cover_url and self.cover_url.startswith('/'):\n self.cover_url = self.cover_url_processor(self.cover_url)\n mi.has_cover = bool(self.cover_url)\n\n detail_bullets = root.xpath('//*[@data-feature-name=\"detailBullets\"]')\n non_hero = tuple(self.selector(\n 'div#bookDetails_container_div div#nonHeroSection')) or tuple(self.selector(\n '#productDetails_techSpec_sections'))\n if detail_bullets:\n self.parse_detail_bullets(root, mi, detail_bullets[0])\n elif non_hero:\n try:\n self.parse_new_details(root, mi, non_hero[0])\n except:\n self.log.exception(\n 'Failed to parse new-style book details section')\n\n else:\n pd = root.xpath(self.pd_xpath)\n if pd:\n pd = pd[0]\n\n try:\n isbn = self.parse_isbn(pd)\n if isbn:\n self.isbn = mi.isbn = isbn\n except:\n self.log.exception(\n 'Error parsing ISBN for url: %r' % self.url)\n\n try:\n mi.publisher = self.parse_publisher(pd)\n except:\n self.log.exception(\n 'Error parsing publisher for url: %r' % self.url)\n\n try:\n mi.pubdate = self.parse_pubdate(pd)\n except:\n self.log.exception(\n 'Error parsing publish date for url: %r' % self.url)\n\n try:\n lang = self.parse_language(pd)\n if lang:\n mi.language = lang\n except:\n self.log.exception(\n 'Error parsing language for url: %r' % self.url)\n\n else:\n self.log.warning(\n 'Failed to find product description for url: %r' % self.url)\n\n mi.source_relevance = self.relevance\n\n if self.amazon_id:\n if self.isbn:\n self.plugin.cache_isbn_to_identifier(self.isbn, self.amazon_id)\n if self.cover_url:\n self.plugin.cache_identifier_to_cover_url(self.amazon_id,\n self.cover_url)\n\n self.plugin.clean_downloaded_metadata(mi)\n\n if self.filter_result(mi, self.log):\n self.result_queue.put(mi)\n\n def totext(self, elem, only_printable=False):\n res = self.tostring(elem, encoding='unicode', method='text')\n if only_printable:\n try:\n filtered_characters = list(s for s in res if s.isprintable())\n except AttributeError:\n filtered_characters = list(s for s in res if s in string.printable)\n res = ''.join(filtered_characters).strip()\n return res\n\n def parse_title(self, root):\n\n def sanitize_title(title):\n ans = title.strip()\n if not ans.startswith('['):\n ans = re.sub(r'[(\\[].*[)\\]]', '', title).strip()\n return ans\n\n h1 = root.xpath('//h1[@id=\"title\"]')\n if h1:\n h1 = h1[0]\n for child in h1.xpath('./*[contains(@class, \"a-color-secondary\")]'):\n h1.remove(child)\n return sanitize_title(self.totext(h1))\n tdiv = root.xpath('//h1[contains(@class, \"parseasinTitle\")]')\n if not tdiv:\n span = root.xpath('//*[@id=\"ebooksTitle\"]')\n if span:\n return sanitize_title(self.totext(span[0]))\n raise ValueError('No title block found')\n tdiv = tdiv[0]\n actual_title = tdiv.xpath('descendant::*[@id=\"btAsinTitle\"]')\n if actual_title:\n title = self.tostring(actual_title[0], encoding='unicode',\n method='text').strip()\n else:\n title = self.tostring(tdiv, encoding='unicode',\n method='text').strip()\n return sanitize_title(title)\n\n def parse_authors(self, root):\n for sel in (\n '#byline .author .contributorNameID',\n '#byline .author a.a-link-normal',\n '#bylineInfo .author .contributorNameID',\n '#bylineInfo .author a.a-link-normal',\n '#bylineInfo #bylineContributor',\n ):\n matches = tuple(self.selector(sel))\n if matches:\n authors = [self.totext(x) for x in matches]\n return [a for a in authors if a]\n\n x = '//h1[contains(@class, \"parseasinTitle\")]/following-sibling::span/*[(name()=\"a\" and @href) or (name()=\"span\" and @class=\"contributorNameTrigger\")]'\n aname = root.xpath(x)\n if not aname:\n aname = root.xpath('''\n //h1[contains(@class, \"parseasinTitle\")]/following-sibling::*[(name()=\"a\" and @href) or (name()=\"span\" and @class=\"contributorNameTrigger\")]\n ''')\n for x in aname:\n x.tail = ''\n authors = [self.tostring(x, encoding='unicode', method='text').strip() for x\n in aname]\n authors = [a for a in authors if a]\n return authors\n\n def parse_rating(self, root):\n for x in root.xpath('//div[@id=\"cpsims-feature\" or @id=\"purchase-sims-feature\" or @id=\"rhf\"]'):\n # Remove the similar books section as it can cause spurious\n # ratings matches\n x.getparent().remove(x)\n\n rating_paths = (\n '//div[@data-feature-name=\"averageCustomerReviews\" or @id=\"averageCustomerReviews\"]',\n '//div[@class=\"jumpBar\"]/descendant::span[contains(@class,\"asinReviewsSummary\")]',\n '//div[@class=\"buying\"]/descendant::span[contains(@class,\"asinReviewsSummary\")]',\n '//span[@class=\"crAvgStars\"]/descendant::span[contains(@class,\"asinReviewsSummary\")]'\n )\n ratings = None\n for p in rating_paths:\n ratings = root.xpath(p)\n if ratings:\n break\n\n def parse_ratings_text(text):\n try:\n m = self.ratings_pat.match(text)\n return float(m.group(1).replace(',', '.')) / float(m.group(3)) * 5\n except Exception:\n pass\n\n if ratings:\n ratings = ratings[0]\n for elem in ratings.xpath('descendant::*[@title]'):\n t = elem.get('title').strip()\n if self.domain == 'cn':\n m = self.ratings_pat_cn.match(t)\n if m is not None:\n return float(m.group(1))\n elif self.domain == 'jp':\n m = self.ratings_pat_jp.match(t)\n if m is not None:\n return float(m.group(1))\n else:\n ans = parse_ratings_text(t)\n if ans is not None:\n return ans\n for elem in ratings.xpath('descendant::span[@class=\"a-icon-alt\"]'):\n t = self.tostring(\n elem, encoding='unicode', method='text', with_tail=False).strip()\n ans = parse_ratings_text(t)\n if ans is not None:\n return ans\n\n def _render_comments(self, desc):\n from calibre.library.comments import sanitize_comments_html\n\n for c in desc.xpath('descendant::noscript'):\n c.getparent().remove(c)\n for c in desc.xpath('descendant::*[@class=\"seeAll\" or'\n ' @class=\"emptyClear\" or @id=\"collapsePS\" or'\n ' @id=\"expandPS\"]'):\n c.getparent().remove(c)\n for b in desc.xpath('descendant::b[@style]'):\n # Bing highlights search results\n s = b.get('style', '')\n if 'color' in s:\n b.tag = 'span'\n del b.attrib['style']\n\n for a in desc.xpath('descendant::a[@href]'):\n del a.attrib['href']\n a.tag = 'span'\n desc = self.tostring(desc, method='html', encoding='unicode').strip()\n desc = xml_replace_entities(desc, 'utf-8')\n\n # Encoding bug in Amazon data U+fffd (replacement char)\n # in some examples it is present in place of '\n desc = desc.replace('\\ufffd', \"'\")\n # remove all attributes from tags\n desc = re.sub(r'<([a-zA-Z0-9]+)\\s[^>]+>', r'<\\1>', desc)\n # Collapse whitespace\n # desc = re.sub('\\n+', '\\n', desc)\n # desc = re.sub(' +', ' ', desc)\n # Remove the notice about text referring to out of print editions\n desc = re.sub(r'(?s)<em>--This text ref.*?</em>', '', desc)\n # Remove comments\n desc = re.sub(r'(?s)<!--.*?-->', '', desc)\n return sanitize_comments_html(desc)\n\n def parse_comments(self, root, raw):\n try:\n from urllib.parse import unquote\n except ImportError:\n from urllib import unquote\n ans = ''\n ns = tuple(self.selector('#bookDescription_feature_div noscript'))\n if ns:\n ns = ns[0]\n if len(ns) == 0 and ns.text:\n import html5lib\n # html5lib parsed noscript as CDATA\n ns = html5lib.parseFragment(\n '<div>%s</div>' % (ns.text), treebuilder='lxml', namespaceHTMLElements=False)[0]\n else:\n ns.tag = 'div'\n ans = self._render_comments(ns)\n else:\n desc = root.xpath('//div[@id=\"ps-content\"]/div[@class=\"content\"]')\n if desc:\n ans = self._render_comments(desc[0])\n else:\n ns = tuple(self.selector('#bookDescription_feature_div .a-expander-content'))\n if ns:\n ans = self._render_comments(ns[0])\n\n desc = root.xpath(\n '//div[@id=\"productDescription\"]/*[@class=\"content\"]')\n if desc:\n ans += self._render_comments(desc[0])\n else:\n # Idiot chickens from amazon strike again. This data is now stored\n # in a JS variable inside a script tag URL encoded.\n m = re.search(br'var\\s+iframeContent\\s*=\\s*\"([^\"]+)\"', raw)\n if m is not None:\n try:\n text = unquote(m.group(1)).decode('utf-8')\n nr = parse_html(text)\n desc = nr.xpath(\n '//div[@id=\"productDescription\"]/*[@class=\"content\"]')\n if desc:\n ans += self._render_comments(desc[0])\n except Exception as e:\n self.log.warn(\n 'Parsing of obfuscated product description failed with error: %s' % as_unicode(e))\n else:\n desc = root.xpath('//div[@id=\"productDescription_fullView\"]')\n if desc:\n ans += self._render_comments(desc[0])\n\n return ans\n\n def parse_series(self, root):\n ans = (None, None)\n\n # This is found on the paperback/hardback pages for books on amazon.com\n series = root.xpath('//div[@data-feature-name=\"seriesTitle\"]')\n if series:\n series = series[0]\n spans = series.xpath('./span')\n if spans:\n raw = self.tostring(\n spans[0], encoding='unicode', method='text', with_tail=False).strip()\n m = re.search(r'\\s+([0-9.]+)$', raw.strip())\n if m is not None:\n series_index = float(m.group(1))\n s = series.xpath('./a[@id=\"series-page-link\"]')\n if s:\n series = self.tostring(\n s[0], encoding='unicode', method='text', with_tail=False).strip()\n if series:\n ans = (series, series_index)\n else:\n series = root.xpath('//div[@id=\"seriesBulletWidget_feature_div\"]')\n if series:\n a = series[0].xpath('descendant::a')\n if a:\n raw = self.tostring(a[0], encoding='unicode', method='text', with_tail=False)\n if self.domain == 'jp':\n m = re.search(r'(?P<index>[0-9.]+)\\s*(?:巻|冊)\\s*\\(全\\s*([0-9.]+)\\s*(?:巻|冊)\\):\\s*(?P<series>.+)', raw.strip())\n else:\n m = re.search(r'(?:Book|Libro|Buch)\\s+(?P<index>[0-9.]+)\\s+(?:of|de|von)\\s+([0-9.]+)\\s*:\\s*(?P<series>.+)', raw.strip())\n if m is not None:\n ans = (m.group('series').strip(), float(m.group('index')))\n\n # This is found on Kindle edition pages on amazon.com\n if ans == (None, None):\n for span in root.xpath('//div[@id=\"aboutEbooksSection\"]//li/span'):\n text = (span.text or '').strip()\n m = re.match(r'Book\\s+([0-9.]+)', text)\n if m is not None:\n series_index = float(m.group(1))\n a = span.xpath('./a[@href]')\n if a:\n series = self.tostring(\n a[0], encoding='unicode', method='text', with_tail=False).strip()\n if series:\n ans = (series, series_index)\n # This is found on newer Kindle edition pages on amazon.com\n if ans == (None, None):\n for b in root.xpath('//div[@id=\"reviewFeatureGroup\"]/span/b'):\n text = (b.text or '').strip()\n m = re.match(r'Book\\s+([0-9.]+)', text)\n if m is not None:\n series_index = float(m.group(1))\n a = b.getparent().xpath('./a[@href]')\n if a:\n series = self.tostring(\n a[0], encoding='unicode', method='text', with_tail=False).partition('(')[0].strip()\n if series:\n ans = series, series_index\n\n if ans == (None, None):\n desc = root.xpath('//div[@id=\"ps-content\"]/div[@class=\"buying\"]')\n if desc:\n raw = self.tostring(desc[0], method='text', encoding='unicode')\n raw = re.sub(r'\\s+', ' ', raw)\n match = self.series_pat.search(raw)\n if match is not None:\n s, i = match.group('series'), float(match.group('index'))\n if s:\n ans = (s, i)\n if ans[0]:\n ans = (re.sub(r'\\s+Series$', '', ans[0]).strip(), ans[1])\n ans = (re.sub(r'\\(.+?\\s+Series\\)$', '', ans[0]).strip(), ans[1])\n return ans\n\n def parse_tags(self, root):\n ans = []\n exclude_tokens = {'kindle', 'a-z'}\n exclude = {'special features', 'by authors',\n 'authors & illustrators', 'books', 'new; used & rental textbooks'}\n seen = set()\n for li in root.xpath(self.tags_xpath):\n for i, a in enumerate(li.iterdescendants('a')):\n if i > 0:\n # we ignore the first category since it is almost always\n # too broad\n raw = (a.text or '').strip().replace(',', ';')\n lraw = icu_lower(raw)\n tokens = frozenset(lraw.split())\n if raw and lraw not in exclude and not tokens.intersection(exclude_tokens) and lraw not in seen:\n ans.append(raw)\n seen.add(lraw)\n return ans\n\n def parse_cover(self, root, raw=b\"\"):\n # Look for the image URL in javascript, using the first image in the\n # image gallery as the cover\n import json\n imgpat = re.compile(r\"\"\"'imageGalleryData'\\s*:\\s*(\\[\\s*{.+])\"\"\")\n for script in root.xpath('//script'):\n m = imgpat.search(script.text or '')\n if m is not None:\n try:\n return json.loads(m.group(1))[0]['mainUrl']\n except Exception:\n continue\n\n def clean_img_src(src):\n parts = src.split('/')\n if len(parts) > 3:\n bn = parts[-1]\n sparts = bn.split('_')\n if len(sparts) > 2:\n bn = re.sub(r'\\.\\.jpg$', '.jpg', (sparts[0] + sparts[-1]))\n return ('/'.join(parts[:-1])) + '/' + bn\n\n imgpat2 = re.compile(r'var imageSrc = \"([^\"]+)\"')\n for script in root.xpath('//script'):\n m = imgpat2.search(script.text or '')\n if m is not None:\n src = m.group(1)\n url = clean_img_src(src)\n if url:\n return url\n\n imgs = root.xpath(\n '//img[(@id=\"prodImage\" or @id=\"original-main-image\" or @id=\"main-image\" or @id=\"main-image-nonjs\") and @src]')\n if not imgs:\n imgs = (\n root.xpath('//div[@class=\"main-image-inner-wrapper\"]/img[@src]') or\n root.xpath('//div[@id=\"main-image-container\" or @id=\"ebooks-main-image-container\"]//img[@src]') or\n root.xpath(\n '//div[@id=\"mainImageContainer\"]//img[@data-a-dynamic-image]')\n )\n for img in imgs:\n try:\n idata = json.loads(img.get('data-a-dynamic-image'))\n except Exception:\n imgs = ()\n else:\n mwidth = 0\n try:\n url = None\n for iurl, (width, height) in idata.items():\n if width > mwidth:\n mwidth = width\n url = iurl\n return url\n except Exception:\n pass\n\n for img in imgs:\n src = img.get('src')\n if 'data:' in src:\n continue\n if 'loading-' in src:\n js_img = re.search(br'\"largeImage\":\"(https?://[^\"]+)\",', raw)\n if js_img:\n src = js_img.group(1).decode('utf-8')\n if ('/no-image-avail' not in src and 'loading-' not in src and '/no-img-sm' not in src):\n self.log('Found image: %s' % src)\n url = clean_img_src(src)\n if url:\n return url\n\n def parse_detail_bullets(self, root, mi, container):\n ul = next(self.selector('.detail-bullet-list', root=container))\n for span in self.selector('.a-list-item', root=ul):\n cells = span.xpath('./span')\n if len(cells) >= 2:\n self.parse_detail_cells(mi, cells[0], cells[1])\n\n def parse_new_details(self, root, mi, non_hero):\n table = non_hero.xpath('descendant::table')[0]\n for tr in table.xpath('descendant::tr'):\n cells = tr.xpath('descendant::*[local-name()=\"td\" or local-name()=\"th\"]')\n if len(cells) == 2:\n self.parse_detail_cells(mi, cells[0], cells[1])\n\n def parse_detail_cells(self, mi, c1, c2):\n name = self.totext(c1, only_printable=True).strip().strip(':').strip()\n val = self.totext(c2).strip()\n if not val:\n return\n if name in self.language_names:\n ans = self.lang_map.get(val, None)\n if not ans:\n ans = canonicalize_lang(val)\n if ans:\n mi.language = ans\n elif name in self.publisher_names:\n pub = val.partition(';')[0].partition('(')[0].strip()\n if pub:\n mi.publisher = pub\n date = val.rpartition('(')[-1].replace(')', '').strip()\n try:\n from calibre.utils.date import parse_only_date\n date = self.delocalize_datestr(date)\n mi.pubdate = parse_only_date(date, assume_utc=True)\n except:\n self.log.exception('Failed to parse pubdate: %s' % val)\n elif name in {'ISBN', 'ISBN-10', 'ISBN-13'}:\n ans = check_isbn(val)\n if ans:\n self.isbn = mi.isbn = ans\n elif name in {'Publication date'}:\n from calibre.utils.date import parse_only_date\n date = self.delocalize_datestr(val)\n mi.pubdate = parse_only_date(date, assume_utc=True)\n\n def parse_isbn(self, pd):\n items = pd.xpath(\n 'descendant::*[starts-with(text(), \"ISBN\")]')\n if not items:\n items = pd.xpath(\n 'descendant::b[contains(text(), \"ISBN:\")]')\n for x in reversed(items):\n if x.tail:\n ans = check_isbn(x.tail.strip())\n if ans:\n return ans\n\n def parse_publisher(self, pd):\n for x in reversed(pd.xpath(self.publisher_xpath)):\n if x.tail:\n ans = x.tail.partition(';')[0]\n return ans.partition('(')[0].strip()\n\n def parse_pubdate(self, pd):\n from calibre.utils.date import parse_only_date\n for x in reversed(pd.xpath(self.pubdate_xpath)):\n if x.tail:\n date = x.tail.strip()\n date = self.delocalize_datestr(date)\n try:\n return parse_only_date(date, assume_utc=True)\n except Exception:\n pass\n for x in reversed(pd.xpath(self.publisher_xpath)):\n if x.tail:\n ans = x.tail\n date = ans.rpartition('(')[-1].replace(')', '').strip()\n date = self.delocalize_datestr(date)\n try:\n return parse_only_date(date, assume_utc=True)\n except Exception:\n pass\n\n def parse_language(self, pd):\n for x in reversed(pd.xpath(self.language_xpath)):\n if x.tail:\n raw = x.tail.strip().partition(',')[0].strip()\n ans = self.lang_map.get(raw, None)\n if ans:\n return ans\n ans = canonicalize_lang(ans)\n if ans:\n return ans\n# }}}\n\n\nclass Amazon(Source):\n\n name = 'Amazon.com'\n version = (1, 3, 0)\n minimum_calibre_version = (2, 82, 0)\n description = _('Downloads metadata and covers from Amazon')\n\n capabilities = frozenset(('identify', 'cover'))\n touched_fields = frozenset(('title', 'authors', 'identifier:amazon',\n 'rating', 'comments', 'publisher', 'pubdate',\n 'languages', 'series', 'tags'))\n has_html_comments = True\n supports_gzip_transfer_encoding = True\n prefer_results_with_isbn = False\n\n AMAZON_DOMAINS = {\n 'com': _('US'),\n 'fr': _('France'),\n 'de': _('Germany'),\n 'uk': _('UK'),\n 'au': _('Australia'),\n 'it': _('Italy'),\n 'jp': _('Japan'),\n 'es': _('Spain'),\n 'br': _('Brazil'),\n 'in': _('India'),\n 'nl': _('Netherlands'),\n 'cn': _('China'),\n 'ca': _('Canada'),\n 'se': _('Sweden'),\n }\n\n SERVERS = {\n 'auto': _('Choose server automatically'),\n 'amazon': _('Amazon servers'),\n 'bing': _('Bing search cache'),\n 'google': _('Google search cache'),\n 'wayback': _('Wayback machine cache (slow)'),\n 'ddg': _('DuckDuckGo search and Google cache'),\n }\n\n options = (\n Option('domain', 'choices', 'com', _('Amazon country website to use:'),\n _('Metadata from Amazon will be fetched using this '\n 'country\\'s Amazon website.'), choices=AMAZON_DOMAINS),\n Option('server', 'choices', 'auto', _('Server to get data from:'),\n _(\n 'Amazon has started blocking attempts to download'\n ' metadata from its servers. To get around this problem,'\n ' calibre can fetch the Amazon data from many different'\n ' places where it is cached. Choose the source you prefer.'\n ), choices=SERVERS),\n Option('use_mobi_asin', 'bool', False, _('Use the MOBI-ASIN for metadata search'),\n _(\n 'Enable this option to search for metadata with an'\n ' ASIN identifier from the MOBI file at the current country website,'\n ' unless any other amazon id is available. Note that if the'\n ' MOBI file came from a different Amazon country store, you could get'\n ' incorrect results.'\n )),\n Option('prefer_kindle_edition', 'bool', False, _('Prefer the Kindle edition, when available'),\n _(\n 'When searching for a book and the search engine returns both paper and Kindle editions,'\n ' always prefer the Kindle edition, instead of whatever the search engine returns at the'\n ' top.')\n ),\n )\n\n def __init__(self, *args, **kwargs):\n Source.__init__(self, *args, **kwargs)\n self.set_amazon_id_touched_fields()\n\n def id_from_url(self, url):\n from polyglot.urllib import urlparse\n purl = urlparse(url)\n if purl.netloc and purl.path and '/dp/' in purl.path:\n host_parts = tuple(x.lower() for x in purl.netloc.split('.'))\n if 'amazon' in host_parts:\n domain = host_parts[-1]\n parts = purl.path.split('/')\n idx = parts.index('dp')\n try:\n val = parts[idx+1]\n except IndexError:\n return\n aid = 'amazon' if domain == 'com' else ('amazon_' + domain)\n return aid, val\n\n def test_fields(self, mi):\n '''\n Return the first field from self.touched_fields that is null on the\n mi object\n '''\n for key in self.touched_fields:\n if key.startswith('identifier:'):\n key = key.partition(':')[-1]\n if key == 'amazon':\n if self.domain != 'com':\n key += '_' + self.domain\n if not mi.has_identifier(key):\n return 'identifier: ' + key\n elif mi.is_null(key):\n return key\n\n @property\n def browser(self):\n br = self._browser\n if br is None:\n ua = 'Mobile '\n while not user_agent_is_ok(ua):\n ua = random_user_agent(allow_ie=False)\n # ua = 'Mozilla/5.0 (Linux; Android 8.0.0; VTR-L29; rv:63.0) Gecko/20100101 Firefox/63.0'\n self._browser = br = browser(user_agent=ua)\n br.set_handle_gzip(True)\n if self.use_search_engine:\n br.addheaders += [\n ('Accept', accept_header_for_ua(ua)),\n ('Upgrade-insecure-requests', '1'),\n ]\n else:\n br.addheaders += [\n ('Accept', accept_header_for_ua(ua)),\n ('Upgrade-insecure-requests', '1'),\n ('Referer', self.referrer_for_domain()),\n ]\n return br\n\n def save_settings(self, *args, **kwargs):\n Source.save_settings(self, *args, **kwargs)\n self.set_amazon_id_touched_fields()\n\n def set_amazon_id_touched_fields(self):\n ident_name = \"identifier:amazon\"\n if self.domain != 'com':\n ident_name += '_' + self.domain\n tf = [x for x in self.touched_fields if not\n x.startswith('identifier:amazon')] + [ident_name]\n self.touched_fields = frozenset(tf)\n\n def get_domain_and_asin(self, identifiers, extra_domains=()):\n identifiers = {k.lower(): v for k, v in identifiers.items()}\n for key, val in identifiers.items():\n if key in ('amazon', 'asin'):\n return 'com', val\n if key.startswith('amazon_'):\n domain = key.partition('_')[-1]\n if domain and (domain in self.AMAZON_DOMAINS or domain in extra_domains):\n return domain, val\n if self.prefs['use_mobi_asin']:\n val = identifiers.get('mobi-asin')\n if val is not None:\n return self.domain, val\n return None, None\n\n def referrer_for_domain(self, domain=None):\n domain = domain or self.domain\n return {\n 'uk': 'https://www.amazon.co.uk/',\n 'au': 'https://www.amazon.com.au/',\n 'br': 'https://www.amazon.com.br/',\n 'jp': 'https://www.amazon.co.jp/',\n }.get(domain, 'https://www.amazon.%s/' % domain)\n\n def _get_book_url(self, identifiers): # {{{\n domain, asin = self.get_domain_and_asin(\n identifiers, extra_domains=('au', 'ca'))\n if domain and asin:\n url = None\n r = self.referrer_for_domain(domain)\n if r is not None:\n url = r + 'dp/' + asin\n if url:\n idtype = 'amazon' if domain == 'com' else 'amazon_' + domain\n return domain, idtype, asin, url\n\n def get_book_url(self, identifiers):\n ans = self._get_book_url(identifiers)\n if ans is not None:\n return ans[1:]\n\n def get_book_url_name(self, idtype, idval, url):\n if idtype == 'amazon':\n return self.name\n return 'A' + idtype.replace('_', '.')[1:]\n # }}}\n\n @property\n def domain(self):\n x = getattr(self, 'testing_domain', None)\n if x is not None:\n return x\n domain = self.prefs['domain']\n if domain not in self.AMAZON_DOMAINS:\n domain = 'com'\n\n return domain\n\n @property\n def server(self):\n x = getattr(self, 'testing_server', None)\n if x is not None:\n return x\n server = self.prefs['server']\n if server not in self.SERVERS:\n server = 'auto'\n return server\n\n @property\n def use_search_engine(self):\n return self.server != 'amazon'\n\n def clean_downloaded_metadata(self, mi):\n docase = (\n mi.language == 'eng' or\n (mi.is_null('language') and self.domain in {'com', 'uk', 'au'})\n )\n if mi.title and docase:\n # Remove series information from title\n m = re.search(r'\\S+\\s+(\\(.+?\\s+Book\\s+\\d+\\))$', mi.title)\n if m is not None:\n mi.title = mi.title.replace(m.group(1), '').strip()\n mi.title = fixcase(mi.title)\n mi.authors = fixauthors(mi.authors)\n if mi.tags and docase:\n mi.tags = list(map(fixcase, mi.tags))\n mi.isbn = check_isbn(mi.isbn)\n if mi.series and docase:\n mi.series = fixcase(mi.series)\n if mi.title and mi.series:\n for pat in (r':\\s*Book\\s+\\d+\\s+of\\s+%s$', r'\\(%s\\)$', r':\\s*%s\\s+Book\\s+\\d+$'):\n pat = pat % re.escape(mi.series)\n q = re.sub(pat, '', mi.title, flags=re.I).strip()\n if q and q != mi.title:\n mi.title = q\n break\n\n def get_website_domain(self, domain):\n return {'uk': 'co.uk', 'jp': 'co.jp', 'br': 'com.br', 'au': 'com.au'}.get(domain, domain)\n\n def create_query(self, log, title=None, authors=None, identifiers={}, # {{{\n domain=None, for_amazon=True):\n try:\n from urllib.parse import urlencode, unquote_plus\n except ImportError:\n from urllib import urlencode, unquote_plus\n if domain is None:\n domain = self.domain\n\n idomain, asin = self.get_domain_and_asin(identifiers)\n if idomain is not None:\n domain = idomain\n\n # See the amazon detailed search page to get all options\n terms = []\n q = {'search-alias': 'aps',\n 'unfiltered': '1',\n }\n\n if domain == 'com':\n q['sort'] = 'relevanceexprank'\n else:\n q['sort'] = 'relevancerank'\n\n isbn = check_isbn(identifiers.get('isbn', None))\n\n if asin is not None:\n q['field-keywords'] = asin\n terms.append(asin)\n elif isbn is not None:\n q['field-isbn'] = isbn\n if len(isbn) == 13:\n terms.extend('({} OR {}-{})'.format(isbn, isbn[:3], isbn[3:]).split())\n else:\n terms.append(isbn)\n else:\n # Only return book results\n q['search-alias'] = {'br': 'digital-text',\n 'nl': 'aps'}.get(domain, 'stripbooks')\n if title:\n title_tokens = list(self.get_title_tokens(title))\n if title_tokens:\n q['field-title'] = ' '.join(title_tokens)\n terms.extend(title_tokens)\n if authors:\n author_tokens = list(self.get_author_tokens(authors,\n only_first_author=True))\n if author_tokens:\n q['field-author'] = ' '.join(author_tokens)\n terms.extend(author_tokens)\n\n if not ('field-keywords' in q or 'field-isbn' in q or\n ('field-title' in q)):\n # Insufficient metadata to make an identify query\n return None, None\n\n if not for_amazon:\n return terms, domain\n\n if domain == 'nl':\n q['__mk_nl_NL'] = 'ÅMÅŽÕÑ'\n if 'field-keywords' not in q:\n q['field-keywords'] = ''\n for f in 'field-isbn field-title field-author'.split():\n q['field-keywords'] += ' ' + q.pop(f, '')\n q['field-keywords'] = q['field-keywords'].strip()\n\n encoded_q = dict([(x.encode('utf-8', 'ignore'), y.encode(\n 'utf-8', 'ignore')) for x, y in q.items()])\n url_query = urlencode(encoded_q)\n # amazon's servers want IRIs with unicode characters not percent esaped\n parts = []\n for x in url_query.split(b'&' if isinstance(url_query, bytes) else '&'):\n k, v = x.split(b'=' if isinstance(x, bytes) else '=', 1)\n parts.append('{}={}'.format(iri_quote_plus(unquote_plus(k)), iri_quote_plus(unquote_plus(v))))\n url_query = '&'.join(parts)\n url = 'https://www.amazon.%s/s/?' % self.get_website_domain(\n domain) + url_query\n return url, domain\n\n # }}}\n\n def get_cached_cover_url(self, identifiers): # {{{\n url = None\n domain, asin = self.get_domain_and_asin(identifiers)\n if asin is None:\n isbn = identifiers.get('isbn', None)\n if isbn is not None:\n asin = self.cached_isbn_to_identifier(isbn)\n if asin is not None:\n url = self.cached_identifier_to_cover_url(asin)\n\n return url\n # }}}\n\n def parse_results_page(self, root, domain): # {{{\n from lxml.html import tostring\n\n matches = []\n\n def title_ok(title):\n title = title.lower()\n bad = ['bulk pack', '[audiobook]', '[audio cd]',\n '(a book companion)', '( slipcase with door )', ': free sampler']\n if self.domain == 'com':\n bad.extend(['(%s edition)' % x for x in ('spanish', 'german')])\n for x in bad:\n if x in title:\n return False\n if title and title[0] in '[{' and re.search(r'\\(\\s*author\\s*\\)', title) is not None:\n # Bad entries in the catalog\n return False\n return True\n\n for query in (\n '//div[contains(@class, \"s-result-list\")]//h2/a[@href]',\n '//div[contains(@class, \"s-result-list\")]//div[@data-index]//h5//a[@href]',\n r'//li[starts-with(@id, \"result_\")]//a[@href and contains(@class, \"s-access-detail-page\")]',\n ):\n result_links = root.xpath(query)\n if result_links:\n break\n for a in result_links:\n title = tostring(a, method='text', encoding='unicode')\n if title_ok(title):\n url = a.get('href')\n if url.startswith('/'):\n url = 'https://www.amazon.%s%s' % (\n self.get_website_domain(domain), url)\n matches.append(url)\n\n if not matches:\n # Previous generation of results page markup\n for div in root.xpath(r'//div[starts-with(@id, \"result_\")]'):\n links = div.xpath(r'descendant::a[@class=\"title\" and @href]')\n if not links:\n # New amazon markup\n links = div.xpath('descendant::h3/a[@href]')\n for a in links:\n title = tostring(a, method='text', encoding='unicode')\n if title_ok(title):\n url = a.get('href')\n if url.startswith('/'):\n url = 'https://www.amazon.%s%s' % (\n self.get_website_domain(domain), url)\n matches.append(url)\n break\n\n if not matches:\n # This can happen for some user agents that Amazon thinks are\n # mobile/less capable\n for td in root.xpath(\n r'//div[@id=\"Results\"]/descendant::td[starts-with(@id, \"search:Td:\")]'):\n for a in td.xpath(r'descendant::td[@class=\"dataColumn\"]/descendant::a[@href]/span[@class=\"srTitle\"]/..'):\n title = tostring(a, method='text', encoding='unicode')\n if title_ok(title):\n url = a.get('href')\n if url.startswith('/'):\n url = 'https://www.amazon.%s%s' % (\n self.get_website_domain(domain), url)\n matches.append(url)\n break\n if not matches and root.xpath('//form[@action=\"/errors/validateCaptcha\"]'):\n raise CaptchaError('Amazon returned a CAPTCHA page. Recently Amazon has begun using statistical'\n ' profiling to block access to its website. As such this metadata plugin is'\n ' unlikely to ever work reliably.')\n\n # Keep only the top 3 matches as the matches are sorted by relevance by\n # Amazon so lower matches are not likely to be very relevant\n return matches[:3]\n # }}}\n\n def search_amazon(self, br, testing, log, abort, title, authors, identifiers, timeout): # {{{\n from calibre.utils.cleantext import clean_ascii_chars\n from calibre.ebooks.chardet import xml_to_unicode\n matches = []\n query, domain = self.create_query(log, title=title, authors=authors,\n identifiers=identifiers)\n if query is None:\n log.error('Insufficient metadata to construct query')\n raise SearchFailed()\n try:\n raw = br.open_novisit(query, timeout=timeout).read().strip()\n except Exception as e:\n if callable(getattr(e, 'getcode', None)) and \\\n e.getcode() == 404:\n log.error('Query malformed: %r' % query)\n raise SearchFailed()\n attr = getattr(e, 'args', [None])\n attr = attr if attr else [None]\n if isinstance(attr[0], socket.timeout):\n msg = _('Amazon timed out. Try again later.')\n log.error(msg)\n else:\n msg = 'Failed to make identify query: %r' % query\n log.exception(msg)\n raise SearchFailed()\n\n raw = clean_ascii_chars(xml_to_unicode(raw,\n strip_encoding_pats=True, resolve_entities=True)[0])\n\n if testing:\n import tempfile\n with tempfile.NamedTemporaryFile(prefix='amazon_results_',\n suffix='.html', delete=False) as f:\n f.write(raw.encode('utf-8'))\n print('Downloaded html for results page saved in', f.name)\n\n matches = []\n found = '<title>404 - ' not in raw\n\n if found:\n try:\n root = parse_html(raw)\n except Exception:\n msg = 'Failed to parse amazon page for query: %r' % query\n log.exception(msg)\n raise SearchFailed()\n\n matches = self.parse_results_page(root, domain)\n\n return matches, query, domain, None\n # }}}\n\n def search_search_engine(self, br, testing, log, abort, title, authors, identifiers, timeout, override_server=None): # {{{\n from calibre.ebooks.metadata.sources.update import search_engines_module\n se = search_engines_module()\n terms, domain = self.create_query(log, title=title, authors=authors,\n identifiers=identifiers, for_amazon=False)\n site = self.referrer_for_domain(\n domain)[len('https://'):].partition('/')[0]\n matches = []\n server = override_server or self.server\n urlproc, sfunc = se.google_url_processor, se.google_search\n if server == 'bing':\n urlproc, sfunc = se.bing_url_processor, se.bing_search\n elif server == 'wayback':\n urlproc, sfunc = se.wayback_url_processor, se.ddg_search\n elif server == 'ddg':\n urlproc, sfunc = se.ddg_url_processor, se.ddg_search\n try:\n results, qurl = sfunc(terms, site, log=log, br=br, timeout=timeout)\n except HTTPError as err:\n if err.code == 429 and sfunc is se.google_search:\n log('Got too many requests error from Google, trying via DuckDuckGo')\n urlproc, sfunc = se.ddg_url_processor, se.ddg_search\n results, qurl = sfunc(terms, site, log=log, br=br, timeout=timeout)\n else:\n raise\n\n br.set_current_header('Referer', qurl)\n for result in results:\n if abort.is_set():\n return matches, terms, domain, None\n\n purl = urlparse(result.url)\n if '/dp/' in purl.path and site in purl.netloc:\n url = result.cached_url\n if url is None:\n url = se.get_cached_url(result.url, br, timeout=timeout)\n if url is None:\n log('Failed to find cached page for:', result.url)\n continue\n if url not in matches:\n matches.append(url)\n if len(matches) >= 3:\n break\n else:\n log('Skipping non-book result:', result)\n if not matches:\n log('No search engine results for terms:', ' '.join(terms))\n if urlproc is se.google_url_processor:\n # Google does not cache adult titles\n log('Trying the bing search engine instead')\n return self.search_search_engine(br, testing, log, abort, title, authors, identifiers, timeout, 'bing')\n return matches, terms, domain, urlproc\n # }}}\n\n def identify(self, log, result_queue, abort, title=None, authors=None, # {{{\n identifiers={}, timeout=60):\n '''\n Note this method will retry without identifiers automatically if no\n match is found with identifiers.\n '''\n\n testing = getattr(self, 'running_a_test', False)\n\n udata = self._get_book_url(identifiers)\n br = self.browser\n log('User-agent:', br.current_user_agent())\n log('Server:', self.server)\n if testing:\n print('User-agent:', br.current_user_agent())\n if udata is not None and not self.use_search_engine:\n # Try to directly get details page instead of running a search\n # Cannot use search engine as the directly constructed URL is\n # usually redirected to a full URL by amazon, and is therefore\n # not cached\n domain, idtype, asin, durl = udata\n if durl is not None:\n preparsed_root = parse_details_page(\n durl, log, timeout, br, domain)\n if preparsed_root is not None:\n qasin = parse_asin(preparsed_root[1], log, durl)\n if qasin == asin:\n w = Worker(durl, result_queue, br, log, 0, domain,\n self, testing=testing, preparsed_root=preparsed_root, timeout=timeout)\n try:\n w.get_details()\n return\n except Exception:\n log.exception(\n 'get_details failed for url: %r' % durl)\n func = self.search_search_engine if self.use_search_engine else self.search_amazon\n try:\n matches, query, domain, cover_url_processor = func(\n br, testing, log, abort, title, authors, identifiers, timeout)\n except SearchFailed:\n return\n\n if abort.is_set():\n return\n\n if not matches:\n if identifiers and title and authors:\n log('No matches found with identifiers, retrying using only'\n ' title and authors. Query: %r' % query)\n time.sleep(1)\n return self.identify(log, result_queue, abort, title=title,\n authors=authors, timeout=timeout)\n log.error('No matches found with query: %r' % query)\n return\n\n if self.prefs['prefer_kindle_edition']:\n matches = sort_matches_preferring_kindle_editions(matches)\n\n workers = [Worker(\n url, result_queue, br, log, i, domain, self, testing=testing, timeout=timeout,\n cover_url_processor=cover_url_processor, filter_result=partial(\n self.filter_result, title, authors, identifiers)) for i, url in enumerate(matches)]\n\n for w in workers:\n # Don't send all requests at the same time\n time.sleep(1)\n w.start()\n if abort.is_set():\n return\n\n while not abort.is_set():\n a_worker_is_alive = False\n for w in workers:\n w.join(0.2)\n if abort.is_set():\n break\n if w.is_alive():\n a_worker_is_alive = True\n if not a_worker_is_alive:\n break\n\n return None\n # }}}\n\n def filter_result(self, title, authors, identifiers, mi, log): # {{{\n if not self.use_search_engine:\n return True\n if title is not None:\n\n def tokenize_title(x):\n return icu_lower(x).replace(\"'\", '').replace('\"', '').rstrip(':')\n\n tokens = {tokenize_title(x) for x in title.split() if len(x) > 3}\n if tokens:\n result_tokens = {tokenize_title(x) for x in mi.title.split()}\n if not tokens.intersection(result_tokens):\n log('Ignoring result:', mi.title, 'as its title does not match')\n return False\n if authors:\n author_tokens = set()\n for author in authors:\n author_tokens |= {icu_lower(x) for x in author.split() if len(x) > 2}\n result_tokens = set()\n for author in mi.authors:\n result_tokens |= {icu_lower(x) for x in author.split() if len(x) > 2}\n if author_tokens and not author_tokens.intersection(result_tokens):\n log('Ignoring result:', mi.title, 'by', ' & '.join(mi.authors), 'as its author does not match')\n return False\n return True\n # }}}\n\n def download_cover(self, log, result_queue, abort, # {{{\n title=None, authors=None, identifiers={}, timeout=60, get_best_cover=False):\n cached_url = self.get_cached_cover_url(identifiers)\n if cached_url is None:\n log.info('No cached cover found, running identify')\n rq = Queue()\n self.identify(log, rq, abort, title=title, authors=authors,\n identifiers=identifiers)\n if abort.is_set():\n return\n if abort.is_set():\n return\n results = []\n while True:\n try:\n results.append(rq.get_nowait())\n except Empty:\n break\n results.sort(key=self.identify_results_keygen(\n title=title, authors=authors, identifiers=identifiers))\n for mi in results:\n cached_url = self.get_cached_cover_url(mi.identifiers)\n if cached_url is not None:\n break\n if cached_url is None:\n log.info('No cover found')\n return\n\n if abort.is_set():\n return\n log('Downloading cover from:', cached_url)\n br = self.browser\n if self.use_search_engine:\n br = br.clone_browser()\n br.set_current_header('Referer', self.referrer_for_domain(self.domain))\n try:\n time.sleep(1)\n cdata = br.open_novisit(\n cached_url, timeout=timeout).read()\n result_queue.put((self, cdata))\n except:\n log.exception('Failed to download cover from:', cached_url)\n # }}}\n\n\ndef manual_tests(domain, **kw): # {{{\n # To run these test use:\n # calibre-debug -c \"from calibre.ebooks.metadata.sources.amazon import *; manual_tests('com')\"\n from calibre.ebooks.metadata.sources.test import (test_identify_plugin,\n isbn_test, title_test, authors_test, comments_test, series_test)\n all_tests = {}\n all_tests['com'] = [ # {{{\n ( # Paperback with series\n {'identifiers': {'amazon': '1423146786'}},\n [title_test('The Heroes of Olympus, Book Five The Blood of Olympus',\n exact=True), series_test('The Heroes of Olympus', 5)]\n ),\n\n ( # Kindle edition with series\n {'identifiers': {'amazon': 'B0085UEQDO'}},\n [title_test('Three Parts Dead', exact=True),\n series_test('Craft Sequence', 1)]\n ),\n\n ( # + in title and uses id=\"main-image\" for cover\n {'identifiers': {'amazon': '1933988770'}},\n [title_test(\n 'C++ Concurrency in Action: Practical Multithreading', exact=True)]\n ),\n\n\n ( # Different comments markup, using Book Description section\n {'identifiers': {'amazon': '0982514506'}},\n [title_test(\n \"Griffin's Destiny: Book Three: The Griffin's Daughter Trilogy\",\n exact=True),\n comments_test('Jelena'), comments_test('Ashinji'),\n ]\n ),\n\n ( # # in title\n {'title': 'Expert C# 2008 Business Objects',\n 'authors': ['Lhotka']},\n [title_test('Expert C#'),\n authors_test(['Rockford Lhotka'])\n ]\n ),\n\n ( # No specific problems\n {'identifiers': {'isbn': '0743273567'}},\n [title_test('the great gatsby: the only authorized edition', exact=True),\n authors_test(['Francis Scott Fitzgerald'])]\n ),\n\n ]\n\n # }}}\n\n all_tests['de'] = [ # {{{\n # series\n (\n {'identifiers': {'isbn': '3499275120'}},\n [title_test('Vespasian: Das Schwert des Tribuns: Historischer Roman',\n exact=False), authors_test(['Robert Fabbri']), series_test('Die Vespasian-Reihe', 1)\n ]\n\n ),\n\n ( # umlaut in title/authors\n {'title': 'Flüsternde Wälder',\n 'authors': ['Nicola Förg']},\n [title_test('Flüsternde Wälder'),\n authors_test(['Nicola Förg'], subset=True)\n ]\n ),\n\n (\n {'identifiers': {'isbn': '9783453314979'}},\n [title_test('Die letzten Wächter: Roman',\n exact=False), authors_test(['Sergej Lukianenko'])\n ]\n\n ),\n\n (\n {'identifiers': {'isbn': '3548283519'}},\n [title_test('Wer Wind Sät: Der Fünfte Fall Für Bodenstein Und Kirchhoff',\n exact=False), authors_test(['Nele Neuhaus'])\n ]\n\n ),\n ] # }}}\n\n all_tests['it'] = [ # {{{\n (\n {'identifiers': {'isbn': '8838922195'}},\n [title_test('La briscola in cinque',\n exact=True), authors_test(['Marco Malvaldi'])\n ]\n\n ),\n ] # }}}\n\n all_tests['fr'] = [ # {{{\n (\n {'identifiers': {'amazon_fr': 'B07L7ST4RS'}},\n [title_test('Le secret de Lola', exact=True),\n authors_test(['Amélie BRIZIO'])\n ]\n ),\n (\n {'identifiers': {'isbn': '2221116798'}},\n [title_test('L\\'étrange voyage de Monsieur Daldry',\n exact=True), authors_test(['Marc Levy'])\n ]\n\n ),\n ] # }}}\n\n all_tests['es'] = [ # {{{\n (\n {'identifiers': {'isbn': '8483460831'}},\n [title_test('Tiempos Interesantes',\n exact=False), authors_test(['Terry Pratchett'])\n ]\n\n ),\n ] # }}}\n\n all_tests['se'] = [ # {{{\n (\n {'identifiers': {'isbn': '9780552140287'}},\n [title_test('Men At Arms: A Discworld Novel: 14',\n exact=False), authors_test(['Terry Pratchett'])\n ]\n\n ),\n ] # }}}\n\n all_tests['jp'] = [ # {{{\n ( # Adult filtering test\n {'identifiers': {'isbn': '4799500066'}},\n [title_test('Bitch Trap'), ]\n ),\n\n ( # isbn -> title, authors\n {'identifiers': {'isbn': '9784101302720'}},\n [title_test('精霊の守り人',\n exact=True), authors_test(['上橋 菜穂子'])\n ]\n ),\n ( # title, authors -> isbn (will use Shift_JIS encoding in query.)\n {'title': '考えない練習',\n 'authors': ['小池 龍之介']},\n [isbn_test('9784093881067'), ]\n ),\n ] # }}}\n\n all_tests['br'] = [ # {{{\n (\n {'title': 'Guerra dos Tronos'},\n [title_test('A Guerra dos Tronos - As Crônicas de Gelo e Fogo',\n exact=True), authors_test(['George R. R. Martin'])\n ]\n\n ),\n ] # }}}\n\n all_tests['nl'] = [ # {{{\n (\n {'title': 'Freakonomics'},\n [title_test('Freakonomics',\n exact=True), authors_test(['Steven Levitt & Stephen Dubner & R. Kuitenbrouwer & O. Brenninkmeijer & A. van Den Berg'])\n ]\n\n ),\n ] # }}}\n\n all_tests['cn'] = [ # {{{\n (\n {'identifiers': {'isbn': '9787115369512'}},\n [title_test('若为自由故 自由软件之父理查德斯托曼传', exact=True),\n authors_test(['[美]sam Williams', '邓楠,李凡希'])]\n ),\n (\n {'title': '爱上Raspberry Pi'},\n [title_test('爱上Raspberry Pi',\n exact=True), authors_test(['Matt Richardson', 'Shawn Wallace', '李凡希'])\n ]\n\n ),\n ] # }}}\n\n all_tests['ca'] = [ # {{{\n ( # Paperback with series\n {'identifiers': {'isbn': '9781623808747'}},\n [title_test('Parting Shot', exact=True),\n authors_test(['Mary Calmes'])]\n ),\n ( # # in title\n {'title': 'Expert C# 2008 Business Objects',\n 'authors': ['Lhotka']},\n [title_test('Expert C# 2008 Business Objects'),\n authors_test(['Rockford Lhotka'])]\n ),\n ( # noscript description\n {'identifiers': {'amazon_ca': '162380874X'}},\n [title_test('Parting Shot', exact=True), authors_test(['Mary Calmes'])\n ]\n ),\n ] # }}}\n\n all_tests['in'] = [ # {{{\n ( # Paperback with series\n {'identifiers': {'amazon_in': '1423146786'}},\n [title_test('The Heroes of Olympus, Book Five The Blood of Olympus', exact=True)]\n ),\n ] # }}}\n\n def do_test(domain, start=0, stop=None, server='auto'):\n tests = all_tests[domain]\n if stop is None:\n stop = len(tests)\n tests = tests[start:stop]\n test_identify_plugin(Amazon.name, tests, modify_plugin=lambda p: (\n setattr(p, 'testing_domain', domain),\n setattr(p, 'touched_fields', p.touched_fields - {'tags'}),\n setattr(p, 'testing_server', server),\n ))\n\n do_test(domain, **kw)\n# }}}\n", + "big_book_search": "#!/usr/bin/env python\n# vim:fileencoding=UTF-8\nfrom __future__ import absolute_import, division, print_function, unicode_literals\n\n__license__ = 'GPL v3'\n__copyright__ = '2013, Kovid Goyal <kovid@kovidgoyal.net>'\n__docformat__ = 'restructuredtext en'\n\nfrom calibre.ebooks.metadata.sources.base import Source, Option\n\n\ndef get_urls(br, tokens):\n from urllib.parse import quote_plus\n from html5_parser import parse\n escaped = (quote_plus(x) for x in tokens if x and x.strip())\n q = '+'.join(escaped)\n url = 'https://bigbooksearch.com/please-dont-scrape-my-site-you-will-put-my-api-key-over-the-usage-limit-and-the-site-will-break/books/'+q\n raw = br.open(url).read()\n root = parse(raw.decode('utf-8'))\n urls = [i.get('src') for i in root.xpath('//img[@src]')]\n return urls\n\n\nclass BigBookSearch(Source):\n\n name = 'Big Book Search'\n version = (1, 0, 1)\n minimum_calibre_version = (2, 80, 0)\n description = _('Downloads multiple book covers from Amazon. Useful to find alternate covers.')\n capabilities = frozenset(['cover'])\n can_get_multiple_covers = True\n options = (Option('max_covers', 'number', 5, _('Maximum number of covers to get'),\n _('The maximum number of covers to process from the search result')),\n )\n supports_gzip_transfer_encoding = True\n\n def download_cover(self, log, result_queue, abort,\n title=None, authors=None, identifiers={}, timeout=30, get_best_cover=False):\n if not title:\n return\n br = self.browser\n tokens = tuple(self.get_title_tokens(title)) + tuple(self.get_author_tokens(authors))\n urls = get_urls(br, tokens)\n self.download_multiple_covers(title, authors, urls, get_best_cover, timeout, result_queue, abort, log)\n\n\ndef test():\n from calibre import browser\n import pprint\n br = browser()\n urls = get_urls(br, ['consider', 'phlebas', 'banks'])\n pprint.pprint(urls)\n\n\nif __name__ == '__main__':\n test()\n", + "edelweiss": "#!/usr/bin/env python\n# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:fdm=marker:ai\nfrom __future__ import absolute_import, division, print_function, unicode_literals\n\n__license__ = 'GPL v3'\n__copyright__ = '2013, Kovid Goyal <kovid at kovidgoyal.net>'\n__docformat__ = 'restructuredtext en'\n\nimport time, re\nfrom threading import Thread\ntry:\n from queue import Empty, Queue\nexcept ImportError:\n from Queue import Empty, Queue\n\nfrom calibre import as_unicode, random_user_agent\nfrom calibre.ebooks.metadata import check_isbn\nfrom calibre.ebooks.metadata.sources.base import Source\n\n\ndef clean_html(raw):\n from calibre.ebooks.chardet import xml_to_unicode\n from calibre.utils.cleantext import clean_ascii_chars\n return clean_ascii_chars(xml_to_unicode(raw, strip_encoding_pats=True,\n resolve_entities=True, assume_utf8=True)[0])\n\n\ndef parse_html(raw):\n raw = clean_html(raw)\n from html5_parser import parse\n return parse(raw)\n\n\ndef astext(node):\n from lxml import etree\n return etree.tostring(node, method='text', encoding='unicode',\n with_tail=False).strip()\n\n\nclass Worker(Thread): # {{{\n\n def __init__(self, basic_data, relevance, result_queue, br, timeout, log, plugin):\n Thread.__init__(self)\n self.daemon = True\n self.basic_data = basic_data\n self.br, self.log, self.timeout = br, log, timeout\n self.result_queue, self.plugin, self.sku = result_queue, plugin, self.basic_data['sku']\n self.relevance = relevance\n\n def run(self):\n url = ('https://www.edelweiss.plus/GetTreelineControl.aspx?controlName=/uc/product/two_Enhanced.ascx&'\n 'sku={0}&idPrefix=content_1_{0}&mode=0'.format(self.sku))\n try:\n raw = self.br.open_novisit(url, timeout=self.timeout).read()\n except:\n self.log.exception('Failed to load comments page: %r'%url)\n return\n\n try:\n mi = self.parse(raw)\n mi.source_relevance = self.relevance\n self.plugin.clean_downloaded_metadata(mi)\n self.result_queue.put(mi)\n except:\n self.log.exception('Failed to parse details for sku: %s'%self.sku)\n\n def parse(self, raw):\n from calibre.ebooks.metadata.book.base import Metadata\n from calibre.utils.date import UNDEFINED_DATE\n root = parse_html(raw)\n mi = Metadata(self.basic_data['title'], self.basic_data['authors'])\n\n # Identifiers\n if self.basic_data['isbns']:\n mi.isbn = self.basic_data['isbns'][0]\n mi.set_identifier('edelweiss', self.sku)\n\n # Tags\n if self.basic_data['tags']:\n mi.tags = self.basic_data['tags']\n mi.tags = [t[1:].strip() if t.startswith('&') else t for t in mi.tags]\n\n # Publisher\n mi.publisher = self.basic_data['publisher']\n\n # Pubdate\n if self.basic_data['pubdate'] and self.basic_data['pubdate'].year != UNDEFINED_DATE:\n mi.pubdate = self.basic_data['pubdate']\n\n # Rating\n if self.basic_data['rating']:\n mi.rating = self.basic_data['rating']\n\n # Comments\n comments = ''\n for cid in ('summary', 'contributorbio', 'quotes_reviews'):\n cid = 'desc_{}{}-content'.format(cid, self.sku)\n div = root.xpath('//*[@id=\"{}\"]'.format(cid))\n if div:\n comments += self.render_comments(div[0])\n if comments:\n mi.comments = comments\n\n mi.has_cover = self.plugin.cached_identifier_to_cover_url(self.sku) is not None\n return mi\n\n def render_comments(self, desc):\n from lxml import etree\n from calibre.library.comments import sanitize_comments_html\n for c in desc.xpath('descendant::noscript'):\n c.getparent().remove(c)\n for a in desc.xpath('descendant::a[@href]'):\n del a.attrib['href']\n a.tag = 'span'\n desc = etree.tostring(desc, method='html', encoding='unicode').strip()\n\n # remove all attributes from tags\n desc = re.sub(r'<([a-zA-Z0-9]+)\\s[^>]+>', r'<\\1>', desc)\n # Collapse whitespace\n # desc = re.sub('\\n+', '\\n', desc)\n # desc = re.sub(' +', ' ', desc)\n # Remove comments\n desc = re.sub(r'(?s)<!--.*?-->', '', desc)\n return sanitize_comments_html(desc)\n# }}}\n\n\ndef get_basic_data(browser, log, *skus):\n from calibre.utils.date import parse_only_date\n from mechanize import Request\n zeroes = ','.join('0' for sku in skus)\n data = {\n 'skus': ','.join(skus),\n 'drc': zeroes,\n 'startPosition': '0',\n 'sequence': '1',\n 'selected': zeroes,\n 'itemID': '0',\n 'orderID': '0',\n 'mailingID': '',\n 'tContentWidth': '926',\n 'originalOrder': ','.join(type('')(i) for i in range(len(skus))),\n 'selectedOrderID': '0',\n 'selectedSortColumn': '0',\n 'listType': '1',\n 'resultType': '32',\n 'blockView': '1',\n }\n items_data_url = 'https://www.edelweiss.plus/GetTreelineControl.aspx?controlName=/uc/listviews/ListView_Title_Multi.ascx'\n req = Request(items_data_url, data)\n response = browser.open_novisit(req)\n raw = response.read()\n root = parse_html(raw)\n for item in root.xpath('//div[@data-priority]'):\n row = item.getparent().getparent()\n sku = item.get('id').split('-')[-1]\n isbns = [x.strip() for x in row.xpath('descendant::*[contains(@class, \"pev_sku\")]/text()')[0].split(',') if check_isbn(x.strip())]\n isbns.sort(key=len, reverse=True)\n try:\n tags = [x.strip() for x in astext(row.xpath('descendant::*[contains(@class, \"pev_categories\")]')[0]).split('/')]\n except IndexError:\n tags = []\n rating = 0\n for bar in row.xpath('descendant::*[contains(@class, \"bgdColorCommunity\")]/@style'):\n m = re.search(r'width: (\\d+)px;.*max-width: (\\d+)px', bar)\n if m is not None:\n rating = float(m.group(1)) / float(m.group(2))\n break\n try:\n pubdate = parse_only_date(astext(row.xpath('descendant::*[contains(@class, \"pev_shipDate\")]')[0]\n ).split(':')[-1].split(u'\\xa0')[-1].strip(), assume_utc=True)\n except Exception:\n log.exception('Error parsing published date')\n pubdate = None\n authors = []\n for x in [x.strip() for x in row.xpath('descendant::*[contains(@class, \"pev_contributor\")]/@title')]:\n authors.extend(a.strip() for a in x.split(','))\n entry = {\n 'sku': sku,\n 'cover': row.xpath('descendant::img/@src')[0].split('?')[0],\n 'publisher': astext(row.xpath('descendant::*[contains(@class, \"headerPublisher\")]')[0]),\n 'title': astext(row.xpath('descendant::*[@id=\"title_{}\"]'.format(sku))[0]),\n 'authors': authors,\n 'isbns': isbns,\n 'tags': tags,\n 'pubdate': pubdate,\n 'format': ' '.join(row.xpath('descendant::*[contains(@class, \"pev_format\")]/text()')).strip(),\n 'rating': rating,\n }\n if entry['cover'].startswith('/'):\n entry['cover'] = None\n yield entry\n\n\nclass Edelweiss(Source):\n\n name = 'Edelweiss'\n version = (2, 0, 1)\n minimum_calibre_version = (3, 6, 0)\n description = _('Downloads metadata and covers from Edelweiss - A catalog updated by book publishers')\n\n capabilities = frozenset(['identify', 'cover'])\n touched_fields = frozenset([\n 'title', 'authors', 'tags', 'pubdate', 'comments', 'publisher',\n 'identifier:isbn', 'identifier:edelweiss', 'rating'])\n supports_gzip_transfer_encoding = True\n has_html_comments = True\n\n @property\n def user_agent(self):\n # Pass in an index to random_user_agent() to test with a particular\n # user agent\n return random_user_agent(allow_ie=False)\n\n def _get_book_url(self, sku):\n if sku:\n return 'https://www.edelweiss.plus/#sku={}&page=1'.format(sku)\n\n def get_book_url(self, identifiers): # {{{\n sku = identifiers.get('edelweiss', None)\n if sku:\n return 'edelweiss', sku, self._get_book_url(sku)\n\n # }}}\n\n def get_cached_cover_url(self, identifiers): # {{{\n sku = identifiers.get('edelweiss', None)\n if not sku:\n isbn = identifiers.get('isbn', None)\n if isbn is not None:\n sku = self.cached_isbn_to_identifier(isbn)\n return self.cached_identifier_to_cover_url(sku)\n # }}}\n\n def create_query(self, log, title=None, authors=None, identifiers={}):\n try:\n from urllib.parse import urlencode\n except ImportError:\n from urllib import urlencode\n import time\n BASE_URL = ('https://www.edelweiss.plus/GetTreelineControl.aspx?'\n 'controlName=/uc/listviews/controls/ListView_data.ascx&itemID=0&resultType=32&dashboardType=8&itemType=1&dataType=products&keywordSearch&')\n keywords = []\n isbn = check_isbn(identifiers.get('isbn', None))\n if isbn is not None:\n keywords.append(isbn)\n elif title:\n title_tokens = list(self.get_title_tokens(title))\n if title_tokens:\n keywords.extend(title_tokens)\n author_tokens = self.get_author_tokens(authors, only_first_author=True)\n if author_tokens:\n keywords.extend(author_tokens)\n if not keywords:\n return None\n params = {\n 'q': (' '.join(keywords)).encode('utf-8'),\n '_': type('')(int(time.time()))\n }\n return BASE_URL+urlencode(params)\n\n # }}}\n\n def identify(self, log, result_queue, abort, title=None, authors=None, # {{{\n identifiers={}, timeout=30):\n import json\n\n br = self.browser\n br.addheaders = [\n ('Referer', 'https://www.edelweiss.plus/'),\n ('X-Requested-With', 'XMLHttpRequest'),\n ('Cache-Control', 'no-cache'),\n ('Pragma', 'no-cache'),\n ]\n if 'edelweiss' in identifiers:\n items = [identifiers['edelweiss']]\n else:\n log.error('Currently Edelweiss returns random books for search queries')\n return\n query = self.create_query(log, title=title, authors=authors,\n identifiers=identifiers)\n if not query:\n log.error('Insufficient metadata to construct query')\n return\n log('Using query URL:', query)\n try:\n raw = br.open(query, timeout=timeout).read().decode('utf-8')\n except Exception as e:\n log.exception('Failed to make identify query: %r'%query)\n return as_unicode(e)\n items = re.search(r'window[.]items\\s*=\\s*(.+?);', raw)\n if items is None:\n log.error('Failed to get list of matching items')\n log.debug('Response text:')\n log.debug(raw)\n return\n items = json.loads(items.group(1))\n\n if (not items and identifiers and title and authors and\n not abort.is_set()):\n return self.identify(log, result_queue, abort, title=title,\n authors=authors, timeout=timeout)\n\n if not items:\n return\n\n workers = []\n items = items[:5]\n for i, item in enumerate(get_basic_data(self.browser, log, *items)):\n sku = item['sku']\n for isbn in item['isbns']:\n self.cache_isbn_to_identifier(isbn, sku)\n if item['cover']:\n self.cache_identifier_to_cover_url(sku, item['cover'])\n fmt = item['format'].lower()\n if 'audio' in fmt or 'mp3' in fmt:\n continue # Audio-book, ignore\n workers.append(Worker(item, i, result_queue, br.clone_browser(), timeout, log, self))\n\n if not workers:\n return\n\n for w in workers:\n w.start()\n # Don't send all requests at the same time\n time.sleep(0.1)\n\n while not abort.is_set():\n a_worker_is_alive = False\n for w in workers:\n w.join(0.2)\n if abort.is_set():\n break\n if w.is_alive():\n a_worker_is_alive = True\n if not a_worker_is_alive:\n break\n\n # }}}\n\n def download_cover(self, log, result_queue, abort, # {{{\n title=None, authors=None, identifiers={}, timeout=30, get_best_cover=False):\n cached_url = self.get_cached_cover_url(identifiers)\n if cached_url is None:\n log.info('No cached cover found, running identify')\n rq = Queue()\n self.identify(log, rq, abort, title=title, authors=authors,\n identifiers=identifiers)\n if abort.is_set():\n return\n results = []\n while True:\n try:\n results.append(rq.get_nowait())\n except Empty:\n break\n results.sort(key=self.identify_results_keygen(\n title=title, authors=authors, identifiers=identifiers))\n for mi in results:\n cached_url = self.get_cached_cover_url(mi.identifiers)\n if cached_url is not None:\n break\n if cached_url is None:\n log.info('No cover found')\n return\n\n if abort.is_set():\n return\n br = self.browser\n log('Downloading cover from:', cached_url)\n try:\n cdata = br.open_novisit(cached_url, timeout=timeout).read()\n result_queue.put((self, cdata))\n except:\n log.exception('Failed to download cover from:', cached_url)\n # }}}\n\n\nif __name__ == '__main__':\n from calibre.ebooks.metadata.sources.test import (\n test_identify_plugin, title_test, authors_test, comments_test, pubdate_test)\n tests = [\n ( # A title and author search\n {'title': 'The Husband\\'s Secret', 'authors':['Liane Moriarty']},\n [title_test('The Husband\\'s Secret', exact=True),\n authors_test(['Liane Moriarty'])]\n ),\n\n ( # An isbn present in edelweiss\n {'identifiers':{'isbn': '9780312621360'}, },\n [title_test('Flame: A Sky Chasers Novel', exact=True),\n authors_test(['Amy Kathleen Ryan'])]\n ),\n\n # Multiple authors and two part title and no general description\n ({'identifiers':{'edelweiss':'0321180607'}},\n [title_test(\n \"XQuery From the Experts: A Guide to the W3C XML Query Language\"\n , exact=True), authors_test([\n 'Howard Katz', 'Don Chamberlin', 'Denise Draper', 'Mary Fernandez',\n 'Michael Kay', 'Jonathan Robie', 'Michael Rys', 'Jerome Simeon',\n 'Jim Tivy', 'Philip Wadler']), pubdate_test(2003, 8, 22),\n comments_test('Jérôme Siméon'), lambda mi: bool(mi.comments and 'No title summary' not in mi.comments)\n ]),\n ]\n start, stop = 0, len(tests)\n\n tests = tests[start:stop]\n test_identify_plugin(Edelweiss.name, tests)\n", + "google": "#!/usr/bin/env python\n# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai\n# License: GPLv3 Copyright: 2011, Kovid Goyal <kovid at kovidgoyal.net>\nfrom __future__ import absolute_import, division, print_function, unicode_literals\nimport hashlib\nimport os\nimport re\nimport regex\nimport sys\nimport tempfile\nimport time\n\ntry:\n from queue import Empty, Queue\nexcept ImportError:\n from Queue import Empty, Queue\n\nfrom calibre import as_unicode, replace_entities, prepare_string_for_xml\nfrom calibre.ebooks.chardet import xml_to_unicode\nfrom calibre.ebooks.metadata import authors_to_string, check_isbn\nfrom calibre.ebooks.metadata.book.base import Metadata\nfrom calibre.ebooks.metadata.sources.base import Source\nfrom calibre.utils.cleantext import clean_ascii_chars\nfrom calibre.utils.localization import canonicalize_lang\n\nNAMESPACES = {\n 'openSearch': 'http://a9.com/-/spec/opensearchrss/1.0/',\n 'atom': 'http://www.w3.org/2005/Atom',\n 'dc': 'http://purl.org/dc/terms',\n 'gd': 'http://schemas.google.com/g/2005'\n}\n\n\ndef pretty_google_books_comments(raw):\n raw = replace_entities(raw)\n # Paragraphs in the comments are removed but whatever software googl uses\n # to do this does not insert a space so we often find the pattern\n # word.Capital in the comments which can be used to find paragraph markers.\n parts = []\n for x in re.split(r'([a-z)\"”])(\\.)([A-Z(\"“])', raw):\n if x == '.':\n parts.append('.</p>\\n\\n<p>')\n else:\n parts.append(prepare_string_for_xml(x))\n raw = '<p>' + ''.join(parts) + '</p>'\n return raw\n\n\ndef get_details(browser, url, timeout): # {{{\n try:\n raw = browser.open_novisit(url, timeout=timeout).read()\n except Exception as e:\n gc = getattr(e, 'getcode', lambda: -1)\n if gc() != 403:\n raise\n # Google is throttling us, wait a little\n time.sleep(2)\n raw = browser.open_novisit(url, timeout=timeout).read()\n\n return raw\n\n\n# }}}\n\nxpath_cache = {}\n\n\ndef XPath(x):\n ans = xpath_cache.get(x)\n if ans is None:\n from lxml import etree\n ans = xpath_cache[x] = etree.XPath(x, namespaces=NAMESPACES)\n return ans\n\n\ndef to_metadata(browser, log, entry_, timeout, running_a_test=False): # {{{\n from lxml import etree\n\n # total_results = XPath('//openSearch:totalResults')\n # start_index = XPath('//openSearch:startIndex')\n # items_per_page = XPath('//openSearch:itemsPerPage')\n entry = XPath('//atom:entry')\n entry_id = XPath('descendant::atom:id')\n url = XPath('descendant::atom:link[@rel=\"self\"]/@href')\n creator = XPath('descendant::dc:creator')\n identifier = XPath('descendant::dc:identifier')\n title = XPath('descendant::dc:title')\n date = XPath('descendant::dc:date')\n publisher = XPath('descendant::dc:publisher')\n subject = XPath('descendant::dc:subject')\n description = XPath('descendant::dc:description')\n language = XPath('descendant::dc:language')\n\n # print(etree.tostring(entry_, pretty_print=True))\n\n def get_text(extra, x):\n try:\n ans = x(extra)\n if ans:\n ans = ans[0].text\n if ans and ans.strip():\n return ans.strip()\n except:\n log.exception('Programming error:')\n return None\n\n def get_extra_details():\n raw = get_details(browser, details_url, timeout)\n if running_a_test:\n with open(os.path.join(tempfile.gettempdir(), 'Google-' + details_url.split('/')[-1] + '.xml'), 'wb') as f:\n f.write(raw)\n print('Book details saved to:', f.name, file=sys.stderr)\n feed = etree.fromstring(\n xml_to_unicode(clean_ascii_chars(raw), strip_encoding_pats=True)[0],\n parser=etree.XMLParser(recover=True, no_network=True, resolve_entities=False)\n )\n return entry(feed)[0]\n\n if isinstance(entry_, str):\n google_id = entry_\n details_url = 'https://www.google.com/books/feeds/volumes/' + google_id\n extra = get_extra_details()\n title_ = ': '.join([x.text for x in title(extra)]).strip()\n authors = [x.text.strip() for x in creator(extra) if x.text]\n else:\n id_url = entry_id(entry_)[0].text\n google_id = id_url.split('/')[-1]\n details_url = url(entry_)[0]\n title_ = ': '.join([x.text for x in title(entry_)]).strip()\n authors = [x.text.strip() for x in creator(entry_) if x.text]\n if not id_url or not title:\n # Silently discard this entry\n return None\n extra = None\n\n if not authors:\n authors = [_('Unknown')]\n if not title:\n return None\n if extra is None:\n extra = get_extra_details()\n mi = Metadata(title_, authors)\n mi.identifiers = {'google': google_id}\n mi.comments = get_text(extra, description)\n lang = canonicalize_lang(get_text(extra, language))\n if lang:\n mi.language = lang\n mi.publisher = get_text(extra, publisher)\n\n # ISBN\n isbns = []\n for x in identifier(extra):\n t = type('')(x.text).strip()\n if t[:5].upper() in ('ISBN:', 'LCCN:', 'OCLC:'):\n if t[:5].upper() == 'ISBN:':\n t = check_isbn(t[5:])\n if t:\n isbns.append(t)\n if isbns:\n mi.isbn = sorted(isbns, key=len)[-1]\n mi.all_isbns = isbns\n\n # Tags\n try:\n btags = [x.text for x in subject(extra) if x.text]\n tags = []\n for t in btags:\n atags = [y.strip() for y in t.split('/')]\n for tag in atags:\n if tag not in tags:\n tags.append(tag)\n except:\n log.exception('Failed to parse tags:')\n tags = []\n if tags:\n mi.tags = [x.replace(',', ';') for x in tags]\n\n # pubdate\n pubdate = get_text(extra, date)\n if pubdate:\n from calibre.utils.date import parse_date, utcnow\n try:\n default = utcnow().replace(day=15)\n mi.pubdate = parse_date(pubdate, assume_utc=True, default=default)\n except:\n log.error('Failed to parse pubdate %r' % pubdate)\n\n # Cover\n mi.has_google_cover = None\n for x in extra.xpath(\n '//*[@href and @rel=\"http://schemas.google.com/books/2008/thumbnail\"]'\n ):\n mi.has_google_cover = x.get('href')\n break\n\n return mi\n\n\n# }}}\n\n\nclass GoogleBooks(Source):\n\n name = 'Google'\n version = (1, 1, 0)\n minimum_calibre_version = (2, 80, 0)\n description = _('Downloads metadata and covers from Google Books')\n\n capabilities = frozenset({'identify'})\n touched_fields = frozenset({\n 'title', 'authors', 'tags', 'pubdate', 'comments', 'publisher',\n 'identifier:isbn', 'identifier:google', 'languages'\n })\n supports_gzip_transfer_encoding = True\n cached_cover_url_is_reliable = False\n\n GOOGLE_COVER = 'https://books.google.com/books?id=%s&printsec=frontcover&img=1'\n\n DUMMY_IMAGE_MD5 = frozenset(\n ('0de4383ebad0adad5eeb8975cd796657', 'a64fa89d7ebc97075c1d363fc5fea71f')\n )\n\n def get_book_url(self, identifiers): # {{{\n goog = identifiers.get('google', None)\n if goog is not None:\n return ('google', goog, 'https://books.google.com/books?id=%s' % goog)\n # }}}\n\n def id_from_url(self, url): # {{{\n from polyglot.urllib import parse_qs, urlparse\n purl = urlparse(url)\n if purl.netloc == 'books.google.com':\n q = parse_qs(purl.query)\n gid = q.get('id')\n if gid:\n return 'google', gid[0]\n # }}}\n\n def create_query(self, title=None, authors=None, identifiers={}, capitalize_isbn=False): # {{{\n try:\n from urllib.parse import urlencode\n except ImportError:\n from urllib import urlencode\n BASE_URL = 'https://books.google.com/books/feeds/volumes?'\n isbn = check_isbn(identifiers.get('isbn', None))\n q = ''\n if isbn is not None:\n q += ('ISBN:' if capitalize_isbn else 'isbn:') + isbn\n elif title or authors:\n\n def build_term(prefix, parts):\n return ' '.join('in' + prefix + ':' + x for x in parts)\n\n title_tokens = list(self.get_title_tokens(title))\n if title_tokens:\n q += build_term('title', title_tokens)\n author_tokens = list(self.get_author_tokens(authors, only_first_author=True))\n if author_tokens:\n q += ('+' if q else '') + build_term('author', author_tokens)\n\n if not q:\n return None\n if not isinstance(q, bytes):\n q = q.encode('utf-8')\n return BASE_URL + urlencode({\n 'q': q,\n 'max-results': 20,\n 'start-index': 1,\n 'min-viewability': 'none',\n })\n\n # }}}\n\n def download_cover( # {{{\n self,\n log,\n result_queue,\n abort,\n title=None,\n authors=None,\n identifiers={},\n timeout=30,\n get_best_cover=False\n ):\n cached_url = self.get_cached_cover_url(identifiers)\n if cached_url is None:\n log.info('No cached cover found, running identify')\n rq = Queue()\n self.identify(\n log,\n rq,\n abort,\n title=title,\n authors=authors,\n identifiers=identifiers\n )\n if abort.is_set():\n return\n results = []\n while True:\n try:\n results.append(rq.get_nowait())\n except Empty:\n break\n results.sort(\n key=self.identify_results_keygen(\n title=title, authors=authors, identifiers=identifiers\n )\n )\n for mi in results:\n cached_url = self.get_cached_cover_url(mi.identifiers)\n if cached_url is not None:\n break\n if cached_url is None:\n log.info('No cover found')\n return\n\n br = self.browser\n for candidate in (0, 1):\n if abort.is_set():\n return\n url = cached_url + '&zoom={}'.format(candidate)\n log('Downloading cover from:', cached_url)\n try:\n cdata = br.open_novisit(url, timeout=timeout).read()\n if cdata:\n if hashlib.md5(cdata).hexdigest() in self.DUMMY_IMAGE_MD5:\n log.warning('Google returned a dummy image, ignoring')\n else:\n result_queue.put((self, cdata))\n break\n except Exception:\n log.exception('Failed to download cover from:', cached_url)\n\n # }}}\n\n def get_cached_cover_url(self, identifiers): # {{{\n url = None\n goog = identifiers.get('google', None)\n if goog is None:\n isbn = identifiers.get('isbn', None)\n if isbn is not None:\n goog = self.cached_isbn_to_identifier(isbn)\n if goog is not None:\n url = self.cached_identifier_to_cover_url(goog)\n\n return url\n\n # }}}\n\n def postprocess_downloaded_google_metadata(self, ans, relevance=0): # {{{\n if not isinstance(ans, Metadata):\n return ans\n ans.source_relevance = relevance\n goog = ans.identifiers['google']\n for isbn in getattr(ans, 'all_isbns', []):\n self.cache_isbn_to_identifier(isbn, goog)\n if getattr(ans, 'has_google_cover', False):\n self.cache_identifier_to_cover_url(goog, self.GOOGLE_COVER % goog)\n if ans.comments:\n ans.comments = pretty_google_books_comments(ans.comments)\n self.clean_downloaded_metadata(ans)\n return ans\n # }}}\n\n def get_all_details( # {{{\n self,\n br,\n log,\n entries,\n abort,\n result_queue,\n timeout\n ):\n from lxml import etree\n for relevance, i in enumerate(entries):\n try:\n ans = self.postprocess_downloaded_google_metadata(to_metadata(br, log, i, timeout, self.running_a_test), relevance)\n if isinstance(ans, Metadata):\n result_queue.put(ans)\n except Exception:\n log.exception(\n 'Failed to get metadata for identify entry:', etree.tostring(i)\n )\n if abort.is_set():\n break\n\n # }}}\n\n def identify_via_web_search( # {{{\n self,\n log,\n result_queue,\n abort,\n title=None,\n authors=None,\n identifiers={},\n timeout=30\n ):\n isbn = check_isbn(identifiers.get('isbn', None))\n q = []\n strip_punc_pat = regex.compile(r'[\\p{C}|\\p{M}|\\p{P}|\\p{S}|\\p{Z}]+', regex.UNICODE)\n google_ids = []\n check_tokens = set()\n has_google_id = 'google' in identifiers\n\n def to_check_tokens(*tokens):\n for t in tokens:\n if len(t) < 3:\n continue\n t = t.lower()\n if t in ('and', 'not', 'the'):\n continue\n yield strip_punc_pat.sub('', t)\n\n if has_google_id:\n google_ids.append(identifiers['google'])\n elif isbn is not None:\n q.append(isbn)\n elif title or authors:\n title_tokens = list(self.get_title_tokens(title))\n if title_tokens:\n q += title_tokens\n check_tokens |= set(to_check_tokens(*title_tokens))\n author_tokens = list(self.get_author_tokens(authors, only_first_author=True))\n if author_tokens:\n q += author_tokens\n check_tokens |= set(to_check_tokens(*author_tokens))\n if not q and not google_ids:\n return None\n from calibre.ebooks.metadata.sources.update import search_engines_module\n se = search_engines_module()\n br = se.google_specialize_browser(se.browser())\n if not has_google_id:\n url = se.google_format_query(q, tbm='bks')\n log('Making query:', url)\n r = []\n root = se.query(br, url, 'google', timeout=timeout, save_raw=r.append)\n pat = re.compile(r'id=([^&]+)')\n for q in se.google_parse_results(root, r[0], log=log, ignore_uncached=False):\n m = pat.search(q.url)\n if m is None or not q.url.startswith('https://books.google'):\n continue\n google_ids.append(m.group(1))\n\n if not google_ids and isbn and (title or authors):\n return self.identify_via_web_search(log, result_queue, abort, title, authors, {}, timeout)\n found = False\n seen = set()\n for relevance, gid in enumerate(google_ids):\n if gid in seen:\n continue\n seen.add(gid)\n try:\n ans = to_metadata(br, log, gid, timeout, self.running_a_test)\n if isinstance(ans, Metadata):\n if isbn:\n if isbn not in ans.all_isbns:\n log('Excluding', ans.title, 'by', authors_to_string(ans.authors), 'as it does not match the ISBN:', isbn,\n 'not in', ' '.join(ans.all_isbns))\n continue\n elif check_tokens:\n candidate = set(to_check_tokens(*self.get_title_tokens(ans.title)))\n candidate |= set(to_check_tokens(*self.get_author_tokens(ans.authors)))\n if candidate.intersection(check_tokens) != check_tokens:\n log('Excluding', ans.title, 'by', authors_to_string(ans.authors), 'as it does not match the query')\n continue\n ans = self.postprocess_downloaded_google_metadata(ans, relevance)\n result_queue.put(ans)\n found = True\n except:\n log.exception('Failed to get metadata for google books id:', gid)\n if abort.is_set():\n break\n if not found and isbn and (title or authors):\n return self.identify_via_web_search(log, result_queue, abort, title, authors, {}, timeout)\n # }}}\n\n def identify( # {{{\n self,\n log,\n result_queue,\n abort,\n title=None,\n authors=None,\n identifiers={},\n timeout=30\n ):\n from lxml import etree\n entry = XPath('//atom:entry')\n identifiers = identifiers.copy()\n br = self.browser\n if 'google' in identifiers:\n try:\n ans = to_metadata(br, log, identifiers['google'], timeout, self.running_a_test)\n if isinstance(ans, Metadata):\n self.postprocess_downloaded_google_metadata(ans)\n result_queue.put(ans)\n return\n except Exception:\n log.exception('Failed to get metadata for Google identifier:', identifiers['google'])\n del identifiers['google']\n\n query = self.create_query(\n title=title, authors=authors, identifiers=identifiers\n )\n if not query:\n log.error('Insufficient metadata to construct query')\n return\n\n def make_query(query):\n log('Making query:', query)\n try:\n raw = br.open_novisit(query, timeout=timeout).read()\n except Exception as e:\n log.exception('Failed to make identify query: %r' % query)\n return False, as_unicode(e)\n\n try:\n feed = etree.fromstring(\n xml_to_unicode(clean_ascii_chars(raw), strip_encoding_pats=True)[0],\n parser=etree.XMLParser(recover=True, no_network=True, resolve_entities=False)\n )\n return True, entry(feed)\n except Exception as e:\n log.exception('Failed to parse identify results')\n return False, as_unicode(e)\n ok, entries = make_query(query)\n if not ok:\n return entries\n if not entries and not abort.is_set():\n log('No results found, doing a web search instead')\n return self.identify_via_web_search(log, result_queue, abort, title, authors, identifiers, timeout)\n\n # There is no point running these queries in threads as google\n # throttles requests returning 403 Forbidden errors\n self.get_all_details(br, log, entries, abort, result_queue, timeout)\n\n # }}}\n\n\nif __name__ == '__main__': # tests {{{\n # To run these test use:\n # calibre-debug src/calibre/ebooks/metadata/sources/google.py\n from calibre.ebooks.metadata.sources.test import (\n authors_test, test_identify_plugin, title_test\n )\n tests = [\n ({\n 'identifiers': {'google': 's7NIrgEACAAJ'},\n }, [title_test('Ride Every Stride', exact=False)]),\n\n ({\n 'identifiers': {'isbn': '0743273567'},\n 'title': 'Great Gatsby',\n 'authors': ['Fitzgerald']\n }, [\n title_test('The great gatsby', exact=True),\n authors_test(['F. Scott Fitzgerald'])\n ]),\n\n ({\n 'title': 'Flatland',\n 'authors': ['Abbott']\n }, [title_test('Flatland', exact=False)]),\n\n ({\n 'title': 'The Blood Red Indian Summer: A Berger and Mitry Mystery',\n 'authors': ['David Handler'],\n }, [title_test('The Blood Red Indian Summer: A Berger and Mitry Mystery')\n ]),\n\n ({\n # requires using web search to find the book\n 'title': 'Dragon Done It',\n 'authors': ['Eric Flint'],\n }, [\n title_test('The dragon done it', exact=True),\n authors_test(['Eric Flint', 'Mike Resnick'])\n ]),\n\n ]\n test_identify_plugin(GoogleBooks.name, tests[:])\n\n# }}}\n", + "google_images": "#!/usr/bin/env python\n# vim:fileencoding=UTF-8\nfrom __future__ import absolute_import, division, print_function, unicode_literals\n\n__license__ = 'GPL v3'\n__copyright__ = '2013, Kovid Goyal <kovid@kovidgoyal.net>'\n__docformat__ = 'restructuredtext en'\n\nfrom collections import OrderedDict\n\nfrom calibre import random_user_agent\nfrom calibre.ebooks.metadata.sources.base import Source, Option\n\n\ndef parse_html(raw):\n try:\n from html5_parser import parse\n except ImportError:\n # Old versions of calibre\n import html5lib\n return html5lib.parse(raw, treebuilder='lxml', namespaceHTMLElements=False)\n else:\n return parse(raw)\n\n\ndef imgurl_from_id(raw, tbnid):\n from json import JSONDecoder\n q = '\"{}\",['.format(tbnid)\n start_pos = raw.index(q)\n if start_pos < 100:\n return\n jd = JSONDecoder()\n data = jd.raw_decode('[' + raw[start_pos:])[0]\n # from pprint import pprint\n # pprint(data)\n url_num = 0\n for x in data:\n if isinstance(x, list) and len(x) == 3:\n q = x[0]\n if hasattr(q, 'lower') and q.lower().startswith('http'):\n url_num += 1\n if url_num > 1:\n return q\n\n\nclass GoogleImages(Source):\n\n name = 'Google Images'\n version = (1, 0, 3)\n minimum_calibre_version = (2, 80, 0)\n description = _('Downloads covers from a Google Image search. Useful to find larger/alternate covers.')\n capabilities = frozenset(['cover'])\n can_get_multiple_covers = True\n supports_gzip_transfer_encoding = True\n options = (Option('max_covers', 'number', 5, _('Maximum number of covers to get'),\n _('The maximum number of covers to process from the Google search result')),\n Option('size', 'choices', 'svga', _('Cover size'),\n _('Search for covers larger than the specified size'),\n choices=OrderedDict((\n ('any', _('Any size'),),\n ('l', _('Large'),),\n ('qsvga', _('Larger than %s')%'400x300',),\n ('vga', _('Larger than %s')%'640x480',),\n ('svga', _('Larger than %s')%'600x800',),\n ('xga', _('Larger than %s')%'1024x768',),\n ('2mp', _('Larger than %s')%'2 MP',),\n ('4mp', _('Larger than %s')%'4 MP',),\n ))),\n )\n\n def download_cover(self, log, result_queue, abort,\n title=None, authors=None, identifiers={}, timeout=30, get_best_cover=False):\n if not title:\n return\n timeout = max(60, timeout) # Needs at least a minute\n title = ' '.join(self.get_title_tokens(title))\n author = ' '.join(self.get_author_tokens(authors))\n urls = self.get_image_urls(title, author, log, abort, timeout)\n self.download_multiple_covers(title, authors, urls, get_best_cover, timeout, result_queue, abort, log)\n\n @property\n def user_agent(self):\n return random_user_agent(allow_ie=False)\n\n def get_image_urls(self, title, author, log, abort, timeout):\n from calibre.utils.cleantext import clean_ascii_chars\n try:\n from urllib.parse import urlencode\n except ImportError:\n from urllib import urlencode\n from collections import OrderedDict\n ans = OrderedDict()\n br = self.browser\n q = urlencode({'as_q': ('%s %s'%(title, author)).encode('utf-8')})\n if isinstance(q, bytes):\n q = q.decode('utf-8')\n sz = self.prefs['size']\n if sz == 'any':\n sz = ''\n elif sz == 'l':\n sz = 'isz:l,'\n else:\n sz = 'isz:lt,islt:%s,' % sz\n # See https://www.google.com/advanced_image_search to understand this\n # URL scheme\n url = 'https://www.google.com/search?as_st=y&tbm=isch&{}&as_epq=&as_oq=&as_eq=&cr=&as_sitesearch=&safe=images&tbs={}iar:t,ift:jpg'.format(q, sz)\n log('Search URL: ' + url)\n br.set_simple_cookie('CONSENT', 'YES+', '.google.com', path='/')\n raw = clean_ascii_chars(br.open(url).read().decode('utf-8'))\n root = parse_html(raw)\n results = root.xpath('//div/@data-tbnid') # could also use data-id\n # from calibre.utils.ipython import ipython\n # ipython({'root': root, 'raw': raw, 'url': url, 'results': results})\n for tbnid in results:\n try:\n imgurl = imgurl_from_id(raw, tbnid)\n except Exception:\n continue\n if imgurl:\n ans[imgurl] = True\n return list(ans)\n\n\ndef test():\n try:\n from queue import Queue\n except ImportError:\n from Queue import Queue\n from threading import Event\n from calibre.utils.logging import default_log\n p = GoogleImages(None)\n p.log = default_log\n rq = Queue()\n p.download_cover(default_log, rq, Event(), title='The Heroes',\n authors=('Joe Abercrombie',))\n print('Downloaded', rq.qsize(), 'covers')\n\n\nif __name__ == '__main__':\n test()\n", + "hashes": { + "amazon": "e2dc988ace313e5689de47912c4c1446e2311868", + "big_book_search": "9b468ff223b7ddbf6bbd26e58194c0fa8fbbfb69", + "edelweiss": "efd8f281a56435895b7916f85598d469bb53bb02", + "google": "bfe34ba5e1be36511f2228a350bd91c676724aac", + "google_images": "3323061049afe11a42422f325783de220991149d", + "openlibrary": "8707d3b3161de476b46ed967dea1116707dcfb0a", + "search_engines": "52a24c5004033fc9f393a260a09e6f8afb80b0ba" + }, + "openlibrary": "#!/usr/bin/env python\n# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai\nfrom __future__ import absolute_import, division, print_function, unicode_literals\n\n__license__ = 'GPL v3'\n__copyright__ = '2011, Kovid Goyal <kovid@kovidgoyal.net>'\n__docformat__ = 'restructuredtext en'\n\nfrom calibre.ebooks.metadata.sources.base import Source\n\n\nclass OpenLibrary(Source):\n\n name = 'Open Library'\n version = (1, 0, 0)\n minimum_calibre_version = (2, 80, 0)\n description = _('Downloads covers from The Open Library')\n\n capabilities = frozenset(['cover'])\n\n OPENLIBRARY = 'https://covers.openlibrary.org/b/isbn/%s-L.jpg?default=false'\n\n def download_cover(self, log, result_queue, abort,\n title=None, authors=None, identifiers={}, timeout=30, get_best_cover=False):\n if 'isbn' not in identifiers:\n return\n isbn = identifiers['isbn']\n br = self.browser\n try:\n ans = br.open_novisit(self.OPENLIBRARY%isbn, timeout=timeout).read()\n result_queue.put((self, ans))\n except Exception as e:\n if callable(getattr(e, 'getcode', None)) and e.getcode() == 404:\n log.error('No cover for ISBN: %r found'%isbn)\n else:\n log.exception('Failed to download cover for ISBN:', isbn)\n", + "search_engines": "#!/usr/bin/env python\n# vim:fileencoding=utf-8\n# License: GPLv3 Copyright: 2017, Kovid Goyal <kovid at kovidgoyal.net>\n\nfrom __future__ import absolute_import, division, print_function, unicode_literals\nimport json\nimport os\nimport re\nimport time\nfrom collections import namedtuple\nfrom contextlib import contextmanager\nfrom threading import Lock\n\ntry:\n from urllib.parse import parse_qs, quote_plus, unquote, urlencode, quote\nexcept ImportError:\n from urlparse import parse_qs\n from urllib import quote_plus, urlencode, unquote, quote\n\nfrom lxml import etree\n\nfrom calibre import browser as _browser, prints, random_user_agent\nfrom calibre.constants import cache_dir\nfrom calibre.ebooks.chardet import xml_to_unicode\nfrom calibre.utils.lock import ExclusiveFile\nfrom calibre.utils.random_ua import accept_header_for_ua\n\ncurrent_version = (1, 2, 0)\nminimum_calibre_version = (2, 80, 0)\nwebcache = {}\nwebcache_lock = Lock()\n\n\nResult = namedtuple('Result', 'url title cached_url')\n\n\n@contextmanager\ndef rate_limit(name='test', time_between_visits=2, max_wait_seconds=5 * 60, sleep_time=0.2):\n lock_file = os.path.join(cache_dir(), 'search-engine.' + name + '.lock')\n with ExclusiveFile(lock_file, timeout=max_wait_seconds, sleep_time=sleep_time) as f:\n try:\n lv = float(f.read().decode('utf-8').strip())\n except Exception:\n lv = 0\n # we cannot use monotonic() as this is cross process and historical\n # data as well\n delta = time.time() - lv\n if delta < time_between_visits:\n time.sleep(time_between_visits - delta)\n try:\n yield\n finally:\n f.seek(0)\n f.truncate()\n f.write(repr(time.time()).encode('utf-8'))\n\n\ndef tostring(elem):\n return etree.tostring(elem, encoding='unicode', method='text', with_tail=False)\n\n\ndef browser():\n ua = random_user_agent(allow_ie=False)\n # ua = 'Mozilla/5.0 (Linux; Android 8.0.0; VTR-L29; rv:63.0) Gecko/20100101 Firefox/63.0'\n br = _browser(user_agent=ua)\n br.set_handle_gzip(True)\n br.addheaders += [\n ('Accept', accept_header_for_ua(ua)),\n ('Upgrade-insecure-requests', '1'),\n ]\n return br\n\n\ndef encode_query(**query):\n q = {k.encode('utf-8'): v.encode('utf-8') for k, v in query.items()}\n return urlencode(q).decode('utf-8')\n\n\ndef parse_html(raw):\n try:\n from html5_parser import parse\n except ImportError:\n # Old versions of calibre\n import html5lib\n return html5lib.parse(raw, treebuilder='lxml', namespaceHTMLElements=False)\n else:\n return parse(raw)\n\n\ndef query(br, url, key, dump_raw=None, limit=1, parser=parse_html, timeout=60, save_raw=None, simple_scraper=None):\n with rate_limit(key):\n if simple_scraper is None:\n raw = br.open_novisit(url, timeout=timeout).read()\n raw = xml_to_unicode(raw, strip_encoding_pats=True)[0]\n else:\n raw = simple_scraper(url, timeout=timeout)\n if dump_raw is not None:\n with open(dump_raw, 'w') as f:\n f.write(raw)\n if save_raw is not None:\n save_raw(raw)\n return parser(raw)\n\n\ndef quote_term(x):\n ans = quote_plus(x.encode('utf-8'))\n if isinstance(ans, bytes):\n ans = ans.decode('utf-8')\n return ans\n\n\n# DDG + Wayback machine {{{\n\n\ndef ddg_url_processor(url):\n return url\n\n\ndef ddg_term(t):\n t = t.replace('\"', '')\n if t.lower() in {'map', 'news'}:\n t = '\"' + t + '\"'\n if t in {'OR', 'AND', 'NOT'}:\n t = t.lower()\n return t\n\n\ndef ddg_href(url):\n if url.startswith('/'):\n q = url.partition('?')[2]\n url = parse_qs(q.encode('utf-8'))['uddg'][0].decode('utf-8')\n return url\n\n\ndef wayback_machine_cached_url(url, br=None, log=prints, timeout=60):\n q = quote_term(url)\n br = br or browser()\n data = query(br, 'https://archive.org/wayback/available?url=' +\n q, 'wayback', parser=json.loads, limit=0.25, timeout=timeout)\n try:\n closest = data['archived_snapshots']['closest']\n if closest['available']:\n return closest['url'].replace('http:', 'https:')\n except Exception:\n pass\n from pprint import pformat\n log('Response from wayback machine:', pformat(data))\n\n\ndef wayback_url_processor(url):\n if url.startswith('/'):\n # Use original URL instead of absolutizing to wayback URL as wayback is\n # slow\n m = re.search('https?:', url)\n if m is None:\n url = 'https://web.archive.org' + url\n else:\n url = url[m.start():]\n return url\n\n\ndef ddg_search(terms, site=None, br=None, log=prints, safe_search=False, dump_raw=None, timeout=60):\n # https://duck.co/help/results/syntax\n terms = [quote_term(ddg_term(t)) for t in terms]\n if site is not None:\n terms.append(quote_term(('site:' + site)))\n q = '+'.join(terms)\n url = 'https://duckduckgo.com/html/?q={q}&kp={kp}'.format(\n q=q, kp=1 if safe_search else -1)\n log('Making ddg query: ' + url)\n br = br or browser()\n root = query(br, url, 'ddg', dump_raw, timeout=timeout)\n ans = []\n for a in root.xpath('//*[@class=\"results\"]//*[@class=\"result__title\"]/a[@href and @class=\"result__a\"]'):\n try:\n ans.append(Result(ddg_href(a.get('href')), tostring(a), None))\n except KeyError:\n log('Failed to find ddg href in:', a.get('href'))\n return ans, url\n\n\ndef ddg_develop():\n br = browser()\n for result in ddg_search('heroes abercrombie'.split(), 'www.amazon.com', dump_raw='/t/raw.html', br=br)[0]:\n if '/dp/' in result.url:\n print(result.title)\n print(' ', result.url)\n print(' ', get_cached_url(result.url, br))\n print()\n# }}}\n\n# Bing {{{\n\n\ndef bing_term(t):\n t = t.replace('\"', '')\n if t in {'OR', 'AND', 'NOT'}:\n t = t.lower()\n return t\n\n\ndef bing_url_processor(url):\n return url\n\n\ndef bing_search(terms, site=None, br=None, log=prints, safe_search=False, dump_raw=None, timeout=60, show_user_agent=False):\n # http://vlaurie.com/computers2/Articles/bing_advanced_search.htm\n terms = [quote_term(bing_term(t)) for t in terms]\n if site is not None:\n terms.append(quote_term(('site:' + site)))\n q = '+'.join(terms)\n url = 'https://www.bing.com/search?q={q}'.format(q=q)\n log('Making bing query: ' + url)\n br = br or browser()\n br.addheaders = [x for x in br.addheaders if x[0].lower() != 'user-agent']\n ua = ''\n from calibre.utils.random_ua import random_common_chrome_user_agent\n while not ua or 'Edg/' in ua:\n ua = random_common_chrome_user_agent()\n if show_user_agent:\n print('User-agent:', ua)\n br.addheaders.append(('User-agent', ua))\n\n root = query(br, url, 'bing', dump_raw, timeout=timeout)\n ans = []\n for li in root.xpath('//*[@id=\"b_results\"]/li[@class=\"b_algo\"]'):\n a = li.xpath('descendant::h2/a[@href]') or li.xpath('descendant::div[@class=\"b_algoheader\"]/a[@href]')\n a = a[0]\n title = tostring(a)\n try:\n div = li.xpath('descendant::div[@class=\"b_attribution\" and @u]')[0]\n except IndexError:\n log('Ignoring {!r} as it has no cached page'.format(title))\n continue\n d, w = div.get('u').split('|')[-2:]\n cached_url = 'https://cc.bingj.com/cache.aspx?q={q}&d={d}&mkt=en-US&setlang=en-US&w={w}'.format(\n q=q, d=d, w=w)\n ans.append(Result(a.get('href'), title, cached_url))\n if not ans:\n title = ' '.join(root.xpath('//title/text()'))\n log('Failed to find any results on results page, with title:', title)\n return ans, url\n\n\ndef bing_develop():\n for result in bing_search('heroes abercrombie'.split(), 'www.amazon.com', dump_raw='/t/raw.html', show_user_agent=True)[0]:\n if '/dp/' in result.url:\n print(result.title)\n print(' ', result.url)\n print(' ', result.cached_url)\n print()\n# }}}\n\n# Google {{{\n\n\ndef google_term(t):\n t = t.replace('\"', '')\n if t in {'OR', 'AND', 'NOT'}:\n t = t.lower()\n return t\n\n\ndef google_url_processor(url):\n return url\n\n\ndef google_get_cached_url(url, br=None, log=prints, timeout=60):\n ourl = url\n if not isinstance(url, bytes):\n url = url.encode('utf-8')\n cu = quote(url, safe='')\n if isinstance(cu, bytes):\n cu = cu.decode('utf-8')\n cached_url = 'https://webcache.googleusercontent.com/search?q=cache:' + cu\n br = google_specialize_browser(br or browser())\n try:\n raw = query(br, cached_url, 'google-cache', parser=lambda x: x.encode('utf-8'), timeout=timeout)\n except Exception as err:\n log('Failed to get cached URL from google for URL: {} with error: {}'.format(ourl, err))\n else:\n with webcache_lock:\n webcache[cached_url] = raw\n return cached_url\n\n\ndef google_extract_cache_urls(raw):\n if isinstance(raw, bytes):\n raw = raw.decode('utf-8', 'replace')\n pat = re.compile(r'\\\\x22(https://webcache\\.googleusercontent\\.com/.+?)\\\\x22')\n upat = re.compile(r'\\\\\\\\u([0-9a-fA-F]{4})')\n cache_pat = re.compile('cache:([^:]+):(.+)')\n\n def urepl(m):\n return chr(int(m.group(1), 16))\n\n seen = set()\n ans = {}\n for m in pat.finditer(raw):\n cache_url = upat.sub(urepl, m.group(1))\n m = cache_pat.search(cache_url)\n cache_id, src_url = m.group(1), m.group(2)\n if cache_id in seen:\n continue\n seen.add(cache_id)\n src_url = src_url.split('+')[0]\n src_url = unquote(src_url)\n ans[src_url] = cache_url\n return ans\n\n\ndef google_parse_results(root, raw, log=prints, ignore_uncached=True):\n cache_url_map = google_extract_cache_urls(raw)\n # print('\\n'.join(cache_url_map))\n ans = []\n for div in root.xpath('//*[@id=\"search\"]//*[@id=\"rso\"]//div[descendant::h3]'):\n try:\n a = div.xpath('descendant::a[@href]')[0]\n except IndexError:\n log('Ignoring div with no main result link')\n continue\n title = tostring(a)\n src_url = a.get('href')\n if src_url in cache_url_map:\n cached_url = cache_url_map[src_url]\n else:\n try:\n c = div.xpath('descendant::*[@role=\"menuitem\"]//a[@class=\"fl\"]')[0]\n except IndexError:\n if ignore_uncached:\n log('Ignoring {!r} as it has no cached page'.format(title))\n continue\n c = {'href': ''}\n cached_url = c.get('href')\n ans.append(Result(a.get('href'), title, cached_url))\n if not ans:\n title = ' '.join(root.xpath('//title/text()'))\n log('Failed to find any results on results page, with title:', title)\n return ans\n\n\ndef google_specialize_browser(br):\n with webcache_lock:\n if not hasattr(br, 'google_consent_cookie_added'):\n br.set_simple_cookie('CONSENT', 'YES+', '.google.com', path='/')\n br.google_consent_cookie_added = True\n return br\n\n\ndef google_format_query(terms, site=None, tbm=None):\n terms = [quote_term(google_term(t)) for t in terms]\n if site is not None:\n terms.append(quote_term(('site:' + site)))\n q = '+'.join(terms)\n url = 'https://www.google.com/search?q={q}'.format(q=q)\n if tbm:\n url += '&tbm=' + tbm\n return url\n\n\ndef google_search(terms, site=None, br=None, log=prints, safe_search=False, dump_raw=None, timeout=60):\n url = google_format_query(terms, site)\n log('Making google query: ' + url)\n br = google_specialize_browser(br or browser())\n r = []\n root = query(br, url, 'google', dump_raw, timeout=timeout, save_raw=r.append)\n return google_parse_results(root, r[0], log=log), url\n\n\ndef google_develop(search_terms='1423146786', raw_from=''):\n if raw_from:\n with open(raw_from, 'rb') as f:\n raw = f.read()\n results = google_parse_results(parse_html(raw), raw)\n else:\n br = browser()\n results = google_search(search_terms.split(), 'www.amazon.com', dump_raw='/t/raw.html', br=br)[0]\n for result in results:\n if '/dp/' in result.url:\n print(result.title)\n print(' ', result.url)\n print(' ', result.cached_url)\n print()\n# }}}\n\n\ndef get_cached_url(url, br=None, log=prints, timeout=60):\n return google_get_cached_url(url, br, log, timeout) or wayback_machine_cached_url(url, br, log, timeout)\n\n\ndef get_data_for_cached_url(url):\n with webcache_lock:\n return webcache.get(url)\n\n\ndef resolve_url(url):\n prefix, rest = url.partition(':')[::2]\n if prefix == 'bing':\n return bing_url_processor(rest)\n if prefix == 'wayback':\n return wayback_url_processor(rest)\n return url\n\n\n# if __name__ == '__main__':\n# import sys\n# func = sys.argv[-1]\n# globals()[func]()\n" +} \ No newline at end of file diff --git a/arch-config/.config/calibre/mtp_devices.json b/arch-config/.config/calibre/mtp_devices.json new file mode 100644 index 00000000..675c62ca --- /dev/null +++ b/arch-config/.config/calibre/mtp_devices.json @@ -0,0 +1,11 @@ +{ + "blacklist": [ + "9d273cd5" + ], + "history": { + "9d273cd5": [ + "ONEPLUS A3003", + "2021-05-15T18:17:07.571225+00:00" + ] + } +} \ No newline at end of file diff --git a/arch-config/.config/calibre/plugins/DeACSM.zip b/arch-config/.config/calibre/plugins/DeACSM.zip new file mode 100644 index 00000000..1eca0f2b Binary files /dev/null and b/arch-config/.config/calibre/plugins/DeACSM.zip differ diff --git a/arch-config/.config/calibre/plugins/DeACSM/account/activation.xml b/arch-config/.config/calibre/plugins/DeACSM/account/activation.xml new file mode 100644 index 00000000..59ea9b6c --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/account/activation.xml @@ -0,0 +1,28 @@ +<?xml version="1.0"?> +<activationInfo xmlns="http://ns.adobe.com/adept"> + <adept:activationServiceInfo xmlns:adept="http://ns.adobe.com/adept"> + <adept:authURL>http://adeactivate.adobe.com/adept</adept:authURL> + <adept:userInfoURL>http://adeactivate.adobe.com/adept</adept:userInfoURL> + <adept:activationURL>http://adeactivate.adobe.com/adept</adept:activationURL> + <adept:certificate>MIIEsjCCA5qgAwIBAgIER2q5eDANBgkqhkiG9w0BAQUFADCBhDELMAkGA1UEBhMCVVMxIzAhBgNVBAoTGkFkb2JlIFN5c3RlbXMgSW5jb3Jwb3JhdGVkMRswGQYDVQQLExJEaWdpdGFsIFB1Ymxpc2hpbmcxMzAxBgNVBAMTKkFkb2JlIENvbnRlbnQgU2VydmVyIENlcnRpZmljYXRlIEF1dGhvcml0eTAeFw0wODAxMDkxODM3NDVaFw0xMzAxMDkxOTA3NDVaMH0xCzAJBgNVBAYTAlVTMSMwIQYDVQQKExpBZG9iZSBTeXN0ZW1zIEluY29ycG9yYXRlZDEbMBkGA1UECxMSRGlnaXRhbCBQdWJsaXNoaW5nMSwwKgYDVQQDEyNodHRwOi8vYWRlYWN0aXZhdGUuYWRvYmUuY29tL2FkZXB0LzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAyXpCCWFh0Q3Bi1S7xf+CJfMd+cZz3HB0NknDScB1Cs8KdU0ygO7iqAgdiAdPliITkUTVEgUPvK+4yYCUderzBjq13/IrKlwEAyWeNgssJekpYgqNywo7Md1OApXzM47wVThNePNydhGYuNEEDDxzO+0JxucfhfArwnp7kIWA6q8CAwEAAaOCAbQwggGwMAsGA1UdDwQEAwIFoDBYBglghkgBhvprHgEESwxJVGhlIHByaXZhdGUga2V5IGNvcnJlc3BvbmRpbmcgdG8gdGhpcyBjZXJ0aWZpY2F0ZSBtYXkgaGF2ZSBiZWVuIGV4cG9ydGVkLjAUBgNVHSUEDTALBgkqhkiG9y8CAQQwgbIGA1UdIASBqjCBpzCBpAYJKoZIhvcvAQIDMIGWMIGTBggrBgEFBQcCAjCBhhqBg1lvdSBhcmUgbm90IHBlcm1pdHRlZCB0byB1c2UgdGhpcyBMaWNlbnNlIENlcnRpZmljYXRlIGV4Y2VwdCBhcyBwZXJtaXR0ZWQgYnkgdGhlIGxpY2Vuc2UgYWdyZWVtZW50IGFjY29tcGFueWluZyB0aGUgQWRvYmUgc29mdHdhcmUuMDEGA1UdHwQqMCgwJqAkoCKGIGh0dHA6Ly9jcmwuYWRvYmUuY29tL2Fkb2JlQ1MuY3JsMB8GA1UdIwQYMBaAFIvu8IFgyaLaHg5SwVgMBLBD94/oMB0GA1UdDgQWBBT9A+kXOPL6N57MN/zovbCGEx2+BTAJBgNVHRMEAjAAMA0GCSqGSIb3DQEBBQUAA4IBAQBVjUalliql3VjpLdT8si7OwPU1wQODllwlgfLH7tI/Ubq5wHDlprGtbf3jZm6tXY1qmh9mz1WnTmQHU3uPk8qgpihrpx4HJTjhAhLP0CXU1rd/t5whwhgT1lYfw77RRG2lZ5BzpHb/XjnY5yc3awd6F3Dli6kTkbcPyOCNoXlW4wiF+jkL+jBImY8xo2EewiJioY/iTYZH5HF+PjHF5mffANiLK/Q43l4f0YF8UagTfAJkD3iQV9lrTOWxKBgpfdyvekGqFCDq9AKzfpllqctxsC29W5bXU0cVYzf6Bj5ALs6tyi7r5fsIPSwszH/i4ixsuD0qccIgTXCwMNbt9zQu</adept:certificate> + <adept:authenticationCertificate>MIIEYDCCA0igAwIBAgIER2q5eTANBgkqhkiG9w0BAQUFADCBhDELMAkGA1UEBhMCVVMxIzAhBgNVBAoTGkFkb2JlIFN5c3RlbXMgSW5jb3Jwb3JhdGVkMRswGQYDVQQLExJEaWdpdGFsIFB1Ymxpc2hpbmcxMzAxBgNVBAMTKkFkb2JlIENvbnRlbnQgU2VydmVyIENlcnRpZmljYXRlIEF1dGhvcml0eTAeFw0wODAxMDkxODQzNDNaFw0xODAxMzEwODAwMDBaMHwxKzApBgNVBAMTImh0dHA6Ly9hZGVhY3RpdmF0ZS5hZG9iZS5jb20vYWRlcHQxGzAZBgNVBAsTEkRpZ2l0YWwgUHVibGlzaGluZzEjMCEGA1UEChMaQWRvYmUgU3lzdGVtcyBJbmNvcnBvcmF0ZWQxCzAJBgNVBAYTAlVTMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDZAxpzOZ7N38ZGlQjfMY/lfu4Ta4xK3FRm069VwdqGZIwrfTTRxnLE4A9i1X00BnNk/5z7C0pQX435ylIEQPxIFBKTH+ip5rfDNh/Iu6cIlB0N4I/t7Pac8cIDwbc9HxcGTvXg3BFqPjaGVbmVZmoUtSVOsphdA43sZc6j1iFfOQIDAQABo4IBYzCCAV8wEgYDVR0TAQH/BAgwBgEB/wIBATAUBgNVHSUEDTALBgkqhkiG9y8CAQUwgbIGA1UdIASBqjCBpzCBpAYJKoZIhvcvAQIDMIGWMIGTBggrBgEFBQcCAjCBhhqBg1lvdSBhcmUgbm90IHBlcm1pdHRlZCB0byB1c2UgdGhpcyBMaWNlbnNlIENlcnRpZmljYXRlIGV4Y2VwdCBhcyBwZXJtaXR0ZWQgYnkgdGhlIGxpY2Vuc2UgYWdyZWVtZW50IGFjY29tcGFueWluZyB0aGUgQWRvYmUgc29mdHdhcmUuMDEGA1UdHwQqMCgwJqAkoCKGIGh0dHA6Ly9jcmwuYWRvYmUuY29tL2Fkb2JlQ1MuY3JsMAsGA1UdDwQEAwIBBjAfBgNVHSMEGDAWgBSL7vCBYMmi2h4OUsFYDASwQ/eP6DAdBgNVHQ4EFgQU9RP19K+lzF03he+0T47hCVkPhdAwDQYJKoZIhvcNAQEFBQADggEBAJoqOj+bUa+bDYyOSljs6SVzWH2BN2ylIeZKpTQYEo7jA62tRqW/rBZcNIgCudFvEYa7vH8lHhvQak1s95g+NaNidb5tpgbS8Q7/XTyEGS/4Q2HYWHD/8ydKFROGbMhfxpdJgkgn21mb7dbsfq5AZVGS3M4PP1xrMDYm50+Sip9QIm1RJuSaKivDa/piA5p8/cv6w44YBefLzGUN674Y7WS5u656MjdyJsN/7Oup+12fHGiye5QS5mToujGd6LpU80gfhNxhrphASiEBYQ/BUhWjHkSi0j4WOiGvGpT1Xvntcj0rf6XV6lNrOddOYUL+KdC1uDIe8PUI+naKI+nWgrs=</adept:authenticationCertificate> + </adept:activationServiceInfo> + +<adept:credentials xmlns:adept="http://ns.adobe.com/adept"> +<adept:user>urn:uuid:2d6cfbec-33fd-43ca-bcf9-e8b281114a17</adept:user> +<adept:username method="AdobeID">adobe@frm01.net</adept:username> +<adept:pkcs12>MIIICgIBAzCCB8MGCSqGSIb3DQEHAaCCB7QEggewMIIHrDCCA3AGCSqGSIb3DQEHAaCCA2EEggNdMIIDWTCCA1UGCyqGSIb3DQEMCgECoIICszCCAq8wKQYKKoZIhvcNAQwBAzAbBBQYnc0dHYbt/zeyPvEbYrhgbYyxgwIDAMNQBIICgFqwh/cekpmgYtd57bU3rUEJEohVOC1OrXVh3j9b8UE7RHwiI04O9D0TZtZv0y6IH4VotY/t0j71JAHpXQwVnyQgSB0zrqi7inwJ8p/xFCPvrS/brzZk4hGmSRMfaeyoaqZhTYHThAFw3Hyz7FqmqU5p8bfggSwQ/xOviU7Ct+nBAfkrpaiNfeTQdY63lMKHghYL4IwmZMs6omaVN0ngMuN4/Nhfp7Ij0FK8SmpMMsRJCXSAAk6VjxNBKlLHwgkA4C+qxdyK7LXLd5JO3lGWpR2x+mBHalYt07xaq6OuuNWQKv0Ho1o75Rv3Blibnj8dvcweb3/3aEP0G3p+BfU2bFKrb3pAn3ClsPO1JJnncYdOLmNdkUlmbHK2RIAgAIqE/aJy1QblRcN34drbbV7FMEHScMdaUf6HVTvEj2TkZRT56GxpI4nhIE9KVzzUrj03COLYkRsfkp1NhfBJC1W324Q9Qd4veQWgpAGzYrpN9KwfQsMvNAEijuV0ExYcDxhcp+8cPcCcyjvm8DICAHKCnHtyDHFTutXR6fMQ8Jphu7uz4Sm++YDXby5M+Kb4luK5u8+PDlqfJ5LGAJ54MlzqGUK0OK/NN9U76ga5ekpFeU5wq2DTCQIZ/M4QuHcaTXpme8YempZzcnFWLh5HD/HDQOddCPoxvinGcjiPxC7MWOMKvWPu/oETHNUWYvCz12O8EycWIi4a0dW6Sa0DlC2S0wBBP2lgvd41/M/CksFuqUjiww9CsBMwzbFlmv0ebi9ZKD7IHVz68s+DV3swIGVq7EKSlCGrHNbthnAeOIlk1lwRUTn09a8cRDo8tomY6cBxxdlyqN24mq0vFhwTfqO2CBgxgY4waQYJKoZIhvcNAQkUMVweWgB1AHIAbgA6AHUAdQBpAGQAOgAyAGQANgBjAGYAYgBlAGMALQAzADMAZgBkAC0ANAAzAGMAYQAtAGIAYwBmADkALQBlADgAYgAyADgAMQAxADEANABhADEANzAhBgkqhkiG9w0BCRUxFAQSVGltZSAxNjU4ODU5ODkzNjE4MIIENAYJKoZIhvcNAQcGoIIEJTCCBCECAQAwggQaBgkqhkiG9w0BBwEwKQYKKoZIhvcNAQwBBjAbBBS6J/ZgKvOxIDg+c1iftQoiDAEjXQIDAMNQgIID4Hvb0y7+KcU6CEWDRPRqY6v9CGWmZxT2Ih2P0azuqio0N3tOb+fl4vymhvcJzdGAG1wTX9c2BpZBM7hMVq1YZuM1/rpdXSnbizBYa+ZzcbbYoNU77yQujwQtcJG1JwZI+VCJMJ+rXCKP+0ebIuCmh7AvcfN2tj48h3TFIeRbeic+YjvqB7RifbnaoVkV56L4k2TeKy1yrTqE8K5I7lICEVJA/ouXWOHdpMcse4SGRZ6n3JmZnC6aCoZTwKydQ0HGW7EvkmK+b3DS8gf3SGLvDEz3k3H41oYvr8zAN40ID7a71wdKHIlDcSeLkzZt6YNZBMXeH8ZlNf3s2qiCX79lRHuKlH7GYjNoUoLlAKO1OSwluxr6qKsLizOrmj7pgledFGYW5iCxVUooXneou/fDJtpOZGVKugPmwT5hL4ouiDI7R7gzWaGDjK0EIorthBTOymwj+hMx5wJ+2g42a0UyD0n73G5e1zRE7hT5axOXULsYMiKTJMCEopRVV70fjAsInBmDOCjIzRsPKtVIrVpOVJIr0zULLqyPucnaeJHpr9sb9hojUqRRZy55wnb5L7JbNLWnRTGLApnmhTx5KmbBTo7UdpyhWUqsApPrhRf3pMXPPBzkEZgeSEp2un3lnPMNhKVpo9lH2Ox206UXlzCYtrK+i+bH1wJdgdoDXzF01ysad8hHAcZJSUNF/i09DaoaFkX3uuPRbiqt5hgYdXb3E3aA5E/ChA80jFjaMLRBbsXSwvn7Ok9LD+kEUOoFvMyz9HrTS3j7fKQRvu20fn3uzyIkUyva46WlNWP/3KGcq1fWarJAuhYgwZbw3o9LB09w87uISN71Wm5pnYpAiFUo48oiTO/PB6F9F8SPiqR8h40Ghjvp7dFm9HzyXjq14T0GBkyG8RaJn9umc4yz1vOt7wPCXyf92cDltlSstpoY+SKrECTMcmnY//b9fyjRiXU4KJ7idSeKmF6thz1SBZ7FzUSoeozPHs+WOmIrVRJDez7J766oJBstqycIq15UVAPGt09ND/WXmhxDyHfZPlrR49YW87CLTFY8MmiOgd/fr+1gTsZqxLLb7L303MKeOQ8Lb0s4bMqGuCLsW/WcniHFhezN7YwyyAsdFhrI/Ugro2uDFlZ3BgAsipaqyzc4kyfGxjkSuIarzxV7huswH8COHSd0Jf9wj8iCLQSw4gX627C9F9dNy0AqT8uwXa/Z78leKUfSbbUB06Veram5y0kXnWGM97WyYKezxpmUHXUagZb5v6zG3o62/ia43tr8YmmUsJ9eyrl3xA+7RkERta/vryBuse5wQhpjd8F/2IxHnSG0MD4wITAJBgUrDgMCGgUABBSD2oMtYGOzFgykxeJda8+qoJQ7BAQUdwkJW7jL0vGmUxZNCAB2k3wM828CAwGGoA==</adept:pkcs12> +<adept:licenseCertificate>MIIDGDCCAoGgAwIBAgIGAYI7wTNyMA0GCSqGSIb3DQEBBQUAMHwxKzApBgNVBAMTImh0dHA6Ly9hZGVhY3RpdmF0ZS5hZG9iZS5jb20vYWRlcHQxGzAZBgNVBAsTEkRpZ2l0YWwgUHVibGlzaGluZzEjMCEGA1UEChMaQWRvYmUgU3lzdGVtcyBJbmNvcnBvcmF0ZWQxCzAJBgNVBAYTAlVTMB4XDTIyMDcyNjE4MjQ1M1oXDTMyMDcyNjE4MjQ1M1owODE2MDQGA1UEAxMtdXJuOnV1aWQ6MmQ2Y2ZiZWMtMzNmZC00M2NhLWJjZjktZThiMjgxMTE0YTE3MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDf+bPePv4GMbGBRssk/3dXktw0nIou8bhWCXha1i+rRi3VpuhHkj02KgBjOaEWEZy3Xkjkv7JGedv2cT0ZShIC6wOvGTsKT2Y3IJpNgWoZzniaWPz1zAGKffe41vjhrVj+8Vbtmt0MhxUbM3uA47echS7Kg9Cp036ydHYX70EeVQIDAQABo4HoMIHlMIG0BgNVHSMEgawwgamAFPUT9fSvpcxdN4XvtE+O4QlZD4XQoYGKpIGHMIGEMQswCQYDVQQGEwJVUzEjMCEGA1UEChMaQWRvYmUgU3lzdGVtcyBJbmNvcnBvcmF0ZWQxGzAZBgNVBAsTEkRpZ2l0YWwgUHVibGlzaGluZzEzMDEGA1UEAxMqQWRvYmUgQ29udGVudCBTZXJ2ZXIgQ2VydGlmaWNhdGUgQXV0aG9yaXR5ggRHarl5MAkGA1UdEwQCMAAwFAYDVR0lBA0wCwYJKoZIhvcvAgEHMAsGA1UdDwQEAwIFIDANBgkqhkiG9w0BAQUFAAOBgQC0lvq2fT3XCu8dB4au2kdQQvMPSVPLet9cS5bF5YSmox4YhLjF8BzBojNinU7fmxAnr5DL4Z4JL2OSf70SL6BOZAZUP8LTf2m3ES5096GGLvGryqNmHIeyublHhAa4sp7ya51NpkAi/Cj765WxORTMY+sF9D92R23Jj+Y8QslG1A==</adept:licenseCertificate> +<adept:privateLicenseKey>MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAN/5s94+/gYxsYFGyyT/d1eS3DScii7xuFYJeFrWL6tGLdWm6EeSPTYqAGM5oRYRnLdeSOS/skZ52/ZxPRlKEgLrA68ZOwpPZjcgmk2BahnOeJpY/PXMAYp997jW+OGtWP7xVu2a3QyHFRsze4Djt5yFLsqD0KnTfrJ0dhfvQR5VAgMBAAECgYBfw07xhnNsSJEBmjg/YG8xZVx7rjay7a0INFJeXFfTXlU4lX2ZJGDBqOGziy9h1TPxfwGhtIjP80hmLXKXPoFGKyTRhf1Z2QsLefX1hhpHhuWI6NxEtQiUiN4oD+igvIWQnPYkRJtth14hvOkl9wtQM6zFG1IV+8hkZf6gJ4c8gQJBAPq3K/UfSjHz1YmIo86wGU8bZHnsdo2uOX0biH3cQ20WsLv2cj6wo/DmFgVAE8hbYkW2yfrfN/ddL1skXTOHnSECQQDksj6mcZyzROW+DGC6csNEMuKVez7/DlWak4M4XwWa8wpQZPAqilNPjmrdK13Bsmxp8TrQDAJt4h/16GrWaEa1AkEAjdgQAJCBU52WVEeAFbG/v+fJgslrkWDemY94O2zgoNlTiCQ4IouhVOt3zeSgzJwXD0YJI+wiJ8sKvc/nAv5YwQJBAJVqp2gTnm+5ueh7Kc9nH5C1Nji3tybo9KDzc64m1wCvfbOc3xTMHzZBNCygIrdknVRyWRyIXCXysTL20KaYpmkCQHNYn681QtlOYC1AyMFcn/w78DmQwTDqlKIyx9oyaRJlEcq6KSeBgu1LJ0pGYq/5EGMYrp0KqMn/qXQ/1OSTY9M=</adept:privateLicenseKey> +<adept:authenticationCertificate>MIIEYDCCA0igAwIBAgIER2q5eTANBgkqhkiG9w0BAQUFADCBhDELMAkGA1UEBhMCVVMxIzAhBgNVBAoTGkFkb2JlIFN5c3RlbXMgSW5jb3Jwb3JhdGVkMRswGQYDVQQLExJEaWdpdGFsIFB1Ymxpc2hpbmcxMzAxBgNVBAMTKkFkb2JlIENvbnRlbnQgU2VydmVyIENlcnRpZmljYXRlIEF1dGhvcml0eTAeFw0wODAxMDkxODQzNDNaFw0xODAxMzEwODAwMDBaMHwxKzApBgNVBAMTImh0dHA6Ly9hZGVhY3RpdmF0ZS5hZG9iZS5jb20vYWRlcHQxGzAZBgNVBAsTEkRpZ2l0YWwgUHVibGlzaGluZzEjMCEGA1UEChMaQWRvYmUgU3lzdGVtcyBJbmNvcnBvcmF0ZWQxCzAJBgNVBAYTAlVTMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDZAxpzOZ7N38ZGlQjfMY/lfu4Ta4xK3FRm069VwdqGZIwrfTTRxnLE4A9i1X00BnNk/5z7C0pQX435ylIEQPxIFBKTH+ip5rfDNh/Iu6cIlB0N4I/t7Pac8cIDwbc9HxcGTvXg3BFqPjaGVbmVZmoUtSVOsphdA43sZc6j1iFfOQIDAQABo4IBYzCCAV8wEgYDVR0TAQH/BAgwBgEB/wIBATAUBgNVHSUEDTALBgkqhkiG9y8CAQUwgbIGA1UdIASBqjCBpzCBpAYJKoZIhvcvAQIDMIGWMIGTBggrBgEFBQcCAjCBhhqBg1lvdSBhcmUgbm90IHBlcm1pdHRlZCB0byB1c2UgdGhpcyBMaWNlbnNlIENlcnRpZmljYXRlIGV4Y2VwdCBhcyBwZXJtaXR0ZWQgYnkgdGhlIGxpY2Vuc2UgYWdyZWVtZW50IGFjY29tcGFueWluZyB0aGUgQWRvYmUgc29mdHdhcmUuMDEGA1UdHwQqMCgwJqAkoCKGIGh0dHA6Ly9jcmwuYWRvYmUuY29tL2Fkb2JlQ1MuY3JsMAsGA1UdDwQEAwIBBjAfBgNVHSMEGDAWgBSL7vCBYMmi2h4OUsFYDASwQ/eP6DAdBgNVHQ4EFgQU9RP19K+lzF03he+0T47hCVkPhdAwDQYJKoZIhvcNAQEFBQADggEBAJoqOj+bUa+bDYyOSljs6SVzWH2BN2ylIeZKpTQYEo7jA62tRqW/rBZcNIgCudFvEYa7vH8lHhvQak1s95g+NaNidb5tpgbS8Q7/XTyEGS/4Q2HYWHD/8ydKFROGbMhfxpdJgkgn21mb7dbsfq5AZVGS3M4PP1xrMDYm50+Sip9QIm1RJuSaKivDa/piA5p8/cv6w44YBefLzGUN674Y7WS5u656MjdyJsN/7Oup+12fHGiye5QS5mToujGd6LpU80gfhNxhrphASiEBYQ/BUhWjHkSi0j4WOiGvGpT1Xvntcj0rf6XV6lNrOddOYUL+KdC1uDIe8PUI+naKI+nWgrs=</adept:authenticationCertificate> +</adept:credentials> + +<activationToken xmlns="http://ns.adobe.com/adept"> + <device>urn:uuid:32095968-696a-46d1-95ef-e76097c33051</device> + <fingerprint>Pa7vI/H67wVERB/TsVjesFE6Kws=</fingerprint> + <deviceType>standalone</deviceType> + <activationURL>http://adeactivate.adobe.com/adept</activationURL> + <user>urn:uuid:2d6cfbec-33fd-43ca-bcf9-e8b281114a17</user> + <signature>B+Y6HxQ3o203HDb/5rSnal6Ca9tE8FEmVyiFcVpE9R7QzHo2NbpFzFHssFd2L+C7HKdFQ4pg+SFxyBLrDpLEdzILfPu+gRsDOvk/AGSisXEvdHsTFK9Yc5Cjkz8WkmWM1N6rgJ30V8AW6/d0mHj81g+Iue8VO8soBPkFwXGX1u4=</signature> +</activationToken> +<adept:operatorURLList xmlns:adept="http://ns.adobe.com/adept"><adept:user>urn:uuid:2d6cfbec-33fd-43ca-bcf9-e8b281114a17</adept:user><adept:operatorURL>https://acs4.kobo.com/fulfillment/Fulfill</adept:operatorURL></adept:operatorURLList><adept:licenseServices xmlns:adept="http://ns.adobe.com/adept"><adept:licenseServiceInfo><adept:licenseURL>https://nasigningservice.adobe.com/licensesign</adept:licenseURL><adept:certificate>MIIEvjCCA6agAwIBAgIER2q5ljANBgkqhkiG9w0BAQUFADCBhDELMAkGA1UEBhMCVVMxIzAhBgNVBAoTGkFkb2JlIFN5c3RlbXMgSW5jb3Jwb3JhdGVkMRswGQYDVQQLExJEaWdpdGFsIFB1Ymxpc2hpbmcxMzAxBgNVBAMTKkFkb2JlIENvbnRlbnQgU2VydmVyIENlcnRpZmljYXRlIEF1dGhvcml0eTAeFw0wODA4MTExNjMzNDhaFw0xMzA4MTEwNzAwMDBaMIGIMQswCQYDVQQGEwJVUzEjMCEGA1UEChMaQWRvYmUgU3lzdGVtcyBJbmNvcnBvcmF0ZWQxGzAZBgNVBAsTEkRpZ2l0YWwgUHVibGlzaGluZzE3MDUGA1UEAxMuaHR0cHM6Ly9uYXNpZ25pbmdzZXJ2aWNlLmFkb2JlLmNvbS9saWNlbnNlc2lnbjCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAs9GRZ1f5UTRySgZ2xAL7TaDKQBfdpIS9ei9Orica0N72BB/WE+82G5lfsZ2HdeCFDZG/oz2WPLXovcuUAbFKSIXVLyc7ONOd4sczeXQYPixeAvqzGtsyMArIzaeJcriGVPRnbD/spbuHR0BHhJEakIiDtQLJz+xgVYHlicx2H/kCAwEAAaOCAbQwggGwMAsGA1UdDwQEAwIFoDBYBglghkgBhvprHgEESwxJVGhlIHByaXZhdGUga2V5IGNvcnJlc3BvbmRpbmcgdG8gdGhpcyBjZXJ0aWZpY2F0ZSBtYXkgaGF2ZSBiZWVuIGV4cG9ydGVkLjAUBgNVHSUEDTALBgkqhkiG9y8CAQIwgbIGA1UdIASBqjCBpzCBpAYJKoZIhvcvAQIDMIGWMIGTBggrBgEFBQcCAjCBhhqBg1lvdSBhcmUgbm90IHBlcm1pdHRlZCB0byB1c2UgdGhpcyBMaWNlbnNlIENlcnRpZmljYXRlIGV4Y2VwdCBhcyBwZXJtaXR0ZWQgYnkgdGhlIGxpY2Vuc2UgYWdyZWVtZW50IGFjY29tcGFueWluZyB0aGUgQWRvYmUgc29mdHdhcmUuMDEGA1UdHwQqMCgwJqAkoCKGIGh0dHA6Ly9jcmwuYWRvYmUuY29tL2Fkb2JlQ1MuY3JsMB8GA1UdIwQYMBaAFIvu8IFgyaLaHg5SwVgMBLBD94/oMB0GA1UdDgQWBBSQ5K+bvggI6Rbh2u9nPhH8bcYTITAJBgNVHRMEAjAAMA0GCSqGSIb3DQEBBQUAA4IBAQC0l1L+BRCccZdb2d9zQBJ7JHkXWt1x/dUydU9I/na+QPFE5x+fGK4cRwaIfp6fNviGyvtJ6Wnxe6du/wlarC1o26UNpyWpnAltcy47LpVXsmcV5rUlhBx10l4lecuX0nx8/xF8joRz2BvvAusK+kxgKeiAjJg2W20wbJKh0Otct1ZihruQsEtGbZJ1L55xfNhrm6CKAHuGuTDYQ/S6W20dUaDUiNFhA2n2eEySLwUwgOuuhfVUPb8amQQKbF4rOQ2rdjAskEl/0CiavW6Xv0LGihThf6CjEbNSdy+vXQ7K9wFbKsE843DflpuSPfj2Aagtyrv/j1HsBjsf03e0uVu5</adept:certificate></adept:licenseServiceInfo></adept:licenseServices></activationInfo> diff --git a/arch-config/.config/calibre/plugins/DeACSM/account/device.xml b/arch-config/.config/calibre/plugins/DeACSM/account/device.xml new file mode 100644 index 00000000..c8915d25 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/account/device.xml @@ -0,0 +1,11 @@ +<?xml version="1.0"?> +<adept:deviceInfo xmlns:adept="http://ns.adobe.com/adept"> + <adept:deviceType>standalone</adept:deviceType> + <adept:deviceClass>Desktop</adept:deviceClass> + <adept:deviceSerial>84abdfab8a0837c803a405f01b2fe493ae7b8c10</adept:deviceSerial> + <adept:deviceName>lupusregina</adept:deviceName> + <adept:version name="hobbes" value="9.3.58046"/> + <adept:version name="clientOS" value="Windows Vista"/> + <adept:version name="clientLocale" value="de"/> + <adept:fingerprint>Pa7vI/H67wVERB/TsVjesFE6Kws=</adept:fingerprint> +</adept:deviceInfo> diff --git a/arch-config/.config/calibre/plugins/DeACSM/account/devicesalt b/arch-config/.config/calibre/plugins/DeACSM/account/devicesalt new file mode 100644 index 00000000..ed0c447a --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/account/devicesalt @@ -0,0 +1 @@ +6(8[hK4w, \ No newline at end of file diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/.gitignore b/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/.gitignore new file mode 100644 index 00000000..b6d1e979 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/.gitignore @@ -0,0 +1,13 @@ +.tox/ +__pycache__/ +build/ +dist/ +tests/output/ +tmp/ +*.egg-info/ +*.pyc +*.pyo +.python-version +.DS_Store +.coverage +coverage.xml diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/LICENSE b/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/LICENSE new file mode 100644 index 00000000..8038d9a7 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2015-2019 Will Bond <will@wbond.net> + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/asn1crypto/__init__.py b/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/asn1crypto/__init__.py new file mode 100644 index 00000000..2c93f00e --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/asn1crypto/__init__.py @@ -0,0 +1,47 @@ +# coding: utf-8 +from __future__ import unicode_literals, division, absolute_import, print_function + +from .version import __version__, __version_info__ + +__all__ = [ + '__version__', + '__version_info__', + 'load_order', +] + + +def load_order(): + """ + Returns a list of the module and sub-module names for asn1crypto in + dependency load order, for the sake of live reloading code + + :return: + A list of unicode strings of module names, as they would appear in + sys.modules, ordered by which module should be reloaded first + """ + + return [ + 'asn1crypto._errors', + 'asn1crypto._int', + 'asn1crypto._ordereddict', + 'asn1crypto._teletex_codec', + 'asn1crypto._types', + 'asn1crypto._inet', + 'asn1crypto._iri', + 'asn1crypto.version', + 'asn1crypto.pem', + 'asn1crypto.util', + 'asn1crypto.parser', + 'asn1crypto.core', + 'asn1crypto.algos', + 'asn1crypto.keys', + 'asn1crypto.x509', + 'asn1crypto.crl', + 'asn1crypto.csr', + 'asn1crypto.ocsp', + 'asn1crypto.cms', + 'asn1crypto.pdf', + 'asn1crypto.pkcs12', + 'asn1crypto.tsp', + 'asn1crypto', + ] diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/asn1crypto/_errors.py b/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/asn1crypto/_errors.py new file mode 100644 index 00000000..d8797a2f --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/asn1crypto/_errors.py @@ -0,0 +1,54 @@ +# coding: utf-8 + +""" +Exports the following items: + + - unwrap() + - APIException() +""" + +from __future__ import unicode_literals, division, absolute_import, print_function + +import re +import textwrap + + +class APIException(Exception): + """ + An exception indicating an API has been removed from asn1crypto + """ + + pass + + +def unwrap(string, *params): + """ + Takes a multi-line string and does the following: + + - dedents + - converts newlines with text before and after into a single line + - strips leading and trailing whitespace + + :param string: + The string to format + + :param *params: + Params to interpolate into the string + + :return: + The formatted string + """ + + output = textwrap.dedent(string) + + # Unwrap lines, taking into account bulleted lists, ordered lists and + # underlines consisting of = signs + if output.find('\n') != -1: + output = re.sub('(?<=\\S)\n(?=[^ \n\t\\d\\*\\-=])', ' ', output) + + if params: + output = output % params + + output = output.strip() + + return output diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/asn1crypto/_inet.py b/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/asn1crypto/_inet.py new file mode 100644 index 00000000..045ba561 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/asn1crypto/_inet.py @@ -0,0 +1,170 @@ +# coding: utf-8 +from __future__ import unicode_literals, division, absolute_import, print_function + +import socket +import struct + +from ._errors import unwrap +from ._types import byte_cls, bytes_to_list, str_cls, type_name + + +def inet_ntop(address_family, packed_ip): + """ + Windows compatibility shim for socket.inet_ntop(). + + :param address_family: + socket.AF_INET for IPv4 or socket.AF_INET6 for IPv6 + + :param packed_ip: + A byte string of the network form of an IP address + + :return: + A unicode string of the IP address + """ + + if address_family not in set([socket.AF_INET, socket.AF_INET6]): + raise ValueError(unwrap( + ''' + address_family must be socket.AF_INET (%s) or socket.AF_INET6 (%s), + not %s + ''', + repr(socket.AF_INET), + repr(socket.AF_INET6), + repr(address_family) + )) + + if not isinstance(packed_ip, byte_cls): + raise TypeError(unwrap( + ''' + packed_ip must be a byte string, not %s + ''', + type_name(packed_ip) + )) + + required_len = 4 if address_family == socket.AF_INET else 16 + if len(packed_ip) != required_len: + raise ValueError(unwrap( + ''' + packed_ip must be %d bytes long - is %d + ''', + required_len, + len(packed_ip) + )) + + if address_family == socket.AF_INET: + return '%d.%d.%d.%d' % tuple(bytes_to_list(packed_ip)) + + octets = struct.unpack(b'!HHHHHHHH', packed_ip) + + runs_of_zero = {} + longest_run = 0 + zero_index = None + for i, octet in enumerate(octets + (-1,)): + if octet != 0: + if zero_index is not None: + length = i - zero_index + if length not in runs_of_zero: + runs_of_zero[length] = zero_index + longest_run = max(longest_run, length) + zero_index = None + elif zero_index is None: + zero_index = i + + hexed = [hex(o)[2:] for o in octets] + + if longest_run < 2: + return ':'.join(hexed) + + zero_start = runs_of_zero[longest_run] + zero_end = zero_start + longest_run + + return ':'.join(hexed[:zero_start]) + '::' + ':'.join(hexed[zero_end:]) + + +def inet_pton(address_family, ip_string): + """ + Windows compatibility shim for socket.inet_ntop(). + + :param address_family: + socket.AF_INET for IPv4 or socket.AF_INET6 for IPv6 + + :param ip_string: + A unicode string of an IP address + + :return: + A byte string of the network form of the IP address + """ + + if address_family not in set([socket.AF_INET, socket.AF_INET6]): + raise ValueError(unwrap( + ''' + address_family must be socket.AF_INET (%s) or socket.AF_INET6 (%s), + not %s + ''', + repr(socket.AF_INET), + repr(socket.AF_INET6), + repr(address_family) + )) + + if not isinstance(ip_string, str_cls): + raise TypeError(unwrap( + ''' + ip_string must be a unicode string, not %s + ''', + type_name(ip_string) + )) + + if address_family == socket.AF_INET: + octets = ip_string.split('.') + error = len(octets) != 4 + if not error: + ints = [] + for o in octets: + o = int(o) + if o > 255 or o < 0: + error = True + break + ints.append(o) + + if error: + raise ValueError(unwrap( + ''' + ip_string must be a dotted string with four integers in the + range of 0 to 255, got %s + ''', + repr(ip_string) + )) + + return struct.pack(b'!BBBB', *ints) + + error = False + omitted = ip_string.count('::') + if omitted > 1: + error = True + elif omitted == 0: + octets = ip_string.split(':') + error = len(octets) != 8 + else: + begin, end = ip_string.split('::') + begin_octets = begin.split(':') + end_octets = end.split(':') + missing = 8 - len(begin_octets) - len(end_octets) + octets = begin_octets + (['0'] * missing) + end_octets + + if not error: + ints = [] + for o in octets: + o = int(o, 16) + if o > 65535 or o < 0: + error = True + break + ints.append(o) + + return struct.pack(b'!HHHHHHHH', *ints) + + raise ValueError(unwrap( + ''' + ip_string must be a valid ipv6 string, got %s + ''', + repr(ip_string) + )) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/asn1crypto/_int.py b/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/asn1crypto/_int.py new file mode 100644 index 00000000..094fc958 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/asn1crypto/_int.py @@ -0,0 +1,22 @@ +# coding: utf-8 +from __future__ import unicode_literals, division, absolute_import, print_function + + +def fill_width(bytes_, width): + """ + Ensure a byte string representing a positive integer is a specific width + (in bytes) + + :param bytes_: + The integer byte string + + :param width: + The desired width as an integer + + :return: + A byte string of the width specified + """ + + while len(bytes_) < width: + bytes_ = b'\x00' + bytes_ + return bytes_ diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/asn1crypto/_iri.py b/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/asn1crypto/_iri.py new file mode 100644 index 00000000..7394b4d5 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/asn1crypto/_iri.py @@ -0,0 +1,291 @@ +# coding: utf-8 + +""" +Functions to convert unicode IRIs into ASCII byte string URIs and back. Exports +the following items: + + - iri_to_uri() + - uri_to_iri() +""" + +from __future__ import unicode_literals, division, absolute_import, print_function + +from encodings import idna # noqa +import codecs +import re +import sys + +from ._errors import unwrap +from ._types import byte_cls, str_cls, type_name, bytes_to_list, int_types + +if sys.version_info < (3,): + from urlparse import urlsplit, urlunsplit + from urllib import ( + quote as urlquote, + unquote as unquote_to_bytes, + ) + +else: + from urllib.parse import ( + quote as urlquote, + unquote_to_bytes, + urlsplit, + urlunsplit, + ) + + +def iri_to_uri(value, normalize=False): + """ + Encodes a unicode IRI into an ASCII byte string URI + + :param value: + A unicode string of an IRI + + :param normalize: + A bool that controls URI normalization + + :return: + A byte string of the ASCII-encoded URI + """ + + if not isinstance(value, str_cls): + raise TypeError(unwrap( + ''' + value must be a unicode string, not %s + ''', + type_name(value) + )) + + scheme = None + # Python 2.6 doesn't split properly is the URL doesn't start with http:// or https:// + if sys.version_info < (2, 7) and not value.startswith('http://') and not value.startswith('https://'): + real_prefix = None + prefix_match = re.match('^[^:]*://', value) + if prefix_match: + real_prefix = prefix_match.group(0) + value = 'http://' + value[len(real_prefix):] + parsed = urlsplit(value) + if real_prefix: + value = real_prefix + value[7:] + scheme = _urlquote(real_prefix[:-3]) + else: + parsed = urlsplit(value) + + if scheme is None: + scheme = _urlquote(parsed.scheme) + hostname = parsed.hostname + if hostname is not None: + hostname = hostname.encode('idna') + # RFC 3986 allows userinfo to contain sub-delims + username = _urlquote(parsed.username, safe='!$&\'()*+,;=') + password = _urlquote(parsed.password, safe='!$&\'()*+,;=') + port = parsed.port + if port is not None: + port = str_cls(port).encode('ascii') + + netloc = b'' + if username is not None: + netloc += username + if password: + netloc += b':' + password + netloc += b'@' + if hostname is not None: + netloc += hostname + if port is not None: + default_http = scheme == b'http' and port == b'80' + default_https = scheme == b'https' and port == b'443' + if not normalize or (not default_http and not default_https): + netloc += b':' + port + + # RFC 3986 allows a path to contain sub-delims, plus "@" and ":" + path = _urlquote(parsed.path, safe='/!$&\'()*+,;=@:') + # RFC 3986 allows the query to contain sub-delims, plus "@", ":" , "/" and "?" + query = _urlquote(parsed.query, safe='/?!$&\'()*+,;=@:') + # RFC 3986 allows the fragment to contain sub-delims, plus "@", ":" , "/" and "?" + fragment = _urlquote(parsed.fragment, safe='/?!$&\'()*+,;=@:') + + if normalize and query is None and fragment is None and path == b'/': + path = None + + # Python 2.7 compat + if path is None: + path = '' + + output = urlunsplit((scheme, netloc, path, query, fragment)) + if isinstance(output, str_cls): + output = output.encode('latin1') + return output + + +def uri_to_iri(value): + """ + Converts an ASCII URI byte string into a unicode IRI + + :param value: + An ASCII-encoded byte string of the URI + + :return: + A unicode string of the IRI + """ + + if not isinstance(value, byte_cls): + raise TypeError(unwrap( + ''' + value must be a byte string, not %s + ''', + type_name(value) + )) + + parsed = urlsplit(value) + + scheme = parsed.scheme + if scheme is not None: + scheme = scheme.decode('ascii') + + username = _urlunquote(parsed.username, remap=[':', '@']) + password = _urlunquote(parsed.password, remap=[':', '@']) + hostname = parsed.hostname + if hostname: + hostname = hostname.decode('idna') + port = parsed.port + if port and not isinstance(port, int_types): + port = port.decode('ascii') + + netloc = '' + if username is not None: + netloc += username + if password: + netloc += ':' + password + netloc += '@' + if hostname is not None: + netloc += hostname + if port is not None: + netloc += ':' + str_cls(port) + + path = _urlunquote(parsed.path, remap=['/'], preserve=True) + query = _urlunquote(parsed.query, remap=['&', '='], preserve=True) + fragment = _urlunquote(parsed.fragment) + + return urlunsplit((scheme, netloc, path, query, fragment)) + + +def _iri_utf8_errors_handler(exc): + """ + Error handler for decoding UTF-8 parts of a URI into an IRI. Leaves byte + sequences encoded in %XX format, but as part of a unicode string. + + :param exc: + The UnicodeDecodeError exception + + :return: + A 2-element tuple of (replacement unicode string, integer index to + resume at) + """ + + bytes_as_ints = bytes_to_list(exc.object[exc.start:exc.end]) + replacements = ['%%%02x' % num for num in bytes_as_ints] + return (''.join(replacements), exc.end) + + +codecs.register_error('iriutf8', _iri_utf8_errors_handler) + + +def _urlquote(string, safe=''): + """ + Quotes a unicode string for use in a URL + + :param string: + A unicode string + + :param safe: + A unicode string of character to not encode + + :return: + None (if string is None) or an ASCII byte string of the quoted string + """ + + if string is None or string == '': + return None + + # Anything already hex quoted is pulled out of the URL and unquoted if + # possible + escapes = [] + if re.search('%[0-9a-fA-F]{2}', string): + # Try to unquote any percent values, restoring them if they are not + # valid UTF-8. Also, requote any safe chars since encoded versions of + # those are functionally different than the unquoted ones. + def _try_unescape(match): + byte_string = unquote_to_bytes(match.group(0)) + unicode_string = byte_string.decode('utf-8', 'iriutf8') + for safe_char in list(safe): + unicode_string = unicode_string.replace(safe_char, '%%%02x' % ord(safe_char)) + return unicode_string + string = re.sub('(?:%[0-9a-fA-F]{2})+', _try_unescape, string) + + # Once we have the minimal set of hex quoted values, removed them from + # the string so that they are not double quoted + def _extract_escape(match): + escapes.append(match.group(0).encode('ascii')) + return '\x00' + string = re.sub('%[0-9a-fA-F]{2}', _extract_escape, string) + + output = urlquote(string.encode('utf-8'), safe=safe.encode('utf-8')) + if not isinstance(output, byte_cls): + output = output.encode('ascii') + + # Restore the existing quoted values that we extracted + if len(escapes) > 0: + def _return_escape(_): + return escapes.pop(0) + output = re.sub(b'%00', _return_escape, output) + + return output + + +def _urlunquote(byte_string, remap=None, preserve=None): + """ + Unquotes a URI portion from a byte string into unicode using UTF-8 + + :param byte_string: + A byte string of the data to unquote + + :param remap: + A list of characters (as unicode) that should be re-mapped to a + %XX encoding. This is used when characters are not valid in part of a + URL. + + :param preserve: + A bool - indicates that the chars to be remapped if they occur in + non-hex form, should be preserved. E.g. / for URL path. + + :return: + A unicode string + """ + + if byte_string is None: + return byte_string + + if byte_string == b'': + return '' + + if preserve: + replacements = ['\x1A', '\x1C', '\x1D', '\x1E', '\x1F'] + preserve_unmap = {} + for char in remap: + replacement = replacements.pop(0) + preserve_unmap[replacement] = char + byte_string = byte_string.replace(char.encode('ascii'), replacement.encode('ascii')) + + byte_string = unquote_to_bytes(byte_string) + + if remap: + for char in remap: + byte_string = byte_string.replace(char.encode('ascii'), ('%%%02x' % ord(char)).encode('ascii')) + + output = byte_string.decode('utf-8', 'iriutf8') + + if preserve: + for replacement, original in preserve_unmap.items(): + output = output.replace(replacement, original) + + return output diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/asn1crypto/_ordereddict.py b/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/asn1crypto/_ordereddict.py new file mode 100644 index 00000000..2f18ab5a --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/asn1crypto/_ordereddict.py @@ -0,0 +1,135 @@ +# Copyright (c) 2009 Raymond Hettinger +# +# Permission is hereby granted, free of charge, to any person +# obtaining a copy of this software and associated documentation files +# (the "Software"), to deal in the Software without restriction, +# including without limitation the rights to use, copy, modify, merge, +# publish, distribute, sublicense, and/or sell copies of the Software, +# and to permit persons to whom the Software is furnished to do so, +# subject to the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +# OTHER DEALINGS IN THE SOFTWARE. + +import sys + +if not sys.version_info < (2, 7): + + from collections import OrderedDict + +else: + + from UserDict import DictMixin + + class OrderedDict(dict, DictMixin): + + def __init__(self, *args, **kwds): + if len(args) > 1: + raise TypeError('expected at most 1 arguments, got %d' % len(args)) + try: + self.__end + except AttributeError: + self.clear() + self.update(*args, **kwds) + + def clear(self): + self.__end = end = [] + end += [None, end, end] # sentinel node for doubly linked list + self.__map = {} # key --> [key, prev, next] + dict.clear(self) + + def __setitem__(self, key, value): + if key not in self: + end = self.__end + curr = end[1] + curr[2] = end[1] = self.__map[key] = [key, curr, end] + dict.__setitem__(self, key, value) + + def __delitem__(self, key): + dict.__delitem__(self, key) + key, prev, next_ = self.__map.pop(key) + prev[2] = next_ + next_[1] = prev + + def __iter__(self): + end = self.__end + curr = end[2] + while curr is not end: + yield curr[0] + curr = curr[2] + + def __reversed__(self): + end = self.__end + curr = end[1] + while curr is not end: + yield curr[0] + curr = curr[1] + + def popitem(self, last=True): + if not self: + raise KeyError('dictionary is empty') + if last: + key = reversed(self).next() + else: + key = iter(self).next() + value = self.pop(key) + return key, value + + def __reduce__(self): + items = [[k, self[k]] for k in self] + tmp = self.__map, self.__end + del self.__map, self.__end + inst_dict = vars(self).copy() + self.__map, self.__end = tmp + if inst_dict: + return (self.__class__, (items,), inst_dict) + return self.__class__, (items,) + + def keys(self): + return list(self) + + setdefault = DictMixin.setdefault + update = DictMixin.update + pop = DictMixin.pop + values = DictMixin.values + items = DictMixin.items + iterkeys = DictMixin.iterkeys + itervalues = DictMixin.itervalues + iteritems = DictMixin.iteritems + + def __repr__(self): + if not self: + return '%s()' % (self.__class__.__name__,) + return '%s(%r)' % (self.__class__.__name__, self.items()) + + def copy(self): + return self.__class__(self) + + @classmethod + def fromkeys(cls, iterable, value=None): + d = cls() + for key in iterable: + d[key] = value + return d + + def __eq__(self, other): + if isinstance(other, OrderedDict): + if len(self) != len(other): + return False + for p, q in zip(self.items(), other.items()): + if p != q: + return False + return True + return dict.__eq__(self, other) + + def __ne__(self, other): + return not self == other diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/asn1crypto/_teletex_codec.py b/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/asn1crypto/_teletex_codec.py new file mode 100644 index 00000000..b5991aaf --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/asn1crypto/_teletex_codec.py @@ -0,0 +1,331 @@ +# coding: utf-8 + +""" +Implementation of the teletex T.61 codec. Exports the following items: + + - register() +""" + +from __future__ import unicode_literals, division, absolute_import, print_function + +import codecs + + +class TeletexCodec(codecs.Codec): + + def encode(self, input_, errors='strict'): + return codecs.charmap_encode(input_, errors, ENCODING_TABLE) + + def decode(self, input_, errors='strict'): + return codecs.charmap_decode(input_, errors, DECODING_TABLE) + + +class TeletexIncrementalEncoder(codecs.IncrementalEncoder): + + def encode(self, input_, final=False): + return codecs.charmap_encode(input_, self.errors, ENCODING_TABLE)[0] + + +class TeletexIncrementalDecoder(codecs.IncrementalDecoder): + + def decode(self, input_, final=False): + return codecs.charmap_decode(input_, self.errors, DECODING_TABLE)[0] + + +class TeletexStreamWriter(TeletexCodec, codecs.StreamWriter): + + pass + + +class TeletexStreamReader(TeletexCodec, codecs.StreamReader): + + pass + + +def teletex_search_function(name): + """ + Search function for teletex codec that is passed to codecs.register() + """ + + if name != 'teletex': + return None + + return codecs.CodecInfo( + name='teletex', + encode=TeletexCodec().encode, + decode=TeletexCodec().decode, + incrementalencoder=TeletexIncrementalEncoder, + incrementaldecoder=TeletexIncrementalDecoder, + streamreader=TeletexStreamReader, + streamwriter=TeletexStreamWriter, + ) + + +def register(): + """ + Registers the teletex codec + """ + + codecs.register(teletex_search_function) + + +# http://en.wikipedia.org/wiki/ITU_T.61 +DECODING_TABLE = ( + '\u0000' + '\u0001' + '\u0002' + '\u0003' + '\u0004' + '\u0005' + '\u0006' + '\u0007' + '\u0008' + '\u0009' + '\u000A' + '\u000B' + '\u000C' + '\u000D' + '\u000E' + '\u000F' + '\u0010' + '\u0011' + '\u0012' + '\u0013' + '\u0014' + '\u0015' + '\u0016' + '\u0017' + '\u0018' + '\u0019' + '\u001A' + '\u001B' + '\u001C' + '\u001D' + '\u001E' + '\u001F' + '\u0020' + '\u0021' + '\u0022' + '\ufffe' + '\ufffe' + '\u0025' + '\u0026' + '\u0027' + '\u0028' + '\u0029' + '\u002A' + '\u002B' + '\u002C' + '\u002D' + '\u002E' + '\u002F' + '\u0030' + '\u0031' + '\u0032' + '\u0033' + '\u0034' + '\u0035' + '\u0036' + '\u0037' + '\u0038' + '\u0039' + '\u003A' + '\u003B' + '\u003C' + '\u003D' + '\u003E' + '\u003F' + '\u0040' + '\u0041' + '\u0042' + '\u0043' + '\u0044' + '\u0045' + '\u0046' + '\u0047' + '\u0048' + '\u0049' + '\u004A' + '\u004B' + '\u004C' + '\u004D' + '\u004E' + '\u004F' + '\u0050' + '\u0051' + '\u0052' + '\u0053' + '\u0054' + '\u0055' + '\u0056' + '\u0057' + '\u0058' + '\u0059' + '\u005A' + '\u005B' + '\ufffe' + '\u005D' + '\ufffe' + '\u005F' + '\ufffe' + '\u0061' + '\u0062' + '\u0063' + '\u0064' + '\u0065' + '\u0066' + '\u0067' + '\u0068' + '\u0069' + '\u006A' + '\u006B' + '\u006C' + '\u006D' + '\u006E' + '\u006F' + '\u0070' + '\u0071' + '\u0072' + '\u0073' + '\u0074' + '\u0075' + '\u0076' + '\u0077' + '\u0078' + '\u0079' + '\u007A' + '\ufffe' + '\u007C' + '\ufffe' + '\ufffe' + '\u007F' + '\u0080' + '\u0081' + '\u0082' + '\u0083' + '\u0084' + '\u0085' + '\u0086' + '\u0087' + '\u0088' + '\u0089' + '\u008A' + '\u008B' + '\u008C' + '\u008D' + '\u008E' + '\u008F' + '\u0090' + '\u0091' + '\u0092' + '\u0093' + '\u0094' + '\u0095' + '\u0096' + '\u0097' + '\u0098' + '\u0099' + '\u009A' + '\u009B' + '\u009C' + '\u009D' + '\u009E' + '\u009F' + '\u00A0' + '\u00A1' + '\u00A2' + '\u00A3' + '\u0024' + '\u00A5' + '\u0023' + '\u00A7' + '\u00A4' + '\ufffe' + '\ufffe' + '\u00AB' + '\ufffe' + '\ufffe' + '\ufffe' + '\ufffe' + '\u00B0' + '\u00B1' + '\u00B2' + '\u00B3' + '\u00D7' + '\u00B5' + '\u00B6' + '\u00B7' + '\u00F7' + '\ufffe' + '\ufffe' + '\u00BB' + '\u00BC' + '\u00BD' + '\u00BE' + '\u00BF' + '\ufffe' + '\u0300' + '\u0301' + '\u0302' + '\u0303' + '\u0304' + '\u0306' + '\u0307' + '\u0308' + '\ufffe' + '\u030A' + '\u0327' + '\u0332' + '\u030B' + '\u0328' + '\u030C' + '\ufffe' + '\ufffe' + '\ufffe' + '\ufffe' + '\ufffe' + '\ufffe' + '\ufffe' + '\ufffe' + '\ufffe' + '\ufffe' + '\ufffe' + '\ufffe' + '\ufffe' + '\ufffe' + '\ufffe' + '\ufffe' + '\u2126' + '\u00C6' + '\u00D0' + '\u00AA' + '\u0126' + '\ufffe' + '\u0132' + '\u013F' + '\u0141' + '\u00D8' + '\u0152' + '\u00BA' + '\u00DE' + '\u0166' + '\u014A' + '\u0149' + '\u0138' + '\u00E6' + '\u0111' + '\u00F0' + '\u0127' + '\u0131' + '\u0133' + '\u0140' + '\u0142' + '\u00F8' + '\u0153' + '\u00DF' + '\u00FE' + '\u0167' + '\u014B' + '\ufffe' +) +ENCODING_TABLE = codecs.charmap_build(DECODING_TABLE) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/asn1crypto/_types.py b/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/asn1crypto/_types.py new file mode 100644 index 00000000..b9ca8cc7 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/asn1crypto/_types.py @@ -0,0 +1,46 @@ +# coding: utf-8 +from __future__ import unicode_literals, division, absolute_import, print_function + +import inspect +import sys + + +if sys.version_info < (3,): + str_cls = unicode # noqa + byte_cls = str + int_types = (int, long) # noqa + + def bytes_to_list(byte_string): + return [ord(b) for b in byte_string] + + chr_cls = chr + +else: + str_cls = str + byte_cls = bytes + int_types = int + + bytes_to_list = list + + def chr_cls(num): + return bytes([num]) + + +def type_name(value): + """ + Returns a user-readable name for the type of an object + + :param value: + A value to get the type name of + + :return: + A unicode string of the object's type name + """ + + if inspect.isclass(value): + cls = value + else: + cls = value.__class__ + if cls.__module__ in set(['builtins', '__builtin__']): + return cls.__name__ + return '%s.%s' % (cls.__module__, cls.__name__) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/asn1crypto/algos.py b/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/asn1crypto/algos.py new file mode 100644 index 00000000..cdd0020a --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/asn1crypto/algos.py @@ -0,0 +1,1189 @@ +# coding: utf-8 + +""" +ASN.1 type classes for various algorithms using in various aspects of public +key cryptography. Exports the following items: + + - AlgorithmIdentifier() + - AnyAlgorithmIdentifier() + - DigestAlgorithm() + - DigestInfo() + - DSASignature() + - EncryptionAlgorithm() + - HmacAlgorithm() + - KdfAlgorithm() + - Pkcs5MacAlgorithm() + - SignedDigestAlgorithm() + +Other type classes are defined that help compose the types listed above. +""" + +from __future__ import unicode_literals, division, absolute_import, print_function + +from ._errors import unwrap +from ._int import fill_width +from .util import int_from_bytes, int_to_bytes +from .core import ( + Any, + Choice, + Integer, + Null, + ObjectIdentifier, + OctetString, + Sequence, + Void, +) + + +# Structures and OIDs in this file are pulled from +# https://tools.ietf.org/html/rfc3279, https://tools.ietf.org/html/rfc4055, +# https://tools.ietf.org/html/rfc5758, https://tools.ietf.org/html/rfc7292, +# http://www.emc.com/collateral/white-papers/h11302-pkcs5v2-1-password-based-cryptography-standard-wp.pdf + +class AlgorithmIdentifier(Sequence): + _fields = [ + ('algorithm', ObjectIdentifier), + ('parameters', Any, {'optional': True}), + ] + + +class _ForceNullParameters(object): + """ + Various structures based on AlgorithmIdentifier require that the parameters + field be core.Null() for certain OIDs. This mixin ensures that happens. + """ + + # The following attribute, plus the parameters spec callback and custom + # __setitem__ are all to handle a situation where parameters should not be + # optional and must be Null for certain OIDs. More info at + # https://tools.ietf.org/html/rfc4055#page-15 and + # https://tools.ietf.org/html/rfc4055#section-2.1 + _null_algos = set([ + '1.2.840.113549.1.1.1', # rsassa_pkcs1v15 / rsaes_pkcs1v15 / rsa + '1.2.840.113549.1.1.11', # sha256_rsa + '1.2.840.113549.1.1.12', # sha384_rsa + '1.2.840.113549.1.1.13', # sha512_rsa + '1.2.840.113549.1.1.14', # sha224_rsa + '1.3.14.3.2.26', # sha1 + '2.16.840.1.101.3.4.2.4', # sha224 + '2.16.840.1.101.3.4.2.1', # sha256 + '2.16.840.1.101.3.4.2.2', # sha384 + '2.16.840.1.101.3.4.2.3', # sha512 + ]) + + def _parameters_spec(self): + if self._oid_pair == ('algorithm', 'parameters'): + algo = self['algorithm'].native + if algo in self._oid_specs: + return self._oid_specs[algo] + + if self['algorithm'].dotted in self._null_algos: + return Null + + return None + + _spec_callbacks = { + 'parameters': _parameters_spec + } + + # We have to override this since the spec callback uses the value of + # algorithm to determine the parameter spec, however default values are + # assigned before setting a field, so a default value can't be based on + # another field value (unless it is a default also). Thus we have to + # manually check to see if the algorithm was set and parameters is unset, + # and then fix the value as appropriate. + def __setitem__(self, key, value): + res = super(_ForceNullParameters, self).__setitem__(key, value) + if key != 'algorithm': + return res + if self['algorithm'].dotted not in self._null_algos: + return res + if self['parameters'].__class__ != Void: + return res + self['parameters'] = Null() + return res + + +class HmacAlgorithmId(ObjectIdentifier): + _map = { + '1.3.14.3.2.10': 'des_mac', + '1.2.840.113549.2.7': 'sha1', + '1.2.840.113549.2.8': 'sha224', + '1.2.840.113549.2.9': 'sha256', + '1.2.840.113549.2.10': 'sha384', + '1.2.840.113549.2.11': 'sha512', + '1.2.840.113549.2.12': 'sha512_224', + '1.2.840.113549.2.13': 'sha512_256', + '2.16.840.1.101.3.4.2.13': 'sha3_224', + '2.16.840.1.101.3.4.2.14': 'sha3_256', + '2.16.840.1.101.3.4.2.15': 'sha3_384', + '2.16.840.1.101.3.4.2.16': 'sha3_512', + } + + +class HmacAlgorithm(Sequence): + _fields = [ + ('algorithm', HmacAlgorithmId), + ('parameters', Any, {'optional': True}), + ] + + +class DigestAlgorithmId(ObjectIdentifier): + _map = { + '1.2.840.113549.2.2': 'md2', + '1.2.840.113549.2.5': 'md5', + '1.3.14.3.2.26': 'sha1', + '2.16.840.1.101.3.4.2.4': 'sha224', + '2.16.840.1.101.3.4.2.1': 'sha256', + '2.16.840.1.101.3.4.2.2': 'sha384', + '2.16.840.1.101.3.4.2.3': 'sha512', + '2.16.840.1.101.3.4.2.5': 'sha512_224', + '2.16.840.1.101.3.4.2.6': 'sha512_256', + '2.16.840.1.101.3.4.2.7': 'sha3_224', + '2.16.840.1.101.3.4.2.8': 'sha3_256', + '2.16.840.1.101.3.4.2.9': 'sha3_384', + '2.16.840.1.101.3.4.2.10': 'sha3_512', + '2.16.840.1.101.3.4.2.11': 'shake128', + '2.16.840.1.101.3.4.2.12': 'shake256', + '2.16.840.1.101.3.4.2.17': 'shake128_len', + '2.16.840.1.101.3.4.2.18': 'shake256_len', + } + + +class DigestAlgorithm(_ForceNullParameters, Sequence): + _fields = [ + ('algorithm', DigestAlgorithmId), + ('parameters', Any, {'optional': True}), + ] + + +# This structure is what is signed with a SignedDigestAlgorithm +class DigestInfo(Sequence): + _fields = [ + ('digest_algorithm', DigestAlgorithm), + ('digest', OctetString), + ] + + +class MaskGenAlgorithmId(ObjectIdentifier): + _map = { + '1.2.840.113549.1.1.8': 'mgf1', + } + + +class MaskGenAlgorithm(Sequence): + _fields = [ + ('algorithm', MaskGenAlgorithmId), + ('parameters', Any, {'optional': True}), + ] + + _oid_pair = ('algorithm', 'parameters') + _oid_specs = { + 'mgf1': DigestAlgorithm + } + + +class TrailerField(Integer): + _map = { + 1: 'trailer_field_bc', + } + + +class RSASSAPSSParams(Sequence): + _fields = [ + ( + 'hash_algorithm', + DigestAlgorithm, + { + 'explicit': 0, + 'default': {'algorithm': 'sha1'}, + } + ), + ( + 'mask_gen_algorithm', + MaskGenAlgorithm, + { + 'explicit': 1, + 'default': { + 'algorithm': 'mgf1', + 'parameters': {'algorithm': 'sha1'}, + }, + } + ), + ( + 'salt_length', + Integer, + { + 'explicit': 2, + 'default': 20, + } + ), + ( + 'trailer_field', + TrailerField, + { + 'explicit': 3, + 'default': 'trailer_field_bc', + } + ), + ] + + +class SignedDigestAlgorithmId(ObjectIdentifier): + _map = { + '1.3.14.3.2.3': 'md5_rsa', + '1.3.14.3.2.29': 'sha1_rsa', + '1.3.14.7.2.3.1': 'md2_rsa', + '1.2.840.113549.1.1.2': 'md2_rsa', + '1.2.840.113549.1.1.4': 'md5_rsa', + '1.2.840.113549.1.1.5': 'sha1_rsa', + '1.2.840.113549.1.1.14': 'sha224_rsa', + '1.2.840.113549.1.1.11': 'sha256_rsa', + '1.2.840.113549.1.1.12': 'sha384_rsa', + '1.2.840.113549.1.1.13': 'sha512_rsa', + '1.2.840.113549.1.1.10': 'rsassa_pss', + '1.2.840.10040.4.3': 'sha1_dsa', + '1.3.14.3.2.13': 'sha1_dsa', + '1.3.14.3.2.27': 'sha1_dsa', + '2.16.840.1.101.3.4.3.1': 'sha224_dsa', + '2.16.840.1.101.3.4.3.2': 'sha256_dsa', + '1.2.840.10045.4.1': 'sha1_ecdsa', + '1.2.840.10045.4.3.1': 'sha224_ecdsa', + '1.2.840.10045.4.3.2': 'sha256_ecdsa', + '1.2.840.10045.4.3.3': 'sha384_ecdsa', + '1.2.840.10045.4.3.4': 'sha512_ecdsa', + '2.16.840.1.101.3.4.3.9': 'sha3_224_ecdsa', + '2.16.840.1.101.3.4.3.10': 'sha3_256_ecdsa', + '2.16.840.1.101.3.4.3.11': 'sha3_384_ecdsa', + '2.16.840.1.101.3.4.3.12': 'sha3_512_ecdsa', + # For when the digest is specified elsewhere in a Sequence + '1.2.840.113549.1.1.1': 'rsassa_pkcs1v15', + '1.2.840.10040.4.1': 'dsa', + '1.2.840.10045.4': 'ecdsa', + # RFC 8410 -- https://tools.ietf.org/html/rfc8410 + '1.3.101.112': 'ed25519', + '1.3.101.113': 'ed448', + } + + _reverse_map = { + 'dsa': '1.2.840.10040.4.1', + 'ecdsa': '1.2.840.10045.4', + 'md2_rsa': '1.2.840.113549.1.1.2', + 'md5_rsa': '1.2.840.113549.1.1.4', + 'rsassa_pkcs1v15': '1.2.840.113549.1.1.1', + 'rsassa_pss': '1.2.840.113549.1.1.10', + 'sha1_dsa': '1.2.840.10040.4.3', + 'sha1_ecdsa': '1.2.840.10045.4.1', + 'sha1_rsa': '1.2.840.113549.1.1.5', + 'sha224_dsa': '2.16.840.1.101.3.4.3.1', + 'sha224_ecdsa': '1.2.840.10045.4.3.1', + 'sha224_rsa': '1.2.840.113549.1.1.14', + 'sha256_dsa': '2.16.840.1.101.3.4.3.2', + 'sha256_ecdsa': '1.2.840.10045.4.3.2', + 'sha256_rsa': '1.2.840.113549.1.1.11', + 'sha384_ecdsa': '1.2.840.10045.4.3.3', + 'sha384_rsa': '1.2.840.113549.1.1.12', + 'sha512_ecdsa': '1.2.840.10045.4.3.4', + 'sha512_rsa': '1.2.840.113549.1.1.13', + 'sha3_224_ecdsa': '2.16.840.1.101.3.4.3.9', + 'sha3_256_ecdsa': '2.16.840.1.101.3.4.3.10', + 'sha3_384_ecdsa': '2.16.840.1.101.3.4.3.11', + 'sha3_512_ecdsa': '2.16.840.1.101.3.4.3.12', + 'ed25519': '1.3.101.112', + 'ed448': '1.3.101.113', + } + + +class SignedDigestAlgorithm(_ForceNullParameters, Sequence): + _fields = [ + ('algorithm', SignedDigestAlgorithmId), + ('parameters', Any, {'optional': True}), + ] + + _oid_pair = ('algorithm', 'parameters') + _oid_specs = { + 'rsassa_pss': RSASSAPSSParams, + } + + @property + def signature_algo(self): + """ + :return: + A unicode string of "rsassa_pkcs1v15", "rsassa_pss", "dsa", + "ecdsa", "ed25519" or "ed448" + """ + + algorithm = self['algorithm'].native + + algo_map = { + 'md2_rsa': 'rsassa_pkcs1v15', + 'md5_rsa': 'rsassa_pkcs1v15', + 'sha1_rsa': 'rsassa_pkcs1v15', + 'sha224_rsa': 'rsassa_pkcs1v15', + 'sha256_rsa': 'rsassa_pkcs1v15', + 'sha384_rsa': 'rsassa_pkcs1v15', + 'sha512_rsa': 'rsassa_pkcs1v15', + 'rsassa_pkcs1v15': 'rsassa_pkcs1v15', + 'rsassa_pss': 'rsassa_pss', + 'sha1_dsa': 'dsa', + 'sha224_dsa': 'dsa', + 'sha256_dsa': 'dsa', + 'dsa': 'dsa', + 'sha1_ecdsa': 'ecdsa', + 'sha224_ecdsa': 'ecdsa', + 'sha256_ecdsa': 'ecdsa', + 'sha384_ecdsa': 'ecdsa', + 'sha512_ecdsa': 'ecdsa', + 'sha3_224_ecdsa': 'ecdsa', + 'sha3_256_ecdsa': 'ecdsa', + 'sha3_384_ecdsa': 'ecdsa', + 'sha3_512_ecdsa': 'ecdsa', + 'ecdsa': 'ecdsa', + 'ed25519': 'ed25519', + 'ed448': 'ed448', + } + if algorithm in algo_map: + return algo_map[algorithm] + + raise ValueError(unwrap( + ''' + Signature algorithm not known for %s + ''', + algorithm + )) + + @property + def hash_algo(self): + """ + :return: + A unicode string of "md2", "md5", "sha1", "sha224", "sha256", + "sha384", "sha512", "sha512_224", "sha512_256" or "shake256" + """ + + algorithm = self['algorithm'].native + + algo_map = { + 'md2_rsa': 'md2', + 'md5_rsa': 'md5', + 'sha1_rsa': 'sha1', + 'sha224_rsa': 'sha224', + 'sha256_rsa': 'sha256', + 'sha384_rsa': 'sha384', + 'sha512_rsa': 'sha512', + 'sha1_dsa': 'sha1', + 'sha224_dsa': 'sha224', + 'sha256_dsa': 'sha256', + 'sha1_ecdsa': 'sha1', + 'sha224_ecdsa': 'sha224', + 'sha256_ecdsa': 'sha256', + 'sha384_ecdsa': 'sha384', + 'sha512_ecdsa': 'sha512', + 'ed25519': 'sha512', + 'ed448': 'shake256', + } + if algorithm in algo_map: + return algo_map[algorithm] + + if algorithm == 'rsassa_pss': + return self['parameters']['hash_algorithm']['algorithm'].native + + raise ValueError(unwrap( + ''' + Hash algorithm not known for %s + ''', + algorithm + )) + + +class Pbkdf2Salt(Choice): + _alternatives = [ + ('specified', OctetString), + ('other_source', AlgorithmIdentifier), + ] + + +class Pbkdf2Params(Sequence): + _fields = [ + ('salt', Pbkdf2Salt), + ('iteration_count', Integer), + ('key_length', Integer, {'optional': True}), + ('prf', HmacAlgorithm, {'default': {'algorithm': 'sha1'}}), + ] + + +class KdfAlgorithmId(ObjectIdentifier): + _map = { + '1.2.840.113549.1.5.12': 'pbkdf2' + } + + +class KdfAlgorithm(Sequence): + _fields = [ + ('algorithm', KdfAlgorithmId), + ('parameters', Any, {'optional': True}), + ] + _oid_pair = ('algorithm', 'parameters') + _oid_specs = { + 'pbkdf2': Pbkdf2Params + } + + +class DHParameters(Sequence): + """ + Original Name: DHParameter + Source: ftp://ftp.rsasecurity.com/pub/pkcs/ascii/pkcs-3.asc section 9 + """ + + _fields = [ + ('p', Integer), + ('g', Integer), + ('private_value_length', Integer, {'optional': True}), + ] + + +class KeyExchangeAlgorithmId(ObjectIdentifier): + _map = { + '1.2.840.113549.1.3.1': 'dh', + } + + +class KeyExchangeAlgorithm(Sequence): + _fields = [ + ('algorithm', KeyExchangeAlgorithmId), + ('parameters', Any, {'optional': True}), + ] + _oid_pair = ('algorithm', 'parameters') + _oid_specs = { + 'dh': DHParameters, + } + + +class Rc2Params(Sequence): + _fields = [ + ('rc2_parameter_version', Integer, {'optional': True}), + ('iv', OctetString), + ] + + +class Rc5ParamVersion(Integer): + _map = { + 16: 'v1-0' + } + + +class Rc5Params(Sequence): + _fields = [ + ('version', Rc5ParamVersion), + ('rounds', Integer), + ('block_size_in_bits', Integer), + ('iv', OctetString, {'optional': True}), + ] + + +class Pbes1Params(Sequence): + _fields = [ + ('salt', OctetString), + ('iterations', Integer), + ] + + +class CcmParams(Sequence): + # https://tools.ietf.org/html/rfc5084 + # aes_ICVlen: 4 | 6 | 8 | 10 | 12 | 14 | 16 + _fields = [ + ('aes_nonce', OctetString), + ('aes_icvlen', Integer), + ] + + +class PSourceAlgorithmId(ObjectIdentifier): + _map = { + '1.2.840.113549.1.1.9': 'p_specified', + } + + +class PSourceAlgorithm(Sequence): + _fields = [ + ('algorithm', PSourceAlgorithmId), + ('parameters', Any, {'optional': True}), + ] + + _oid_pair = ('algorithm', 'parameters') + _oid_specs = { + 'p_specified': OctetString + } + + +class RSAESOAEPParams(Sequence): + _fields = [ + ( + 'hash_algorithm', + DigestAlgorithm, + { + 'explicit': 0, + 'default': {'algorithm': 'sha1'} + } + ), + ( + 'mask_gen_algorithm', + MaskGenAlgorithm, + { + 'explicit': 1, + 'default': { + 'algorithm': 'mgf1', + 'parameters': {'algorithm': 'sha1'} + } + } + ), + ( + 'p_source_algorithm', + PSourceAlgorithm, + { + 'explicit': 2, + 'default': { + 'algorithm': 'p_specified', + 'parameters': b'' + } + } + ), + ] + + +class DSASignature(Sequence): + """ + An ASN.1 class for translating between the OS crypto library's + representation of an (EC)DSA signature and the ASN.1 structure that is part + of various RFCs. + + Original Name: DSS-Sig-Value + Source: https://tools.ietf.org/html/rfc3279#section-2.2.2 + """ + + _fields = [ + ('r', Integer), + ('s', Integer), + ] + + @classmethod + def from_p1363(cls, data): + """ + Reads a signature from a byte string encoding accordint to IEEE P1363, + which is used by Microsoft's BCryptSignHash() function. + + :param data: + A byte string from BCryptSignHash() + + :return: + A DSASignature object + """ + + r = int_from_bytes(data[0:len(data) // 2]) + s = int_from_bytes(data[len(data) // 2:]) + return cls({'r': r, 's': s}) + + def to_p1363(self): + """ + Dumps a signature to a byte string compatible with Microsoft's + BCryptVerifySignature() function. + + :return: + A byte string compatible with BCryptVerifySignature() + """ + + r_bytes = int_to_bytes(self['r'].native) + s_bytes = int_to_bytes(self['s'].native) + + int_byte_length = max(len(r_bytes), len(s_bytes)) + r_bytes = fill_width(r_bytes, int_byte_length) + s_bytes = fill_width(s_bytes, int_byte_length) + + return r_bytes + s_bytes + + +class EncryptionAlgorithmId(ObjectIdentifier): + _map = { + '1.3.14.3.2.7': 'des', + '1.2.840.113549.3.7': 'tripledes_3key', + '1.2.840.113549.3.2': 'rc2', + '1.2.840.113549.3.4': 'rc4', + '1.2.840.113549.3.9': 'rc5', + # From http://csrc.nist.gov/groups/ST/crypto_apps_infra/csor/algorithms.html#AES + '2.16.840.1.101.3.4.1.1': 'aes128_ecb', + '2.16.840.1.101.3.4.1.2': 'aes128_cbc', + '2.16.840.1.101.3.4.1.3': 'aes128_ofb', + '2.16.840.1.101.3.4.1.4': 'aes128_cfb', + '2.16.840.1.101.3.4.1.5': 'aes128_wrap', + '2.16.840.1.101.3.4.1.6': 'aes128_gcm', + '2.16.840.1.101.3.4.1.7': 'aes128_ccm', + '2.16.840.1.101.3.4.1.8': 'aes128_wrap_pad', + '2.16.840.1.101.3.4.1.21': 'aes192_ecb', + '2.16.840.1.101.3.4.1.22': 'aes192_cbc', + '2.16.840.1.101.3.4.1.23': 'aes192_ofb', + '2.16.840.1.101.3.4.1.24': 'aes192_cfb', + '2.16.840.1.101.3.4.1.25': 'aes192_wrap', + '2.16.840.1.101.3.4.1.26': 'aes192_gcm', + '2.16.840.1.101.3.4.1.27': 'aes192_ccm', + '2.16.840.1.101.3.4.1.28': 'aes192_wrap_pad', + '2.16.840.1.101.3.4.1.41': 'aes256_ecb', + '2.16.840.1.101.3.4.1.42': 'aes256_cbc', + '2.16.840.1.101.3.4.1.43': 'aes256_ofb', + '2.16.840.1.101.3.4.1.44': 'aes256_cfb', + '2.16.840.1.101.3.4.1.45': 'aes256_wrap', + '2.16.840.1.101.3.4.1.46': 'aes256_gcm', + '2.16.840.1.101.3.4.1.47': 'aes256_ccm', + '2.16.840.1.101.3.4.1.48': 'aes256_wrap_pad', + # From PKCS#5 + '1.2.840.113549.1.5.13': 'pbes2', + '1.2.840.113549.1.5.1': 'pbes1_md2_des', + '1.2.840.113549.1.5.3': 'pbes1_md5_des', + '1.2.840.113549.1.5.4': 'pbes1_md2_rc2', + '1.2.840.113549.1.5.6': 'pbes1_md5_rc2', + '1.2.840.113549.1.5.10': 'pbes1_sha1_des', + '1.2.840.113549.1.5.11': 'pbes1_sha1_rc2', + # From PKCS#12 + '1.2.840.113549.1.12.1.1': 'pkcs12_sha1_rc4_128', + '1.2.840.113549.1.12.1.2': 'pkcs12_sha1_rc4_40', + '1.2.840.113549.1.12.1.3': 'pkcs12_sha1_tripledes_3key', + '1.2.840.113549.1.12.1.4': 'pkcs12_sha1_tripledes_2key', + '1.2.840.113549.1.12.1.5': 'pkcs12_sha1_rc2_128', + '1.2.840.113549.1.12.1.6': 'pkcs12_sha1_rc2_40', + # PKCS#1 v2.2 + '1.2.840.113549.1.1.1': 'rsaes_pkcs1v15', + '1.2.840.113549.1.1.7': 'rsaes_oaep', + } + + +class EncryptionAlgorithm(_ForceNullParameters, Sequence): + _fields = [ + ('algorithm', EncryptionAlgorithmId), + ('parameters', Any, {'optional': True}), + ] + + _oid_pair = ('algorithm', 'parameters') + _oid_specs = { + 'des': OctetString, + 'tripledes_3key': OctetString, + 'rc2': Rc2Params, + 'rc5': Rc5Params, + 'aes128_cbc': OctetString, + 'aes192_cbc': OctetString, + 'aes256_cbc': OctetString, + 'aes128_ofb': OctetString, + 'aes192_ofb': OctetString, + 'aes256_ofb': OctetString, + # From RFC5084 + 'aes128_ccm': CcmParams, + 'aes192_ccm': CcmParams, + 'aes256_ccm': CcmParams, + # From PKCS#5 + 'pbes1_md2_des': Pbes1Params, + 'pbes1_md5_des': Pbes1Params, + 'pbes1_md2_rc2': Pbes1Params, + 'pbes1_md5_rc2': Pbes1Params, + 'pbes1_sha1_des': Pbes1Params, + 'pbes1_sha1_rc2': Pbes1Params, + # From PKCS#12 + 'pkcs12_sha1_rc4_128': Pbes1Params, + 'pkcs12_sha1_rc4_40': Pbes1Params, + 'pkcs12_sha1_tripledes_3key': Pbes1Params, + 'pkcs12_sha1_tripledes_2key': Pbes1Params, + 'pkcs12_sha1_rc2_128': Pbes1Params, + 'pkcs12_sha1_rc2_40': Pbes1Params, + # PKCS#1 v2.2 + 'rsaes_oaep': RSAESOAEPParams, + } + + @property + def kdf(self): + """ + Returns the name of the key derivation function to use. + + :return: + A unicode from of one of the following: "pbkdf1", "pbkdf2", + "pkcs12_kdf" + """ + + encryption_algo = self['algorithm'].native + + if encryption_algo == 'pbes2': + return self['parameters']['key_derivation_func']['algorithm'].native + + if encryption_algo.find('.') == -1: + if encryption_algo.find('_') != -1: + encryption_algo, _ = encryption_algo.split('_', 1) + + if encryption_algo == 'pbes1': + return 'pbkdf1' + + if encryption_algo == 'pkcs12': + return 'pkcs12_kdf' + + raise ValueError(unwrap( + ''' + Encryption algorithm "%s" does not have a registered key + derivation function + ''', + encryption_algo + )) + + raise ValueError(unwrap( + ''' + Unrecognized encryption algorithm "%s", can not determine key + derivation function + ''', + encryption_algo + )) + + @property + def kdf_hmac(self): + """ + Returns the HMAC algorithm to use with the KDF. + + :return: + A unicode string of one of the following: "md2", "md5", "sha1", + "sha224", "sha256", "sha384", "sha512" + """ + + encryption_algo = self['algorithm'].native + + if encryption_algo == 'pbes2': + return self['parameters']['key_derivation_func']['parameters']['prf']['algorithm'].native + + if encryption_algo.find('.') == -1: + if encryption_algo.find('_') != -1: + _, hmac_algo, _ = encryption_algo.split('_', 2) + return hmac_algo + + raise ValueError(unwrap( + ''' + Encryption algorithm "%s" does not have a registered key + derivation function + ''', + encryption_algo + )) + + raise ValueError(unwrap( + ''' + Unrecognized encryption algorithm "%s", can not determine key + derivation hmac algorithm + ''', + encryption_algo + )) + + @property + def kdf_salt(self): + """ + Returns the byte string to use as the salt for the KDF. + + :return: + A byte string + """ + + encryption_algo = self['algorithm'].native + + if encryption_algo == 'pbes2': + salt = self['parameters']['key_derivation_func']['parameters']['salt'] + + if salt.name == 'other_source': + raise ValueError(unwrap( + ''' + Can not determine key derivation salt - the + reserved-for-future-use other source salt choice was + specified in the PBKDF2 params structure + ''' + )) + + return salt.native + + if encryption_algo.find('.') == -1: + if encryption_algo.find('_') != -1: + return self['parameters']['salt'].native + + raise ValueError(unwrap( + ''' + Encryption algorithm "%s" does not have a registered key + derivation function + ''', + encryption_algo + )) + + raise ValueError(unwrap( + ''' + Unrecognized encryption algorithm "%s", can not determine key + derivation salt + ''', + encryption_algo + )) + + @property + def kdf_iterations(self): + """ + Returns the number of iterations that should be run via the KDF. + + :return: + An integer + """ + + encryption_algo = self['algorithm'].native + + if encryption_algo == 'pbes2': + return self['parameters']['key_derivation_func']['parameters']['iteration_count'].native + + if encryption_algo.find('.') == -1: + if encryption_algo.find('_') != -1: + return self['parameters']['iterations'].native + + raise ValueError(unwrap( + ''' + Encryption algorithm "%s" does not have a registered key + derivation function + ''', + encryption_algo + )) + + raise ValueError(unwrap( + ''' + Unrecognized encryption algorithm "%s", can not determine key + derivation iterations + ''', + encryption_algo + )) + + @property + def key_length(self): + """ + Returns the key length to pass to the cipher/kdf. The PKCS#5 spec does + not specify a way to store the RC5 key length, however this tends not + to be a problem since OpenSSL does not support RC5 in PKCS#8 and OS X + does not provide an RC5 cipher for use in the Security Transforms + library. + + :raises: + ValueError - when the key length can not be determined + + :return: + An integer representing the length in bytes + """ + + encryption_algo = self['algorithm'].native + + if encryption_algo[0:3] == 'aes': + return { + 'aes128_': 16, + 'aes192_': 24, + 'aes256_': 32, + }[encryption_algo[0:7]] + + cipher_lengths = { + 'des': 8, + 'tripledes_3key': 24, + } + + if encryption_algo in cipher_lengths: + return cipher_lengths[encryption_algo] + + if encryption_algo == 'rc2': + rc2_parameter_version = self['parameters']['rc2_parameter_version'].native + + # See page 24 of + # http://www.emc.com/collateral/white-papers/h11302-pkcs5v2-1-password-based-cryptography-standard-wp.pdf + encoded_key_bits_map = { + 160: 5, # 40-bit + 120: 8, # 64-bit + 58: 16, # 128-bit + } + + if rc2_parameter_version in encoded_key_bits_map: + return encoded_key_bits_map[rc2_parameter_version] + + if rc2_parameter_version >= 256: + return rc2_parameter_version + + if rc2_parameter_version is None: + return 4 # 32-bit default + + raise ValueError(unwrap( + ''' + Invalid RC2 parameter version found in EncryptionAlgorithm + parameters + ''' + )) + + if encryption_algo == 'pbes2': + key_length = self['parameters']['key_derivation_func']['parameters']['key_length'].native + if key_length is not None: + return key_length + + # If the KDF params don't specify the key size, we can infer it from + # the encryption scheme for all schemes except for RC5. However, in + # practical terms, neither OpenSSL or OS X support RC5 for PKCS#8 + # so it is unlikely to be an issue that is run into. + + return self['parameters']['encryption_scheme'].key_length + + if encryption_algo.find('.') == -1: + return { + 'pbes1_md2_des': 8, + 'pbes1_md5_des': 8, + 'pbes1_md2_rc2': 8, + 'pbes1_md5_rc2': 8, + 'pbes1_sha1_des': 8, + 'pbes1_sha1_rc2': 8, + 'pkcs12_sha1_rc4_128': 16, + 'pkcs12_sha1_rc4_40': 5, + 'pkcs12_sha1_tripledes_3key': 24, + 'pkcs12_sha1_tripledes_2key': 16, + 'pkcs12_sha1_rc2_128': 16, + 'pkcs12_sha1_rc2_40': 5, + }[encryption_algo] + + raise ValueError(unwrap( + ''' + Unrecognized encryption algorithm "%s" + ''', + encryption_algo + )) + + @property + def encryption_mode(self): + """ + Returns the name of the encryption mode to use. + + :return: + A unicode string from one of the following: "cbc", "ecb", "ofb", + "cfb", "wrap", "gcm", "ccm", "wrap_pad" + """ + + encryption_algo = self['algorithm'].native + + if encryption_algo[0:7] in set(['aes128_', 'aes192_', 'aes256_']): + return encryption_algo[7:] + + if encryption_algo[0:6] == 'pbes1_': + return 'cbc' + + if encryption_algo[0:7] == 'pkcs12_': + return 'cbc' + + if encryption_algo in set(['des', 'tripledes_3key', 'rc2', 'rc5']): + return 'cbc' + + if encryption_algo == 'pbes2': + return self['parameters']['encryption_scheme'].encryption_mode + + raise ValueError(unwrap( + ''' + Unrecognized encryption algorithm "%s" + ''', + encryption_algo + )) + + @property + def encryption_cipher(self): + """ + Returns the name of the symmetric encryption cipher to use. The key + length can be retrieved via the .key_length property to disabiguate + between different variations of TripleDES, AES, and the RC* ciphers. + + :return: + A unicode string from one of the following: "rc2", "rc5", "des", + "tripledes", "aes" + """ + + encryption_algo = self['algorithm'].native + + if encryption_algo[0:7] in set(['aes128_', 'aes192_', 'aes256_']): + return 'aes' + + if encryption_algo in set(['des', 'rc2', 'rc5']): + return encryption_algo + + if encryption_algo == 'tripledes_3key': + return 'tripledes' + + if encryption_algo == 'pbes2': + return self['parameters']['encryption_scheme'].encryption_cipher + + if encryption_algo.find('.') == -1: + return { + 'pbes1_md2_des': 'des', + 'pbes1_md5_des': 'des', + 'pbes1_md2_rc2': 'rc2', + 'pbes1_md5_rc2': 'rc2', + 'pbes1_sha1_des': 'des', + 'pbes1_sha1_rc2': 'rc2', + 'pkcs12_sha1_rc4_128': 'rc4', + 'pkcs12_sha1_rc4_40': 'rc4', + 'pkcs12_sha1_tripledes_3key': 'tripledes', + 'pkcs12_sha1_tripledes_2key': 'tripledes', + 'pkcs12_sha1_rc2_128': 'rc2', + 'pkcs12_sha1_rc2_40': 'rc2', + }[encryption_algo] + + raise ValueError(unwrap( + ''' + Unrecognized encryption algorithm "%s" + ''', + encryption_algo + )) + + @property + def encryption_block_size(self): + """ + Returns the block size of the encryption cipher, in bytes. + + :return: + An integer that is the block size in bytes + """ + + encryption_algo = self['algorithm'].native + + if encryption_algo[0:7] in set(['aes128_', 'aes192_', 'aes256_']): + return 16 + + cipher_map = { + 'des': 8, + 'tripledes_3key': 8, + 'rc2': 8, + } + if encryption_algo in cipher_map: + return cipher_map[encryption_algo] + + if encryption_algo == 'rc5': + return self['parameters']['block_size_in_bits'].native // 8 + + if encryption_algo == 'pbes2': + return self['parameters']['encryption_scheme'].encryption_block_size + + if encryption_algo.find('.') == -1: + return { + 'pbes1_md2_des': 8, + 'pbes1_md5_des': 8, + 'pbes1_md2_rc2': 8, + 'pbes1_md5_rc2': 8, + 'pbes1_sha1_des': 8, + 'pbes1_sha1_rc2': 8, + 'pkcs12_sha1_rc4_128': 0, + 'pkcs12_sha1_rc4_40': 0, + 'pkcs12_sha1_tripledes_3key': 8, + 'pkcs12_sha1_tripledes_2key': 8, + 'pkcs12_sha1_rc2_128': 8, + 'pkcs12_sha1_rc2_40': 8, + }[encryption_algo] + + raise ValueError(unwrap( + ''' + Unrecognized encryption algorithm "%s" + ''', + encryption_algo + )) + + @property + def encryption_iv(self): + """ + Returns the byte string of the initialization vector for the encryption + scheme. Only the PBES2 stores the IV in the params. For PBES1, the IV + is derived from the KDF and this property will return None. + + :return: + A byte string or None + """ + + encryption_algo = self['algorithm'].native + + if encryption_algo in set(['rc2', 'rc5']): + return self['parameters']['iv'].native + + # For DES/Triple DES and AES the IV is the entirety of the parameters + octet_string_iv_oids = set([ + 'des', + 'tripledes_3key', + 'aes128_cbc', + 'aes192_cbc', + 'aes256_cbc', + 'aes128_ofb', + 'aes192_ofb', + 'aes256_ofb', + ]) + if encryption_algo in octet_string_iv_oids: + return self['parameters'].native + + if encryption_algo == 'pbes2': + return self['parameters']['encryption_scheme'].encryption_iv + + # All of the PBES1 algos use their KDF to create the IV. For the pbkdf1, + # the KDF is told to generate a key that is an extra 8 bytes long, and + # that is used for the IV. For the PKCS#12 KDF, it is called with an id + # of 2 to generate the IV. In either case, we can't return the IV + # without knowing the user's password. + if encryption_algo.find('.') == -1: + return None + + raise ValueError(unwrap( + ''' + Unrecognized encryption algorithm "%s" + ''', + encryption_algo + )) + + +class Pbes2Params(Sequence): + _fields = [ + ('key_derivation_func', KdfAlgorithm), + ('encryption_scheme', EncryptionAlgorithm), + ] + + +class Pbmac1Params(Sequence): + _fields = [ + ('key_derivation_func', KdfAlgorithm), + ('message_auth_scheme', HmacAlgorithm), + ] + + +class Pkcs5MacId(ObjectIdentifier): + _map = { + '1.2.840.113549.1.5.14': 'pbmac1', + } + + +class Pkcs5MacAlgorithm(Sequence): + _fields = [ + ('algorithm', Pkcs5MacId), + ('parameters', Any), + ] + + _oid_pair = ('algorithm', 'parameters') + _oid_specs = { + 'pbmac1': Pbmac1Params, + } + + +EncryptionAlgorithm._oid_specs['pbes2'] = Pbes2Params + + +class AnyAlgorithmId(ObjectIdentifier): + _map = {} + + def _setup(self): + _map = self.__class__._map + for other_cls in (EncryptionAlgorithmId, SignedDigestAlgorithmId, DigestAlgorithmId): + for oid, name in other_cls._map.items(): + _map[oid] = name + + +class AnyAlgorithmIdentifier(_ForceNullParameters, Sequence): + _fields = [ + ('algorithm', AnyAlgorithmId), + ('parameters', Any, {'optional': True}), + ] + + _oid_pair = ('algorithm', 'parameters') + _oid_specs = {} + + def _setup(self): + Sequence._setup(self) + specs = self.__class__._oid_specs + for other_cls in (EncryptionAlgorithm, SignedDigestAlgorithm): + for oid, spec in other_cls._oid_specs.items(): + specs[oid] = spec diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/asn1crypto/cms.py b/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/asn1crypto/cms.py new file mode 100644 index 00000000..2115aed5 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/asn1crypto/cms.py @@ -0,0 +1,984 @@ +# coding: utf-8 + +""" +ASN.1 type classes for cryptographic message syntax (CMS). Structures are also +compatible with PKCS#7. Exports the following items: + + - AuthenticatedData() + - AuthEnvelopedData() + - CompressedData() + - ContentInfo() + - DigestedData() + - EncryptedData() + - EnvelopedData() + - SignedAndEnvelopedData() + - SignedData() + +Other type classes are defined that help compose the types listed above. + +Most CMS structures in the wild are formatted as ContentInfo encapsulating one of the other types. +""" + +from __future__ import unicode_literals, division, absolute_import, print_function + +try: + import zlib +except (ImportError): + zlib = None + +from .algos import ( + _ForceNullParameters, + DigestAlgorithm, + EncryptionAlgorithm, + HmacAlgorithm, + KdfAlgorithm, + RSAESOAEPParams, + SignedDigestAlgorithm, +) +from .core import ( + Any, + BitString, + Choice, + Enumerated, + GeneralizedTime, + Integer, + ObjectIdentifier, + OctetBitString, + OctetString, + ParsableOctetString, + Sequence, + SequenceOf, + SetOf, + UTCTime, + UTF8String, +) +from .crl import CertificateList +from .keys import PublicKeyInfo +from .ocsp import OCSPResponse +from .x509 import Attributes, Certificate, Extensions, GeneralName, GeneralNames, Name + + +# These structures are taken from +# ftp://ftp.rsasecurity.com/pub/pkcs/ascii/pkcs-6.asc + +class ExtendedCertificateInfo(Sequence): + _fields = [ + ('version', Integer), + ('certificate', Certificate), + ('attributes', Attributes), + ] + + +class ExtendedCertificate(Sequence): + _fields = [ + ('extended_certificate_info', ExtendedCertificateInfo), + ('signature_algorithm', SignedDigestAlgorithm), + ('signature', OctetBitString), + ] + + +# These structures are taken from https://tools.ietf.org/html/rfc5652, +# https://tools.ietf.org/html/rfc5083, http://tools.ietf.org/html/rfc2315, +# https://tools.ietf.org/html/rfc5940, https://tools.ietf.org/html/rfc3274, +# https://tools.ietf.org/html/rfc3281 + + +class CMSVersion(Integer): + _map = { + 0: 'v0', + 1: 'v1', + 2: 'v2', + 3: 'v3', + 4: 'v4', + 5: 'v5', + } + + +class CMSAttributeType(ObjectIdentifier): + _map = { + '1.2.840.113549.1.9.3': 'content_type', + '1.2.840.113549.1.9.4': 'message_digest', + '1.2.840.113549.1.9.5': 'signing_time', + '1.2.840.113549.1.9.6': 'counter_signature', + # https://tools.ietf.org/html/rfc2633#page-26 + '1.2.840.113549.1.9.16.2.11': 'encrypt_key_pref', + # https://tools.ietf.org/html/rfc3161#page-20 + '1.2.840.113549.1.9.16.2.14': 'signature_time_stamp_token', + # https://tools.ietf.org/html/rfc6211#page-5 + '1.2.840.113549.1.9.52': 'cms_algorithm_protection', + # https://docs.microsoft.com/en-us/previous-versions/hh968145(v%3Dvs.85) + '1.3.6.1.4.1.311.2.4.1': 'microsoft_nested_signature', + # Some places refer to this as SPC_RFC3161_OBJID, others szOID_RFC3161_counterSign. + # https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/ns-wincrypt-crypt_algorithm_identifier + # refers to szOID_RFC3161_counterSign as "1.2.840.113549.1.9.16.1.4", + # but that OID is also called szOID_TIMESTAMP_TOKEN. Because of there being + # no canonical source for this OID, we give it our own name + '1.3.6.1.4.1.311.3.3.1': 'microsoft_time_stamp_token', + } + + +class Time(Choice): + _alternatives = [ + ('utc_time', UTCTime), + ('generalized_time', GeneralizedTime), + ] + + +class ContentType(ObjectIdentifier): + _map = { + '1.2.840.113549.1.7.1': 'data', + '1.2.840.113549.1.7.2': 'signed_data', + '1.2.840.113549.1.7.3': 'enveloped_data', + '1.2.840.113549.1.7.4': 'signed_and_enveloped_data', + '1.2.840.113549.1.7.5': 'digested_data', + '1.2.840.113549.1.7.6': 'encrypted_data', + '1.2.840.113549.1.9.16.1.2': 'authenticated_data', + '1.2.840.113549.1.9.16.1.9': 'compressed_data', + '1.2.840.113549.1.9.16.1.23': 'authenticated_enveloped_data', + } + + +class CMSAlgorithmProtection(Sequence): + _fields = [ + ('digest_algorithm', DigestAlgorithm), + ('signature_algorithm', SignedDigestAlgorithm, {'implicit': 1, 'optional': True}), + ('mac_algorithm', HmacAlgorithm, {'implicit': 2, 'optional': True}), + ] + + +class SetOfContentType(SetOf): + _child_spec = ContentType + + +class SetOfOctetString(SetOf): + _child_spec = OctetString + + +class SetOfTime(SetOf): + _child_spec = Time + + +class SetOfAny(SetOf): + _child_spec = Any + + +class SetOfCMSAlgorithmProtection(SetOf): + _child_spec = CMSAlgorithmProtection + + +class CMSAttribute(Sequence): + _fields = [ + ('type', CMSAttributeType), + ('values', None), + ] + + _oid_specs = {} + + def _values_spec(self): + return self._oid_specs.get(self['type'].native, SetOfAny) + + _spec_callbacks = { + 'values': _values_spec + } + + +class CMSAttributes(SetOf): + _child_spec = CMSAttribute + + +class IssuerSerial(Sequence): + _fields = [ + ('issuer', GeneralNames), + ('serial', Integer), + ('issuer_uid', OctetBitString, {'optional': True}), + ] + + +class AttCertVersion(Integer): + _map = { + 0: 'v1', + 1: 'v2', + } + + +class AttCertSubject(Choice): + _alternatives = [ + ('base_certificate_id', IssuerSerial, {'explicit': 0}), + ('subject_name', GeneralNames, {'explicit': 1}), + ] + + +class AttCertValidityPeriod(Sequence): + _fields = [ + ('not_before_time', GeneralizedTime), + ('not_after_time', GeneralizedTime), + ] + + +class AttributeCertificateInfoV1(Sequence): + _fields = [ + ('version', AttCertVersion, {'default': 'v1'}), + ('subject', AttCertSubject), + ('issuer', GeneralNames), + ('signature', SignedDigestAlgorithm), + ('serial_number', Integer), + ('att_cert_validity_period', AttCertValidityPeriod), + ('attributes', Attributes), + ('issuer_unique_id', OctetBitString, {'optional': True}), + ('extensions', Extensions, {'optional': True}), + ] + + +class AttributeCertificateV1(Sequence): + _fields = [ + ('ac_info', AttributeCertificateInfoV1), + ('signature_algorithm', SignedDigestAlgorithm), + ('signature', OctetBitString), + ] + + +class DigestedObjectType(Enumerated): + _map = { + 0: 'public_key', + 1: 'public_key_cert', + 2: 'other_objy_types', + } + + +class ObjectDigestInfo(Sequence): + _fields = [ + ('digested_object_type', DigestedObjectType), + ('other_object_type_id', ObjectIdentifier, {'optional': True}), + ('digest_algorithm', DigestAlgorithm), + ('object_digest', OctetBitString), + ] + + +class Holder(Sequence): + _fields = [ + ('base_certificate_id', IssuerSerial, {'implicit': 0, 'optional': True}), + ('entity_name', GeneralNames, {'implicit': 1, 'optional': True}), + ('object_digest_info', ObjectDigestInfo, {'implicit': 2, 'optional': True}), + ] + + +class V2Form(Sequence): + _fields = [ + ('issuer_name', GeneralNames, {'optional': True}), + ('base_certificate_id', IssuerSerial, {'explicit': 0, 'optional': True}), + ('object_digest_info', ObjectDigestInfo, {'explicit': 1, 'optional': True}), + ] + + +class AttCertIssuer(Choice): + _alternatives = [ + ('v1_form', GeneralNames), + ('v2_form', V2Form, {'explicit': 0}), + ] + + +class IetfAttrValue(Choice): + _alternatives = [ + ('octets', OctetString), + ('oid', ObjectIdentifier), + ('string', UTF8String), + ] + + +class IetfAttrValues(SequenceOf): + _child_spec = IetfAttrValue + + +class IetfAttrSyntax(Sequence): + _fields = [ + ('policy_authority', GeneralNames, {'implicit': 0, 'optional': True}), + ('values', IetfAttrValues), + ] + + +class SetOfIetfAttrSyntax(SetOf): + _child_spec = IetfAttrSyntax + + +class SvceAuthInfo(Sequence): + _fields = [ + ('service', GeneralName), + ('ident', GeneralName), + ('auth_info', OctetString, {'optional': True}), + ] + + +class SetOfSvceAuthInfo(SetOf): + _child_spec = SvceAuthInfo + + +class RoleSyntax(Sequence): + _fields = [ + ('role_authority', GeneralNames, {'implicit': 0, 'optional': True}), + ('role_name', GeneralName, {'implicit': 1}), + ] + + +class SetOfRoleSyntax(SetOf): + _child_spec = RoleSyntax + + +class ClassList(BitString): + _map = { + 0: 'unmarked', + 1: 'unclassified', + 2: 'restricted', + 3: 'confidential', + 4: 'secret', + 5: 'top_secret', + } + + +class SecurityCategory(Sequence): + _fields = [ + ('type', ObjectIdentifier, {'implicit': 0}), + ('value', Any, {'implicit': 1}), + ] + + +class SetOfSecurityCategory(SetOf): + _child_spec = SecurityCategory + + +class Clearance(Sequence): + _fields = [ + ('policy_id', ObjectIdentifier, {'implicit': 0}), + ('class_list', ClassList, {'implicit': 1, 'default': 'unclassified'}), + ('security_categories', SetOfSecurityCategory, {'implicit': 2, 'optional': True}), + ] + + +class SetOfClearance(SetOf): + _child_spec = Clearance + + +class BigTime(Sequence): + _fields = [ + ('major', Integer), + ('fractional_seconds', Integer), + ('sign', Integer, {'optional': True}), + ] + + +class LeapData(Sequence): + _fields = [ + ('leap_time', BigTime), + ('action', Integer), + ] + + +class SetOfLeapData(SetOf): + _child_spec = LeapData + + +class TimingMetrics(Sequence): + _fields = [ + ('ntp_time', BigTime), + ('offset', BigTime), + ('delay', BigTime), + ('expiration', BigTime), + ('leap_event', SetOfLeapData, {'optional': True}), + ] + + +class SetOfTimingMetrics(SetOf): + _child_spec = TimingMetrics + + +class TimingPolicy(Sequence): + _fields = [ + ('policy_id', SequenceOf, {'spec': ObjectIdentifier}), + ('max_offset', BigTime, {'explicit': 0, 'optional': True}), + ('max_delay', BigTime, {'explicit': 1, 'optional': True}), + ] + + +class SetOfTimingPolicy(SetOf): + _child_spec = TimingPolicy + + +class AttCertAttributeType(ObjectIdentifier): + _map = { + '1.3.6.1.5.5.7.10.1': 'authentication_info', + '1.3.6.1.5.5.7.10.2': 'access_identity', + '1.3.6.1.5.5.7.10.3': 'charging_identity', + '1.3.6.1.5.5.7.10.4': 'group', + '2.5.4.72': 'role', + '2.5.4.55': 'clearance', + '1.3.6.1.4.1.601.10.4.1': 'timing_metrics', + '1.3.6.1.4.1.601.10.4.2': 'timing_policy', + } + + +class AttCertAttribute(Sequence): + _fields = [ + ('type', AttCertAttributeType), + ('values', None), + ] + + _oid_specs = { + 'authentication_info': SetOfSvceAuthInfo, + 'access_identity': SetOfSvceAuthInfo, + 'charging_identity': SetOfIetfAttrSyntax, + 'group': SetOfIetfAttrSyntax, + 'role': SetOfRoleSyntax, + 'clearance': SetOfClearance, + 'timing_metrics': SetOfTimingMetrics, + 'timing_policy': SetOfTimingPolicy, + } + + def _values_spec(self): + return self._oid_specs.get(self['type'].native, SetOfAny) + + _spec_callbacks = { + 'values': _values_spec + } + + +class AttCertAttributes(SequenceOf): + _child_spec = AttCertAttribute + + +class AttributeCertificateInfoV2(Sequence): + _fields = [ + ('version', AttCertVersion), + ('holder', Holder), + ('issuer', AttCertIssuer), + ('signature', SignedDigestAlgorithm), + ('serial_number', Integer), + ('att_cert_validity_period', AttCertValidityPeriod), + ('attributes', AttCertAttributes), + ('issuer_unique_id', OctetBitString, {'optional': True}), + ('extensions', Extensions, {'optional': True}), + ] + + +class AttributeCertificateV2(Sequence): + # Handle the situation where a V2 cert is encoded as V1 + _bad_tag = 1 + + _fields = [ + ('ac_info', AttributeCertificateInfoV2), + ('signature_algorithm', SignedDigestAlgorithm), + ('signature', OctetBitString), + ] + + +class OtherCertificateFormat(Sequence): + _fields = [ + ('other_cert_format', ObjectIdentifier), + ('other_cert', Any), + ] + + +class CertificateChoices(Choice): + _alternatives = [ + ('certificate', Certificate), + ('extended_certificate', ExtendedCertificate, {'implicit': 0}), + ('v1_attr_cert', AttributeCertificateV1, {'implicit': 1}), + ('v2_attr_cert', AttributeCertificateV2, {'implicit': 2}), + ('other', OtherCertificateFormat, {'implicit': 3}), + ] + + def validate(self, class_, tag, contents): + """ + Ensures that the class and tag specified exist as an alternative. This + custom version fixes parsing broken encodings there a V2 attribute + # certificate is encoded as a V1 + + :param class_: + The integer class_ from the encoded value header + + :param tag: + The integer tag from the encoded value header + + :param contents: + A byte string of the contents of the value - used when the object + is explicitly tagged + + :raises: + ValueError - when value is not a valid alternative + """ + + super(CertificateChoices, self).validate(class_, tag, contents) + if self._choice == 2: + if AttCertVersion.load(Sequence.load(contents)[0].dump()).native == 'v2': + self._choice = 3 + + +class CertificateSet(SetOf): + _child_spec = CertificateChoices + + +class ContentInfo(Sequence): + _fields = [ + ('content_type', ContentType), + ('content', Any, {'explicit': 0, 'optional': True}), + ] + + _oid_pair = ('content_type', 'content') + _oid_specs = {} + + +class SetOfContentInfo(SetOf): + _child_spec = ContentInfo + + +class EncapsulatedContentInfo(Sequence): + _fields = [ + ('content_type', ContentType), + ('content', ParsableOctetString, {'explicit': 0, 'optional': True}), + ] + + _oid_pair = ('content_type', 'content') + _oid_specs = {} + + +class IssuerAndSerialNumber(Sequence): + _fields = [ + ('issuer', Name), + ('serial_number', Integer), + ] + + +class SignerIdentifier(Choice): + _alternatives = [ + ('issuer_and_serial_number', IssuerAndSerialNumber), + ('subject_key_identifier', OctetString, {'implicit': 0}), + ] + + +class DigestAlgorithms(SetOf): + _child_spec = DigestAlgorithm + + +class CertificateRevocationLists(SetOf): + _child_spec = CertificateList + + +class SCVPReqRes(Sequence): + _fields = [ + ('request', ContentInfo, {'explicit': 0, 'optional': True}), + ('response', ContentInfo), + ] + + +class OtherRevInfoFormatId(ObjectIdentifier): + _map = { + '1.3.6.1.5.5.7.16.2': 'ocsp_response', + '1.3.6.1.5.5.7.16.4': 'scvp', + } + + +class OtherRevocationInfoFormat(Sequence): + _fields = [ + ('other_rev_info_format', OtherRevInfoFormatId), + ('other_rev_info', Any), + ] + + _oid_pair = ('other_rev_info_format', 'other_rev_info') + _oid_specs = { + 'ocsp_response': OCSPResponse, + 'scvp': SCVPReqRes, + } + + +class RevocationInfoChoice(Choice): + _alternatives = [ + ('crl', CertificateList), + ('other', OtherRevocationInfoFormat, {'implicit': 1}), + ] + + +class RevocationInfoChoices(SetOf): + _child_spec = RevocationInfoChoice + + +class SignerInfo(Sequence): + _fields = [ + ('version', CMSVersion), + ('sid', SignerIdentifier), + ('digest_algorithm', DigestAlgorithm), + ('signed_attrs', CMSAttributes, {'implicit': 0, 'optional': True}), + ('signature_algorithm', SignedDigestAlgorithm), + ('signature', OctetString), + ('unsigned_attrs', CMSAttributes, {'implicit': 1, 'optional': True}), + ] + + +class SignerInfos(SetOf): + _child_spec = SignerInfo + + +class SignedData(Sequence): + _fields = [ + ('version', CMSVersion), + ('digest_algorithms', DigestAlgorithms), + ('encap_content_info', None), + ('certificates', CertificateSet, {'implicit': 0, 'optional': True}), + ('crls', RevocationInfoChoices, {'implicit': 1, 'optional': True}), + ('signer_infos', SignerInfos), + ] + + def _encap_content_info_spec(self): + # If the encap_content_info is version v1, then this could be a PKCS#7 + # structure, or a CMS structure. CMS wraps the encoded value in an + # Octet String tag. + + # If the version is greater than 1, it is definite CMS + if self['version'].native != 'v1': + return EncapsulatedContentInfo + + # Otherwise, the ContentInfo spec from PKCS#7 will be compatible with + # CMS v1 (which only allows Data, an Octet String) and PKCS#7, which + # allows Any + return ContentInfo + + _spec_callbacks = { + 'encap_content_info': _encap_content_info_spec + } + + +class OriginatorInfo(Sequence): + _fields = [ + ('certs', CertificateSet, {'implicit': 0, 'optional': True}), + ('crls', RevocationInfoChoices, {'implicit': 1, 'optional': True}), + ] + + +class RecipientIdentifier(Choice): + _alternatives = [ + ('issuer_and_serial_number', IssuerAndSerialNumber), + ('subject_key_identifier', OctetString, {'implicit': 0}), + ] + + +class KeyEncryptionAlgorithmId(ObjectIdentifier): + _map = { + '1.2.840.113549.1.1.1': 'rsaes_pkcs1v15', + '1.2.840.113549.1.1.7': 'rsaes_oaep', + '2.16.840.1.101.3.4.1.5': 'aes128_wrap', + '2.16.840.1.101.3.4.1.8': 'aes128_wrap_pad', + '2.16.840.1.101.3.4.1.25': 'aes192_wrap', + '2.16.840.1.101.3.4.1.28': 'aes192_wrap_pad', + '2.16.840.1.101.3.4.1.45': 'aes256_wrap', + '2.16.840.1.101.3.4.1.48': 'aes256_wrap_pad', + } + + _reverse_map = { + 'rsa': '1.2.840.113549.1.1.1', + 'rsaes_pkcs1v15': '1.2.840.113549.1.1.1', + 'rsaes_oaep': '1.2.840.113549.1.1.7', + 'aes128_wrap': '2.16.840.1.101.3.4.1.5', + 'aes128_wrap_pad': '2.16.840.1.101.3.4.1.8', + 'aes192_wrap': '2.16.840.1.101.3.4.1.25', + 'aes192_wrap_pad': '2.16.840.1.101.3.4.1.28', + 'aes256_wrap': '2.16.840.1.101.3.4.1.45', + 'aes256_wrap_pad': '2.16.840.1.101.3.4.1.48', + } + + +class KeyEncryptionAlgorithm(_ForceNullParameters, Sequence): + _fields = [ + ('algorithm', KeyEncryptionAlgorithmId), + ('parameters', Any, {'optional': True}), + ] + + _oid_pair = ('algorithm', 'parameters') + _oid_specs = { + 'rsaes_oaep': RSAESOAEPParams, + } + + +class KeyTransRecipientInfo(Sequence): + _fields = [ + ('version', CMSVersion), + ('rid', RecipientIdentifier), + ('key_encryption_algorithm', KeyEncryptionAlgorithm), + ('encrypted_key', OctetString), + ] + + +class OriginatorIdentifierOrKey(Choice): + _alternatives = [ + ('issuer_and_serial_number', IssuerAndSerialNumber), + ('subject_key_identifier', OctetString, {'implicit': 0}), + ('originator_key', PublicKeyInfo, {'implicit': 1}), + ] + + +class OtherKeyAttribute(Sequence): + _fields = [ + ('key_attr_id', ObjectIdentifier), + ('key_attr', Any), + ] + + +class RecipientKeyIdentifier(Sequence): + _fields = [ + ('subject_key_identifier', OctetString), + ('date', GeneralizedTime, {'optional': True}), + ('other', OtherKeyAttribute, {'optional': True}), + ] + + +class KeyAgreementRecipientIdentifier(Choice): + _alternatives = [ + ('issuer_and_serial_number', IssuerAndSerialNumber), + ('r_key_id', RecipientKeyIdentifier, {'implicit': 0}), + ] + + +class RecipientEncryptedKey(Sequence): + _fields = [ + ('rid', KeyAgreementRecipientIdentifier), + ('encrypted_key', OctetString), + ] + + +class RecipientEncryptedKeys(SequenceOf): + _child_spec = RecipientEncryptedKey + + +class KeyAgreeRecipientInfo(Sequence): + _fields = [ + ('version', CMSVersion), + ('originator', OriginatorIdentifierOrKey, {'explicit': 0}), + ('ukm', OctetString, {'explicit': 1, 'optional': True}), + ('key_encryption_algorithm', KeyEncryptionAlgorithm), + ('recipient_encrypted_keys', RecipientEncryptedKeys), + ] + + +class KEKIdentifier(Sequence): + _fields = [ + ('key_identifier', OctetString), + ('date', GeneralizedTime, {'optional': True}), + ('other', OtherKeyAttribute, {'optional': True}), + ] + + +class KEKRecipientInfo(Sequence): + _fields = [ + ('version', CMSVersion), + ('kekid', KEKIdentifier), + ('key_encryption_algorithm', KeyEncryptionAlgorithm), + ('encrypted_key', OctetString), + ] + + +class PasswordRecipientInfo(Sequence): + _fields = [ + ('version', CMSVersion), + ('key_derivation_algorithm', KdfAlgorithm, {'implicit': 0, 'optional': True}), + ('key_encryption_algorithm', KeyEncryptionAlgorithm), + ('encrypted_key', OctetString), + ] + + +class OtherRecipientInfo(Sequence): + _fields = [ + ('ori_type', ObjectIdentifier), + ('ori_value', Any), + ] + + +class RecipientInfo(Choice): + _alternatives = [ + ('ktri', KeyTransRecipientInfo), + ('kari', KeyAgreeRecipientInfo, {'implicit': 1}), + ('kekri', KEKRecipientInfo, {'implicit': 2}), + ('pwri', PasswordRecipientInfo, {'implicit': 3}), + ('ori', OtherRecipientInfo, {'implicit': 4}), + ] + + +class RecipientInfos(SetOf): + _child_spec = RecipientInfo + + +class EncryptedContentInfo(Sequence): + _fields = [ + ('content_type', ContentType), + ('content_encryption_algorithm', EncryptionAlgorithm), + ('encrypted_content', OctetString, {'implicit': 0, 'optional': True}), + ] + + +class EnvelopedData(Sequence): + _fields = [ + ('version', CMSVersion), + ('originator_info', OriginatorInfo, {'implicit': 0, 'optional': True}), + ('recipient_infos', RecipientInfos), + ('encrypted_content_info', EncryptedContentInfo), + ('unprotected_attrs', CMSAttributes, {'implicit': 1, 'optional': True}), + ] + + +class SignedAndEnvelopedData(Sequence): + _fields = [ + ('version', CMSVersion), + ('recipient_infos', RecipientInfos), + ('digest_algorithms', DigestAlgorithms), + ('encrypted_content_info', EncryptedContentInfo), + ('certificates', CertificateSet, {'implicit': 0, 'optional': True}), + ('crls', CertificateRevocationLists, {'implicit': 1, 'optional': True}), + ('signer_infos', SignerInfos), + ] + + +class DigestedData(Sequence): + _fields = [ + ('version', CMSVersion), + ('digest_algorithm', DigestAlgorithm), + ('encap_content_info', None), + ('digest', OctetString), + ] + + def _encap_content_info_spec(self): + # If the encap_content_info is version v1, then this could be a PKCS#7 + # structure, or a CMS structure. CMS wraps the encoded value in an + # Octet String tag. + + # If the version is greater than 1, it is definite CMS + if self['version'].native != 'v1': + return EncapsulatedContentInfo + + # Otherwise, the ContentInfo spec from PKCS#7 will be compatible with + # CMS v1 (which only allows Data, an Octet String) and PKCS#7, which + # allows Any + return ContentInfo + + _spec_callbacks = { + 'encap_content_info': _encap_content_info_spec + } + + +class EncryptedData(Sequence): + _fields = [ + ('version', CMSVersion), + ('encrypted_content_info', EncryptedContentInfo), + ('unprotected_attrs', CMSAttributes, {'implicit': 1, 'optional': True}), + ] + + +class AuthenticatedData(Sequence): + _fields = [ + ('version', CMSVersion), + ('originator_info', OriginatorInfo, {'implicit': 0, 'optional': True}), + ('recipient_infos', RecipientInfos), + ('mac_algorithm', HmacAlgorithm), + ('digest_algorithm', DigestAlgorithm, {'implicit': 1, 'optional': True}), + # This does not require the _spec_callbacks approach of SignedData and + # DigestedData since AuthenticatedData was not part of PKCS#7 + ('encap_content_info', EncapsulatedContentInfo), + ('auth_attrs', CMSAttributes, {'implicit': 2, 'optional': True}), + ('mac', OctetString), + ('unauth_attrs', CMSAttributes, {'implicit': 3, 'optional': True}), + ] + + +class AuthEnvelopedData(Sequence): + _fields = [ + ('version', CMSVersion), + ('originator_info', OriginatorInfo, {'implicit': 0, 'optional': True}), + ('recipient_infos', RecipientInfos), + ('auth_encrypted_content_info', EncryptedContentInfo), + ('auth_attrs', CMSAttributes, {'implicit': 1, 'optional': True}), + ('mac', OctetString), + ('unauth_attrs', CMSAttributes, {'implicit': 2, 'optional': True}), + ] + + +class CompressionAlgorithmId(ObjectIdentifier): + _map = { + '1.2.840.113549.1.9.16.3.8': 'zlib', + } + + +class CompressionAlgorithm(Sequence): + _fields = [ + ('algorithm', CompressionAlgorithmId), + ('parameters', Any, {'optional': True}), + ] + + +class CompressedData(Sequence): + _fields = [ + ('version', CMSVersion), + ('compression_algorithm', CompressionAlgorithm), + ('encap_content_info', EncapsulatedContentInfo), + ] + + _decompressed = None + + @property + def decompressed(self): + if self._decompressed is None: + if zlib is None: + raise SystemError('The zlib module is not available') + self._decompressed = zlib.decompress(self['encap_content_info']['content'].native) + return self._decompressed + + +class RecipientKeyIdentifier(Sequence): + _fields = [ + ('subjectKeyIdentifier', OctetString), + ('date', GeneralizedTime, {'optional': True}), + ('other', OtherKeyAttribute, {'optional': True}), + ] + + +class SMIMEEncryptionKeyPreference(Choice): + _alternatives = [ + ('issuer_and_serial_number', IssuerAndSerialNumber, {'implicit': 0}), + ('recipientKeyId', RecipientKeyIdentifier, {'implicit': 1}), + ('subjectAltKeyIdentifier', PublicKeyInfo, {'implicit': 2}), + ] + + +class SMIMEEncryptionKeyPreferences(SetOf): + _child_spec = SMIMEEncryptionKeyPreference + + +ContentInfo._oid_specs = { + 'data': OctetString, + 'signed_data': SignedData, + 'enveloped_data': EnvelopedData, + 'signed_and_enveloped_data': SignedAndEnvelopedData, + 'digested_data': DigestedData, + 'encrypted_data': EncryptedData, + 'authenticated_data': AuthenticatedData, + 'compressed_data': CompressedData, + 'authenticated_enveloped_data': AuthEnvelopedData, +} + + +EncapsulatedContentInfo._oid_specs = { + 'signed_data': SignedData, + 'enveloped_data': EnvelopedData, + 'signed_and_enveloped_data': SignedAndEnvelopedData, + 'digested_data': DigestedData, + 'encrypted_data': EncryptedData, + 'authenticated_data': AuthenticatedData, + 'compressed_data': CompressedData, + 'authenticated_enveloped_data': AuthEnvelopedData, +} + + +CMSAttribute._oid_specs = { + 'content_type': SetOfContentType, + 'message_digest': SetOfOctetString, + 'signing_time': SetOfTime, + 'counter_signature': SignerInfos, + 'signature_time_stamp_token': SetOfContentInfo, + 'cms_algorithm_protection': SetOfCMSAlgorithmProtection, + 'microsoft_nested_signature': SetOfContentInfo, + 'microsoft_time_stamp_token': SetOfContentInfo, + 'encrypt_key_pref': SMIMEEncryptionKeyPreferences, +} diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/asn1crypto/core.py b/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/asn1crypto/core.py new file mode 100644 index 00000000..7133367d --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/asn1crypto/core.py @@ -0,0 +1,5672 @@ +# coding: utf-8 + +""" +ASN.1 type classes for universal types. Exports the following items: + + - load() + - Any() + - Asn1Value() + - BitString() + - BMPString() + - Boolean() + - CharacterString() + - Choice() + - EmbeddedPdv() + - Enumerated() + - GeneralizedTime() + - GeneralString() + - GraphicString() + - IA5String() + - InstanceOf() + - Integer() + - IntegerBitString() + - IntegerOctetString() + - Null() + - NumericString() + - ObjectDescriptor() + - ObjectIdentifier() + - OctetBitString() + - OctetString() + - PrintableString() + - Real() + - RelativeOid() + - Sequence() + - SequenceOf() + - Set() + - SetOf() + - TeletexString() + - UniversalString() + - UTCTime() + - UTF8String() + - VideotexString() + - VisibleString() + - VOID + - Void() + +Other type classes are defined that help compose the types listed above. +""" + +from __future__ import unicode_literals, division, absolute_import, print_function + +from datetime import datetime, timedelta +from fractions import Fraction +import binascii +import copy +import math +import re +import sys + +from . import _teletex_codec +from ._errors import unwrap +from ._ordereddict import OrderedDict +from ._types import type_name, str_cls, byte_cls, int_types, chr_cls +from .parser import _parse, _dump_header +from .util import int_to_bytes, int_from_bytes, timezone, extended_datetime, create_timezone, utc_with_dst + +if sys.version_info <= (3,): + from cStringIO import StringIO as BytesIO + + range = xrange # noqa + _PY2 = True + +else: + from io import BytesIO + + _PY2 = False + + +_teletex_codec.register() + + +CLASS_NUM_TO_NAME_MAP = { + 0: 'universal', + 1: 'application', + 2: 'context', + 3: 'private', +} + +CLASS_NAME_TO_NUM_MAP = { + 'universal': 0, + 'application': 1, + 'context': 2, + 'private': 3, + 0: 0, + 1: 1, + 2: 2, + 3: 3, +} + +METHOD_NUM_TO_NAME_MAP = { + 0: 'primitive', + 1: 'constructed', +} + + +_OID_RE = re.compile(r'^\d+(\.\d+)*$') + + +# A global tracker to ensure that _setup() is called for every class, even +# if is has been called for a parent class. This allows different _fields +# definitions for child classes. Without such a construct, the child classes +# would just see the parent class attributes and would use them. +_SETUP_CLASSES = {} + + +def load(encoded_data, strict=False): + """ + Loads a BER/DER-encoded byte string and construct a universal object based + on the tag value: + + - 1: Boolean + - 2: Integer + - 3: BitString + - 4: OctetString + - 5: Null + - 6: ObjectIdentifier + - 7: ObjectDescriptor + - 8: InstanceOf + - 9: Real + - 10: Enumerated + - 11: EmbeddedPdv + - 12: UTF8String + - 13: RelativeOid + - 16: Sequence, + - 17: Set + - 18: NumericString + - 19: PrintableString + - 20: TeletexString + - 21: VideotexString + - 22: IA5String + - 23: UTCTime + - 24: GeneralizedTime + - 25: GraphicString + - 26: VisibleString + - 27: GeneralString + - 28: UniversalString + - 29: CharacterString + - 30: BMPString + + :param encoded_data: + A byte string of BER or DER-encoded data + + :param strict: + A boolean indicating if trailing data should be forbidden - if so, a + ValueError will be raised when trailing data exists + + :raises: + ValueError - when strict is True and trailing data is present + ValueError - when the encoded value tag a tag other than listed above + ValueError - when the ASN.1 header length is longer than the data + TypeError - when encoded_data is not a byte string + + :return: + An instance of the one of the universal classes + """ + + return Asn1Value.load(encoded_data, strict=strict) + + +class Asn1Value(object): + """ + The basis of all ASN.1 values + """ + + # The integer 0 for primitive, 1 for constructed + method = None + + # An integer 0 through 3 - see CLASS_NUM_TO_NAME_MAP for value + class_ = None + + # An integer 1 or greater indicating the tag number + tag = None + + # An alternate tag allowed for this type - used for handling broken + # structures where a string value is encoded using an incorrect tag + _bad_tag = None + + # If the value has been implicitly tagged + implicit = False + + # If explicitly tagged, a tuple of 2-element tuples containing the + # class int and tag int, from innermost to outermost + explicit = None + + # The BER/DER header bytes + _header = None + + # Raw encoded value bytes not including class, method, tag, length header + contents = None + + # The BER/DER trailer bytes + _trailer = b'' + + # The native python representation of the value - this is not used by + # some classes since they utilize _bytes or _unicode + _native = None + + @classmethod + def load(cls, encoded_data, strict=False, **kwargs): + """ + Loads a BER/DER-encoded byte string using the current class as the spec + + :param encoded_data: + A byte string of BER or DER-encoded data + + :param strict: + A boolean indicating if trailing data should be forbidden - if so, a + ValueError will be raised when trailing data exists + + :return: + An instance of the current class + """ + + if not isinstance(encoded_data, byte_cls): + raise TypeError('encoded_data must be a byte string, not %s' % type_name(encoded_data)) + + spec = None + if cls.tag is not None: + spec = cls + + value, _ = _parse_build(encoded_data, spec=spec, spec_params=kwargs, strict=strict) + return value + + def __init__(self, explicit=None, implicit=None, no_explicit=False, tag_type=None, class_=None, tag=None, + optional=None, default=None, contents=None, method=None): + """ + The optional parameter is not used, but rather included so we don't + have to delete it from the parameter dictionary when passing as keyword + args + + :param explicit: + An int tag number for explicit tagging, or a 2-element tuple of + class and tag. + + :param implicit: + An int tag number for implicit tagging, or a 2-element tuple of + class and tag. + + :param no_explicit: + If explicit tagging info should be removed from this instance. + Used internally to allow contructing the underlying value that + has been wrapped in an explicit tag. + + :param tag_type: + None for normal values, or one of "implicit", "explicit" for tagged + values. Deprecated in favor of explicit and implicit params. + + :param class_: + The class for the value - defaults to "universal" if tag_type is + None, otherwise defaults to "context". Valid values include: + - "universal" + - "application" + - "context" + - "private" + Deprecated in favor of explicit and implicit params. + + :param tag: + The integer tag to override - usually this is used with tag_type or + class_. Deprecated in favor of explicit and implicit params. + + :param optional: + Dummy parameter that allows "optional" key in spec param dicts + + :param default: + The default value to use if the value is currently None + + :param contents: + A byte string of the encoded contents of the value + + :param method: + The method for the value - no default value since this is + normally set on a class. Valid values include: + - "primitive" or 0 + - "constructed" or 1 + + :raises: + ValueError - when implicit, explicit, tag_type, class_ or tag are invalid values + """ + + try: + if self.__class__ not in _SETUP_CLASSES: + cls = self.__class__ + # Allow explicit to be specified as a simple 2-element tuple + # instead of requiring the user make a nested tuple + if cls.explicit is not None and isinstance(cls.explicit[0], int_types): + cls.explicit = (cls.explicit, ) + if hasattr(cls, '_setup'): + self._setup() + _SETUP_CLASSES[cls] = True + + # Normalize tagging values + if explicit is not None: + if isinstance(explicit, int_types): + if class_ is None: + class_ = 'context' + explicit = (class_, explicit) + # Prevent both explicit and tag_type == 'explicit' + if tag_type == 'explicit': + tag_type = None + tag = None + + if implicit is not None: + if isinstance(implicit, int_types): + if class_ is None: + class_ = 'context' + implicit = (class_, implicit) + # Prevent both implicit and tag_type == 'implicit' + if tag_type == 'implicit': + tag_type = None + tag = None + + # Convert old tag_type API to explicit/implicit params + if tag_type is not None: + if class_ is None: + class_ = 'context' + if tag_type == 'explicit': + explicit = (class_, tag) + elif tag_type == 'implicit': + implicit = (class_, tag) + else: + raise ValueError(unwrap( + ''' + tag_type must be one of "implicit", "explicit", not %s + ''', + repr(tag_type) + )) + + if explicit is not None: + # Ensure we have a tuple of 2-element tuples + if len(explicit) == 2 and isinstance(explicit[1], int_types): + explicit = (explicit, ) + for class_, tag in explicit: + invalid_class = None + if isinstance(class_, int_types): + if class_ not in CLASS_NUM_TO_NAME_MAP: + invalid_class = class_ + else: + if class_ not in CLASS_NAME_TO_NUM_MAP: + invalid_class = class_ + class_ = CLASS_NAME_TO_NUM_MAP[class_] + if invalid_class is not None: + raise ValueError(unwrap( + ''' + explicit class must be one of "universal", "application", + "context", "private", not %s + ''', + repr(invalid_class) + )) + if tag is not None: + if not isinstance(tag, int_types): + raise TypeError(unwrap( + ''' + explicit tag must be an integer, not %s + ''', + type_name(tag) + )) + if self.explicit is None: + self.explicit = ((class_, tag), ) + else: + self.explicit = self.explicit + ((class_, tag), ) + + elif implicit is not None: + class_, tag = implicit + if class_ not in CLASS_NAME_TO_NUM_MAP: + raise ValueError(unwrap( + ''' + implicit class must be one of "universal", "application", + "context", "private", not %s + ''', + repr(class_) + )) + if tag is not None: + if not isinstance(tag, int_types): + raise TypeError(unwrap( + ''' + implicit tag must be an integer, not %s + ''', + type_name(tag) + )) + self.class_ = CLASS_NAME_TO_NUM_MAP[class_] + self.tag = tag + self.implicit = True + else: + if class_ is not None: + if class_ not in CLASS_NAME_TO_NUM_MAP: + raise ValueError(unwrap( + ''' + class_ must be one of "universal", "application", + "context", "private", not %s + ''', + repr(class_) + )) + self.class_ = CLASS_NAME_TO_NUM_MAP[class_] + + if self.class_ is None: + self.class_ = 0 + + if tag is not None: + self.tag = tag + + if method is not None: + if method not in set(["primitive", 0, "constructed", 1]): + raise ValueError(unwrap( + ''' + method must be one of "primitive" or "constructed", + not %s + ''', + repr(method) + )) + if method == "primitive": + method = 0 + elif method == "constructed": + method = 1 + self.method = method + + if no_explicit: + self.explicit = None + + if contents is not None: + self.contents = contents + + elif default is not None: + self.set(default) + + except (ValueError, TypeError) as e: + args = e.args[1:] + e.args = (e.args[0] + '\n while constructing %s' % type_name(self),) + args + raise e + + def __str__(self): + """ + Since str is different in Python 2 and 3, this calls the appropriate + method, __unicode__() or __bytes__() + + :return: + A unicode string + """ + + if _PY2: + return self.__bytes__() + else: + return self.__unicode__() + + def __repr__(self): + """ + :return: + A unicode string + """ + + if _PY2: + return '<%s %s b%s>' % (type_name(self), id(self), repr(self.dump())) + else: + return '<%s %s %s>' % (type_name(self), id(self), repr(self.dump())) + + def __bytes__(self): + """ + A fall-back method for print() in Python 2 + + :return: + A byte string of the output of repr() + """ + + return self.__repr__().encode('utf-8') + + def __unicode__(self): + """ + A fall-back method for print() in Python 3 + + :return: + A unicode string of the output of repr() + """ + + return self.__repr__() + + def _new_instance(self): + """ + Constructs a new copy of the current object, preserving any tagging + + :return: + An Asn1Value object + """ + + new_obj = self.__class__() + new_obj.class_ = self.class_ + new_obj.tag = self.tag + new_obj.implicit = self.implicit + new_obj.explicit = self.explicit + return new_obj + + def __copy__(self): + """ + Implements the copy.copy() interface + + :return: + A new shallow copy of the current Asn1Value object + """ + + new_obj = self._new_instance() + new_obj._copy(self, copy.copy) + return new_obj + + def __deepcopy__(self, memo): + """ + Implements the copy.deepcopy() interface + + :param memo: + A dict for memoization + + :return: + A new deep copy of the current Asn1Value object + """ + + new_obj = self._new_instance() + memo[id(self)] = new_obj + new_obj._copy(self, copy.deepcopy) + return new_obj + + def copy(self): + """ + Copies the object, preserving any special tagging from it + + :return: + An Asn1Value object + """ + + return copy.deepcopy(self) + + def retag(self, tagging, tag=None): + """ + Copies the object, applying a new tagging to it + + :param tagging: + A dict containing the keys "explicit" and "implicit". Legacy + API allows a unicode string of "implicit" or "explicit". + + :param tag: + A integer tag number. Only used when tagging is a unicode string. + + :return: + An Asn1Value object + """ + + # This is required to preserve the old API + if not isinstance(tagging, dict): + tagging = {tagging: tag} + new_obj = self.__class__(explicit=tagging.get('explicit'), implicit=tagging.get('implicit')) + new_obj._copy(self, copy.deepcopy) + return new_obj + + def untag(self): + """ + Copies the object, removing any special tagging from it + + :return: + An Asn1Value object + """ + + new_obj = self.__class__() + new_obj._copy(self, copy.deepcopy) + return new_obj + + def _copy(self, other, copy_func): + """ + Copies the contents of another Asn1Value object to itself + + :param object: + Another instance of the same class + + :param copy_func: + An reference of copy.copy() or copy.deepcopy() to use when copying + lists, dicts and objects + """ + + if self.__class__ != other.__class__: + raise TypeError(unwrap( + ''' + Can not copy values from %s object to %s object + ''', + type_name(other), + type_name(self) + )) + + self.contents = other.contents + self._native = copy_func(other._native) + + def debug(self, nest_level=1): + """ + Show the binary data and parsed data in a tree structure + """ + + prefix = ' ' * nest_level + + # This interacts with Any and moves the tag, implicit, explicit, _header, + # contents, _footer to the parsed value so duplicate data isn't present + has_parsed = hasattr(self, 'parsed') + + _basic_debug(prefix, self) + if has_parsed: + self.parsed.debug(nest_level + 2) + elif hasattr(self, 'chosen'): + self.chosen.debug(nest_level + 2) + else: + if _PY2 and isinstance(self.native, byte_cls): + print('%s Native: b%s' % (prefix, repr(self.native))) + else: + print('%s Native: %s' % (prefix, self.native)) + + def dump(self, force=False): + """ + Encodes the value using DER + + :param force: + If the encoded contents already exist, clear them and regenerate + to ensure they are in DER format instead of BER format + + :return: + A byte string of the DER-encoded value + """ + + contents = self.contents + + # If the length is indefinite, force the re-encoding + if self._header is not None and self._header[-1:] == b'\x80': + force = True + + if self._header is None or force: + if isinstance(self, Constructable) and self._indefinite: + self.method = 0 + + header = _dump_header(self.class_, self.method, self.tag, self.contents) + + if self.explicit is not None: + for class_, tag in self.explicit: + header = _dump_header(class_, 1, tag, header + self.contents) + header + + self._header = header + self._trailer = b'' + + return self._header + contents + self._trailer + + +class ValueMap(): + """ + Basic functionality that allows for mapping values from ints or OIDs to + python unicode strings + """ + + # A dict from primitive value (int or OID) to unicode string. This needs + # to be defined in the source code + _map = None + + # A dict from unicode string to int/OID. This is automatically generated + # from _map the first time it is needed + _reverse_map = None + + def _setup(self): + """ + Generates _reverse_map from _map + """ + + cls = self.__class__ + if cls._map is None or cls._reverse_map is not None: + return + cls._reverse_map = {} + for key, value in cls._map.items(): + cls._reverse_map[value] = key + + +class Castable(object): + """ + A mixin to handle converting an object between different classes that + represent the same encoded value, but with different rules for converting + to and from native Python values + """ + + def cast(self, other_class): + """ + Converts the current object into an object of a different class. The + new class must use the ASN.1 encoding for the value. + + :param other_class: + The class to instantiate the new object from + + :return: + An instance of the type other_class + """ + + if other_class.tag != self.__class__.tag: + raise TypeError(unwrap( + ''' + Can not covert a value from %s object to %s object since they + use different tags: %d versus %d + ''', + type_name(other_class), + type_name(self), + other_class.tag, + self.__class__.tag + )) + + new_obj = other_class() + new_obj.class_ = self.class_ + new_obj.implicit = self.implicit + new_obj.explicit = self.explicit + new_obj._header = self._header + new_obj.contents = self.contents + new_obj._trailer = self._trailer + if isinstance(self, Constructable): + new_obj.method = self.method + new_obj._indefinite = self._indefinite + return new_obj + + +class Constructable(object): + """ + A mixin to handle string types that may be constructed from chunks + contained within an indefinite length BER-encoded container + """ + + # Instance attribute indicating if an object was indefinite + # length when parsed - affects parsing and dumping + _indefinite = False + + def _merge_chunks(self): + """ + :return: + A concatenation of the native values of the contained chunks + """ + + if not self._indefinite: + return self._as_chunk() + + pointer = 0 + contents_len = len(self.contents) + output = None + + while pointer < contents_len: + # We pass the current class as the spec so content semantics are preserved + sub_value, pointer = _parse_build(self.contents, pointer, spec=self.__class__) + if output is None: + output = sub_value._merge_chunks() + else: + output += sub_value._merge_chunks() + + if output is None: + return self._as_chunk() + + return output + + def _as_chunk(self): + """ + A method to return a chunk of data that can be combined for + constructed method values + + :return: + A native Python value that can be added together. Examples include + byte strings, unicode strings or tuples. + """ + + return self.contents + + def _setable_native(self): + """ + Returns a native value that can be round-tripped into .set(), to + result in a DER encoding. This differs from .native in that .native + is designed for the end use, and may account for the fact that the + merged value is further parsed as ASN.1, such as in the case of + ParsableOctetString() and ParsableOctetBitString(). + + :return: + A python value that is valid to pass to .set() + """ + + return self.native + + def _copy(self, other, copy_func): + """ + Copies the contents of another Constructable object to itself + + :param object: + Another instance of the same class + + :param copy_func: + An reference of copy.copy() or copy.deepcopy() to use when copying + lists, dicts and objects + """ + + super(Constructable, self)._copy(other, copy_func) + # We really don't want to dump BER encodings, so if we see an + # indefinite encoding, let's re-encode it + if other._indefinite: + self.set(other._setable_native()) + + +class Void(Asn1Value): + """ + A representation of an optional value that is not present. Has .native + property and .dump() method to be compatible with other value classes. + """ + + contents = b'' + + def __eq__(self, other): + """ + :param other: + The other Primitive to compare to + + :return: + A boolean + """ + + return other.__class__ == self.__class__ + + def __nonzero__(self): + return False + + def __len__(self): + return 0 + + def __iter__(self): + return iter(()) + + @property + def native(self): + """ + The native Python datatype representation of this value + + :return: + None + """ + + return None + + def dump(self, force=False): + """ + Encodes the value using DER + + :param force: + If the encoded contents already exist, clear them and regenerate + to ensure they are in DER format instead of BER format + + :return: + A byte string of the DER-encoded value + """ + + return b'' + + +VOID = Void() + + +class Any(Asn1Value): + """ + A value class that can contain any value, and allows for easy parsing of + the underlying encoded value using a spec. This is normally contained in + a Structure that has an ObjectIdentifier field and _oid_pair and _oid_specs + defined. + """ + + # The parsed value object + _parsed = None + + def __init__(self, value=None, **kwargs): + """ + Sets the value of the object before passing to Asn1Value.__init__() + + :param value: + An Asn1Value object that will be set as the parsed value + """ + + Asn1Value.__init__(self, **kwargs) + + try: + if value is not None: + if not isinstance(value, Asn1Value): + raise TypeError(unwrap( + ''' + value must be an instance of Asn1Value, not %s + ''', + type_name(value) + )) + + self._parsed = (value, value.__class__, None) + self.contents = value.dump() + + except (ValueError, TypeError) as e: + args = e.args[1:] + e.args = (e.args[0] + '\n while constructing %s' % type_name(self),) + args + raise e + + @property + def native(self): + """ + The native Python datatype representation of this value + + :return: + The .native value from the parsed value object + """ + + if self._parsed is None: + self.parse() + + return self._parsed[0].native + + @property + def parsed(self): + """ + Returns the parsed object from .parse() + + :return: + The object returned by .parse() + """ + + if self._parsed is None: + self.parse() + + return self._parsed[0] + + def parse(self, spec=None, spec_params=None): + """ + Parses the contents generically, or using a spec with optional params + + :param spec: + A class derived from Asn1Value that defines what class_ and tag the + value should have, and the semantics of the encoded value. The + return value will be of this type. If omitted, the encoded value + will be decoded using the standard universal tag based on the + encoded tag number. + + :param spec_params: + A dict of params to pass to the spec object + + :return: + An object of the type spec, or if not present, a child of Asn1Value + """ + + if self._parsed is None or self._parsed[1:3] != (spec, spec_params): + try: + passed_params = spec_params or {} + _tag_type_to_explicit_implicit(passed_params) + if self.explicit is not None: + if 'explicit' in passed_params: + passed_params['explicit'] = self.explicit + passed_params['explicit'] + else: + passed_params['explicit'] = self.explicit + contents = self._header + self.contents + self._trailer + parsed_value, _ = _parse_build( + contents, + spec=spec, + spec_params=passed_params + ) + self._parsed = (parsed_value, spec, spec_params) + + # Once we've parsed the Any value, clear any attributes from this object + # since they are now duplicate + self.tag = None + self.explicit = None + self.implicit = False + self._header = b'' + self.contents = contents + self._trailer = b'' + + except (ValueError, TypeError) as e: + args = e.args[1:] + e.args = (e.args[0] + '\n while parsing %s' % type_name(self),) + args + raise e + return self._parsed[0] + + def _copy(self, other, copy_func): + """ + Copies the contents of another Any object to itself + + :param object: + Another instance of the same class + + :param copy_func: + An reference of copy.copy() or copy.deepcopy() to use when copying + lists, dicts and objects + """ + + super(Any, self)._copy(other, copy_func) + self._parsed = copy_func(other._parsed) + + def dump(self, force=False): + """ + Encodes the value using DER + + :param force: + If the encoded contents already exist, clear them and regenerate + to ensure they are in DER format instead of BER format + + :return: + A byte string of the DER-encoded value + """ + + if self._parsed is None: + self.parse() + + return self._parsed[0].dump(force=force) + + +class Choice(Asn1Value): + """ + A class to handle when a value may be one of several options + """ + + # The index in _alternatives of the validated alternative + _choice = None + + # The name of the chosen alternative + _name = None + + # The Asn1Value object for the chosen alternative + _parsed = None + + # Choice overrides .contents to be a property so that the code expecting + # the .contents attribute will get the .contents of the chosen alternative + _contents = None + + # A list of tuples in one of the following forms. + # + # Option 1, a unicode string field name and a value class + # + # ("name", Asn1ValueClass) + # + # Option 2, same as Option 1, but with a dict of class params + # + # ("name", Asn1ValueClass, {'explicit': 5}) + _alternatives = None + + # A dict that maps tuples of (class_, tag) to an index in _alternatives + _id_map = None + + # A dict that maps alternative names to an index in _alternatives + _name_map = None + + @classmethod + def load(cls, encoded_data, strict=False, **kwargs): + """ + Loads a BER/DER-encoded byte string using the current class as the spec + + :param encoded_data: + A byte string of BER or DER encoded data + + :param strict: + A boolean indicating if trailing data should be forbidden - if so, a + ValueError will be raised when trailing data exists + + :return: + A instance of the current class + """ + + if not isinstance(encoded_data, byte_cls): + raise TypeError('encoded_data must be a byte string, not %s' % type_name(encoded_data)) + + value, _ = _parse_build(encoded_data, spec=cls, spec_params=kwargs, strict=strict) + return value + + def _setup(self): + """ + Generates _id_map from _alternatives to allow validating contents + """ + + cls = self.__class__ + cls._id_map = {} + cls._name_map = {} + for index, info in enumerate(cls._alternatives): + if len(info) < 3: + info = info + ({},) + cls._alternatives[index] = info + id_ = _build_id_tuple(info[2], info[1]) + cls._id_map[id_] = index + cls._name_map[info[0]] = index + + def __init__(self, name=None, value=None, **kwargs): + """ + Checks to ensure implicit tagging is not being used since it is + incompatible with Choice, then forwards on to Asn1Value.__init__() + + :param name: + The name of the alternative to be set - used with value. + Alternatively this may be a dict with a single key being the name + and the value being the value, or a two-element tuple of the name + and the value. + + :param value: + The alternative value to set - used with name + + :raises: + ValueError - when implicit param is passed (or legacy tag_type param is "implicit") + """ + + _tag_type_to_explicit_implicit(kwargs) + + Asn1Value.__init__(self, **kwargs) + + try: + if kwargs.get('implicit') is not None: + raise ValueError(unwrap( + ''' + The Choice type can not be implicitly tagged even if in an + implicit module - due to its nature any tagging must be + explicit + ''' + )) + + if name is not None: + if isinstance(name, dict): + if len(name) != 1: + raise ValueError(unwrap( + ''' + When passing a dict as the "name" argument to %s, + it must have a single key/value - however %d were + present + ''', + type_name(self), + len(name) + )) + name, value = list(name.items())[0] + + if isinstance(name, tuple): + if len(name) != 2: + raise ValueError(unwrap( + ''' + When passing a tuple as the "name" argument to %s, + it must have two elements, the name and value - + however %d were present + ''', + type_name(self), + len(name) + )) + value = name[1] + name = name[0] + + if name not in self._name_map: + raise ValueError(unwrap( + ''' + The name specified, "%s", is not a valid alternative + for %s + ''', + name, + type_name(self) + )) + + self._choice = self._name_map[name] + _, spec, params = self._alternatives[self._choice] + + if not isinstance(value, spec): + value = spec(value, **params) + else: + value = _fix_tagging(value, params) + self._parsed = value + + except (ValueError, TypeError) as e: + args = e.args[1:] + e.args = (e.args[0] + '\n while constructing %s' % type_name(self),) + args + raise e + + @property + def contents(self): + """ + :return: + A byte string of the DER-encoded contents of the chosen alternative + """ + + if self._parsed is not None: + return self._parsed.contents + + return self._contents + + @contents.setter + def contents(self, value): + """ + :param value: + A byte string of the DER-encoded contents of the chosen alternative + """ + + self._contents = value + + @property + def name(self): + """ + :return: + A unicode string of the field name of the chosen alternative + """ + if not self._name: + self._name = self._alternatives[self._choice][0] + return self._name + + def parse(self): + """ + Parses the detected alternative + + :return: + An Asn1Value object of the chosen alternative + """ + + if self._parsed is None: + try: + _, spec, params = self._alternatives[self._choice] + self._parsed, _ = _parse_build(self._contents, spec=spec, spec_params=params) + except (ValueError, TypeError) as e: + args = e.args[1:] + e.args = (e.args[0] + '\n while parsing %s' % type_name(self),) + args + raise e + return self._parsed + + @property + def chosen(self): + """ + :return: + An Asn1Value object of the chosen alternative + """ + + return self.parse() + + @property + def native(self): + """ + The native Python datatype representation of this value + + :return: + The .native value from the contained value object + """ + + return self.chosen.native + + def validate(self, class_, tag, contents): + """ + Ensures that the class and tag specified exist as an alternative + + :param class_: + The integer class_ from the encoded value header + + :param tag: + The integer tag from the encoded value header + + :param contents: + A byte string of the contents of the value - used when the object + is explicitly tagged + + :raises: + ValueError - when value is not a valid alternative + """ + + id_ = (class_, tag) + + if self.explicit is not None: + if self.explicit[-1] != id_: + raise ValueError(unwrap( + ''' + %s was explicitly tagged, but the value provided does not + match the class and tag + ''', + type_name(self) + )) + + ((class_, _, tag, _, _, _), _) = _parse(contents, len(contents)) + id_ = (class_, tag) + + if id_ in self._id_map: + self._choice = self._id_map[id_] + return + + # This means the Choice was implicitly tagged + if self.class_ is not None and self.tag is not None: + if len(self._alternatives) > 1: + raise ValueError(unwrap( + ''' + %s was implicitly tagged, but more than one alternative + exists + ''', + type_name(self) + )) + if id_ == (self.class_, self.tag): + self._choice = 0 + return + + asn1 = self._format_class_tag(class_, tag) + asn1s = [self._format_class_tag(pair[0], pair[1]) for pair in self._id_map] + + raise ValueError(unwrap( + ''' + Value %s did not match the class and tag of any of the alternatives + in %s: %s + ''', + asn1, + type_name(self), + ', '.join(asn1s) + )) + + def _format_class_tag(self, class_, tag): + """ + :return: + A unicode string of a human-friendly representation of the class and tag + """ + + return '[%s %s]' % (CLASS_NUM_TO_NAME_MAP[class_].upper(), tag) + + def _copy(self, other, copy_func): + """ + Copies the contents of another Choice object to itself + + :param object: + Another instance of the same class + + :param copy_func: + An reference of copy.copy() or copy.deepcopy() to use when copying + lists, dicts and objects + """ + + super(Choice, self)._copy(other, copy_func) + self._choice = other._choice + self._name = other._name + self._parsed = copy_func(other._parsed) + + def dump(self, force=False): + """ + Encodes the value using DER + + :param force: + If the encoded contents already exist, clear them and regenerate + to ensure they are in DER format instead of BER format + + :return: + A byte string of the DER-encoded value + """ + + # If the length is indefinite, force the re-encoding + if self._header is not None and self._header[-1:] == b'\x80': + force = True + + self._contents = self.chosen.dump(force=force) + if self._header is None or force: + self._header = b'' + if self.explicit is not None: + for class_, tag in self.explicit: + self._header = _dump_header(class_, 1, tag, self._header + self._contents) + self._header + return self._header + self._contents + + +class Concat(object): + """ + A class that contains two or more encoded child values concatentated + together. THIS IS NOT PART OF THE ASN.1 SPECIFICATION! This exists to handle + the x509.TrustedCertificate() class for OpenSSL certificates containing + extra information. + """ + + # A list of the specs of the concatenated values + _child_specs = None + + _children = None + + @classmethod + def load(cls, encoded_data, strict=False): + """ + Loads a BER/DER-encoded byte string using the current class as the spec + + :param encoded_data: + A byte string of BER or DER encoded data + + :param strict: + A boolean indicating if trailing data should be forbidden - if so, a + ValueError will be raised when trailing data exists + + :return: + A Concat object + """ + + return cls(contents=encoded_data, strict=strict) + + def __init__(self, value=None, contents=None, strict=False): + """ + :param value: + A native Python datatype to initialize the object value with + + :param contents: + A byte string of the encoded contents of the value + + :param strict: + A boolean indicating if trailing data should be forbidden - if so, a + ValueError will be raised when trailing data exists in contents + + :raises: + ValueError - when an error occurs with one of the children + TypeError - when an error occurs with one of the children + """ + + if contents is not None: + try: + contents_len = len(contents) + self._children = [] + + offset = 0 + for spec in self._child_specs: + if offset < contents_len: + child_value, offset = _parse_build(contents, pointer=offset, spec=spec) + else: + child_value = spec() + self._children.append(child_value) + + if strict and offset != contents_len: + extra_bytes = contents_len - offset + raise ValueError('Extra data - %d bytes of trailing data were provided' % extra_bytes) + + except (ValueError, TypeError) as e: + args = e.args[1:] + e.args = (e.args[0] + '\n while constructing %s' % type_name(self),) + args + raise e + + if value is not None: + if self._children is None: + self._children = [None] * len(self._child_specs) + for index, data in enumerate(value): + self.__setitem__(index, data) + + def __str__(self): + """ + Since str is different in Python 2 and 3, this calls the appropriate + method, __unicode__() or __bytes__() + + :return: + A unicode string + """ + + if _PY2: + return self.__bytes__() + else: + return self.__unicode__() + + def __bytes__(self): + """ + A byte string of the DER-encoded contents + """ + + return self.dump() + + def __unicode__(self): + """ + :return: + A unicode string + """ + + return repr(self) + + def __repr__(self): + """ + :return: + A unicode string + """ + + return '<%s %s %s>' % (type_name(self), id(self), repr(self.dump())) + + def __copy__(self): + """ + Implements the copy.copy() interface + + :return: + A new shallow copy of the Concat object + """ + + new_obj = self.__class__() + new_obj._copy(self, copy.copy) + return new_obj + + def __deepcopy__(self, memo): + """ + Implements the copy.deepcopy() interface + + :param memo: + A dict for memoization + + :return: + A new deep copy of the Concat object and all child objects + """ + + new_obj = self.__class__() + memo[id(self)] = new_obj + new_obj._copy(self, copy.deepcopy) + return new_obj + + def copy(self): + """ + Copies the object + + :return: + A Concat object + """ + + return copy.deepcopy(self) + + def _copy(self, other, copy_func): + """ + Copies the contents of another Concat object to itself + + :param object: + Another instance of the same class + + :param copy_func: + An reference of copy.copy() or copy.deepcopy() to use when copying + lists, dicts and objects + """ + + if self.__class__ != other.__class__: + raise TypeError(unwrap( + ''' + Can not copy values from %s object to %s object + ''', + type_name(other), + type_name(self) + )) + + self._children = copy_func(other._children) + + def debug(self, nest_level=1): + """ + Show the binary data and parsed data in a tree structure + """ + + prefix = ' ' * nest_level + print('%s%s Object #%s' % (prefix, type_name(self), id(self))) + print('%s Children:' % (prefix,)) + for child in self._children: + child.debug(nest_level + 2) + + def dump(self, force=False): + """ + Encodes the value using DER + + :param force: + If the encoded contents already exist, clear them and regenerate + to ensure they are in DER format instead of BER format + + :return: + A byte string of the DER-encoded value + """ + + contents = b'' + for child in self._children: + contents += child.dump(force=force) + return contents + + @property + def contents(self): + """ + :return: + A byte string of the DER-encoded contents of the children + """ + + return self.dump() + + def __len__(self): + """ + :return: + Integer + """ + + return len(self._children) + + def __getitem__(self, key): + """ + Allows accessing children by index + + :param key: + An integer of the child index + + :raises: + KeyError - when an index is invalid + + :return: + The Asn1Value object of the child specified + """ + + if key > len(self._child_specs) - 1 or key < 0: + raise KeyError(unwrap( + ''' + No child is definition for position %d of %s + ''', + key, + type_name(self) + )) + + return self._children[key] + + def __setitem__(self, key, value): + """ + Allows settings children by index + + :param key: + An integer of the child index + + :param value: + An Asn1Value object to set the child to + + :raises: + KeyError - when an index is invalid + ValueError - when the value is not an instance of Asn1Value + """ + + if key > len(self._child_specs) - 1 or key < 0: + raise KeyError(unwrap( + ''' + No child is defined for position %d of %s + ''', + key, + type_name(self) + )) + + if not isinstance(value, Asn1Value): + raise ValueError(unwrap( + ''' + Value for child %s of %s is not an instance of + asn1crypto.core.Asn1Value + ''', + key, + type_name(self) + )) + + self._children[key] = value + + def __iter__(self): + """ + :return: + An iterator of child values + """ + + return iter(self._children) + + +class Primitive(Asn1Value): + """ + Sets the class_ and method attributes for primitive, universal values + """ + + class_ = 0 + + method = 0 + + def __init__(self, value=None, default=None, contents=None, **kwargs): + """ + Sets the value of the object before passing to Asn1Value.__init__() + + :param value: + A native Python datatype to initialize the object value with + + :param default: + The default value if no value is specified + + :param contents: + A byte string of the encoded contents of the value + """ + + Asn1Value.__init__(self, **kwargs) + + try: + if contents is not None: + self.contents = contents + + elif value is not None: + self.set(value) + + elif default is not None: + self.set(default) + + except (ValueError, TypeError) as e: + args = e.args[1:] + e.args = (e.args[0] + '\n while constructing %s' % type_name(self),) + args + raise e + + def set(self, value): + """ + Sets the value of the object + + :param value: + A byte string + """ + + if not isinstance(value, byte_cls): + raise TypeError(unwrap( + ''' + %s value must be a byte string, not %s + ''', + type_name(self), + type_name(value) + )) + + self._native = value + self.contents = value + self._header = None + if self._trailer != b'': + self._trailer = b'' + + def dump(self, force=False): + """ + Encodes the value using DER + + :param force: + If the encoded contents already exist, clear them and regenerate + to ensure they are in DER format instead of BER format + + :return: + A byte string of the DER-encoded value + """ + + # If the length is indefinite, force the re-encoding + if self._header is not None and self._header[-1:] == b'\x80': + force = True + + if force: + native = self.native + self.contents = None + self.set(native) + + return Asn1Value.dump(self) + + def __ne__(self, other): + return not self == other + + def __eq__(self, other): + """ + :param other: + The other Primitive to compare to + + :return: + A boolean + """ + + if not isinstance(other, Primitive): + return False + + if self.contents != other.contents: + return False + + # We compare class tag numbers since object tag numbers could be + # different due to implicit or explicit tagging + if self.__class__.tag != other.__class__.tag: + return False + + if self.__class__ == other.__class__ and self.contents == other.contents: + return True + + # If the objects share a common base class that is not too low-level + # then we can compare the contents + self_bases = (set(self.__class__.__bases__) | set([self.__class__])) - set([Asn1Value, Primitive, ValueMap]) + other_bases = (set(other.__class__.__bases__) | set([other.__class__])) - set([Asn1Value, Primitive, ValueMap]) + if self_bases | other_bases: + return self.contents == other.contents + + # When tagging is going on, do the extra work of constructing new + # objects to see if the dumped representation are the same + if self.implicit or self.explicit or other.implicit or other.explicit: + return self.untag().dump() == other.untag().dump() + + return self.dump() == other.dump() + + +class AbstractString(Constructable, Primitive): + """ + A base class for all strings that have a known encoding. In general, we do + not worry ourselves with confirming that the decoded values match a specific + set of characters, only that they are decoded into a Python unicode string + """ + + # The Python encoding name to use when decoding or encoded the contents + _encoding = 'latin1' + + # Instance attribute of (possibly-merged) unicode string + _unicode = None + + def set(self, value): + """ + Sets the value of the string + + :param value: + A unicode string + """ + + if not isinstance(value, str_cls): + raise TypeError(unwrap( + ''' + %s value must be a unicode string, not %s + ''', + type_name(self), + type_name(value) + )) + + self._unicode = value + self.contents = value.encode(self._encoding) + self._header = None + if self._indefinite: + self._indefinite = False + self.method = 0 + if self._trailer != b'': + self._trailer = b'' + + def __unicode__(self): + """ + :return: + A unicode string + """ + + if self.contents is None: + return '' + if self._unicode is None: + self._unicode = self._merge_chunks().decode(self._encoding) + return self._unicode + + def _copy(self, other, copy_func): + """ + Copies the contents of another AbstractString object to itself + + :param object: + Another instance of the same class + + :param copy_func: + An reference of copy.copy() or copy.deepcopy() to use when copying + lists, dicts and objects + """ + + super(AbstractString, self)._copy(other, copy_func) + self._unicode = other._unicode + + @property + def native(self): + """ + The native Python datatype representation of this value + + :return: + A unicode string or None + """ + + if self.contents is None: + return None + + return self.__unicode__() + + +class Boolean(Primitive): + """ + Represents a boolean in both ASN.1 and Python + """ + + tag = 1 + + def set(self, value): + """ + Sets the value of the object + + :param value: + True, False or another value that works with bool() + """ + + self._native = bool(value) + self.contents = b'\x00' if not value else b'\xff' + self._header = None + if self._trailer != b'': + self._trailer = b'' + + # Python 2 + def __nonzero__(self): + """ + :return: + True or False + """ + return self.__bool__() + + def __bool__(self): + """ + :return: + True or False + """ + return self.contents != b'\x00' + + @property + def native(self): + """ + The native Python datatype representation of this value + + :return: + True, False or None + """ + + if self.contents is None: + return None + + if self._native is None: + self._native = self.__bool__() + return self._native + + +class Integer(Primitive, ValueMap): + """ + Represents an integer in both ASN.1 and Python + """ + + tag = 2 + + def set(self, value): + """ + Sets the value of the object + + :param value: + An integer, or a unicode string if _map is set + + :raises: + ValueError - when an invalid value is passed + """ + + if isinstance(value, str_cls): + if self._map is None: + raise ValueError(unwrap( + ''' + %s value is a unicode string, but no _map provided + ''', + type_name(self) + )) + + if value not in self._reverse_map: + raise ValueError(unwrap( + ''' + %s value, %s, is not present in the _map + ''', + type_name(self), + value + )) + + value = self._reverse_map[value] + + elif not isinstance(value, int_types): + raise TypeError(unwrap( + ''' + %s value must be an integer or unicode string when a name_map + is provided, not %s + ''', + type_name(self), + type_name(value) + )) + + self._native = self._map[value] if self._map and value in self._map else value + + self.contents = int_to_bytes(value, signed=True) + self._header = None + if self._trailer != b'': + self._trailer = b'' + + def __int__(self): + """ + :return: + An integer + """ + return int_from_bytes(self.contents, signed=True) + + @property + def native(self): + """ + The native Python datatype representation of this value + + :return: + An integer or None + """ + + if self.contents is None: + return None + + if self._native is None: + self._native = self.__int__() + if self._map is not None and self._native in self._map: + self._native = self._map[self._native] + return self._native + + +class _IntegerBitString(object): + """ + A mixin for IntegerBitString and BitString to parse the contents as an integer. + """ + + # Tuple of 1s and 0s; set through native + _unused_bits = () + + def _as_chunk(self): + """ + Parse the contents of a primitive BitString encoding as an integer value. + Allows reconstructing indefinite length values. + + :raises: + ValueError - when an invalid value is passed + + :return: + A list with one tuple (value, bits, unused_bits) where value is an integer + with the value of the BitString, bits is the bit count of value and + unused_bits is a tuple of 1s and 0s. + """ + + if self._indefinite: + # return an empty chunk, for cases like \x23\x80\x00\x00 + return [] + + unused_bits_len = ord(self.contents[0]) if _PY2 else self.contents[0] + value = int_from_bytes(self.contents[1:]) + bits = (len(self.contents) - 1) * 8 + + if not unused_bits_len: + return [(value, bits, ())] + + if len(self.contents) == 1: + # Disallowed by X.690 §8.6.2.3 + raise ValueError('Empty bit string has {0} unused bits'.format(unused_bits_len)) + + if unused_bits_len > 7: + # Disallowed by X.690 §8.6.2.2 + raise ValueError('Bit string has {0} unused bits'.format(unused_bits_len)) + + unused_bits = _int_to_bit_tuple(value & ((1 << unused_bits_len) - 1), unused_bits_len) + value >>= unused_bits_len + bits -= unused_bits_len + + return [(value, bits, unused_bits)] + + def _chunks_to_int(self): + """ + Combines the chunks into a single value. + + :raises: + ValueError - when an invalid value is passed + + :return: + A tuple (value, bits, unused_bits) where value is an integer with the + value of the BitString, bits is the bit count of value and unused_bits + is a tuple of 1s and 0s. + """ + + if not self._indefinite: + # Fast path + return self._as_chunk()[0] + + value = 0 + total_bits = 0 + unused_bits = () + + # X.690 §8.6.3 allows empty indefinite encodings + for chunk, bits, unused_bits in self._merge_chunks(): + if total_bits & 7: + # Disallowed by X.690 §8.6.4 + raise ValueError('Only last chunk in a bit string may have unused bits') + total_bits += bits + value = (value << bits) | chunk + + return value, total_bits, unused_bits + + def _copy(self, other, copy_func): + """ + Copies the contents of another _IntegerBitString object to itself + + :param object: + Another instance of the same class + + :param copy_func: + An reference of copy.copy() or copy.deepcopy() to use when copying + lists, dicts and objects + """ + + super(_IntegerBitString, self)._copy(other, copy_func) + self._unused_bits = other._unused_bits + + @property + def unused_bits(self): + """ + The unused bits of the bit string encoding. + + :return: + A tuple of 1s and 0s + """ + + # call native to set _unused_bits + self.native + + return self._unused_bits + + +class BitString(_IntegerBitString, Constructable, Castable, Primitive, ValueMap): + """ + Represents a bit string from ASN.1 as a Python tuple of 1s and 0s + """ + + tag = 3 + + _size = None + + def _setup(self): + """ + Generates _reverse_map from _map + """ + + ValueMap._setup(self) + + cls = self.__class__ + if cls._map is not None: + cls._size = max(self._map.keys()) + 1 + + def set(self, value): + """ + Sets the value of the object + + :param value: + An integer or a tuple of integers 0 and 1 + + :raises: + ValueError - when an invalid value is passed + """ + + if isinstance(value, set): + if self._map is None: + raise ValueError(unwrap( + ''' + %s._map has not been defined + ''', + type_name(self) + )) + + bits = [0] * self._size + self._native = value + for index in range(0, self._size): + key = self._map.get(index) + if key is None: + continue + if key in value: + bits[index] = 1 + + value = ''.join(map(str_cls, bits)) + + elif value.__class__ == tuple: + if self._map is None: + self._native = value + else: + self._native = set() + for index, bit in enumerate(value): + if bit: + name = self._map.get(index, index) + self._native.add(name) + value = ''.join(map(str_cls, value)) + + else: + raise TypeError(unwrap( + ''' + %s value must be a tuple of ones and zeros or a set of unicode + strings, not %s + ''', + type_name(self), + type_name(value) + )) + + if self._map is not None: + if len(value) > self._size: + raise ValueError(unwrap( + ''' + %s value must be at most %s bits long, specified was %s long + ''', + type_name(self), + self._size, + len(value) + )) + # A NamedBitList must have trailing zero bit truncated. See + # https://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf + # section 11.2, + # https://tools.ietf.org/html/rfc5280#page-134 and + # https://www.ietf.org/mail-archive/web/pkix/current/msg10443.html + value = value.rstrip('0') + size = len(value) + + size_mod = size % 8 + extra_bits = 0 + if size_mod != 0: + extra_bits = 8 - size_mod + value += '0' * extra_bits + + size_in_bytes = int(math.ceil(size / 8)) + + if extra_bits: + extra_bits_byte = int_to_bytes(extra_bits) + else: + extra_bits_byte = b'\x00' + + if value == '': + value_bytes = b'' + else: + value_bytes = int_to_bytes(int(value, 2)) + if len(value_bytes) != size_in_bytes: + value_bytes = (b'\x00' * (size_in_bytes - len(value_bytes))) + value_bytes + + self.contents = extra_bits_byte + value_bytes + self._unused_bits = (0,) * extra_bits + self._header = None + if self._indefinite: + self._indefinite = False + self.method = 0 + if self._trailer != b'': + self._trailer = b'' + + def __getitem__(self, key): + """ + Retrieves a boolean version of one of the bits based on a name from the + _map + + :param key: + The unicode string of one of the bit names + + :raises: + ValueError - when _map is not set or the key name is invalid + + :return: + A boolean if the bit is set + """ + + is_int = isinstance(key, int_types) + if not is_int: + if not isinstance(self._map, dict): + raise ValueError(unwrap( + ''' + %s._map has not been defined + ''', + type_name(self) + )) + + if key not in self._reverse_map: + raise ValueError(unwrap( + ''' + %s._map does not contain an entry for "%s" + ''', + type_name(self), + key + )) + + if self._native is None: + self.native + + if self._map is None: + if len(self._native) >= key + 1: + return bool(self._native[key]) + return False + + if is_int: + key = self._map.get(key, key) + + return key in self._native + + def __setitem__(self, key, value): + """ + Sets one of the bits based on a name from the _map + + :param key: + The unicode string of one of the bit names + + :param value: + A boolean value + + :raises: + ValueError - when _map is not set or the key name is invalid + """ + + is_int = isinstance(key, int_types) + if not is_int: + if self._map is None: + raise ValueError(unwrap( + ''' + %s._map has not been defined + ''', + type_name(self) + )) + + if key not in self._reverse_map: + raise ValueError(unwrap( + ''' + %s._map does not contain an entry for "%s" + ''', + type_name(self), + key + )) + + if self._native is None: + self.native + + if self._map is None: + new_native = list(self._native) + max_key = len(new_native) - 1 + if key > max_key: + new_native.extend([0] * (key - max_key)) + new_native[key] = 1 if value else 0 + self._native = tuple(new_native) + + else: + if is_int: + key = self._map.get(key, key) + + if value: + if key not in self._native: + self._native.add(key) + else: + if key in self._native: + self._native.remove(key) + + self.set(self._native) + + @property + def native(self): + """ + The native Python datatype representation of this value + + :return: + If a _map is set, a set of names, or if no _map is set, a tuple of + integers 1 and 0. None if no value. + """ + + # For BitString we default the value to be all zeros + if self.contents is None: + if self._map is None: + self.set(()) + else: + self.set(set()) + + if self._native is None: + int_value, bit_count, self._unused_bits = self._chunks_to_int() + bits = _int_to_bit_tuple(int_value, bit_count) + + if self._map: + self._native = set() + for index, bit in enumerate(bits): + if bit: + name = self._map.get(index, index) + self._native.add(name) + else: + self._native = bits + return self._native + + +class OctetBitString(Constructable, Castable, Primitive): + """ + Represents a bit string in ASN.1 as a Python byte string + """ + + tag = 3 + + # Instance attribute of (possibly-merged) byte string + _bytes = None + + # Tuple of 1s and 0s; set through native + _unused_bits = () + + def set(self, value): + """ + Sets the value of the object + + :param value: + A byte string + + :raises: + ValueError - when an invalid value is passed + """ + + if not isinstance(value, byte_cls): + raise TypeError(unwrap( + ''' + %s value must be a byte string, not %s + ''', + type_name(self), + type_name(value) + )) + + self._bytes = value + # Set the unused bits to 0 + self.contents = b'\x00' + value + self._unused_bits = () + self._header = None + if self._indefinite: + self._indefinite = False + self.method = 0 + if self._trailer != b'': + self._trailer = b'' + + def __bytes__(self): + """ + :return: + A byte string + """ + + if self.contents is None: + return b'' + if self._bytes is None: + if not self._indefinite: + self._bytes, self._unused_bits = self._as_chunk()[0] + else: + chunks = self._merge_chunks() + self._unused_bits = () + for chunk in chunks: + if self._unused_bits: + # Disallowed by X.690 §8.6.4 + raise ValueError('Only last chunk in a bit string may have unused bits') + self._unused_bits = chunk[1] + self._bytes = b''.join(chunk[0] for chunk in chunks) + + return self._bytes + + def _copy(self, other, copy_func): + """ + Copies the contents of another OctetBitString object to itself + + :param object: + Another instance of the same class + + :param copy_func: + An reference of copy.copy() or copy.deepcopy() to use when copying + lists, dicts and objects + """ + + super(OctetBitString, self)._copy(other, copy_func) + self._bytes = other._bytes + self._unused_bits = other._unused_bits + + def _as_chunk(self): + """ + Allows reconstructing indefinite length values + + :raises: + ValueError - when an invalid value is passed + + :return: + List with one tuple, consisting of a byte string and an integer (unused bits) + """ + + unused_bits_len = ord(self.contents[0]) if _PY2 else self.contents[0] + if not unused_bits_len: + return [(self.contents[1:], ())] + + if len(self.contents) == 1: + # Disallowed by X.690 §8.6.2.3 + raise ValueError('Empty bit string has {0} unused bits'.format(unused_bits_len)) + + if unused_bits_len > 7: + # Disallowed by X.690 §8.6.2.2 + raise ValueError('Bit string has {0} unused bits'.format(unused_bits_len)) + + mask = (1 << unused_bits_len) - 1 + last_byte = ord(self.contents[-1]) if _PY2 else self.contents[-1] + + # zero out the unused bits in the last byte. + zeroed_byte = last_byte & ~mask + value = self.contents[1:-1] + (chr(zeroed_byte) if _PY2 else bytes((zeroed_byte,))) + + unused_bits = _int_to_bit_tuple(last_byte & mask, unused_bits_len) + + return [(value, unused_bits)] + + @property + def native(self): + """ + The native Python datatype representation of this value + + :return: + A byte string or None + """ + + if self.contents is None: + return None + + return self.__bytes__() + + @property + def unused_bits(self): + """ + The unused bits of the bit string encoding. + + :return: + A tuple of 1s and 0s + """ + + # call native to set _unused_bits + self.native + + return self._unused_bits + + +class IntegerBitString(_IntegerBitString, Constructable, Castable, Primitive): + """ + Represents a bit string in ASN.1 as a Python integer + """ + + tag = 3 + + def set(self, value): + """ + Sets the value of the object + + :param value: + An integer + + :raises: + ValueError - when an invalid value is passed + """ + + if not isinstance(value, int_types): + raise TypeError(unwrap( + ''' + %s value must be a positive integer, not %s + ''', + type_name(self), + type_name(value) + )) + + if value < 0: + raise ValueError(unwrap( + ''' + %s value must be a positive integer, not %d + ''', + type_name(self), + value + )) + + self._native = value + # Set the unused bits to 0 + self.contents = b'\x00' + int_to_bytes(value, signed=True) + self._unused_bits = () + self._header = None + if self._indefinite: + self._indefinite = False + self.method = 0 + if self._trailer != b'': + self._trailer = b'' + + @property + def native(self): + """ + The native Python datatype representation of this value + + :return: + An integer or None + """ + + if self.contents is None: + return None + + if self._native is None: + self._native, __, self._unused_bits = self._chunks_to_int() + + return self._native + + +class OctetString(Constructable, Castable, Primitive): + """ + Represents a byte string in both ASN.1 and Python + """ + + tag = 4 + + # Instance attribute of (possibly-merged) byte string + _bytes = None + + def set(self, value): + """ + Sets the value of the object + + :param value: + A byte string + """ + + if not isinstance(value, byte_cls): + raise TypeError(unwrap( + ''' + %s value must be a byte string, not %s + ''', + type_name(self), + type_name(value) + )) + + self._bytes = value + self.contents = value + self._header = None + if self._indefinite: + self._indefinite = False + self.method = 0 + if self._trailer != b'': + self._trailer = b'' + + def __bytes__(self): + """ + :return: + A byte string + """ + + if self.contents is None: + return b'' + if self._bytes is None: + self._bytes = self._merge_chunks() + return self._bytes + + def _copy(self, other, copy_func): + """ + Copies the contents of another OctetString object to itself + + :param object: + Another instance of the same class + + :param copy_func: + An reference of copy.copy() or copy.deepcopy() to use when copying + lists, dicts and objects + """ + + super(OctetString, self)._copy(other, copy_func) + self._bytes = other._bytes + + @property + def native(self): + """ + The native Python datatype representation of this value + + :return: + A byte string or None + """ + + if self.contents is None: + return None + + return self.__bytes__() + + +class IntegerOctetString(Constructable, Castable, Primitive): + """ + Represents a byte string in ASN.1 as a Python integer + """ + + tag = 4 + + # An explicit length in bytes the integer should be encoded to. This should + # generally not be used since DER defines a canonical encoding, however some + # use of this, such as when storing elliptic curve private keys, requires an + # exact number of bytes, even if the leading bytes are null. + _encoded_width = None + + def set(self, value): + """ + Sets the value of the object + + :param value: + An integer + + :raises: + ValueError - when an invalid value is passed + """ + + if not isinstance(value, int_types): + raise TypeError(unwrap( + ''' + %s value must be a positive integer, not %s + ''', + type_name(self), + type_name(value) + )) + + if value < 0: + raise ValueError(unwrap( + ''' + %s value must be a positive integer, not %d + ''', + type_name(self), + value + )) + + self._native = value + self.contents = int_to_bytes(value, signed=False, width=self._encoded_width) + self._header = None + if self._indefinite: + self._indefinite = False + self.method = 0 + if self._trailer != b'': + self._trailer = b'' + + @property + def native(self): + """ + The native Python datatype representation of this value + + :return: + An integer or None + """ + + if self.contents is None: + return None + + if self._native is None: + self._native = int_from_bytes(self._merge_chunks()) + return self._native + + def set_encoded_width(self, width): + """ + Set the explicit enoding width for the integer + + :param width: + An integer byte width to encode the integer to + """ + + self._encoded_width = width + # Make sure the encoded value is up-to-date with the proper width + if self.contents is not None and len(self.contents) != width: + self.set(self.native) + + +class ParsableOctetString(Constructable, Castable, Primitive): + + tag = 4 + + _parsed = None + + # Instance attribute of (possibly-merged) byte string + _bytes = None + + def __init__(self, value=None, parsed=None, **kwargs): + """ + Allows providing a parsed object that will be serialized to get the + byte string value + + :param value: + A native Python datatype to initialize the object value with + + :param parsed: + If value is None and this is an Asn1Value object, this will be + set as the parsed value, and the value will be obtained by calling + .dump() on this object. + """ + + set_parsed = False + if value is None and parsed is not None and isinstance(parsed, Asn1Value): + value = parsed.dump() + set_parsed = True + + Primitive.__init__(self, value=value, **kwargs) + + if set_parsed: + self._parsed = (parsed, parsed.__class__, None) + + def set(self, value): + """ + Sets the value of the object + + :param value: + A byte string + """ + + if not isinstance(value, byte_cls): + raise TypeError(unwrap( + ''' + %s value must be a byte string, not %s + ''', + type_name(self), + type_name(value) + )) + + self._bytes = value + self.contents = value + self._header = None + if self._indefinite: + self._indefinite = False + self.method = 0 + if self._trailer != b'': + self._trailer = b'' + + def parse(self, spec=None, spec_params=None): + """ + Parses the contents generically, or using a spec with optional params + + :param spec: + A class derived from Asn1Value that defines what class_ and tag the + value should have, and the semantics of the encoded value. The + return value will be of this type. If omitted, the encoded value + will be decoded using the standard universal tag based on the + encoded tag number. + + :param spec_params: + A dict of params to pass to the spec object + + :return: + An object of the type spec, or if not present, a child of Asn1Value + """ + + if self._parsed is None or self._parsed[1:3] != (spec, spec_params): + parsed_value, _ = _parse_build(self.__bytes__(), spec=spec, spec_params=spec_params) + self._parsed = (parsed_value, spec, spec_params) + return self._parsed[0] + + def __bytes__(self): + """ + :return: + A byte string + """ + + if self.contents is None: + return b'' + if self._bytes is None: + self._bytes = self._merge_chunks() + return self._bytes + + def _setable_native(self): + """ + Returns a byte string that can be passed into .set() + + :return: + A python value that is valid to pass to .set() + """ + + return self.__bytes__() + + def _copy(self, other, copy_func): + """ + Copies the contents of another ParsableOctetString object to itself + + :param object: + Another instance of the same class + + :param copy_func: + An reference of copy.copy() or copy.deepcopy() to use when copying + lists, dicts and objects + """ + + super(ParsableOctetString, self)._copy(other, copy_func) + self._bytes = other._bytes + self._parsed = copy_func(other._parsed) + + @property + def native(self): + """ + The native Python datatype representation of this value + + :return: + A byte string or None + """ + + if self.contents is None: + return None + + if self._parsed is not None: + return self._parsed[0].native + else: + return self.__bytes__() + + @property + def parsed(self): + """ + Returns the parsed object from .parse() + + :return: + The object returned by .parse() + """ + + if self._parsed is None: + self.parse() + + return self._parsed[0] + + def dump(self, force=False): + """ + Encodes the value using DER + + :param force: + If the encoded contents already exist, clear them and regenerate + to ensure they are in DER format instead of BER format + + :return: + A byte string of the DER-encoded value + """ + + # If the length is indefinite, force the re-encoding + if self._indefinite: + force = True + + if force: + if self._parsed is not None: + native = self.parsed.dump(force=force) + else: + native = self.native + self.contents = None + self.set(native) + + return Asn1Value.dump(self) + + +class ParsableOctetBitString(ParsableOctetString): + + tag = 3 + + def set(self, value): + """ + Sets the value of the object + + :param value: + A byte string + + :raises: + ValueError - when an invalid value is passed + """ + + if not isinstance(value, byte_cls): + raise TypeError(unwrap( + ''' + %s value must be a byte string, not %s + ''', + type_name(self), + type_name(value) + )) + + self._bytes = value + # Set the unused bits to 0 + self.contents = b'\x00' + value + self._header = None + if self._indefinite: + self._indefinite = False + self.method = 0 + if self._trailer != b'': + self._trailer = b'' + + def _as_chunk(self): + """ + Allows reconstructing indefinite length values + + :raises: + ValueError - when an invalid value is passed + + :return: + A byte string + """ + + unused_bits_len = ord(self.contents[0]) if _PY2 else self.contents[0] + if unused_bits_len: + raise ValueError('ParsableOctetBitString should have no unused bits') + + return self.contents[1:] + + +class Null(Primitive): + """ + Represents a null value in ASN.1 as None in Python + """ + + tag = 5 + + contents = b'' + + def set(self, value): + """ + Sets the value of the object + + :param value: + None + """ + + self.contents = b'' + + @property + def native(self): + """ + The native Python datatype representation of this value + + :return: + None + """ + + return None + + +class ObjectIdentifier(Primitive, ValueMap): + """ + Represents an object identifier in ASN.1 as a Python unicode dotted + integer string + """ + + tag = 6 + + # A unicode string of the dotted form of the object identifier + _dotted = None + + @classmethod + def map(cls, value): + """ + Converts a dotted unicode string OID into a mapped unicode string + + :param value: + A dotted unicode string OID + + :raises: + ValueError - when no _map dict has been defined on the class + TypeError - when value is not a unicode string + + :return: + A mapped unicode string + """ + + if cls._map is None: + raise ValueError(unwrap( + ''' + %s._map has not been defined + ''', + type_name(cls) + )) + + if not isinstance(value, str_cls): + raise TypeError(unwrap( + ''' + value must be a unicode string, not %s + ''', + type_name(value) + )) + + return cls._map.get(value, value) + + @classmethod + def unmap(cls, value): + """ + Converts a mapped unicode string value into a dotted unicode string OID + + :param value: + A mapped unicode string OR dotted unicode string OID + + :raises: + ValueError - when no _map dict has been defined on the class or the value can't be unmapped + TypeError - when value is not a unicode string + + :return: + A dotted unicode string OID + """ + + if cls not in _SETUP_CLASSES: + cls()._setup() + _SETUP_CLASSES[cls] = True + + if cls._map is None: + raise ValueError(unwrap( + ''' + %s._map has not been defined + ''', + type_name(cls) + )) + + if not isinstance(value, str_cls): + raise TypeError(unwrap( + ''' + value must be a unicode string, not %s + ''', + type_name(value) + )) + + if value in cls._reverse_map: + return cls._reverse_map[value] + + if not _OID_RE.match(value): + raise ValueError(unwrap( + ''' + %s._map does not contain an entry for "%s" + ''', + type_name(cls), + value + )) + + return value + + def set(self, value): + """ + Sets the value of the object + + :param value: + A unicode string. May be a dotted integer string, or if _map is + provided, one of the mapped values. + + :raises: + ValueError - when an invalid value is passed + """ + + if not isinstance(value, str_cls): + raise TypeError(unwrap( + ''' + %s value must be a unicode string, not %s + ''', + type_name(self), + type_name(value) + )) + + self._native = value + + if self._map is not None: + if value in self._reverse_map: + value = self._reverse_map[value] + + self.contents = b'' + first = None + for index, part in enumerate(value.split('.')): + part = int(part) + + # The first two parts are merged into a single byte + if index == 0: + first = part + continue + elif index == 1: + if first > 2: + raise ValueError(unwrap( + ''' + First arc must be one of 0, 1 or 2, not %s + ''', + repr(first) + )) + elif first < 2 and part >= 40: + raise ValueError(unwrap( + ''' + Second arc must be less than 40 if first arc is 0 or + 1, not %s + ''', + repr(part) + )) + part = (first * 40) + part + + encoded_part = chr_cls(0x7F & part) + part = part >> 7 + while part > 0: + encoded_part = chr_cls(0x80 | (0x7F & part)) + encoded_part + part = part >> 7 + self.contents += encoded_part + + self._header = None + if self._trailer != b'': + self._trailer = b'' + + def __unicode__(self): + """ + :return: + A unicode string + """ + + return self.dotted + + @property + def dotted(self): + """ + :return: + A unicode string of the object identifier in dotted notation, thus + ignoring any mapped value + """ + + if self._dotted is None: + output = [] + + part = 0 + for byte in self.contents: + if _PY2: + byte = ord(byte) + part = part * 128 + part += byte & 127 + # Last byte in subidentifier has the eighth bit set to 0 + if byte & 0x80 == 0: + if len(output) == 0: + if part >= 80: + output.append(str_cls(2)) + output.append(str_cls(part - 80)) + elif part >= 40: + output.append(str_cls(1)) + output.append(str_cls(part - 40)) + else: + output.append(str_cls(0)) + output.append(str_cls(part)) + else: + output.append(str_cls(part)) + part = 0 + + self._dotted = '.'.join(output) + return self._dotted + + @property + def native(self): + """ + The native Python datatype representation of this value + + :return: + A unicode string or None. If _map is not defined, the unicode string + is a string of dotted integers. If _map is defined and the dotted + string is present in the _map, the mapped value is returned. + """ + + if self.contents is None: + return None + + if self._native is None: + self._native = self.dotted + if self._map is not None and self._native in self._map: + self._native = self._map[self._native] + return self._native + + +class ObjectDescriptor(Primitive): + """ + Represents an object descriptor from ASN.1 - no Python implementation + """ + + tag = 7 + + +class InstanceOf(Primitive): + """ + Represents an instance from ASN.1 - no Python implementation + """ + + tag = 8 + + +class Real(Primitive): + """ + Represents a real number from ASN.1 - no Python implementation + """ + + tag = 9 + + +class Enumerated(Integer): + """ + Represents a enumerated list of integers from ASN.1 as a Python + unicode string + """ + + tag = 10 + + def set(self, value): + """ + Sets the value of the object + + :param value: + An integer or a unicode string from _map + + :raises: + ValueError - when an invalid value is passed + """ + + if not isinstance(value, int_types) and not isinstance(value, str_cls): + raise TypeError(unwrap( + ''' + %s value must be an integer or a unicode string, not %s + ''', + type_name(self), + type_name(value) + )) + + if isinstance(value, str_cls): + if value not in self._reverse_map: + raise ValueError(unwrap( + ''' + %s value "%s" is not a valid value + ''', + type_name(self), + value + )) + + value = self._reverse_map[value] + + elif value not in self._map: + raise ValueError(unwrap( + ''' + %s value %s is not a valid value + ''', + type_name(self), + value + )) + + Integer.set(self, value) + + @property + def native(self): + """ + The native Python datatype representation of this value + + :return: + A unicode string or None + """ + + if self.contents is None: + return None + + if self._native is None: + self._native = self._map[self.__int__()] + return self._native + + +class UTF8String(AbstractString): + """ + Represents a UTF-8 string from ASN.1 as a Python unicode string + """ + + tag = 12 + _encoding = 'utf-8' + + +class RelativeOid(ObjectIdentifier): + """ + Represents an object identifier in ASN.1 as a Python unicode dotted + integer string + """ + + tag = 13 + + +class Sequence(Asn1Value): + """ + Represents a sequence of fields from ASN.1 as a Python object with a + dict-like interface + """ + + tag = 16 + + class_ = 0 + method = 1 + + # A list of child objects, in order of _fields + children = None + + # Sequence overrides .contents to be a property so that the mutated state + # of child objects can be checked to ensure everything is up-to-date + _contents = None + + # Variable to track if the object has been mutated + _mutated = False + + # A list of tuples in one of the following forms. + # + # Option 1, a unicode string field name and a value class + # + # ("name", Asn1ValueClass) + # + # Option 2, same as Option 1, but with a dict of class params + # + # ("name", Asn1ValueClass, {'explicit': 5}) + _fields = [] + + # A dict with keys being the name of a field and the value being a unicode + # string of the method name on self to call to get the spec for that field + _spec_callbacks = None + + # A dict that maps unicode string field names to an index in _fields + _field_map = None + + # A list in the same order as _fields that has tuples in the form (class_, tag) + _field_ids = None + + # An optional 2-element tuple that defines the field names of an OID field + # and the field that the OID should be used to help decode. Works with the + # _oid_specs attribute. + _oid_pair = None + + # A dict with keys that are unicode string OID values and values that are + # Asn1Value classes to use for decoding a variable-type field. + _oid_specs = None + + # A 2-element tuple of the indexes in _fields of the OID and value fields + _oid_nums = None + + # Predetermined field specs to optimize away calls to _determine_spec() + _precomputed_specs = None + + def __init__(self, value=None, default=None, **kwargs): + """ + Allows setting field values before passing everything else along to + Asn1Value.__init__() + + :param value: + A native Python datatype to initialize the object value with + + :param default: + The default value if no value is specified + """ + + Asn1Value.__init__(self, **kwargs) + + check_existing = False + if value is None and default is not None: + check_existing = True + if self.children is None: + if self.contents is None: + check_existing = False + else: + self._parse_children() + value = default + + if value is not None: + try: + # Fields are iterated in definition order to allow things like + # OID-based specs. Otherwise sometimes the value would be processed + # before the OID field, resulting in invalid value object creation. + if self._fields: + keys = [info[0] for info in self._fields] + unused_keys = set(value.keys()) + else: + keys = value.keys() + unused_keys = set(keys) + + for key in keys: + # If we are setting defaults, but a real value has already + # been set for the field, then skip it + if check_existing: + index = self._field_map[key] + if index < len(self.children) and self.children[index] is not VOID: + if key in unused_keys: + unused_keys.remove(key) + continue + + if key in value: + self.__setitem__(key, value[key]) + unused_keys.remove(key) + + if len(unused_keys): + raise ValueError(unwrap( + ''' + One or more unknown fields was passed to the constructor + of %s: %s + ''', + type_name(self), + ', '.join(sorted(list(unused_keys))) + )) + + except (ValueError, TypeError) as e: + args = e.args[1:] + e.args = (e.args[0] + '\n while constructing %s' % type_name(self),) + args + raise e + + @property + def contents(self): + """ + :return: + A byte string of the DER-encoded contents of the sequence + """ + + if self.children is None: + return self._contents + + if self._is_mutated(): + self._set_contents() + + return self._contents + + @contents.setter + def contents(self, value): + """ + :param value: + A byte string of the DER-encoded contents of the sequence + """ + + self._contents = value + + def _is_mutated(self): + """ + :return: + A boolean - if the sequence or any children (recursively) have been + mutated + """ + + mutated = self._mutated + if self.children is not None: + for child in self.children: + if isinstance(child, Sequence) or isinstance(child, SequenceOf): + mutated = mutated or child._is_mutated() + + return mutated + + def _lazy_child(self, index): + """ + Builds a child object if the child has only been parsed into a tuple so far + """ + + child = self.children[index] + if child.__class__ == tuple: + child = self.children[index] = _build(*child) + return child + + def __len__(self): + """ + :return: + Integer + """ + # We inline this check to prevent method invocation each time + if self.children is None: + self._parse_children() + + return len(self.children) + + def __getitem__(self, key): + """ + Allows accessing fields by name or index + + :param key: + A unicode string of the field name, or an integer of the field index + + :raises: + KeyError - when a field name or index is invalid + + :return: + The Asn1Value object of the field specified + """ + + # We inline this check to prevent method invocation each time + if self.children is None: + self._parse_children() + + if not isinstance(key, int_types): + if key not in self._field_map: + raise KeyError(unwrap( + ''' + No field named "%s" defined for %s + ''', + key, + type_name(self) + )) + key = self._field_map[key] + + if key >= len(self.children): + raise KeyError(unwrap( + ''' + No field numbered %s is present in this %s + ''', + key, + type_name(self) + )) + + try: + return self._lazy_child(key) + + except (ValueError, TypeError) as e: + args = e.args[1:] + e.args = (e.args[0] + '\n while parsing %s' % type_name(self),) + args + raise e + + def __setitem__(self, key, value): + """ + Allows settings fields by name or index + + :param key: + A unicode string of the field name, or an integer of the field index + + :param value: + A native Python datatype to set the field value to. This method will + construct the appropriate Asn1Value object from _fields. + + :raises: + ValueError - when a field name or index is invalid + """ + + # We inline this check to prevent method invocation each time + if self.children is None: + self._parse_children() + + if not isinstance(key, int_types): + if key not in self._field_map: + raise KeyError(unwrap( + ''' + No field named "%s" defined for %s + ''', + key, + type_name(self) + )) + key = self._field_map[key] + + field_name, field_spec, value_spec, field_params, _ = self._determine_spec(key) + + new_value = self._make_value(field_name, field_spec, value_spec, field_params, value) + + invalid_value = False + if isinstance(new_value, Any): + invalid_value = new_value.parsed is None + else: + invalid_value = new_value.contents is None + + if invalid_value: + raise ValueError(unwrap( + ''' + Value for field "%s" of %s is not set + ''', + field_name, + type_name(self) + )) + + self.children[key] = new_value + + if self._native is not None: + self._native[self._fields[key][0]] = self.children[key].native + self._mutated = True + + def __delitem__(self, key): + """ + Allows deleting optional or default fields by name or index + + :param key: + A unicode string of the field name, or an integer of the field index + + :raises: + ValueError - when a field name or index is invalid, or the field is not optional or defaulted + """ + + # We inline this check to prevent method invocation each time + if self.children is None: + self._parse_children() + + if not isinstance(key, int_types): + if key not in self._field_map: + raise KeyError(unwrap( + ''' + No field named "%s" defined for %s + ''', + key, + type_name(self) + )) + key = self._field_map[key] + + name, _, params = self._fields[key] + if not params or ('default' not in params and 'optional' not in params): + raise ValueError(unwrap( + ''' + Can not delete the value for the field "%s" of %s since it is + not optional or defaulted + ''', + name, + type_name(self) + )) + + if 'optional' in params: + self.children[key] = VOID + if self._native is not None: + self._native[name] = None + else: + self.__setitem__(key, None) + self._mutated = True + + def __iter__(self): + """ + :return: + An iterator of field key names + """ + + for info in self._fields: + yield info[0] + + def _set_contents(self, force=False): + """ + Updates the .contents attribute of the value with the encoded value of + all of the child objects + + :param force: + Ensure all contents are in DER format instead of possibly using + cached BER-encoded data + """ + + if self.children is None: + self._parse_children() + + contents = BytesIO() + for index, info in enumerate(self._fields): + child = self.children[index] + if child is None: + child_dump = b'' + elif child.__class__ == tuple: + if force: + child_dump = self._lazy_child(index).dump(force=force) + else: + child_dump = child[3] + child[4] + child[5] + else: + child_dump = child.dump(force=force) + # Skip values that are the same as the default + if info[2] and 'default' in info[2]: + default_value = info[1](**info[2]) + if default_value.dump() == child_dump: + continue + contents.write(child_dump) + self._contents = contents.getvalue() + + self._header = None + if self._trailer != b'': + self._trailer = b'' + + def _setup(self): + """ + Generates _field_map, _field_ids and _oid_nums for use in parsing + """ + + cls = self.__class__ + cls._field_map = {} + cls._field_ids = [] + cls._precomputed_specs = [] + for index, field in enumerate(cls._fields): + if len(field) < 3: + field = field + ({},) + cls._fields[index] = field + cls._field_map[field[0]] = index + cls._field_ids.append(_build_id_tuple(field[2], field[1])) + + if cls._oid_pair is not None: + cls._oid_nums = (cls._field_map[cls._oid_pair[0]], cls._field_map[cls._oid_pair[1]]) + + for index, field in enumerate(cls._fields): + has_callback = cls._spec_callbacks is not None and field[0] in cls._spec_callbacks + is_mapped_oid = cls._oid_nums is not None and cls._oid_nums[1] == index + if has_callback or is_mapped_oid: + cls._precomputed_specs.append(None) + else: + cls._precomputed_specs.append((field[0], field[1], field[1], field[2], None)) + + def _determine_spec(self, index): + """ + Determine how a value for a field should be constructed + + :param index: + The field number + + :return: + A tuple containing the following elements: + - unicode string of the field name + - Asn1Value class of the field spec + - Asn1Value class of the value spec + - None or dict of params to pass to the field spec + - None or Asn1Value class indicating the value spec was derived from an OID or a spec callback + """ + + name, field_spec, field_params = self._fields[index] + value_spec = field_spec + spec_override = None + + if self._spec_callbacks is not None and name in self._spec_callbacks: + callback = self._spec_callbacks[name] + spec_override = callback(self) + if spec_override: + # Allow a spec callback to specify both the base spec and + # the override, for situations such as OctetString and parse_as + if spec_override.__class__ == tuple and len(spec_override) == 2: + field_spec, value_spec = spec_override + if value_spec is None: + value_spec = field_spec + spec_override = None + # When no field spec is specified, use a single return value as that + elif field_spec is None: + field_spec = spec_override + value_spec = field_spec + spec_override = None + else: + value_spec = spec_override + + elif self._oid_nums is not None and self._oid_nums[1] == index: + oid = self._lazy_child(self._oid_nums[0]).native + if oid in self._oid_specs: + spec_override = self._oid_specs[oid] + value_spec = spec_override + + return (name, field_spec, value_spec, field_params, spec_override) + + def _make_value(self, field_name, field_spec, value_spec, field_params, value): + """ + Contructs an appropriate Asn1Value object for a field + + :param field_name: + A unicode string of the field name + + :param field_spec: + An Asn1Value class that is the field spec + + :param value_spec: + An Asn1Value class that is the vaue spec + + :param field_params: + None or a dict of params for the field spec + + :param value: + The value to construct an Asn1Value object from + + :return: + An instance of a child class of Asn1Value + """ + + if value is None and 'optional' in field_params: + return VOID + + specs_different = field_spec != value_spec + is_any = issubclass(field_spec, Any) + + if issubclass(value_spec, Choice): + is_asn1value = isinstance(value, Asn1Value) + is_tuple = isinstance(value, tuple) and len(value) == 2 + is_dict = isinstance(value, dict) and len(value) == 1 + if not is_asn1value and not is_tuple and not is_dict: + raise ValueError(unwrap( + ''' + Can not set a native python value to %s, which has the + choice type of %s - value must be an instance of Asn1Value + ''', + field_name, + type_name(value_spec) + )) + if is_tuple or is_dict: + value = value_spec(value) + if not isinstance(value, value_spec): + wrapper = value_spec() + wrapper.validate(value.class_, value.tag, value.contents) + wrapper._parsed = value + new_value = wrapper + else: + new_value = value + + elif isinstance(value, field_spec): + new_value = value + if specs_different: + new_value.parse(value_spec) + + elif (not specs_different or is_any) and not isinstance(value, value_spec): + if (not is_any or specs_different) and isinstance(value, Asn1Value): + raise TypeError(unwrap( + ''' + %s value must be %s, not %s + ''', + field_name, + type_name(value_spec), + type_name(value) + )) + new_value = value_spec(value, **field_params) + + else: + if isinstance(value, value_spec): + new_value = value + else: + if isinstance(value, Asn1Value): + raise TypeError(unwrap( + ''' + %s value must be %s, not %s + ''', + field_name, + type_name(value_spec), + type_name(value) + )) + new_value = value_spec(value) + + # For when the field is OctetString or OctetBitString with embedded + # values we need to wrap the value in the field spec to get the + # appropriate encoded value. + if specs_different and not is_any: + wrapper = field_spec(value=new_value.dump(), **field_params) + wrapper._parsed = (new_value, new_value.__class__, None) + new_value = wrapper + + new_value = _fix_tagging(new_value, field_params) + + return new_value + + def _parse_children(self, recurse=False): + """ + Parses the contents and generates Asn1Value objects based on the + definitions from _fields. + + :param recurse: + If child objects that are Sequence or SequenceOf objects should + be recursively parsed + + :raises: + ValueError - when an error occurs parsing child objects + """ + + cls = self.__class__ + if self._contents is None: + if self._fields: + self.children = [VOID] * len(self._fields) + for index, (_, _, params) in enumerate(self._fields): + if 'default' in params: + if cls._precomputed_specs[index]: + field_name, field_spec, value_spec, field_params, _ = cls._precomputed_specs[index] + else: + field_name, field_spec, value_spec, field_params, _ = self._determine_spec(index) + self.children[index] = self._make_value(field_name, field_spec, value_spec, field_params, None) + return + + try: + self.children = [] + contents_length = len(self._contents) + child_pointer = 0 + field = 0 + field_len = len(self._fields) + parts = None + again = child_pointer < contents_length + while again: + if parts is None: + parts, child_pointer = _parse(self._contents, contents_length, pointer=child_pointer) + again = child_pointer < contents_length + + if field < field_len: + _, field_spec, value_spec, field_params, spec_override = ( + cls._precomputed_specs[field] or self._determine_spec(field)) + + # If the next value is optional or default, allow it to be absent + if field_params and ('optional' in field_params or 'default' in field_params): + if self._field_ids[field] != (parts[0], parts[2]) and field_spec != Any: + + # See if the value is a valid choice before assuming + # that we have a missing optional or default value + choice_match = False + if issubclass(field_spec, Choice): + try: + tester = field_spec(**field_params) + tester.validate(parts[0], parts[2], parts[4]) + choice_match = True + except (ValueError): + pass + + if not choice_match: + if 'optional' in field_params: + self.children.append(VOID) + else: + self.children.append(field_spec(**field_params)) + field += 1 + again = True + continue + + if field_spec is None or (spec_override and issubclass(field_spec, Any)): + field_spec = value_spec + spec_override = None + + if spec_override: + child = parts + (field_spec, field_params, value_spec) + else: + child = parts + (field_spec, field_params) + + # Handle situations where an optional or defaulted field definition is incorrect + elif field_len > 0 and field + 1 <= field_len: + missed_fields = [] + prev_field = field - 1 + while prev_field >= 0: + prev_field_info = self._fields[prev_field] + if len(prev_field_info) < 3: + break + if 'optional' in prev_field_info[2] or 'default' in prev_field_info[2]: + missed_fields.append(prev_field_info[0]) + prev_field -= 1 + plural = 's' if len(missed_fields) > 1 else '' + missed_field_names = ', '.join(missed_fields) + raise ValueError(unwrap( + ''' + Data for field %s (%s class, %s method, tag %s) does + not match the field definition%s of %s + ''', + field + 1, + CLASS_NUM_TO_NAME_MAP.get(parts[0]), + METHOD_NUM_TO_NAME_MAP.get(parts[1]), + parts[2], + plural, + missed_field_names + )) + + else: + child = parts + + if recurse: + child = _build(*child) + if isinstance(child, (Sequence, SequenceOf)): + child._parse_children(recurse=True) + + self.children.append(child) + field += 1 + parts = None + + index = len(self.children) + while index < field_len: + name, field_spec, field_params = self._fields[index] + if 'default' in field_params: + self.children.append(field_spec(**field_params)) + elif 'optional' in field_params: + self.children.append(VOID) + else: + raise ValueError(unwrap( + ''' + Field "%s" is missing from structure + ''', + name + )) + index += 1 + + except (ValueError, TypeError) as e: + self.children = None + args = e.args[1:] + e.args = (e.args[0] + '\n while parsing %s' % type_name(self),) + args + raise e + + def spec(self, field_name): + """ + Determines the spec to use for the field specified. Depending on how + the spec is determined (_oid_pair or _spec_callbacks), it may be + necessary to set preceding field values before calling this. Usually + specs, if dynamic, are controlled by a preceding ObjectIdentifier + field. + + :param field_name: + A unicode string of the field name to get the spec for + + :return: + A child class of asn1crypto.core.Asn1Value that the field must be + encoded using + """ + + if not isinstance(field_name, str_cls): + raise TypeError(unwrap( + ''' + field_name must be a unicode string, not %s + ''', + type_name(field_name) + )) + + if self._fields is None: + raise ValueError(unwrap( + ''' + Unable to retrieve spec for field %s in the class %s because + _fields has not been set + ''', + repr(field_name), + type_name(self) + )) + + index = self._field_map[field_name] + info = self._determine_spec(index) + + return info[2] + + @property + def native(self): + """ + The native Python datatype representation of this value + + :return: + An OrderedDict or None. If an OrderedDict, all child values are + recursively converted to native representation also. + """ + + if self.contents is None: + return None + + if self._native is None: + if self.children is None: + self._parse_children(recurse=True) + try: + self._native = OrderedDict() + for index, child in enumerate(self.children): + if child.__class__ == tuple: + child = _build(*child) + self.children[index] = child + try: + name = self._fields[index][0] + except (IndexError): + name = str_cls(index) + self._native[name] = child.native + except (ValueError, TypeError) as e: + self._native = None + args = e.args[1:] + e.args = (e.args[0] + '\n while parsing %s' % type_name(self),) + args + raise e + return self._native + + def _copy(self, other, copy_func): + """ + Copies the contents of another Sequence object to itself + + :param object: + Another instance of the same class + + :param copy_func: + An reference of copy.copy() or copy.deepcopy() to use when copying + lists, dicts and objects + """ + + super(Sequence, self)._copy(other, copy_func) + if self.children is not None: + self.children = [] + for child in other.children: + if child.__class__ == tuple: + self.children.append(child) + else: + self.children.append(child.copy()) + + def debug(self, nest_level=1): + """ + Show the binary data and parsed data in a tree structure + """ + + if self.children is None: + self._parse_children() + + prefix = ' ' * nest_level + _basic_debug(prefix, self) + for field_name in self: + child = self._lazy_child(self._field_map[field_name]) + if child is not VOID: + print('%s Field "%s"' % (prefix, field_name)) + child.debug(nest_level + 3) + + def dump(self, force=False): + """ + Encodes the value using DER + + :param force: + If the encoded contents already exist, clear them and regenerate + to ensure they are in DER format instead of BER format + + :return: + A byte string of the DER-encoded value + """ + + # If the length is indefinite, force the re-encoding + if self._header is not None and self._header[-1:] == b'\x80': + force = True + + if force: + self._set_contents(force=force) + + if self._fields and self.children is not None: + for index, (field_name, _, params) in enumerate(self._fields): + if self.children[index] is not VOID: + continue + if 'default' in params or 'optional' in params: + continue + raise ValueError(unwrap( + ''' + Field "%s" is missing from structure + ''', + field_name + )) + + return Asn1Value.dump(self) + + +class SequenceOf(Asn1Value): + """ + Represents a sequence (ordered) of a single type of values from ASN.1 as a + Python object with a list-like interface + """ + + tag = 16 + + class_ = 0 + method = 1 + + # A list of child objects + children = None + + # SequenceOf overrides .contents to be a property so that the mutated state + # of child objects can be checked to ensure everything is up-to-date + _contents = None + + # Variable to track if the object has been mutated + _mutated = False + + # An Asn1Value class to use when parsing children + _child_spec = None + + def __init__(self, value=None, default=None, contents=None, spec=None, **kwargs): + """ + Allows setting child objects and the _child_spec via the spec parameter + before passing everything else along to Asn1Value.__init__() + + :param value: + A native Python datatype to initialize the object value with + + :param default: + The default value if no value is specified + + :param contents: + A byte string of the encoded contents of the value + + :param spec: + A class derived from Asn1Value to use to parse children + """ + + if spec: + self._child_spec = spec + + Asn1Value.__init__(self, **kwargs) + + try: + if contents is not None: + self.contents = contents + else: + if value is None and default is not None: + value = default + + if value is not None: + for index, child in enumerate(value): + self.__setitem__(index, child) + + # Make sure a blank list is serialized + if self.contents is None: + self._set_contents() + + except (ValueError, TypeError) as e: + args = e.args[1:] + e.args = (e.args[0] + '\n while constructing %s' % type_name(self),) + args + raise e + + @property + def contents(self): + """ + :return: + A byte string of the DER-encoded contents of the sequence + """ + + if self.children is None: + return self._contents + + if self._is_mutated(): + self._set_contents() + + return self._contents + + @contents.setter + def contents(self, value): + """ + :param value: + A byte string of the DER-encoded contents of the sequence + """ + + self._contents = value + + def _is_mutated(self): + """ + :return: + A boolean - if the sequence or any children (recursively) have been + mutated + """ + + mutated = self._mutated + if self.children is not None: + for child in self.children: + if isinstance(child, Sequence) or isinstance(child, SequenceOf): + mutated = mutated or child._is_mutated() + + return mutated + + def _lazy_child(self, index): + """ + Builds a child object if the child has only been parsed into a tuple so far + """ + + child = self.children[index] + if child.__class__ == tuple: + child = _build(*child) + self.children[index] = child + return child + + def _make_value(self, value): + """ + Constructs a _child_spec value from a native Python data type, or + an appropriate Asn1Value object + + :param value: + A native Python value, or some child of Asn1Value + + :return: + An object of type _child_spec + """ + + if isinstance(value, self._child_spec): + new_value = value + + elif issubclass(self._child_spec, Any): + if isinstance(value, Asn1Value): + new_value = value + else: + raise ValueError(unwrap( + ''' + Can not set a native python value to %s where the + _child_spec is Any - value must be an instance of Asn1Value + ''', + type_name(self) + )) + + elif issubclass(self._child_spec, Choice): + if not isinstance(value, Asn1Value): + raise ValueError(unwrap( + ''' + Can not set a native python value to %s where the + _child_spec is the choice type %s - value must be an + instance of Asn1Value + ''', + type_name(self), + self._child_spec.__name__ + )) + if not isinstance(value, self._child_spec): + wrapper = self._child_spec() + wrapper.validate(value.class_, value.tag, value.contents) + wrapper._parsed = value + value = wrapper + new_value = value + + else: + return self._child_spec(value=value) + + params = {} + if self._child_spec.explicit: + params['explicit'] = self._child_spec.explicit + if self._child_spec.implicit: + params['implicit'] = (self._child_spec.class_, self._child_spec.tag) + return _fix_tagging(new_value, params) + + def __len__(self): + """ + :return: + An integer + """ + # We inline this checks to prevent method invocation each time + if self.children is None: + self._parse_children() + + return len(self.children) + + def __getitem__(self, key): + """ + Allows accessing children via index + + :param key: + Integer index of child + """ + + # We inline this checks to prevent method invocation each time + if self.children is None: + self._parse_children() + + return self._lazy_child(key) + + def __setitem__(self, key, value): + """ + Allows overriding a child via index + + :param key: + Integer index of child + + :param value: + Native python datatype that will be passed to _child_spec to create + new child object + """ + + # We inline this checks to prevent method invocation each time + if self.children is None: + self._parse_children() + + new_value = self._make_value(value) + + # If adding at the end, create a space for the new value + if key == len(self.children): + self.children.append(None) + if self._native is not None: + self._native.append(None) + + self.children[key] = new_value + + if self._native is not None: + self._native[key] = self.children[key].native + + self._mutated = True + + def __delitem__(self, key): + """ + Allows removing a child via index + + :param key: + Integer index of child + """ + + # We inline this checks to prevent method invocation each time + if self.children is None: + self._parse_children() + + self.children.pop(key) + if self._native is not None: + self._native.pop(key) + + self._mutated = True + + def __iter__(self): + """ + :return: + An iter() of child objects + """ + + # We inline this checks to prevent method invocation each time + if self.children is None: + self._parse_children() + + for index in range(0, len(self.children)): + yield self._lazy_child(index) + + def __contains__(self, item): + """ + :param item: + An object of the type cls._child_spec + + :return: + A boolean if the item is contained in this SequenceOf + """ + + if item is None or item is VOID: + return False + + if not isinstance(item, self._child_spec): + raise TypeError(unwrap( + ''' + Checking membership in %s is only available for instances of + %s, not %s + ''', + type_name(self), + type_name(self._child_spec), + type_name(item) + )) + + for child in self: + if child == item: + return True + + return False + + def append(self, value): + """ + Allows adding a child to the end of the sequence + + :param value: + Native python datatype that will be passed to _child_spec to create + new child object + """ + + # We inline this checks to prevent method invocation each time + if self.children is None: + self._parse_children() + + self.children.append(self._make_value(value)) + + if self._native is not None: + self._native.append(self.children[-1].native) + + self._mutated = True + + def _set_contents(self, force=False): + """ + Encodes all child objects into the contents for this object + + :param force: + Ensure all contents are in DER format instead of possibly using + cached BER-encoded data + """ + + if self.children is None: + self._parse_children() + + contents = BytesIO() + for child in self: + contents.write(child.dump(force=force)) + self._contents = contents.getvalue() + self._header = None + if self._trailer != b'': + self._trailer = b'' + + def _parse_children(self, recurse=False): + """ + Parses the contents and generates Asn1Value objects based on the + definitions from _child_spec. + + :param recurse: + If child objects that are Sequence or SequenceOf objects should + be recursively parsed + + :raises: + ValueError - when an error occurs parsing child objects + """ + + try: + self.children = [] + if self._contents is None: + return + contents_length = len(self._contents) + child_pointer = 0 + while child_pointer < contents_length: + parts, child_pointer = _parse(self._contents, contents_length, pointer=child_pointer) + if self._child_spec: + child = parts + (self._child_spec,) + else: + child = parts + if recurse: + child = _build(*child) + if isinstance(child, (Sequence, SequenceOf)): + child._parse_children(recurse=True) + self.children.append(child) + except (ValueError, TypeError) as e: + self.children = None + args = e.args[1:] + e.args = (e.args[0] + '\n while parsing %s' % type_name(self),) + args + raise e + + def spec(self): + """ + Determines the spec to use for child values. + + :return: + A child class of asn1crypto.core.Asn1Value that child values must be + encoded using + """ + + return self._child_spec + + @property + def native(self): + """ + The native Python datatype representation of this value + + :return: + A list or None. If a list, all child values are recursively + converted to native representation also. + """ + + if self.contents is None: + return None + + if self._native is None: + if self.children is None: + self._parse_children(recurse=True) + try: + self._native = [child.native for child in self] + except (ValueError, TypeError) as e: + args = e.args[1:] + e.args = (e.args[0] + '\n while parsing %s' % type_name(self),) + args + raise e + return self._native + + def _copy(self, other, copy_func): + """ + Copies the contents of another SequenceOf object to itself + + :param object: + Another instance of the same class + + :param copy_func: + An reference of copy.copy() or copy.deepcopy() to use when copying + lists, dicts and objects + """ + + super(SequenceOf, self)._copy(other, copy_func) + if self.children is not None: + self.children = [] + for child in other.children: + if child.__class__ == tuple: + self.children.append(child) + else: + self.children.append(child.copy()) + + def debug(self, nest_level=1): + """ + Show the binary data and parsed data in a tree structure + """ + + if self.children is None: + self._parse_children() + + prefix = ' ' * nest_level + _basic_debug(prefix, self) + for child in self: + child.debug(nest_level + 1) + + def dump(self, force=False): + """ + Encodes the value using DER + + :param force: + If the encoded contents already exist, clear them and regenerate + to ensure they are in DER format instead of BER format + + :return: + A byte string of the DER-encoded value + """ + + # If the length is indefinite, force the re-encoding + if self._header is not None and self._header[-1:] == b'\x80': + force = True + + if force: + self._set_contents(force=force) + + return Asn1Value.dump(self) + + +class Set(Sequence): + """ + Represents a set of fields (unordered) from ASN.1 as a Python object with a + dict-like interface + """ + + method = 1 + class_ = 0 + tag = 17 + + # A dict of 2-element tuples in the form (class_, tag) as keys and integers + # as values that are the index of the field in _fields + _field_ids = None + + def _setup(self): + """ + Generates _field_map, _field_ids and _oid_nums for use in parsing + """ + + cls = self.__class__ + cls._field_map = {} + cls._field_ids = {} + cls._precomputed_specs = [] + for index, field in enumerate(cls._fields): + if len(field) < 3: + field = field + ({},) + cls._fields[index] = field + cls._field_map[field[0]] = index + cls._field_ids[_build_id_tuple(field[2], field[1])] = index + + if cls._oid_pair is not None: + cls._oid_nums = (cls._field_map[cls._oid_pair[0]], cls._field_map[cls._oid_pair[1]]) + + for index, field in enumerate(cls._fields): + has_callback = cls._spec_callbacks is not None and field[0] in cls._spec_callbacks + is_mapped_oid = cls._oid_nums is not None and cls._oid_nums[1] == index + if has_callback or is_mapped_oid: + cls._precomputed_specs.append(None) + else: + cls._precomputed_specs.append((field[0], field[1], field[1], field[2], None)) + + def _parse_children(self, recurse=False): + """ + Parses the contents and generates Asn1Value objects based on the + definitions from _fields. + + :param recurse: + If child objects that are Sequence or SequenceOf objects should + be recursively parsed + + :raises: + ValueError - when an error occurs parsing child objects + """ + + cls = self.__class__ + if self._contents is None: + if self._fields: + self.children = [VOID] * len(self._fields) + for index, (_, _, params) in enumerate(self._fields): + if 'default' in params: + if cls._precomputed_specs[index]: + field_name, field_spec, value_spec, field_params, _ = cls._precomputed_specs[index] + else: + field_name, field_spec, value_spec, field_params, _ = self._determine_spec(index) + self.children[index] = self._make_value(field_name, field_spec, value_spec, field_params, None) + return + + try: + child_map = {} + contents_length = len(self.contents) + child_pointer = 0 + seen_field = 0 + while child_pointer < contents_length: + parts, child_pointer = _parse(self.contents, contents_length, pointer=child_pointer) + + id_ = (parts[0], parts[2]) + + field = self._field_ids.get(id_) + if field is None: + raise ValueError(unwrap( + ''' + Data for field %s (%s class, %s method, tag %s) does + not match any of the field definitions + ''', + seen_field, + CLASS_NUM_TO_NAME_MAP.get(parts[0]), + METHOD_NUM_TO_NAME_MAP.get(parts[1]), + parts[2], + )) + + _, field_spec, value_spec, field_params, spec_override = ( + cls._precomputed_specs[field] or self._determine_spec(field)) + + if field_spec is None or (spec_override and issubclass(field_spec, Any)): + field_spec = value_spec + spec_override = None + + if spec_override: + child = parts + (field_spec, field_params, value_spec) + else: + child = parts + (field_spec, field_params) + + if recurse: + child = _build(*child) + if isinstance(child, (Sequence, SequenceOf)): + child._parse_children(recurse=True) + + child_map[field] = child + seen_field += 1 + + total_fields = len(self._fields) + + for index in range(0, total_fields): + if index in child_map: + continue + + name, field_spec, value_spec, field_params, spec_override = ( + cls._precomputed_specs[index] or self._determine_spec(index)) + + if field_spec is None or (spec_override and issubclass(field_spec, Any)): + field_spec = value_spec + spec_override = None + + missing = False + + if not field_params: + missing = True + elif 'optional' not in field_params and 'default' not in field_params: + missing = True + elif 'optional' in field_params: + child_map[index] = VOID + elif 'default' in field_params: + child_map[index] = field_spec(**field_params) + + if missing: + raise ValueError(unwrap( + ''' + Missing required field "%s" from %s + ''', + name, + type_name(self) + )) + + self.children = [] + for index in range(0, total_fields): + self.children.append(child_map[index]) + + except (ValueError, TypeError) as e: + args = e.args[1:] + e.args = (e.args[0] + '\n while parsing %s' % type_name(self),) + args + raise e + + def _set_contents(self, force=False): + """ + Encodes all child objects into the contents for this object. + + This method is overridden because a Set needs to be encoded by + removing defaulted fields and then sorting the fields by tag. + + :param force: + Ensure all contents are in DER format instead of possibly using + cached BER-encoded data + """ + + if self.children is None: + self._parse_children() + + child_tag_encodings = [] + for index, child in enumerate(self.children): + child_encoding = child.dump(force=force) + + # Skip encoding defaulted children + name, spec, field_params = self._fields[index] + if 'default' in field_params: + if spec(**field_params).dump() == child_encoding: + continue + + child_tag_encodings.append((child.tag, child_encoding)) + child_tag_encodings.sort(key=lambda ct: ct[0]) + + self._contents = b''.join([ct[1] for ct in child_tag_encodings]) + self._header = None + if self._trailer != b'': + self._trailer = b'' + + +class SetOf(SequenceOf): + """ + Represents a set (unordered) of a single type of values from ASN.1 as a + Python object with a list-like interface + """ + + tag = 17 + + def _set_contents(self, force=False): + """ + Encodes all child objects into the contents for this object. + + This method is overridden because a SetOf needs to be encoded by + sorting the child encodings. + + :param force: + Ensure all contents are in DER format instead of possibly using + cached BER-encoded data + """ + + if self.children is None: + self._parse_children() + + child_encodings = [] + for child in self: + child_encodings.append(child.dump(force=force)) + + self._contents = b''.join(sorted(child_encodings)) + self._header = None + if self._trailer != b'': + self._trailer = b'' + + +class EmbeddedPdv(Sequence): + """ + A sequence structure + """ + + tag = 11 + + +class NumericString(AbstractString): + """ + Represents a numeric string from ASN.1 as a Python unicode string + """ + + tag = 18 + _encoding = 'latin1' + + +class PrintableString(AbstractString): + """ + Represents a printable string from ASN.1 as a Python unicode string + """ + + tag = 19 + _encoding = 'latin1' + + +class TeletexString(AbstractString): + """ + Represents a teletex string from ASN.1 as a Python unicode string + """ + + tag = 20 + _encoding = 'teletex' + + +class VideotexString(OctetString): + """ + Represents a videotex string from ASN.1 as a Python byte string + """ + + tag = 21 + + +class IA5String(AbstractString): + """ + Represents an IA5 string from ASN.1 as a Python unicode string + """ + + tag = 22 + _encoding = 'ascii' + + +class AbstractTime(AbstractString): + """ + Represents a time from ASN.1 as a Python datetime.datetime object + """ + + @property + def _parsed_time(self): + """ + The parsed datetime string. + + :raises: + ValueError - when an invalid value is passed + + :return: + A dict with the parsed values + """ + + string = str_cls(self) + + m = self._TIMESTRING_RE.match(string) + if not m: + raise ValueError(unwrap( + ''' + Error parsing %s to a %s + ''', + string, + type_name(self), + )) + + groups = m.groupdict() + + tz = None + if groups['zulu']: + tz = timezone.utc + elif groups['dsign']: + sign = 1 if groups['dsign'] == '+' else -1 + tz = create_timezone(sign * timedelta( + hours=int(groups['dhour']), + minutes=int(groups['dminute'] or 0) + )) + + if groups['fraction']: + # Compute fraction in microseconds + fract = Fraction( + int(groups['fraction']), + 10 ** len(groups['fraction']) + ) * 1000000 + + if groups['minute'] is None: + fract *= 3600 + elif groups['second'] is None: + fract *= 60 + + fract_usec = int(fract.limit_denominator(1)) + + else: + fract_usec = 0 + + return { + 'year': int(groups['year']), + 'month': int(groups['month']), + 'day': int(groups['day']), + 'hour': int(groups['hour']), + 'minute': int(groups['minute'] or 0), + 'second': int(groups['second'] or 0), + 'tzinfo': tz, + 'fraction': fract_usec, + } + + @property + def native(self): + """ + The native Python datatype representation of this value + + :return: + A datetime.datetime object, asn1crypto.util.extended_datetime object or + None. The datetime object is usually timezone aware. If it's naive, then + it's in the sender's local time; see X.680 sect. 42.3 + """ + + if self.contents is None: + return None + + if self._native is None: + parsed = self._parsed_time + + fraction = parsed.pop('fraction', 0) + + value = self._get_datetime(parsed) + + if fraction: + value += timedelta(microseconds=fraction) + + self._native = value + + return self._native + + +class UTCTime(AbstractTime): + """ + Represents a UTC time from ASN.1 as a timezone aware Python datetime.datetime object + """ + + tag = 23 + + # Regular expression for UTCTime as described in X.680 sect. 43 and ISO 8601 + _TIMESTRING_RE = re.compile(r''' + ^ + # YYMMDD + (?P<year>\d{2}) + (?P<month>\d{2}) + (?P<day>\d{2}) + + # hhmm or hhmmss + (?P<hour>\d{2}) + (?P<minute>\d{2}) + (?P<second>\d{2})? + + # Matches nothing, needed because GeneralizedTime uses this. + (?P<fraction>) + + # Z or [-+]hhmm + (?: + (?P<zulu>Z) + | + (?: + (?P<dsign>[-+]) + (?P<dhour>\d{2}) + (?P<dminute>\d{2}) + ) + ) + $ + ''', re.X) + + def set(self, value): + """ + Sets the value of the object + + :param value: + A unicode string or a datetime.datetime object + + :raises: + ValueError - when an invalid value is passed + """ + + if isinstance(value, datetime): + if not value.tzinfo: + raise ValueError('Must be timezone aware') + + # Convert value to UTC. + value = value.astimezone(utc_with_dst) + + if not 1950 <= value.year <= 2049: + raise ValueError('Year of the UTCTime is not in range [1950, 2049], use GeneralizedTime instead') + + value = value.strftime('%y%m%d%H%M%SZ') + if _PY2: + value = value.decode('ascii') + + AbstractString.set(self, value) + # Set it to None and let the class take care of converting the next + # time that .native is called + self._native = None + + def _get_datetime(self, parsed): + """ + Create a datetime object from the parsed time. + + :return: + An aware datetime.datetime object + """ + + # X.680 only specifies that UTCTime is not using a century. + # So "18" could as well mean 2118 or 1318. + # X.509 and CMS specify to use UTCTime for years earlier than 2050. + # Assume that UTCTime is only used for years [1950, 2049]. + if parsed['year'] < 50: + parsed['year'] += 2000 + else: + parsed['year'] += 1900 + + return datetime(**parsed) + + +class GeneralizedTime(AbstractTime): + """ + Represents a generalized time from ASN.1 as a Python datetime.datetime + object or asn1crypto.util.extended_datetime object in UTC + """ + + tag = 24 + + # Regular expression for GeneralizedTime as described in X.680 sect. 42 and ISO 8601 + _TIMESTRING_RE = re.compile(r''' + ^ + # YYYYMMDD + (?P<year>\d{4}) + (?P<month>\d{2}) + (?P<day>\d{2}) + + # hh or hhmm or hhmmss + (?P<hour>\d{2}) + (?: + (?P<minute>\d{2}) + (?P<second>\d{2})? + )? + + # Optional fraction; [.,]dddd (one or more decimals) + # If Seconds are given, it's fractions of Seconds. + # Else if Minutes are given, it's fractions of Minutes. + # Else it's fractions of Hours. + (?: + [,.] + (?P<fraction>\d+) + )? + + # Optional timezone. If left out, the time is in local time. + # Z or [-+]hh or [-+]hhmm + (?: + (?P<zulu>Z) + | + (?: + (?P<dsign>[-+]) + (?P<dhour>\d{2}) + (?P<dminute>\d{2})? + ) + )? + $ + ''', re.X) + + def set(self, value): + """ + Sets the value of the object + + :param value: + A unicode string, a datetime.datetime object or an + asn1crypto.util.extended_datetime object + + :raises: + ValueError - when an invalid value is passed + """ + + if isinstance(value, (datetime, extended_datetime)): + if not value.tzinfo: + raise ValueError('Must be timezone aware') + + # Convert value to UTC. + value = value.astimezone(utc_with_dst) + + if value.microsecond: + fraction = '.' + str(value.microsecond).zfill(6).rstrip('0') + else: + fraction = '' + + value = value.strftime('%Y%m%d%H%M%S') + fraction + 'Z' + if _PY2: + value = value.decode('ascii') + + AbstractString.set(self, value) + # Set it to None and let the class take care of converting the next + # time that .native is called + self._native = None + + def _get_datetime(self, parsed): + """ + Create a datetime object from the parsed time. + + :return: + A datetime.datetime object or asn1crypto.util.extended_datetime object. + It may or may not be aware. + """ + + if parsed['year'] == 0: + # datetime does not support year 0. Use extended_datetime instead. + return extended_datetime(**parsed) + else: + return datetime(**parsed) + + +class GraphicString(AbstractString): + """ + Represents a graphic string from ASN.1 as a Python unicode string + """ + + tag = 25 + # This is technically not correct since this type can contain any charset + _encoding = 'latin1' + + +class VisibleString(AbstractString): + """ + Represents a visible string from ASN.1 as a Python unicode string + """ + + tag = 26 + _encoding = 'latin1' + + +class GeneralString(AbstractString): + """ + Represents a general string from ASN.1 as a Python unicode string + """ + + tag = 27 + # This is technically not correct since this type can contain any charset + _encoding = 'latin1' + + +class UniversalString(AbstractString): + """ + Represents a universal string from ASN.1 as a Python unicode string + """ + + tag = 28 + _encoding = 'utf-32-be' + + +class CharacterString(AbstractString): + """ + Represents a character string from ASN.1 as a Python unicode string + """ + + tag = 29 + # This is technically not correct since this type can contain any charset + _encoding = 'latin1' + + +class BMPString(AbstractString): + """ + Represents a BMP string from ASN.1 as a Python unicode string + """ + + tag = 30 + _encoding = 'utf-16-be' + + +def _basic_debug(prefix, self): + """ + Prints out basic information about an Asn1Value object. Extracted for reuse + among different classes that customize the debug information. + + :param prefix: + A unicode string of spaces to prefix output line with + + :param self: + The object to print the debugging information about + """ + + print('%s%s Object #%s' % (prefix, type_name(self), id(self))) + if self._header: + print('%s Header: 0x%s' % (prefix, binascii.hexlify(self._header or b'').decode('utf-8'))) + + has_header = self.method is not None and self.class_ is not None and self.tag is not None + if has_header: + method_name = METHOD_NUM_TO_NAME_MAP.get(self.method) + class_name = CLASS_NUM_TO_NAME_MAP.get(self.class_) + + if self.explicit is not None: + for class_, tag in self.explicit: + print( + '%s %s tag %s (explicitly tagged)' % + ( + prefix, + CLASS_NUM_TO_NAME_MAP.get(class_), + tag + ) + ) + if has_header: + print('%s %s %s %s' % (prefix, method_name, class_name, self.tag)) + + elif self.implicit: + if has_header: + print('%s %s %s tag %s (implicitly tagged)' % (prefix, method_name, class_name, self.tag)) + + elif has_header: + print('%s %s %s tag %s' % (prefix, method_name, class_name, self.tag)) + + if self._trailer: + print('%s Trailer: 0x%s' % (prefix, binascii.hexlify(self._trailer or b'').decode('utf-8'))) + + print('%s Data: 0x%s' % (prefix, binascii.hexlify(self.contents or b'').decode('utf-8'))) + + +def _tag_type_to_explicit_implicit(params): + """ + Converts old-style "tag_type" and "tag" params to "explicit" and "implicit" + + :param params: + A dict of parameters to convert from tag_type/tag to explicit/implicit + """ + + if 'tag_type' in params: + if params['tag_type'] == 'explicit': + params['explicit'] = (params.get('class', 2), params['tag']) + elif params['tag_type'] == 'implicit': + params['implicit'] = (params.get('class', 2), params['tag']) + del params['tag_type'] + del params['tag'] + if 'class' in params: + del params['class'] + + +def _fix_tagging(value, params): + """ + Checks if a value is properly tagged based on the spec, and re/untags as + necessary + + :param value: + An Asn1Value object + + :param params: + A dict of spec params + + :return: + An Asn1Value that is properly tagged + """ + + _tag_type_to_explicit_implicit(params) + + retag = False + if 'implicit' not in params: + if value.implicit is not False: + retag = True + else: + if isinstance(params['implicit'], tuple): + class_, tag = params['implicit'] + else: + tag = params['implicit'] + class_ = 'context' + if value.implicit is False: + retag = True + elif value.class_ != CLASS_NAME_TO_NUM_MAP[class_] or value.tag != tag: + retag = True + + if params.get('explicit') != value.explicit: + retag = True + + if retag: + return value.retag(params) + return value + + +def _build_id_tuple(params, spec): + """ + Builds a 2-element tuple used to identify fields by grabbing the class_ + and tag from an Asn1Value class and the params dict being passed to it + + :param params: + A dict of params to pass to spec + + :param spec: + An Asn1Value class + + :return: + A 2-element integer tuple in the form (class_, tag) + """ + + # Handle situations where the spec is not known at setup time + if spec is None: + return (None, None) + + required_class = spec.class_ + required_tag = spec.tag + + _tag_type_to_explicit_implicit(params) + + if 'explicit' in params: + if isinstance(params['explicit'], tuple): + required_class, required_tag = params['explicit'] + else: + required_class = 2 + required_tag = params['explicit'] + elif 'implicit' in params: + if isinstance(params['implicit'], tuple): + required_class, required_tag = params['implicit'] + else: + required_class = 2 + required_tag = params['implicit'] + if required_class is not None and not isinstance(required_class, int_types): + required_class = CLASS_NAME_TO_NUM_MAP[required_class] + + required_class = params.get('class_', required_class) + required_tag = params.get('tag', required_tag) + + return (required_class, required_tag) + + +def _int_to_bit_tuple(value, bits): + """ + Format value as a tuple of 1s and 0s. + + :param value: + A non-negative integer to format + + :param bits: + Number of bits in the output + + :return: + A tuple of 1s and 0s with bits members. + """ + + if not value and not bits: + return () + + result = tuple(map(int, format(value, '0{0}b'.format(bits)))) + if len(result) != bits: + raise ValueError('Result too large: {0} > {1}'.format(len(result), bits)) + + return result + + +_UNIVERSAL_SPECS = { + 1: Boolean, + 2: Integer, + 3: BitString, + 4: OctetString, + 5: Null, + 6: ObjectIdentifier, + 7: ObjectDescriptor, + 8: InstanceOf, + 9: Real, + 10: Enumerated, + 11: EmbeddedPdv, + 12: UTF8String, + 13: RelativeOid, + 16: Sequence, + 17: Set, + 18: NumericString, + 19: PrintableString, + 20: TeletexString, + 21: VideotexString, + 22: IA5String, + 23: UTCTime, + 24: GeneralizedTime, + 25: GraphicString, + 26: VisibleString, + 27: GeneralString, + 28: UniversalString, + 29: CharacterString, + 30: BMPString +} + + +def _build(class_, method, tag, header, contents, trailer, spec=None, spec_params=None, nested_spec=None): + """ + Builds an Asn1Value object generically, or using a spec with optional params + + :param class_: + An integer representing the ASN.1 class + + :param method: + An integer representing the ASN.1 method + + :param tag: + An integer representing the ASN.1 tag + + :param header: + A byte string of the ASN.1 header (class, method, tag, length) + + :param contents: + A byte string of the ASN.1 value + + :param trailer: + A byte string of any ASN.1 trailer (only used by indefinite length encodings) + + :param spec: + A class derived from Asn1Value that defines what class_ and tag the + value should have, and the semantics of the encoded value. The + return value will be of this type. If omitted, the encoded value + will be decoded using the standard universal tag based on the + encoded tag number. + + :param spec_params: + A dict of params to pass to the spec object + + :param nested_spec: + For certain Asn1Value classes (such as OctetString and BitString), the + contents can be further parsed and interpreted as another Asn1Value. + This parameter controls the spec for that sub-parsing. + + :return: + An object of the type spec, or if not specified, a child of Asn1Value + """ + + if spec_params is not None: + _tag_type_to_explicit_implicit(spec_params) + + if header is None: + return VOID + + header_set = False + + # If an explicit specification was passed in, make sure it matches + if spec is not None: + # If there is explicit tagging and contents, we have to split + # the header and trailer off before we do the parsing + no_explicit = spec_params and 'no_explicit' in spec_params + if not no_explicit and (spec.explicit or (spec_params and 'explicit' in spec_params)): + if spec_params: + value = spec(**spec_params) + else: + value = spec() + original_explicit = value.explicit + explicit_info = reversed(original_explicit) + parsed_class = class_ + parsed_method = method + parsed_tag = tag + to_parse = contents + explicit_header = header + explicit_trailer = trailer or b'' + for expected_class, expected_tag in explicit_info: + if parsed_class != expected_class: + raise ValueError(unwrap( + ''' + Error parsing %s - explicitly-tagged class should have been + %s, but %s was found + ''', + type_name(value), + CLASS_NUM_TO_NAME_MAP.get(expected_class), + CLASS_NUM_TO_NAME_MAP.get(parsed_class, parsed_class) + )) + if parsed_method != 1: + raise ValueError(unwrap( + ''' + Error parsing %s - explicitly-tagged method should have + been %s, but %s was found + ''', + type_name(value), + METHOD_NUM_TO_NAME_MAP.get(1), + METHOD_NUM_TO_NAME_MAP.get(parsed_method, parsed_method) + )) + if parsed_tag != expected_tag: + raise ValueError(unwrap( + ''' + Error parsing %s - explicitly-tagged tag should have been + %s, but %s was found + ''', + type_name(value), + expected_tag, + parsed_tag + )) + info, _ = _parse(to_parse, len(to_parse)) + parsed_class, parsed_method, parsed_tag, parsed_header, to_parse, parsed_trailer = info + + if not isinstance(value, Choice): + explicit_header += parsed_header + explicit_trailer = parsed_trailer + explicit_trailer + + value = _build(*info, spec=spec, spec_params={'no_explicit': True}) + value._header = explicit_header + value._trailer = explicit_trailer + value.explicit = original_explicit + header_set = True + else: + if spec_params: + value = spec(contents=contents, **spec_params) + else: + value = spec(contents=contents) + + if spec is Any: + pass + + elif isinstance(value, Choice): + value.validate(class_, tag, contents) + try: + # Force parsing the Choice now + value.contents = header + value.contents + header = b'' + value.parse() + except (ValueError, TypeError) as e: + args = e.args[1:] + e.args = (e.args[0] + '\n while parsing %s' % type_name(value),) + args + raise e + + else: + if class_ != value.class_: + raise ValueError(unwrap( + ''' + Error parsing %s - class should have been %s, but %s was + found + ''', + type_name(value), + CLASS_NUM_TO_NAME_MAP.get(value.class_), + CLASS_NUM_TO_NAME_MAP.get(class_, class_) + )) + if method != value.method: + # Allow parsing a primitive method as constructed if the value + # is indefinite length. This is to allow parsing BER. + ber_indef = method == 1 and value.method == 0 and trailer == b'\x00\x00' + if not ber_indef or not isinstance(value, Constructable): + raise ValueError(unwrap( + ''' + Error parsing %s - method should have been %s, but %s was found + ''', + type_name(value), + METHOD_NUM_TO_NAME_MAP.get(value.method), + METHOD_NUM_TO_NAME_MAP.get(method, method) + )) + else: + value.method = method + value._indefinite = True + if tag != value.tag: + if isinstance(value._bad_tag, tuple): + is_bad_tag = tag in value._bad_tag + else: + is_bad_tag = tag == value._bad_tag + if not is_bad_tag: + raise ValueError(unwrap( + ''' + Error parsing %s - tag should have been %s, but %s was found + ''', + type_name(value), + value.tag, + tag + )) + + # For explicitly tagged, un-speced parsings, we use a generic container + # since we will be parsing the contents and discarding the outer object + # anyway a little further on + elif spec_params and 'explicit' in spec_params: + original_value = Asn1Value(contents=contents, **spec_params) + original_explicit = original_value.explicit + + to_parse = contents + explicit_header = header + explicit_trailer = trailer or b'' + for expected_class, expected_tag in reversed(original_explicit): + info, _ = _parse(to_parse, len(to_parse)) + _, _, _, parsed_header, to_parse, parsed_trailer = info + explicit_header += parsed_header + explicit_trailer = parsed_trailer + explicit_trailer + value = _build(*info, spec=spec, spec_params={'no_explicit': True}) + value._header = header + value._header + value._trailer += trailer or b'' + value.explicit = original_explicit + header_set = True + + # If no spec was specified, allow anything and just process what + # is in the input data + else: + if tag not in _UNIVERSAL_SPECS: + raise ValueError(unwrap( + ''' + Unknown element - %s class, %s method, tag %s + ''', + CLASS_NUM_TO_NAME_MAP.get(class_), + METHOD_NUM_TO_NAME_MAP.get(method), + tag + )) + + spec = _UNIVERSAL_SPECS[tag] + + value = spec(contents=contents, class_=class_) + ber_indef = method == 1 and value.method == 0 and trailer == b'\x00\x00' + if ber_indef and isinstance(value, Constructable): + value._indefinite = True + value.method = method + + if not header_set: + value._header = header + value._trailer = trailer or b'' + + # Destroy any default value that our contents have overwritten + value._native = None + + if nested_spec: + try: + value.parse(nested_spec) + except (ValueError, TypeError) as e: + args = e.args[1:] + e.args = (e.args[0] + '\n while parsing %s' % type_name(value),) + args + raise e + + return value + + +def _parse_build(encoded_data, pointer=0, spec=None, spec_params=None, strict=False): + """ + Parses a byte string generically, or using a spec with optional params + + :param encoded_data: + A byte string that contains BER-encoded data + + :param pointer: + The index in the byte string to parse from + + :param spec: + A class derived from Asn1Value that defines what class_ and tag the + value should have, and the semantics of the encoded value. The + return value will be of this type. If omitted, the encoded value + will be decoded using the standard universal tag based on the + encoded tag number. + + :param spec_params: + A dict of params to pass to the spec object + + :param strict: + A boolean indicating if trailing data should be forbidden - if so, a + ValueError will be raised when trailing data exists + + :return: + A 2-element tuple: + - 0: An object of the type spec, or if not specified, a child of Asn1Value + - 1: An integer indicating how many bytes were consumed + """ + + encoded_len = len(encoded_data) + info, new_pointer = _parse(encoded_data, encoded_len, pointer) + if strict and new_pointer != pointer + encoded_len: + extra_bytes = pointer + encoded_len - new_pointer + raise ValueError('Extra data - %d bytes of trailing data were provided' % extra_bytes) + return (_build(*info, spec=spec, spec_params=spec_params), new_pointer) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/asn1crypto/crl.py b/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/asn1crypto/crl.py new file mode 100644 index 00000000..84cb1683 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/asn1crypto/crl.py @@ -0,0 +1,536 @@ +# coding: utf-8 + +""" +ASN.1 type classes for certificate revocation lists (CRL). Exports the +following items: + + - CertificateList() + +Other type classes are defined that help compose the types listed above. +""" + +from __future__ import unicode_literals, division, absolute_import, print_function + +import hashlib + +from .algos import SignedDigestAlgorithm +from .core import ( + Boolean, + Enumerated, + GeneralizedTime, + Integer, + ObjectIdentifier, + OctetBitString, + ParsableOctetString, + Sequence, + SequenceOf, +) +from .x509 import ( + AuthorityInfoAccessSyntax, + AuthorityKeyIdentifier, + CRLDistributionPoints, + DistributionPointName, + GeneralNames, + Name, + ReasonFlags, + Time, +) + + +# The structures in this file are taken from https://tools.ietf.org/html/rfc5280 + + +class Version(Integer): + _map = { + 0: 'v1', + 1: 'v2', + 2: 'v3', + } + + +class IssuingDistributionPoint(Sequence): + _fields = [ + ('distribution_point', DistributionPointName, {'explicit': 0, 'optional': True}), + ('only_contains_user_certs', Boolean, {'implicit': 1, 'default': False}), + ('only_contains_ca_certs', Boolean, {'implicit': 2, 'default': False}), + ('only_some_reasons', ReasonFlags, {'implicit': 3, 'optional': True}), + ('indirect_crl', Boolean, {'implicit': 4, 'default': False}), + ('only_contains_attribute_certs', Boolean, {'implicit': 5, 'default': False}), + ] + + +class TBSCertListExtensionId(ObjectIdentifier): + _map = { + '2.5.29.18': 'issuer_alt_name', + '2.5.29.20': 'crl_number', + '2.5.29.27': 'delta_crl_indicator', + '2.5.29.28': 'issuing_distribution_point', + '2.5.29.35': 'authority_key_identifier', + '2.5.29.46': 'freshest_crl', + '1.3.6.1.5.5.7.1.1': 'authority_information_access', + } + + +class TBSCertListExtension(Sequence): + _fields = [ + ('extn_id', TBSCertListExtensionId), + ('critical', Boolean, {'default': False}), + ('extn_value', ParsableOctetString), + ] + + _oid_pair = ('extn_id', 'extn_value') + _oid_specs = { + 'issuer_alt_name': GeneralNames, + 'crl_number': Integer, + 'delta_crl_indicator': Integer, + 'issuing_distribution_point': IssuingDistributionPoint, + 'authority_key_identifier': AuthorityKeyIdentifier, + 'freshest_crl': CRLDistributionPoints, + 'authority_information_access': AuthorityInfoAccessSyntax, + } + + +class TBSCertListExtensions(SequenceOf): + _child_spec = TBSCertListExtension + + +class CRLReason(Enumerated): + _map = { + 0: 'unspecified', + 1: 'key_compromise', + 2: 'ca_compromise', + 3: 'affiliation_changed', + 4: 'superseded', + 5: 'cessation_of_operation', + 6: 'certificate_hold', + 8: 'remove_from_crl', + 9: 'privilege_withdrawn', + 10: 'aa_compromise', + } + + @property + def human_friendly(self): + """ + :return: + A unicode string with revocation description that is suitable to + show to end-users. Starts with a lower case letter and phrased in + such a way that it makes sense after the phrase "because of" or + "due to". + """ + + return { + 'unspecified': 'an unspecified reason', + 'key_compromise': 'a compromised key', + 'ca_compromise': 'the CA being compromised', + 'affiliation_changed': 'an affiliation change', + 'superseded': 'certificate supersession', + 'cessation_of_operation': 'a cessation of operation', + 'certificate_hold': 'a certificate hold', + 'remove_from_crl': 'removal from the CRL', + 'privilege_withdrawn': 'privilege withdrawl', + 'aa_compromise': 'the AA being compromised', + }[self.native] + + +class CRLEntryExtensionId(ObjectIdentifier): + _map = { + '2.5.29.21': 'crl_reason', + '2.5.29.23': 'hold_instruction_code', + '2.5.29.24': 'invalidity_date', + '2.5.29.29': 'certificate_issuer', + } + + +class CRLEntryExtension(Sequence): + _fields = [ + ('extn_id', CRLEntryExtensionId), + ('critical', Boolean, {'default': False}), + ('extn_value', ParsableOctetString), + ] + + _oid_pair = ('extn_id', 'extn_value') + _oid_specs = { + 'crl_reason': CRLReason, + 'hold_instruction_code': ObjectIdentifier, + 'invalidity_date': GeneralizedTime, + 'certificate_issuer': GeneralNames, + } + + +class CRLEntryExtensions(SequenceOf): + _child_spec = CRLEntryExtension + + +class RevokedCertificate(Sequence): + _fields = [ + ('user_certificate', Integer), + ('revocation_date', Time), + ('crl_entry_extensions', CRLEntryExtensions, {'optional': True}), + ] + + _processed_extensions = False + _critical_extensions = None + _crl_reason_value = None + _invalidity_date_value = None + _certificate_issuer_value = None + _issuer_name = False + + def _set_extensions(self): + """ + Sets common named extensions to private attributes and creates a list + of critical extensions + """ + + self._critical_extensions = set() + + for extension in self['crl_entry_extensions']: + name = extension['extn_id'].native + attribute_name = '_%s_value' % name + if hasattr(self, attribute_name): + setattr(self, attribute_name, extension['extn_value'].parsed) + if extension['critical'].native: + self._critical_extensions.add(name) + + self._processed_extensions = True + + @property + def critical_extensions(self): + """ + Returns a set of the names (or OID if not a known extension) of the + extensions marked as critical + + :return: + A set of unicode strings + """ + + if not self._processed_extensions: + self._set_extensions() + return self._critical_extensions + + @property + def crl_reason_value(self): + """ + This extension indicates the reason that a certificate was revoked. + + :return: + None or a CRLReason object + """ + + if self._processed_extensions is False: + self._set_extensions() + return self._crl_reason_value + + @property + def invalidity_date_value(self): + """ + This extension indicates the suspected date/time the private key was + compromised or the certificate became invalid. This would usually be + before the revocation date, which is when the CA processed the + revocation. + + :return: + None or a GeneralizedTime object + """ + + if self._processed_extensions is False: + self._set_extensions() + return self._invalidity_date_value + + @property + def certificate_issuer_value(self): + """ + This extension indicates the issuer of the certificate in question, + and is used in indirect CRLs. CRL entries without this extension are + for certificates issued from the last seen issuer. + + :return: + None or an x509.GeneralNames object + """ + + if self._processed_extensions is False: + self._set_extensions() + return self._certificate_issuer_value + + @property + def issuer_name(self): + """ + :return: + None, or an asn1crypto.x509.Name object for the issuer of the cert + """ + + if self._issuer_name is False: + self._issuer_name = None + if self.certificate_issuer_value: + for general_name in self.certificate_issuer_value: + if general_name.name == 'directory_name': + self._issuer_name = general_name.chosen + break + return self._issuer_name + + +class RevokedCertificates(SequenceOf): + _child_spec = RevokedCertificate + + +class TbsCertList(Sequence): + _fields = [ + ('version', Version, {'optional': True}), + ('signature', SignedDigestAlgorithm), + ('issuer', Name), + ('this_update', Time), + ('next_update', Time, {'optional': True}), + ('revoked_certificates', RevokedCertificates, {'optional': True}), + ('crl_extensions', TBSCertListExtensions, {'explicit': 0, 'optional': True}), + ] + + +class CertificateList(Sequence): + _fields = [ + ('tbs_cert_list', TbsCertList), + ('signature_algorithm', SignedDigestAlgorithm), + ('signature', OctetBitString), + ] + + _processed_extensions = False + _critical_extensions = None + _issuer_alt_name_value = None + _crl_number_value = None + _delta_crl_indicator_value = None + _issuing_distribution_point_value = None + _authority_key_identifier_value = None + _freshest_crl_value = None + _authority_information_access_value = None + _issuer_cert_urls = None + _delta_crl_distribution_points = None + _sha1 = None + _sha256 = None + + def _set_extensions(self): + """ + Sets common named extensions to private attributes and creates a list + of critical extensions + """ + + self._critical_extensions = set() + + for extension in self['tbs_cert_list']['crl_extensions']: + name = extension['extn_id'].native + attribute_name = '_%s_value' % name + if hasattr(self, attribute_name): + setattr(self, attribute_name, extension['extn_value'].parsed) + if extension['critical'].native: + self._critical_extensions.add(name) + + self._processed_extensions = True + + @property + def critical_extensions(self): + """ + Returns a set of the names (or OID if not a known extension) of the + extensions marked as critical + + :return: + A set of unicode strings + """ + + if not self._processed_extensions: + self._set_extensions() + return self._critical_extensions + + @property + def issuer_alt_name_value(self): + """ + This extension allows associating one or more alternative names with + the issuer of the CRL. + + :return: + None or an x509.GeneralNames object + """ + + if self._processed_extensions is False: + self._set_extensions() + return self._issuer_alt_name_value + + @property + def crl_number_value(self): + """ + This extension adds a monotonically increasing number to the CRL and is + used to distinguish different versions of the CRL. + + :return: + None or an Integer object + """ + + if self._processed_extensions is False: + self._set_extensions() + return self._crl_number_value + + @property + def delta_crl_indicator_value(self): + """ + This extension indicates a CRL is a delta CRL, and contains the CRL + number of the base CRL that it is a delta from. + + :return: + None or an Integer object + """ + + if self._processed_extensions is False: + self._set_extensions() + return self._delta_crl_indicator_value + + @property + def issuing_distribution_point_value(self): + """ + This extension includes information about what types of revocations + and certificates are part of the CRL. + + :return: + None or an IssuingDistributionPoint object + """ + + if self._processed_extensions is False: + self._set_extensions() + return self._issuing_distribution_point_value + + @property + def authority_key_identifier_value(self): + """ + This extension helps in identifying the public key with which to + validate the authenticity of the CRL. + + :return: + None or an AuthorityKeyIdentifier object + """ + + if self._processed_extensions is False: + self._set_extensions() + return self._authority_key_identifier_value + + @property + def freshest_crl_value(self): + """ + This extension is used in complete CRLs to indicate where a delta CRL + may be located. + + :return: + None or a CRLDistributionPoints object + """ + + if self._processed_extensions is False: + self._set_extensions() + return self._freshest_crl_value + + @property + def authority_information_access_value(self): + """ + This extension is used to provide a URL with which to download the + certificate used to sign this CRL. + + :return: + None or an AuthorityInfoAccessSyntax object + """ + + if self._processed_extensions is False: + self._set_extensions() + return self._authority_information_access_value + + @property + def issuer(self): + """ + :return: + An asn1crypto.x509.Name object for the issuer of the CRL + """ + + return self['tbs_cert_list']['issuer'] + + @property + def authority_key_identifier(self): + """ + :return: + None or a byte string of the key_identifier from the authority key + identifier extension + """ + + if not self.authority_key_identifier_value: + return None + + return self.authority_key_identifier_value['key_identifier'].native + + @property + def issuer_cert_urls(self): + """ + :return: + A list of unicode strings that are URLs that should contain either + an individual DER-encoded X.509 certificate, or a DER-encoded CMS + message containing multiple certificates + """ + + if self._issuer_cert_urls is None: + self._issuer_cert_urls = [] + if self.authority_information_access_value: + for entry in self.authority_information_access_value: + if entry['access_method'].native == 'ca_issuers': + location = entry['access_location'] + if location.name != 'uniform_resource_identifier': + continue + url = location.native + if url.lower()[0:7] == 'http://': + self._issuer_cert_urls.append(url) + return self._issuer_cert_urls + + @property + def delta_crl_distribution_points(self): + """ + Returns delta CRL URLs - only applies to complete CRLs + + :return: + A list of zero or more DistributionPoint objects + """ + + if self._delta_crl_distribution_points is None: + self._delta_crl_distribution_points = [] + + if self.freshest_crl_value is not None: + for distribution_point in self.freshest_crl_value: + distribution_point_name = distribution_point['distribution_point'] + # RFC 5280 indicates conforming CA should not use the relative form + if distribution_point_name.name == 'name_relative_to_crl_issuer': + continue + # This library is currently only concerned with HTTP-based CRLs + for general_name in distribution_point_name.chosen: + if general_name.name == 'uniform_resource_identifier': + self._delta_crl_distribution_points.append(distribution_point) + + return self._delta_crl_distribution_points + + @property + def signature(self): + """ + :return: + A byte string of the signature + """ + + return self['signature'].native + + @property + def sha1(self): + """ + :return: + The SHA1 hash of the DER-encoded bytes of this certificate list + """ + + if self._sha1 is None: + self._sha1 = hashlib.sha1(self.dump()).digest() + return self._sha1 + + @property + def sha256(self): + """ + :return: + The SHA-256 hash of the DER-encoded bytes of this certificate list + """ + + if self._sha256 is None: + self._sha256 = hashlib.sha256(self.dump()).digest() + return self._sha256 diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/asn1crypto/csr.py b/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/asn1crypto/csr.py new file mode 100644 index 00000000..7d5ba447 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/asn1crypto/csr.py @@ -0,0 +1,133 @@ +# coding: utf-8 + +""" +ASN.1 type classes for certificate signing requests (CSR). Exports the +following items: + + - CertificationRequest() + +Other type classes are defined that help compose the types listed above. +""" + +from __future__ import unicode_literals, division, absolute_import, print_function + +from .algos import SignedDigestAlgorithm +from .core import ( + Any, + BitString, + BMPString, + Integer, + ObjectIdentifier, + OctetBitString, + Sequence, + SetOf, + UTF8String +) +from .keys import PublicKeyInfo +from .x509 import DirectoryString, Extensions, Name + + +# The structures in this file are taken from https://tools.ietf.org/html/rfc2986 +# and https://tools.ietf.org/html/rfc2985 + + +class Version(Integer): + _map = { + 0: 'v1', + } + + +class CSRAttributeType(ObjectIdentifier): + _map = { + '1.2.840.113549.1.9.7': 'challenge_password', + '1.2.840.113549.1.9.9': 'extended_certificate_attributes', + '1.2.840.113549.1.9.14': 'extension_request', + # https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-wcce/a5eaae36-e9f3-4dc5-a687-bfa7115954f1 + '1.3.6.1.4.1.311.13.2.2': 'microsoft_enrollment_csp_provider', + # https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-wcce/7c677cba-030d-48be-ba2b-01e407705f34 + '1.3.6.1.4.1.311.13.2.3': 'microsoft_os_version', + # https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-wcce/64e5ff6d-c6dd-4578-92f7-b3d895f9b9c7 + '1.3.6.1.4.1.311.21.20': 'microsoft_request_client_info', + } + + +class SetOfDirectoryString(SetOf): + _child_spec = DirectoryString + + +class Attribute(Sequence): + _fields = [ + ('type', ObjectIdentifier), + ('values', SetOf, {'spec': Any}), + ] + + +class SetOfAttributes(SetOf): + _child_spec = Attribute + + +class SetOfExtensions(SetOf): + _child_spec = Extensions + + +class MicrosoftEnrollmentCSProvider(Sequence): + _fields = [ + ('keyspec', Integer), + ('cspname', BMPString), # cryptographic service provider name + ('signature', BitString), + ] + + +class SetOfMicrosoftEnrollmentCSProvider(SetOf): + _child_spec = MicrosoftEnrollmentCSProvider + + +class MicrosoftRequestClientInfo(Sequence): + _fields = [ + ('clientid', Integer), + ('machinename', UTF8String), + ('username', UTF8String), + ('processname', UTF8String), + ] + + +class SetOfMicrosoftRequestClientInfo(SetOf): + _child_spec = MicrosoftRequestClientInfo + + +class CRIAttribute(Sequence): + _fields = [ + ('type', CSRAttributeType), + ('values', Any), + ] + + _oid_pair = ('type', 'values') + _oid_specs = { + 'challenge_password': SetOfDirectoryString, + 'extended_certificate_attributes': SetOfAttributes, + 'extension_request': SetOfExtensions, + 'microsoft_enrollment_csp_provider': SetOfMicrosoftEnrollmentCSProvider, + 'microsoft_os_version': SetOfDirectoryString, + 'microsoft_request_client_info': SetOfMicrosoftRequestClientInfo, + } + + +class CRIAttributes(SetOf): + _child_spec = CRIAttribute + + +class CertificationRequestInfo(Sequence): + _fields = [ + ('version', Version), + ('subject', Name), + ('subject_pk_info', PublicKeyInfo), + ('attributes', CRIAttributes, {'implicit': 0, 'optional': True}), + ] + + +class CertificationRequest(Sequence): + _fields = [ + ('certification_request_info', CertificationRequestInfo), + ('signature_algorithm', SignedDigestAlgorithm), + ('signature', OctetBitString), + ] diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/asn1crypto/keys.py b/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/asn1crypto/keys.py new file mode 100644 index 00000000..dcfbdbee --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/asn1crypto/keys.py @@ -0,0 +1,1301 @@ +# coding: utf-8 + +""" +ASN.1 type classes for public and private keys. Exports the following items: + + - DSAPrivateKey() + - ECPrivateKey() + - EncryptedPrivateKeyInfo() + - PrivateKeyInfo() + - PublicKeyInfo() + - RSAPrivateKey() + - RSAPublicKey() + +Other type classes are defined that help compose the types listed above. +""" + +from __future__ import unicode_literals, division, absolute_import, print_function + +import hashlib +import math + +from ._errors import unwrap, APIException +from ._types import type_name, byte_cls +from .algos import _ForceNullParameters, DigestAlgorithm, EncryptionAlgorithm, RSAESOAEPParams, RSASSAPSSParams +from .core import ( + Any, + Asn1Value, + BitString, + Choice, + Integer, + IntegerOctetString, + Null, + ObjectIdentifier, + OctetBitString, + OctetString, + ParsableOctetString, + ParsableOctetBitString, + Sequence, + SequenceOf, + SetOf, +) +from .util import int_from_bytes, int_to_bytes + + +class OtherPrimeInfo(Sequence): + """ + Source: https://tools.ietf.org/html/rfc3447#page-46 + """ + + _fields = [ + ('prime', Integer), + ('exponent', Integer), + ('coefficient', Integer), + ] + + +class OtherPrimeInfos(SequenceOf): + """ + Source: https://tools.ietf.org/html/rfc3447#page-46 + """ + + _child_spec = OtherPrimeInfo + + +class RSAPrivateKeyVersion(Integer): + """ + Original Name: Version + Source: https://tools.ietf.org/html/rfc3447#page-45 + """ + + _map = { + 0: 'two-prime', + 1: 'multi', + } + + +class RSAPrivateKey(Sequence): + """ + Source: https://tools.ietf.org/html/rfc3447#page-45 + """ + + _fields = [ + ('version', RSAPrivateKeyVersion), + ('modulus', Integer), + ('public_exponent', Integer), + ('private_exponent', Integer), + ('prime1', Integer), + ('prime2', Integer), + ('exponent1', Integer), + ('exponent2', Integer), + ('coefficient', Integer), + ('other_prime_infos', OtherPrimeInfos, {'optional': True}) + ] + + +class RSAPublicKey(Sequence): + """ + Source: https://tools.ietf.org/html/rfc3447#page-44 + """ + + _fields = [ + ('modulus', Integer), + ('public_exponent', Integer) + ] + + +class DSAPrivateKey(Sequence): + """ + The ASN.1 structure that OpenSSL uses to store a DSA private key that is + not part of a PKCS#8 structure. Reversed engineered from english-language + description on linked OpenSSL documentation page. + + Original Name: None + Source: https://www.openssl.org/docs/apps/dsa.html + """ + + _fields = [ + ('version', Integer), + ('p', Integer), + ('q', Integer), + ('g', Integer), + ('public_key', Integer), + ('private_key', Integer), + ] + + +class _ECPoint(): + """ + In both PublicKeyInfo and PrivateKeyInfo, the EC public key is a byte + string that is encoded as a bit string. This class adds convenience + methods for converting to and from the byte string to a pair of integers + that are the X and Y coordinates. + """ + + @classmethod + def from_coords(cls, x, y): + """ + Creates an ECPoint object from the X and Y integer coordinates of the + point + + :param x: + The X coordinate, as an integer + + :param y: + The Y coordinate, as an integer + + :return: + An ECPoint object + """ + + x_bytes = int(math.ceil(math.log(x, 2) / 8.0)) + y_bytes = int(math.ceil(math.log(y, 2) / 8.0)) + + num_bytes = max(x_bytes, y_bytes) + + byte_string = b'\x04' + byte_string += int_to_bytes(x, width=num_bytes) + byte_string += int_to_bytes(y, width=num_bytes) + + return cls(byte_string) + + def to_coords(self): + """ + Returns the X and Y coordinates for this EC point, as native Python + integers + + :return: + A 2-element tuple containing integers (X, Y) + """ + + data = self.native + first_byte = data[0:1] + + # Uncompressed + if first_byte == b'\x04': + remaining = data[1:] + field_len = len(remaining) // 2 + x = int_from_bytes(remaining[0:field_len]) + y = int_from_bytes(remaining[field_len:]) + return (x, y) + + if first_byte not in set([b'\x02', b'\x03']): + raise ValueError(unwrap( + ''' + Invalid EC public key - first byte is incorrect + ''' + )) + + raise ValueError(unwrap( + ''' + Compressed representations of EC public keys are not supported due + to patent US6252960 + ''' + )) + + +class ECPoint(OctetString, _ECPoint): + + pass + + +class ECPointBitString(OctetBitString, _ECPoint): + + pass + + +class SpecifiedECDomainVersion(Integer): + """ + Source: http://www.secg.org/sec1-v2.pdf page 104 + """ + _map = { + 1: 'ecdpVer1', + 2: 'ecdpVer2', + 3: 'ecdpVer3', + } + + +class FieldType(ObjectIdentifier): + """ + Original Name: None + Source: http://www.secg.org/sec1-v2.pdf page 101 + """ + + _map = { + '1.2.840.10045.1.1': 'prime_field', + '1.2.840.10045.1.2': 'characteristic_two_field', + } + + +class CharacteristicTwoBasis(ObjectIdentifier): + """ + Original Name: None + Source: http://www.secg.org/sec1-v2.pdf page 102 + """ + + _map = { + '1.2.840.10045.1.2.1.1': 'gn_basis', + '1.2.840.10045.1.2.1.2': 'tp_basis', + '1.2.840.10045.1.2.1.3': 'pp_basis', + } + + +class Pentanomial(Sequence): + """ + Source: http://www.secg.org/sec1-v2.pdf page 102 + """ + + _fields = [ + ('k1', Integer), + ('k2', Integer), + ('k3', Integer), + ] + + +class CharacteristicTwo(Sequence): + """ + Original Name: Characteristic-two + Source: http://www.secg.org/sec1-v2.pdf page 101 + """ + + _fields = [ + ('m', Integer), + ('basis', CharacteristicTwoBasis), + ('parameters', Any), + ] + + _oid_pair = ('basis', 'parameters') + _oid_specs = { + 'gn_basis': Null, + 'tp_basis': Integer, + 'pp_basis': Pentanomial, + } + + +class FieldID(Sequence): + """ + Source: http://www.secg.org/sec1-v2.pdf page 100 + """ + + _fields = [ + ('field_type', FieldType), + ('parameters', Any), + ] + + _oid_pair = ('field_type', 'parameters') + _oid_specs = { + 'prime_field': Integer, + 'characteristic_two_field': CharacteristicTwo, + } + + +class Curve(Sequence): + """ + Source: http://www.secg.org/sec1-v2.pdf page 104 + """ + + _fields = [ + ('a', OctetString), + ('b', OctetString), + ('seed', OctetBitString, {'optional': True}), + ] + + +class SpecifiedECDomain(Sequence): + """ + Source: http://www.secg.org/sec1-v2.pdf page 103 + """ + + _fields = [ + ('version', SpecifiedECDomainVersion), + ('field_id', FieldID), + ('curve', Curve), + ('base', ECPoint), + ('order', Integer), + ('cofactor', Integer, {'optional': True}), + ('hash', DigestAlgorithm, {'optional': True}), + ] + + +class NamedCurve(ObjectIdentifier): + """ + Various named curves + + Original Name: None + Source: https://tools.ietf.org/html/rfc3279#page-23, + https://tools.ietf.org/html/rfc5480#page-5 + """ + + _map = { + # https://tools.ietf.org/html/rfc3279#page-23 + '1.2.840.10045.3.0.1': 'c2pnb163v1', + '1.2.840.10045.3.0.2': 'c2pnb163v2', + '1.2.840.10045.3.0.3': 'c2pnb163v3', + '1.2.840.10045.3.0.4': 'c2pnb176w1', + '1.2.840.10045.3.0.5': 'c2tnb191v1', + '1.2.840.10045.3.0.6': 'c2tnb191v2', + '1.2.840.10045.3.0.7': 'c2tnb191v3', + '1.2.840.10045.3.0.8': 'c2onb191v4', + '1.2.840.10045.3.0.9': 'c2onb191v5', + '1.2.840.10045.3.0.10': 'c2pnb208w1', + '1.2.840.10045.3.0.11': 'c2tnb239v1', + '1.2.840.10045.3.0.12': 'c2tnb239v2', + '1.2.840.10045.3.0.13': 'c2tnb239v3', + '1.2.840.10045.3.0.14': 'c2onb239v4', + '1.2.840.10045.3.0.15': 'c2onb239v5', + '1.2.840.10045.3.0.16': 'c2pnb272w1', + '1.2.840.10045.3.0.17': 'c2pnb304w1', + '1.2.840.10045.3.0.18': 'c2tnb359v1', + '1.2.840.10045.3.0.19': 'c2pnb368w1', + '1.2.840.10045.3.0.20': 'c2tnb431r1', + '1.2.840.10045.3.1.2': 'prime192v2', + '1.2.840.10045.3.1.3': 'prime192v3', + '1.2.840.10045.3.1.4': 'prime239v1', + '1.2.840.10045.3.1.5': 'prime239v2', + '1.2.840.10045.3.1.6': 'prime239v3', + # https://tools.ietf.org/html/rfc5480#page-5 + # http://www.secg.org/SEC2-Ver-1.0.pdf + '1.2.840.10045.3.1.1': 'secp192r1', + '1.2.840.10045.3.1.7': 'secp256r1', + '1.3.132.0.1': 'sect163k1', + '1.3.132.0.2': 'sect163r1', + '1.3.132.0.3': 'sect239k1', + '1.3.132.0.4': 'sect113r1', + '1.3.132.0.5': 'sect113r2', + '1.3.132.0.6': 'secp112r1', + '1.3.132.0.7': 'secp112r2', + '1.3.132.0.8': 'secp160r1', + '1.3.132.0.9': 'secp160k1', + '1.3.132.0.10': 'secp256k1', + '1.3.132.0.15': 'sect163r2', + '1.3.132.0.16': 'sect283k1', + '1.3.132.0.17': 'sect283r1', + '1.3.132.0.22': 'sect131r1', + '1.3.132.0.23': 'sect131r2', + '1.3.132.0.24': 'sect193r1', + '1.3.132.0.25': 'sect193r2', + '1.3.132.0.26': 'sect233k1', + '1.3.132.0.27': 'sect233r1', + '1.3.132.0.28': 'secp128r1', + '1.3.132.0.29': 'secp128r2', + '1.3.132.0.30': 'secp160r2', + '1.3.132.0.31': 'secp192k1', + '1.3.132.0.32': 'secp224k1', + '1.3.132.0.33': 'secp224r1', + '1.3.132.0.34': 'secp384r1', + '1.3.132.0.35': 'secp521r1', + '1.3.132.0.36': 'sect409k1', + '1.3.132.0.37': 'sect409r1', + '1.3.132.0.38': 'sect571k1', + '1.3.132.0.39': 'sect571r1', + # https://tools.ietf.org/html/rfc5639#section-4.1 + '1.3.36.3.3.2.8.1.1.1': 'brainpoolp160r1', + '1.3.36.3.3.2.8.1.1.2': 'brainpoolp160t1', + '1.3.36.3.3.2.8.1.1.3': 'brainpoolp192r1', + '1.3.36.3.3.2.8.1.1.4': 'brainpoolp192t1', + '1.3.36.3.3.2.8.1.1.5': 'brainpoolp224r1', + '1.3.36.3.3.2.8.1.1.6': 'brainpoolp224t1', + '1.3.36.3.3.2.8.1.1.7': 'brainpoolp256r1', + '1.3.36.3.3.2.8.1.1.8': 'brainpoolp256t1', + '1.3.36.3.3.2.8.1.1.9': 'brainpoolp320r1', + '1.3.36.3.3.2.8.1.1.10': 'brainpoolp320t1', + '1.3.36.3.3.2.8.1.1.11': 'brainpoolp384r1', + '1.3.36.3.3.2.8.1.1.12': 'brainpoolp384t1', + '1.3.36.3.3.2.8.1.1.13': 'brainpoolp512r1', + '1.3.36.3.3.2.8.1.1.14': 'brainpoolp512t1', + } + + _key_sizes = { + # Order values used to compute these sourced from + # http://cr.openjdk.java.net/~vinnie/7194075/webrev-3/src/share/classes/sun/security/ec/CurveDB.java.html + '1.2.840.10045.3.0.1': 21, + '1.2.840.10045.3.0.2': 21, + '1.2.840.10045.3.0.3': 21, + '1.2.840.10045.3.0.4': 21, + '1.2.840.10045.3.0.5': 24, + '1.2.840.10045.3.0.6': 24, + '1.2.840.10045.3.0.7': 24, + '1.2.840.10045.3.0.8': 24, + '1.2.840.10045.3.0.9': 24, + '1.2.840.10045.3.0.10': 25, + '1.2.840.10045.3.0.11': 30, + '1.2.840.10045.3.0.12': 30, + '1.2.840.10045.3.0.13': 30, + '1.2.840.10045.3.0.14': 30, + '1.2.840.10045.3.0.15': 30, + '1.2.840.10045.3.0.16': 33, + '1.2.840.10045.3.0.17': 37, + '1.2.840.10045.3.0.18': 45, + '1.2.840.10045.3.0.19': 45, + '1.2.840.10045.3.0.20': 53, + '1.2.840.10045.3.1.2': 24, + '1.2.840.10045.3.1.3': 24, + '1.2.840.10045.3.1.4': 30, + '1.2.840.10045.3.1.5': 30, + '1.2.840.10045.3.1.6': 30, + # Order values used to compute these sourced from + # http://www.secg.org/SEC2-Ver-1.0.pdf + # ceil(n.bit_length() / 8) + '1.2.840.10045.3.1.1': 24, + '1.2.840.10045.3.1.7': 32, + '1.3.132.0.1': 21, + '1.3.132.0.2': 21, + '1.3.132.0.3': 30, + '1.3.132.0.4': 15, + '1.3.132.0.5': 15, + '1.3.132.0.6': 14, + '1.3.132.0.7': 14, + '1.3.132.0.8': 21, + '1.3.132.0.9': 21, + '1.3.132.0.10': 32, + '1.3.132.0.15': 21, + '1.3.132.0.16': 36, + '1.3.132.0.17': 36, + '1.3.132.0.22': 17, + '1.3.132.0.23': 17, + '1.3.132.0.24': 25, + '1.3.132.0.25': 25, + '1.3.132.0.26': 29, + '1.3.132.0.27': 30, + '1.3.132.0.28': 16, + '1.3.132.0.29': 16, + '1.3.132.0.30': 21, + '1.3.132.0.31': 24, + '1.3.132.0.32': 29, + '1.3.132.0.33': 28, + '1.3.132.0.34': 48, + '1.3.132.0.35': 66, + '1.3.132.0.36': 51, + '1.3.132.0.37': 52, + '1.3.132.0.38': 72, + '1.3.132.0.39': 72, + # Order values used to compute these sourced from + # https://tools.ietf.org/html/rfc5639#section-3 + # ceil(q.bit_length() / 8) + '1.3.36.3.3.2.8.1.1.1': 20, + '1.3.36.3.3.2.8.1.1.2': 20, + '1.3.36.3.3.2.8.1.1.3': 24, + '1.3.36.3.3.2.8.1.1.4': 24, + '1.3.36.3.3.2.8.1.1.5': 28, + '1.3.36.3.3.2.8.1.1.6': 28, + '1.3.36.3.3.2.8.1.1.7': 32, + '1.3.36.3.3.2.8.1.1.8': 32, + '1.3.36.3.3.2.8.1.1.9': 40, + '1.3.36.3.3.2.8.1.1.10': 40, + '1.3.36.3.3.2.8.1.1.11': 48, + '1.3.36.3.3.2.8.1.1.12': 48, + '1.3.36.3.3.2.8.1.1.13': 64, + '1.3.36.3.3.2.8.1.1.14': 64, + } + + @classmethod + def register(cls, name, oid, key_size): + """ + Registers a new named elliptic curve that is not included in the + default list of named curves + + :param name: + A unicode string of the curve name + + :param oid: + A unicode string of the dotted format OID + + :param key_size: + An integer of the number of bytes the private key should be + encoded to + """ + + cls._map[oid] = name + if cls._reverse_map is not None: + cls._reverse_map[name] = oid + cls._key_sizes[oid] = key_size + + +class ECDomainParameters(Choice): + """ + Source: http://www.secg.org/sec1-v2.pdf page 102 + """ + + _alternatives = [ + ('specified', SpecifiedECDomain), + ('named', NamedCurve), + ('implicit_ca', Null), + ] + + @property + def key_size(self): + if self.name == 'implicit_ca': + raise ValueError(unwrap( + ''' + Unable to calculate key_size from ECDomainParameters + that are implicitly defined by the CA key + ''' + )) + + if self.name == 'specified': + order = self.chosen['order'].native + return math.ceil(math.log(order, 2.0) / 8.0) + + oid = self.chosen.dotted + if oid not in NamedCurve._key_sizes: + raise ValueError(unwrap( + ''' + The asn1crypto.keys.NamedCurve %s does not have a registered key length, + please call asn1crypto.keys.NamedCurve.register() + ''', + repr(oid) + )) + return NamedCurve._key_sizes[oid] + + +class ECPrivateKeyVersion(Integer): + """ + Original Name: None + Source: http://www.secg.org/sec1-v2.pdf page 108 + """ + + _map = { + 1: 'ecPrivkeyVer1', + } + + +class ECPrivateKey(Sequence): + """ + Source: http://www.secg.org/sec1-v2.pdf page 108 + """ + + _fields = [ + ('version', ECPrivateKeyVersion), + ('private_key', IntegerOctetString), + ('parameters', ECDomainParameters, {'explicit': 0, 'optional': True}), + ('public_key', ECPointBitString, {'explicit': 1, 'optional': True}), + ] + + # Ensures the key is set to the correct length when encoding + _key_size = None + + # This is necessary to ensure the private_key IntegerOctetString is encoded properly + def __setitem__(self, key, value): + res = super(ECPrivateKey, self).__setitem__(key, value) + + if key == 'private_key': + if self._key_size is None: + # Infer the key_size from the existing private key if possible + pkey_contents = self['private_key'].contents + if isinstance(pkey_contents, byte_cls) and len(pkey_contents) > 1: + self.set_key_size(len(self['private_key'].contents)) + + elif self._key_size is not None: + self._update_key_size() + + elif key == 'parameters' and isinstance(self['parameters'], ECDomainParameters) and \ + self['parameters'].name != 'implicit_ca': + self.set_key_size(self['parameters'].key_size) + + return res + + def set_key_size(self, key_size): + """ + Sets the key_size to ensure the private key is encoded to the proper length + + :param key_size: + An integer byte length to encode the private_key to + """ + + self._key_size = key_size + self._update_key_size() + + def _update_key_size(self): + """ + Ensure the private_key explicit encoding width is set + """ + + if self._key_size is not None and isinstance(self['private_key'], IntegerOctetString): + self['private_key'].set_encoded_width(self._key_size) + + +class DSAParams(Sequence): + """ + Parameters for a DSA public or private key + + Original Name: Dss-Parms + Source: https://tools.ietf.org/html/rfc3279#page-9 + """ + + _fields = [ + ('p', Integer), + ('q', Integer), + ('g', Integer), + ] + + +class Attribute(Sequence): + """ + Source: https://www.itu.int/rec/dologin_pub.asp?lang=e&id=T-REC-X.501-198811-S!!PDF-E&type=items page 8 + """ + + _fields = [ + ('type', ObjectIdentifier), + ('values', SetOf, {'spec': Any}), + ] + + +class Attributes(SetOf): + """ + Source: https://tools.ietf.org/html/rfc5208#page-3 + """ + + _child_spec = Attribute + + +class PrivateKeyAlgorithmId(ObjectIdentifier): + """ + These OIDs for various public keys are reused when storing private keys + inside of a PKCS#8 structure + + Original Name: None + Source: https://tools.ietf.org/html/rfc3279 + """ + + _map = { + # https://tools.ietf.org/html/rfc3279#page-19 + '1.2.840.113549.1.1.1': 'rsa', + # https://tools.ietf.org/html/rfc4055#page-8 + '1.2.840.113549.1.1.10': 'rsassa_pss', + # https://tools.ietf.org/html/rfc3279#page-18 + '1.2.840.10040.4.1': 'dsa', + # https://tools.ietf.org/html/rfc3279#page-13 + '1.2.840.10045.2.1': 'ec', + # https://tools.ietf.org/html/rfc8410#section-9 + '1.3.101.110': 'x25519', + '1.3.101.111': 'x448', + '1.3.101.112': 'ed25519', + '1.3.101.113': 'ed448', + } + + +class PrivateKeyAlgorithm(_ForceNullParameters, Sequence): + """ + Original Name: PrivateKeyAlgorithmIdentifier + Source: https://tools.ietf.org/html/rfc5208#page-3 + """ + + _fields = [ + ('algorithm', PrivateKeyAlgorithmId), + ('parameters', Any, {'optional': True}), + ] + + _oid_pair = ('algorithm', 'parameters') + _oid_specs = { + 'dsa': DSAParams, + 'ec': ECDomainParameters, + 'rsassa_pss': RSASSAPSSParams, + } + + +class PrivateKeyInfo(Sequence): + """ + Source: https://tools.ietf.org/html/rfc5208#page-3 + """ + + _fields = [ + ('version', Integer), + ('private_key_algorithm', PrivateKeyAlgorithm), + ('private_key', ParsableOctetString), + ('attributes', Attributes, {'implicit': 0, 'optional': True}), + ] + + def _private_key_spec(self): + algorithm = self['private_key_algorithm']['algorithm'].native + return { + 'rsa': RSAPrivateKey, + 'rsassa_pss': RSAPrivateKey, + 'dsa': Integer, + 'ec': ECPrivateKey, + # These should be treated as opaque octet strings according + # to RFC 8410 + 'x25519': OctetString, + 'x448': OctetString, + 'ed25519': OctetString, + 'ed448': OctetString, + }[algorithm] + + _spec_callbacks = { + 'private_key': _private_key_spec + } + + _algorithm = None + _bit_size = None + _public_key = None + _fingerprint = None + + @classmethod + def wrap(cls, private_key, algorithm): + """ + Wraps a private key in a PrivateKeyInfo structure + + :param private_key: + A byte string or Asn1Value object of the private key + + :param algorithm: + A unicode string of "rsa", "dsa" or "ec" + + :return: + A PrivateKeyInfo object + """ + + if not isinstance(private_key, byte_cls) and not isinstance(private_key, Asn1Value): + raise TypeError(unwrap( + ''' + private_key must be a byte string or Asn1Value, not %s + ''', + type_name(private_key) + )) + + if algorithm == 'rsa': + if not isinstance(private_key, RSAPrivateKey): + private_key = RSAPrivateKey.load(private_key) + params = Null() + elif algorithm == 'dsa': + if not isinstance(private_key, DSAPrivateKey): + private_key = DSAPrivateKey.load(private_key) + params = DSAParams() + params['p'] = private_key['p'] + params['q'] = private_key['q'] + params['g'] = private_key['g'] + public_key = private_key['public_key'] + private_key = private_key['private_key'] + elif algorithm == 'ec': + if not isinstance(private_key, ECPrivateKey): + private_key = ECPrivateKey.load(private_key) + else: + private_key = private_key.copy() + params = private_key['parameters'] + del private_key['parameters'] + else: + raise ValueError(unwrap( + ''' + algorithm must be one of "rsa", "dsa", "ec", not %s + ''', + repr(algorithm) + )) + + private_key_algo = PrivateKeyAlgorithm() + private_key_algo['algorithm'] = PrivateKeyAlgorithmId(algorithm) + private_key_algo['parameters'] = params + + container = cls() + container._algorithm = algorithm + container['version'] = Integer(0) + container['private_key_algorithm'] = private_key_algo + container['private_key'] = private_key + + # Here we save the DSA public key if possible since it is not contained + # within the PKCS#8 structure for a DSA key + if algorithm == 'dsa': + container._public_key = public_key + + return container + + # This is necessary to ensure any contained ECPrivateKey is the + # correct size + def __setitem__(self, key, value): + res = super(PrivateKeyInfo, self).__setitem__(key, value) + + algorithm = self['private_key_algorithm'] + + # When possible, use the parameter info to make sure the private key encoding + # retains any necessary leading bytes, instead of them being dropped + if (key == 'private_key_algorithm' or key == 'private_key') and \ + algorithm['algorithm'].native == 'ec' and \ + isinstance(algorithm['parameters'], ECDomainParameters) and \ + algorithm['parameters'].name != 'implicit_ca' and \ + isinstance(self['private_key'], ParsableOctetString) and \ + isinstance(self['private_key'].parsed, ECPrivateKey): + self['private_key'].parsed.set_key_size(algorithm['parameters'].key_size) + + return res + + def unwrap(self): + """ + Unwraps the private key into an RSAPrivateKey, DSAPrivateKey or + ECPrivateKey object + + :return: + An RSAPrivateKey, DSAPrivateKey or ECPrivateKey object + """ + + raise APIException( + 'asn1crypto.keys.PrivateKeyInfo().unwrap() has been removed, ' + 'please use oscrypto.asymmetric.PrivateKey().unwrap() instead') + + @property + def curve(self): + """ + Returns information about the curve used for an EC key + + :raises: + ValueError - when the key is not an EC key + + :return: + A two-element tuple, with the first element being a unicode string + of "implicit_ca", "specified" or "named". If the first element is + "implicit_ca", the second is None. If "specified", the second is + an OrderedDict that is the native version of SpecifiedECDomain. If + "named", the second is a unicode string of the curve name. + """ + + if self.algorithm != 'ec': + raise ValueError(unwrap( + ''' + Only EC keys have a curve, this key is %s + ''', + self.algorithm.upper() + )) + + params = self['private_key_algorithm']['parameters'] + chosen = params.chosen + + if params.name == 'implicit_ca': + value = None + else: + value = chosen.native + + return (params.name, value) + + @property + def hash_algo(self): + """ + Returns the name of the family of hash algorithms used to generate a + DSA key + + :raises: + ValueError - when the key is not a DSA key + + :return: + A unicode string of "sha1" or "sha2" + """ + + if self.algorithm != 'dsa': + raise ValueError(unwrap( + ''' + Only DSA keys are generated using a hash algorithm, this key is + %s + ''', + self.algorithm.upper() + )) + + byte_len = math.log(self['private_key_algorithm']['parameters']['q'].native, 2) / 8 + + return 'sha1' if byte_len <= 20 else 'sha2' + + @property + def algorithm(self): + """ + :return: + A unicode string of "rsa", "dsa" or "ec" + """ + + if self._algorithm is None: + self._algorithm = self['private_key_algorithm']['algorithm'].native + return self._algorithm + + @property + def bit_size(self): + """ + :return: + The bit size of the private key, as an integer + """ + + if self._bit_size is None: + if self.algorithm == 'rsa': + prime = self['private_key'].parsed['modulus'].native + elif self.algorithm == 'dsa': + prime = self['private_key_algorithm']['parameters']['p'].native + elif self.algorithm == 'ec': + prime = self['private_key'].parsed['private_key'].native + self._bit_size = int(math.ceil(math.log(prime, 2))) + modulus = self._bit_size % 8 + if modulus != 0: + self._bit_size += 8 - modulus + return self._bit_size + + @property + def byte_size(self): + """ + :return: + The byte size of the private key, as an integer + """ + + return int(math.ceil(self.bit_size / 8)) + + @property + def public_key(self): + """ + :return: + If an RSA key, an RSAPublicKey object. If a DSA key, an Integer + object. If an EC key, an ECPointBitString object. + """ + + raise APIException( + 'asn1crypto.keys.PrivateKeyInfo().public_key has been removed, ' + 'please use oscrypto.asymmetric.PrivateKey().public_key.unwrap() instead') + + @property + def public_key_info(self): + """ + :return: + A PublicKeyInfo object derived from this private key. + """ + + raise APIException( + 'asn1crypto.keys.PrivateKeyInfo().public_key_info has been removed, ' + 'please use oscrypto.asymmetric.PrivateKey().public_key.asn1 instead') + + @property + def fingerprint(self): + """ + Creates a fingerprint that can be compared with a public key to see if + the two form a pair. + + This fingerprint is not compatible with fingerprints generated by any + other software. + + :return: + A byte string that is a sha256 hash of selected components (based + on the key type) + """ + + raise APIException( + 'asn1crypto.keys.PrivateKeyInfo().fingerprint has been removed, ' + 'please use oscrypto.asymmetric.PrivateKey().fingerprint instead') + + +class EncryptedPrivateKeyInfo(Sequence): + """ + Source: https://tools.ietf.org/html/rfc5208#page-4 + """ + + _fields = [ + ('encryption_algorithm', EncryptionAlgorithm), + ('encrypted_data', OctetString), + ] + + +# These structures are from https://tools.ietf.org/html/rfc3279 + +class ValidationParms(Sequence): + """ + Source: https://tools.ietf.org/html/rfc3279#page-10 + """ + + _fields = [ + ('seed', BitString), + ('pgen_counter', Integer), + ] + + +class DomainParameters(Sequence): + """ + Source: https://tools.ietf.org/html/rfc3279#page-10 + """ + + _fields = [ + ('p', Integer), + ('g', Integer), + ('q', Integer), + ('j', Integer, {'optional': True}), + ('validation_params', ValidationParms, {'optional': True}), + ] + + +class PublicKeyAlgorithmId(ObjectIdentifier): + """ + Original Name: None + Source: https://tools.ietf.org/html/rfc3279 + """ + + _map = { + # https://tools.ietf.org/html/rfc3279#page-19 + '1.2.840.113549.1.1.1': 'rsa', + # https://tools.ietf.org/html/rfc3447#page-47 + '1.2.840.113549.1.1.7': 'rsaes_oaep', + # https://tools.ietf.org/html/rfc4055#page-8 + '1.2.840.113549.1.1.10': 'rsassa_pss', + # https://tools.ietf.org/html/rfc3279#page-18 + '1.2.840.10040.4.1': 'dsa', + # https://tools.ietf.org/html/rfc3279#page-13 + '1.2.840.10045.2.1': 'ec', + # https://tools.ietf.org/html/rfc3279#page-10 + '1.2.840.10046.2.1': 'dh', + # https://tools.ietf.org/html/rfc8410#section-9 + '1.3.101.110': 'x25519', + '1.3.101.111': 'x448', + '1.3.101.112': 'ed25519', + '1.3.101.113': 'ed448', + } + + +class PublicKeyAlgorithm(_ForceNullParameters, Sequence): + """ + Original Name: AlgorithmIdentifier + Source: https://tools.ietf.org/html/rfc5280#page-18 + """ + + _fields = [ + ('algorithm', PublicKeyAlgorithmId), + ('parameters', Any, {'optional': True}), + ] + + _oid_pair = ('algorithm', 'parameters') + _oid_specs = { + 'dsa': DSAParams, + 'ec': ECDomainParameters, + 'dh': DomainParameters, + 'rsaes_oaep': RSAESOAEPParams, + 'rsassa_pss': RSASSAPSSParams, + } + + +class PublicKeyInfo(Sequence): + """ + Original Name: SubjectPublicKeyInfo + Source: https://tools.ietf.org/html/rfc5280#page-17 + """ + + _fields = [ + ('algorithm', PublicKeyAlgorithm), + ('public_key', ParsableOctetBitString), + ] + + def _public_key_spec(self): + algorithm = self['algorithm']['algorithm'].native + return { + 'rsa': RSAPublicKey, + 'rsaes_oaep': RSAPublicKey, + 'rsassa_pss': RSAPublicKey, + 'dsa': Integer, + # We override the field spec with ECPoint so that users can easily + # decompose the byte string into the constituent X and Y coords + 'ec': (ECPointBitString, None), + 'dh': Integer, + # These should be treated as opaque bit strings according + # to RFC 8410, and need not even be valid ASN.1 + 'x25519': (OctetBitString, None), + 'x448': (OctetBitString, None), + 'ed25519': (OctetBitString, None), + 'ed448': (OctetBitString, None), + }[algorithm] + + _spec_callbacks = { + 'public_key': _public_key_spec + } + + _algorithm = None + _bit_size = None + _fingerprint = None + _sha1 = None + _sha256 = None + + @classmethod + def wrap(cls, public_key, algorithm): + """ + Wraps a public key in a PublicKeyInfo structure + + :param public_key: + A byte string or Asn1Value object of the public key + + :param algorithm: + A unicode string of "rsa" + + :return: + A PublicKeyInfo object + """ + + if not isinstance(public_key, byte_cls) and not isinstance(public_key, Asn1Value): + raise TypeError(unwrap( + ''' + public_key must be a byte string or Asn1Value, not %s + ''', + type_name(public_key) + )) + + if algorithm != 'rsa': + raise ValueError(unwrap( + ''' + algorithm must "rsa", not %s + ''', + repr(algorithm) + )) + + algo = PublicKeyAlgorithm() + algo['algorithm'] = PublicKeyAlgorithmId(algorithm) + algo['parameters'] = Null() + + container = cls() + container['algorithm'] = algo + if isinstance(public_key, Asn1Value): + public_key = public_key.untag().dump() + container['public_key'] = ParsableOctetBitString(public_key) + + return container + + def unwrap(self): + """ + Unwraps an RSA public key into an RSAPublicKey object. Does not support + DSA or EC public keys since they do not have an unwrapped form. + + :return: + An RSAPublicKey object + """ + + raise APIException( + 'asn1crypto.keys.PublicKeyInfo().unwrap() has been removed, ' + 'please use oscrypto.asymmetric.PublicKey().unwrap() instead') + + @property + def curve(self): + """ + Returns information about the curve used for an EC key + + :raises: + ValueError - when the key is not an EC key + + :return: + A two-element tuple, with the first element being a unicode string + of "implicit_ca", "specified" or "named". If the first element is + "implicit_ca", the second is None. If "specified", the second is + an OrderedDict that is the native version of SpecifiedECDomain. If + "named", the second is a unicode string of the curve name. + """ + + if self.algorithm != 'ec': + raise ValueError(unwrap( + ''' + Only EC keys have a curve, this key is %s + ''', + self.algorithm.upper() + )) + + params = self['algorithm']['parameters'] + chosen = params.chosen + + if params.name == 'implicit_ca': + value = None + else: + value = chosen.native + + return (params.name, value) + + @property + def hash_algo(self): + """ + Returns the name of the family of hash algorithms used to generate a + DSA key + + :raises: + ValueError - when the key is not a DSA key + + :return: + A unicode string of "sha1" or "sha2" or None if no parameters are + present + """ + + if self.algorithm != 'dsa': + raise ValueError(unwrap( + ''' + Only DSA keys are generated using a hash algorithm, this key is + %s + ''', + self.algorithm.upper() + )) + + parameters = self['algorithm']['parameters'] + if parameters.native is None: + return None + + byte_len = math.log(parameters['q'].native, 2) / 8 + + return 'sha1' if byte_len <= 20 else 'sha2' + + @property + def algorithm(self): + """ + :return: + A unicode string of "rsa", "dsa" or "ec" + """ + + if self._algorithm is None: + self._algorithm = self['algorithm']['algorithm'].native + return self._algorithm + + @property + def bit_size(self): + """ + :return: + The bit size of the public key, as an integer + """ + + if self._bit_size is None: + if self.algorithm == 'ec': + self._bit_size = int(((len(self['public_key'].native) - 1) / 2) * 8) + else: + if self.algorithm == 'rsa': + prime = self['public_key'].parsed['modulus'].native + elif self.algorithm == 'dsa': + prime = self['algorithm']['parameters']['p'].native + self._bit_size = int(math.ceil(math.log(prime, 2))) + modulus = self._bit_size % 8 + if modulus != 0: + self._bit_size += 8 - modulus + + return self._bit_size + + @property + def byte_size(self): + """ + :return: + The byte size of the public key, as an integer + """ + + return int(math.ceil(self.bit_size / 8)) + + @property + def sha1(self): + """ + :return: + The SHA1 hash of the DER-encoded bytes of this public key info + """ + + if self._sha1 is None: + self._sha1 = hashlib.sha1(byte_cls(self['public_key'])).digest() + return self._sha1 + + @property + def sha256(self): + """ + :return: + The SHA-256 hash of the DER-encoded bytes of this public key info + """ + + if self._sha256 is None: + self._sha256 = hashlib.sha256(byte_cls(self['public_key'])).digest() + return self._sha256 + + @property + def fingerprint(self): + """ + Creates a fingerprint that can be compared with a private key to see if + the two form a pair. + + This fingerprint is not compatible with fingerprints generated by any + other software. + + :return: + A byte string that is a sha256 hash of selected components (based + on the key type) + """ + + raise APIException( + 'asn1crypto.keys.PublicKeyInfo().fingerprint has been removed, ' + 'please use oscrypto.asymmetric.PublicKey().fingerprint instead') diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/asn1crypto/ocsp.py b/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/asn1crypto/ocsp.py new file mode 100644 index 00000000..91c7fbf3 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/asn1crypto/ocsp.py @@ -0,0 +1,703 @@ +# coding: utf-8 + +""" +ASN.1 type classes for the online certificate status protocol (OCSP). Exports +the following items: + + - OCSPRequest() + - OCSPResponse() + +Other type classes are defined that help compose the types listed above. +""" + +from __future__ import unicode_literals, division, absolute_import, print_function + +from ._errors import unwrap +from .algos import DigestAlgorithm, SignedDigestAlgorithm +from .core import ( + Boolean, + Choice, + Enumerated, + GeneralizedTime, + IA5String, + Integer, + Null, + ObjectIdentifier, + OctetBitString, + OctetString, + ParsableOctetString, + Sequence, + SequenceOf, +) +from .crl import AuthorityInfoAccessSyntax, CRLReason +from .keys import PublicKeyAlgorithm +from .x509 import Certificate, GeneralName, GeneralNames, Name + + +# The structures in this file are taken from https://tools.ietf.org/html/rfc6960 + + +class Version(Integer): + _map = { + 0: 'v1' + } + + +class CertId(Sequence): + _fields = [ + ('hash_algorithm', DigestAlgorithm), + ('issuer_name_hash', OctetString), + ('issuer_key_hash', OctetString), + ('serial_number', Integer), + ] + + +class ServiceLocator(Sequence): + _fields = [ + ('issuer', Name), + ('locator', AuthorityInfoAccessSyntax), + ] + + +class RequestExtensionId(ObjectIdentifier): + _map = { + '1.3.6.1.5.5.7.48.1.7': 'service_locator', + } + + +class RequestExtension(Sequence): + _fields = [ + ('extn_id', RequestExtensionId), + ('critical', Boolean, {'default': False}), + ('extn_value', ParsableOctetString), + ] + + _oid_pair = ('extn_id', 'extn_value') + _oid_specs = { + 'service_locator': ServiceLocator, + } + + +class RequestExtensions(SequenceOf): + _child_spec = RequestExtension + + +class Request(Sequence): + _fields = [ + ('req_cert', CertId), + ('single_request_extensions', RequestExtensions, {'explicit': 0, 'optional': True}), + ] + + _processed_extensions = False + _critical_extensions = None + _service_locator_value = None + + def _set_extensions(self): + """ + Sets common named extensions to private attributes and creates a list + of critical extensions + """ + + self._critical_extensions = set() + + for extension in self['single_request_extensions']: + name = extension['extn_id'].native + attribute_name = '_%s_value' % name + if hasattr(self, attribute_name): + setattr(self, attribute_name, extension['extn_value'].parsed) + if extension['critical'].native: + self._critical_extensions.add(name) + + self._processed_extensions = True + + @property + def critical_extensions(self): + """ + Returns a set of the names (or OID if not a known extension) of the + extensions marked as critical + + :return: + A set of unicode strings + """ + + if not self._processed_extensions: + self._set_extensions() + return self._critical_extensions + + @property + def service_locator_value(self): + """ + This extension is used when communicating with an OCSP responder that + acts as a proxy for OCSP requests + + :return: + None or a ServiceLocator object + """ + + if self._processed_extensions is False: + self._set_extensions() + return self._service_locator_value + + +class Requests(SequenceOf): + _child_spec = Request + + +class ResponseType(ObjectIdentifier): + _map = { + '1.3.6.1.5.5.7.48.1.1': 'basic_ocsp_response', + } + + +class AcceptableResponses(SequenceOf): + _child_spec = ResponseType + + +class PreferredSignatureAlgorithm(Sequence): + _fields = [ + ('sig_identifier', SignedDigestAlgorithm), + ('cert_identifier', PublicKeyAlgorithm, {'optional': True}), + ] + + +class PreferredSignatureAlgorithms(SequenceOf): + _child_spec = PreferredSignatureAlgorithm + + +class TBSRequestExtensionId(ObjectIdentifier): + _map = { + '1.3.6.1.5.5.7.48.1.2': 'nonce', + '1.3.6.1.5.5.7.48.1.4': 'acceptable_responses', + '1.3.6.1.5.5.7.48.1.8': 'preferred_signature_algorithms', + } + + +class TBSRequestExtension(Sequence): + _fields = [ + ('extn_id', TBSRequestExtensionId), + ('critical', Boolean, {'default': False}), + ('extn_value', ParsableOctetString), + ] + + _oid_pair = ('extn_id', 'extn_value') + _oid_specs = { + 'nonce': OctetString, + 'acceptable_responses': AcceptableResponses, + 'preferred_signature_algorithms': PreferredSignatureAlgorithms, + } + + +class TBSRequestExtensions(SequenceOf): + _child_spec = TBSRequestExtension + + +class TBSRequest(Sequence): + _fields = [ + ('version', Version, {'explicit': 0, 'default': 'v1'}), + ('requestor_name', GeneralName, {'explicit': 1, 'optional': True}), + ('request_list', Requests), + ('request_extensions', TBSRequestExtensions, {'explicit': 2, 'optional': True}), + ] + + +class Certificates(SequenceOf): + _child_spec = Certificate + + +class Signature(Sequence): + _fields = [ + ('signature_algorithm', SignedDigestAlgorithm), + ('signature', OctetBitString), + ('certs', Certificates, {'explicit': 0, 'optional': True}), + ] + + +class OCSPRequest(Sequence): + _fields = [ + ('tbs_request', TBSRequest), + ('optional_signature', Signature, {'explicit': 0, 'optional': True}), + ] + + _processed_extensions = False + _critical_extensions = None + _nonce_value = None + _acceptable_responses_value = None + _preferred_signature_algorithms_value = None + + def _set_extensions(self): + """ + Sets common named extensions to private attributes and creates a list + of critical extensions + """ + + self._critical_extensions = set() + + for extension in self['tbs_request']['request_extensions']: + name = extension['extn_id'].native + attribute_name = '_%s_value' % name + if hasattr(self, attribute_name): + setattr(self, attribute_name, extension['extn_value'].parsed) + if extension['critical'].native: + self._critical_extensions.add(name) + + self._processed_extensions = True + + @property + def critical_extensions(self): + """ + Returns a set of the names (or OID if not a known extension) of the + extensions marked as critical + + :return: + A set of unicode strings + """ + + if not self._processed_extensions: + self._set_extensions() + return self._critical_extensions + + @property + def nonce_value(self): + """ + This extension is used to prevent replay attacks by including a unique, + random value with each request/response pair + + :return: + None or an OctetString object + """ + + if self._processed_extensions is False: + self._set_extensions() + return self._nonce_value + + @property + def acceptable_responses_value(self): + """ + This extension is used to allow the client and server to communicate + with alternative response formats other than just basic_ocsp_response, + although no other formats are defined in the standard. + + :return: + None or an AcceptableResponses object + """ + + if self._processed_extensions is False: + self._set_extensions() + return self._acceptable_responses_value + + @property + def preferred_signature_algorithms_value(self): + """ + This extension is used by the client to define what signature algorithms + are preferred, including both the hash algorithm and the public key + algorithm, with a level of detail down to even the public key algorithm + parameters, such as curve name. + + :return: + None or a PreferredSignatureAlgorithms object + """ + + if self._processed_extensions is False: + self._set_extensions() + return self._preferred_signature_algorithms_value + + +class OCSPResponseStatus(Enumerated): + _map = { + 0: 'successful', + 1: 'malformed_request', + 2: 'internal_error', + 3: 'try_later', + 5: 'sign_required', + 6: 'unauthorized', + } + + +class ResponderId(Choice): + _alternatives = [ + ('by_name', Name, {'explicit': 1}), + ('by_key', OctetString, {'explicit': 2}), + ] + + +# Custom class to return a meaningful .native attribute from CertStatus() +class StatusGood(Null): + def set(self, value): + """ + Sets the value of the object + + :param value: + None or 'good' + """ + + if value is not None and value != 'good' and not isinstance(value, Null): + raise ValueError(unwrap( + ''' + value must be one of None, "good", not %s + ''', + repr(value) + )) + + self.contents = b'' + + @property + def native(self): + return 'good' + + +# Custom class to return a meaningful .native attribute from CertStatus() +class StatusUnknown(Null): + def set(self, value): + """ + Sets the value of the object + + :param value: + None or 'unknown' + """ + + if value is not None and value != 'unknown' and not isinstance(value, Null): + raise ValueError(unwrap( + ''' + value must be one of None, "unknown", not %s + ''', + repr(value) + )) + + self.contents = b'' + + @property + def native(self): + return 'unknown' + + +class RevokedInfo(Sequence): + _fields = [ + ('revocation_time', GeneralizedTime), + ('revocation_reason', CRLReason, {'explicit': 0, 'optional': True}), + ] + + +class CertStatus(Choice): + _alternatives = [ + ('good', StatusGood, {'implicit': 0}), + ('revoked', RevokedInfo, {'implicit': 1}), + ('unknown', StatusUnknown, {'implicit': 2}), + ] + + +class CrlId(Sequence): + _fields = [ + ('crl_url', IA5String, {'explicit': 0, 'optional': True}), + ('crl_num', Integer, {'explicit': 1, 'optional': True}), + ('crl_time', GeneralizedTime, {'explicit': 2, 'optional': True}), + ] + + +class SingleResponseExtensionId(ObjectIdentifier): + _map = { + '1.3.6.1.5.5.7.48.1.3': 'crl', + '1.3.6.1.5.5.7.48.1.6': 'archive_cutoff', + # These are CRLEntryExtension values from + # https://tools.ietf.org/html/rfc5280 + '2.5.29.21': 'crl_reason', + '2.5.29.24': 'invalidity_date', + '2.5.29.29': 'certificate_issuer', + # https://tools.ietf.org/html/rfc6962.html#page-13 + '1.3.6.1.4.1.11129.2.4.5': 'signed_certificate_timestamp_list', + } + + +class SingleResponseExtension(Sequence): + _fields = [ + ('extn_id', SingleResponseExtensionId), + ('critical', Boolean, {'default': False}), + ('extn_value', ParsableOctetString), + ] + + _oid_pair = ('extn_id', 'extn_value') + _oid_specs = { + 'crl': CrlId, + 'archive_cutoff': GeneralizedTime, + 'crl_reason': CRLReason, + 'invalidity_date': GeneralizedTime, + 'certificate_issuer': GeneralNames, + 'signed_certificate_timestamp_list': OctetString, + } + + +class SingleResponseExtensions(SequenceOf): + _child_spec = SingleResponseExtension + + +class SingleResponse(Sequence): + _fields = [ + ('cert_id', CertId), + ('cert_status', CertStatus), + ('this_update', GeneralizedTime), + ('next_update', GeneralizedTime, {'explicit': 0, 'optional': True}), + ('single_extensions', SingleResponseExtensions, {'explicit': 1, 'optional': True}), + ] + + _processed_extensions = False + _critical_extensions = None + _crl_value = None + _archive_cutoff_value = None + _crl_reason_value = None + _invalidity_date_value = None + _certificate_issuer_value = None + + def _set_extensions(self): + """ + Sets common named extensions to private attributes and creates a list + of critical extensions + """ + + self._critical_extensions = set() + + for extension in self['single_extensions']: + name = extension['extn_id'].native + attribute_name = '_%s_value' % name + if hasattr(self, attribute_name): + setattr(self, attribute_name, extension['extn_value'].parsed) + if extension['critical'].native: + self._critical_extensions.add(name) + + self._processed_extensions = True + + @property + def critical_extensions(self): + """ + Returns a set of the names (or OID if not a known extension) of the + extensions marked as critical + + :return: + A set of unicode strings + """ + + if not self._processed_extensions: + self._set_extensions() + return self._critical_extensions + + @property + def crl_value(self): + """ + This extension is used to locate the CRL that a certificate's revocation + is contained within. + + :return: + None or a CrlId object + """ + + if self._processed_extensions is False: + self._set_extensions() + return self._crl_value + + @property + def archive_cutoff_value(self): + """ + This extension is used to indicate the date at which an archived + (historical) certificate status entry will no longer be available. + + :return: + None or a GeneralizedTime object + """ + + if self._processed_extensions is False: + self._set_extensions() + return self._archive_cutoff_value + + @property + def crl_reason_value(self): + """ + This extension indicates the reason that a certificate was revoked. + + :return: + None or a CRLReason object + """ + + if self._processed_extensions is False: + self._set_extensions() + return self._crl_reason_value + + @property + def invalidity_date_value(self): + """ + This extension indicates the suspected date/time the private key was + compromised or the certificate became invalid. This would usually be + before the revocation date, which is when the CA processed the + revocation. + + :return: + None or a GeneralizedTime object + """ + + if self._processed_extensions is False: + self._set_extensions() + return self._invalidity_date_value + + @property + def certificate_issuer_value(self): + """ + This extension indicates the issuer of the certificate in question. + + :return: + None or an x509.GeneralNames object + """ + + if self._processed_extensions is False: + self._set_extensions() + return self._certificate_issuer_value + + +class Responses(SequenceOf): + _child_spec = SingleResponse + + +class ResponseDataExtensionId(ObjectIdentifier): + _map = { + '1.3.6.1.5.5.7.48.1.2': 'nonce', + '1.3.6.1.5.5.7.48.1.9': 'extended_revoke', + } + + +class ResponseDataExtension(Sequence): + _fields = [ + ('extn_id', ResponseDataExtensionId), + ('critical', Boolean, {'default': False}), + ('extn_value', ParsableOctetString), + ] + + _oid_pair = ('extn_id', 'extn_value') + _oid_specs = { + 'nonce': OctetString, + 'extended_revoke': Null, + } + + +class ResponseDataExtensions(SequenceOf): + _child_spec = ResponseDataExtension + + +class ResponseData(Sequence): + _fields = [ + ('version', Version, {'explicit': 0, 'default': 'v1'}), + ('responder_id', ResponderId), + ('produced_at', GeneralizedTime), + ('responses', Responses), + ('response_extensions', ResponseDataExtensions, {'explicit': 1, 'optional': True}), + ] + + +class BasicOCSPResponse(Sequence): + _fields = [ + ('tbs_response_data', ResponseData), + ('signature_algorithm', SignedDigestAlgorithm), + ('signature', OctetBitString), + ('certs', Certificates, {'explicit': 0, 'optional': True}), + ] + + +class ResponseBytes(Sequence): + _fields = [ + ('response_type', ResponseType), + ('response', ParsableOctetString), + ] + + _oid_pair = ('response_type', 'response') + _oid_specs = { + 'basic_ocsp_response': BasicOCSPResponse, + } + + +class OCSPResponse(Sequence): + _fields = [ + ('response_status', OCSPResponseStatus), + ('response_bytes', ResponseBytes, {'explicit': 0, 'optional': True}), + ] + + _processed_extensions = False + _critical_extensions = None + _nonce_value = None + _extended_revoke_value = None + + def _set_extensions(self): + """ + Sets common named extensions to private attributes and creates a list + of critical extensions + """ + + self._critical_extensions = set() + + for extension in self['response_bytes']['response'].parsed['tbs_response_data']['response_extensions']: + name = extension['extn_id'].native + attribute_name = '_%s_value' % name + if hasattr(self, attribute_name): + setattr(self, attribute_name, extension['extn_value'].parsed) + if extension['critical'].native: + self._critical_extensions.add(name) + + self._processed_extensions = True + + @property + def critical_extensions(self): + """ + Returns a set of the names (or OID if not a known extension) of the + extensions marked as critical + + :return: + A set of unicode strings + """ + + if not self._processed_extensions: + self._set_extensions() + return self._critical_extensions + + @property + def nonce_value(self): + """ + This extension is used to prevent replay attacks on the request/response + exchange + + :return: + None or an OctetString object + """ + + if self._processed_extensions is False: + self._set_extensions() + return self._nonce_value + + @property + def extended_revoke_value(self): + """ + This extension is used to signal that the responder will return a + "revoked" status for non-issued certificates. + + :return: + None or a Null object (if present) + """ + + if self._processed_extensions is False: + self._set_extensions() + return self._extended_revoke_value + + @property + def basic_ocsp_response(self): + """ + A shortcut into the BasicOCSPResponse sequence + + :return: + None or an asn1crypto.ocsp.BasicOCSPResponse object + """ + + return self['response_bytes']['response'].parsed + + @property + def response_data(self): + """ + A shortcut into the parsed, ResponseData sequence + + :return: + None or an asn1crypto.ocsp.ResponseData object + """ + + return self['response_bytes']['response'].parsed['tbs_response_data'] diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/asn1crypto/parser.py b/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/asn1crypto/parser.py new file mode 100644 index 00000000..2f5a63e1 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/asn1crypto/parser.py @@ -0,0 +1,292 @@ +# coding: utf-8 + +""" +Functions for parsing and dumping using the ASN.1 DER encoding. Exports the +following items: + + - emit() + - parse() + - peek() + +Other type classes are defined that help compose the types listed above. +""" + +from __future__ import unicode_literals, division, absolute_import, print_function + +import sys + +from ._types import byte_cls, chr_cls, type_name +from .util import int_from_bytes, int_to_bytes + +_PY2 = sys.version_info <= (3,) +_INSUFFICIENT_DATA_MESSAGE = 'Insufficient data - %s bytes requested but only %s available' +_MAX_DEPTH = 10 + + +def emit(class_, method, tag, contents): + """ + Constructs a byte string of an ASN.1 DER-encoded value + + This is typically not useful. Instead, use one of the standard classes from + asn1crypto.core, or construct a new class with specific fields, and call the + .dump() method. + + :param class_: + An integer ASN.1 class value: 0 (universal), 1 (application), + 2 (context), 3 (private) + + :param method: + An integer ASN.1 method value: 0 (primitive), 1 (constructed) + + :param tag: + An integer ASN.1 tag value + + :param contents: + A byte string of the encoded byte contents + + :return: + A byte string of the ASN.1 DER value (header and contents) + """ + + if not isinstance(class_, int): + raise TypeError('class_ must be an integer, not %s' % type_name(class_)) + + if class_ < 0 or class_ > 3: + raise ValueError('class_ must be one of 0, 1, 2 or 3, not %s' % class_) + + if not isinstance(method, int): + raise TypeError('method must be an integer, not %s' % type_name(method)) + + if method < 0 or method > 1: + raise ValueError('method must be 0 or 1, not %s' % method) + + if not isinstance(tag, int): + raise TypeError('tag must be an integer, not %s' % type_name(tag)) + + if tag < 0: + raise ValueError('tag must be greater than zero, not %s' % tag) + + if not isinstance(contents, byte_cls): + raise TypeError('contents must be a byte string, not %s' % type_name(contents)) + + return _dump_header(class_, method, tag, contents) + contents + + +def parse(contents, strict=False): + """ + Parses a byte string of ASN.1 BER/DER-encoded data. + + This is typically not useful. Instead, use one of the standard classes from + asn1crypto.core, or construct a new class with specific fields, and call the + .load() class method. + + :param contents: + A byte string of BER/DER-encoded data + + :param strict: + A boolean indicating if trailing data should be forbidden - if so, a + ValueError will be raised when trailing data exists + + :raises: + ValueError - when the contents do not contain an ASN.1 header or are truncated in some way + TypeError - when contents is not a byte string + + :return: + A 6-element tuple: + - 0: integer class (0 to 3) + - 1: integer method + - 2: integer tag + - 3: byte string header + - 4: byte string content + - 5: byte string trailer + """ + + if not isinstance(contents, byte_cls): + raise TypeError('contents must be a byte string, not %s' % type_name(contents)) + + contents_len = len(contents) + info, consumed = _parse(contents, contents_len) + if strict and consumed != contents_len: + raise ValueError('Extra data - %d bytes of trailing data were provided' % (contents_len - consumed)) + return info + + +def peek(contents): + """ + Parses a byte string of ASN.1 BER/DER-encoded data to find the length + + This is typically used to look into an encoded value to see how long the + next chunk of ASN.1-encoded data is. Primarily it is useful when a + value is a concatenation of multiple values. + + :param contents: + A byte string of BER/DER-encoded data + + :raises: + ValueError - when the contents do not contain an ASN.1 header or are truncated in some way + TypeError - when contents is not a byte string + + :return: + An integer with the number of bytes occupied by the ASN.1 value + """ + + if not isinstance(contents, byte_cls): + raise TypeError('contents must be a byte string, not %s' % type_name(contents)) + + info, consumed = _parse(contents, len(contents)) + return consumed + + +def _parse(encoded_data, data_len, pointer=0, lengths_only=False, depth=0): + """ + Parses a byte string into component parts + + :param encoded_data: + A byte string that contains BER-encoded data + + :param data_len: + The integer length of the encoded data + + :param pointer: + The index in the byte string to parse from + + :param lengths_only: + A boolean to cause the call to return a 2-element tuple of the integer + number of bytes in the header and the integer number of bytes in the + contents. Internal use only. + + :param depth: + The recursion depth when evaluating indefinite-length encoding. + + :return: + A 2-element tuple: + - 0: A tuple of (class_, method, tag, header, content, trailer) + - 1: An integer indicating how many bytes were consumed + """ + + if depth > _MAX_DEPTH: + raise ValueError('Indefinite-length recursion limit exceeded') + + start = pointer + + if data_len < pointer + 1: + raise ValueError(_INSUFFICIENT_DATA_MESSAGE % (1, data_len - pointer)) + first_octet = ord(encoded_data[pointer]) if _PY2 else encoded_data[pointer] + + pointer += 1 + + tag = first_octet & 31 + constructed = (first_octet >> 5) & 1 + # Base 128 length using 8th bit as continuation indicator + if tag == 31: + tag = 0 + while True: + if data_len < pointer + 1: + raise ValueError(_INSUFFICIENT_DATA_MESSAGE % (1, data_len - pointer)) + num = ord(encoded_data[pointer]) if _PY2 else encoded_data[pointer] + pointer += 1 + if num == 0x80 and tag == 0: + raise ValueError('Non-minimal tag encoding') + tag *= 128 + tag += num & 127 + if num >> 7 == 0: + break + if tag < 31: + raise ValueError('Non-minimal tag encoding') + + if data_len < pointer + 1: + raise ValueError(_INSUFFICIENT_DATA_MESSAGE % (1, data_len - pointer)) + length_octet = ord(encoded_data[pointer]) if _PY2 else encoded_data[pointer] + pointer += 1 + trailer = b'' + + if length_octet >> 7 == 0: + contents_end = pointer + (length_octet & 127) + + else: + length_octets = length_octet & 127 + if length_octets: + if data_len < pointer + length_octets: + raise ValueError(_INSUFFICIENT_DATA_MESSAGE % (length_octets, data_len - pointer)) + pointer += length_octets + contents_end = pointer + int_from_bytes(encoded_data[pointer - length_octets:pointer], signed=False) + + else: + # To properly parse indefinite length values, we need to scan forward + # parsing headers until we find a value with a length of zero. If we + # just scanned looking for \x00\x00, nested indefinite length values + # would not work. + if not constructed: + raise ValueError('Indefinite-length element must be constructed') + contents_end = pointer + while data_len < contents_end + 2 or encoded_data[contents_end:contents_end+2] != b'\x00\x00': + _, contents_end = _parse(encoded_data, data_len, contents_end, lengths_only=True, depth=depth+1) + contents_end += 2 + trailer = b'\x00\x00' + + if contents_end > data_len: + raise ValueError(_INSUFFICIENT_DATA_MESSAGE % (contents_end - pointer, data_len - pointer)) + + if lengths_only: + return (pointer, contents_end) + + return ( + ( + first_octet >> 6, + constructed, + tag, + encoded_data[start:pointer], + encoded_data[pointer:contents_end-len(trailer)], + trailer + ), + contents_end + ) + + +def _dump_header(class_, method, tag, contents): + """ + Constructs the header bytes for an ASN.1 object + + :param class_: + An integer ASN.1 class value: 0 (universal), 1 (application), + 2 (context), 3 (private) + + :param method: + An integer ASN.1 method value: 0 (primitive), 1 (constructed) + + :param tag: + An integer ASN.1 tag value + + :param contents: + A byte string of the encoded byte contents + + :return: + A byte string of the ASN.1 DER header + """ + + header = b'' + + id_num = 0 + id_num |= class_ << 6 + id_num |= method << 5 + + if tag >= 31: + cont_bit = 0 + while tag > 0: + header = chr_cls(cont_bit | (tag & 0x7f)) + header + if not cont_bit: + cont_bit = 0x80 + tag = tag >> 7 + header = chr_cls(id_num | 31) + header + else: + header += chr_cls(id_num | tag) + + length = len(contents) + if length <= 127: + header += chr_cls(length) + else: + length_bytes = int_to_bytes(length) + header += chr_cls(0x80 | len(length_bytes)) + header += length_bytes + + return header diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/asn1crypto/pdf.py b/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/asn1crypto/pdf.py new file mode 100644 index 00000000..b72c886c --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/asn1crypto/pdf.py @@ -0,0 +1,84 @@ +# coding: utf-8 + +""" +ASN.1 type classes for PDF signature structures. Adds extra oid mapping and +value parsing to asn1crypto.x509.Extension() and asn1crypto.xms.CMSAttribute(). +""" + +from __future__ import unicode_literals, division, absolute_import, print_function + +from .cms import CMSAttributeType, CMSAttribute +from .core import ( + Boolean, + Integer, + Null, + ObjectIdentifier, + OctetString, + Sequence, + SequenceOf, + SetOf, +) +from .crl import CertificateList +from .ocsp import OCSPResponse +from .x509 import ( + Extension, + ExtensionId, + GeneralName, + KeyPurposeId, +) + + +class AdobeArchiveRevInfo(Sequence): + _fields = [ + ('version', Integer) + ] + + +class AdobeTimestamp(Sequence): + _fields = [ + ('version', Integer), + ('location', GeneralName), + ('requires_auth', Boolean, {'optional': True, 'default': False}), + ] + + +class OtherRevInfo(Sequence): + _fields = [ + ('type', ObjectIdentifier), + ('value', OctetString), + ] + + +class SequenceOfCertificateList(SequenceOf): + _child_spec = CertificateList + + +class SequenceOfOCSPResponse(SequenceOf): + _child_spec = OCSPResponse + + +class SequenceOfOtherRevInfo(SequenceOf): + _child_spec = OtherRevInfo + + +class RevocationInfoArchival(Sequence): + _fields = [ + ('crl', SequenceOfCertificateList, {'explicit': 0, 'optional': True}), + ('ocsp', SequenceOfOCSPResponse, {'explicit': 1, 'optional': True}), + ('other_rev_info', SequenceOfOtherRevInfo, {'explicit': 2, 'optional': True}), + ] + + +class SetOfRevocationInfoArchival(SetOf): + _child_spec = RevocationInfoArchival + + +ExtensionId._map['1.2.840.113583.1.1.9.2'] = 'adobe_archive_rev_info' +ExtensionId._map['1.2.840.113583.1.1.9.1'] = 'adobe_timestamp' +ExtensionId._map['1.2.840.113583.1.1.10'] = 'adobe_ppklite_credential' +Extension._oid_specs['adobe_archive_rev_info'] = AdobeArchiveRevInfo +Extension._oid_specs['adobe_timestamp'] = AdobeTimestamp +Extension._oid_specs['adobe_ppklite_credential'] = Null +KeyPurposeId._map['1.2.840.113583.1.1.5'] = 'pdf_signing' +CMSAttributeType._map['1.2.840.113583.1.1.8'] = 'adobe_revocation_info_archival' +CMSAttribute._oid_specs['adobe_revocation_info_archival'] = SetOfRevocationInfoArchival diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/asn1crypto/pem.py b/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/asn1crypto/pem.py new file mode 100644 index 00000000..511ea4b5 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/asn1crypto/pem.py @@ -0,0 +1,222 @@ +# coding: utf-8 + +""" +Encoding DER to PEM and decoding PEM to DER. Exports the following items: + + - armor() + - detect() + - unarmor() + +""" + +from __future__ import unicode_literals, division, absolute_import, print_function + +import base64 +import re +import sys + +from ._errors import unwrap +from ._types import type_name as _type_name, str_cls, byte_cls + +if sys.version_info < (3,): + from cStringIO import StringIO as BytesIO +else: + from io import BytesIO + + +def detect(byte_string): + """ + Detect if a byte string seems to contain a PEM-encoded block + + :param byte_string: + A byte string to look through + + :return: + A boolean, indicating if a PEM-encoded block is contained in the byte + string + """ + + if not isinstance(byte_string, byte_cls): + raise TypeError(unwrap( + ''' + byte_string must be a byte string, not %s + ''', + _type_name(byte_string) + )) + + return byte_string.find(b'-----BEGIN') != -1 or byte_string.find(b'---- BEGIN') != -1 + + +def armor(type_name, der_bytes, headers=None): + """ + Armors a DER-encoded byte string in PEM + + :param type_name: + A unicode string that will be capitalized and placed in the header + and footer of the block. E.g. "CERTIFICATE", "PRIVATE KEY", etc. This + will appear as "-----BEGIN CERTIFICATE-----" and + "-----END CERTIFICATE-----". + + :param der_bytes: + A byte string to be armored + + :param headers: + An OrderedDict of the header lines to write after the BEGIN line + + :return: + A byte string of the PEM block + """ + + if not isinstance(der_bytes, byte_cls): + raise TypeError(unwrap( + ''' + der_bytes must be a byte string, not %s + ''' % _type_name(der_bytes) + )) + + if not isinstance(type_name, str_cls): + raise TypeError(unwrap( + ''' + type_name must be a unicode string, not %s + ''', + _type_name(type_name) + )) + + type_name = type_name.upper().encode('ascii') + + output = BytesIO() + output.write(b'-----BEGIN ') + output.write(type_name) + output.write(b'-----\n') + if headers: + for key in headers: + output.write(key.encode('ascii')) + output.write(b': ') + output.write(headers[key].encode('ascii')) + output.write(b'\n') + output.write(b'\n') + b64_bytes = base64.b64encode(der_bytes) + b64_len = len(b64_bytes) + i = 0 + while i < b64_len: + output.write(b64_bytes[i:i + 64]) + output.write(b'\n') + i += 64 + output.write(b'-----END ') + output.write(type_name) + output.write(b'-----\n') + + return output.getvalue() + + +def _unarmor(pem_bytes): + """ + Convert a PEM-encoded byte string into one or more DER-encoded byte strings + + :param pem_bytes: + A byte string of the PEM-encoded data + + :raises: + ValueError - when the pem_bytes do not appear to be PEM-encoded bytes + + :return: + A generator of 3-element tuples in the format: (object_type, headers, + der_bytes). The object_type is a unicode string of what is between + "-----BEGIN " and "-----". Examples include: "CERTIFICATE", + "PUBLIC KEY", "PRIVATE KEY". The headers is a dict containing any lines + in the form "Name: Value" that are right after the begin line. + """ + + if not isinstance(pem_bytes, byte_cls): + raise TypeError(unwrap( + ''' + pem_bytes must be a byte string, not %s + ''', + _type_name(pem_bytes) + )) + + # Valid states include: "trash", "headers", "body" + state = 'trash' + headers = {} + base64_data = b'' + object_type = None + + found_start = False + found_end = False + + for line in pem_bytes.splitlines(False): + if line == b'': + continue + + if state == "trash": + # Look for a starting line since some CA cert bundle show the cert + # into in a parsed format above each PEM block + type_name_match = re.match(b'^(?:---- |-----)BEGIN ([A-Z0-9 ]+)(?: ----|-----)', line) + if not type_name_match: + continue + object_type = type_name_match.group(1).decode('ascii') + + found_start = True + state = 'headers' + continue + + if state == 'headers': + if line.find(b':') == -1: + state = 'body' + else: + decoded_line = line.decode('ascii') + name, value = decoded_line.split(':', 1) + headers[name] = value.strip() + continue + + if state == 'body': + if line[0:5] in (b'-----', b'---- '): + der_bytes = base64.b64decode(base64_data) + + yield (object_type, headers, der_bytes) + + state = 'trash' + headers = {} + base64_data = b'' + object_type = None + found_end = True + continue + + base64_data += line + + if not found_start or not found_end: + raise ValueError(unwrap( + ''' + pem_bytes does not appear to contain PEM-encoded data - no + BEGIN/END combination found + ''' + )) + + +def unarmor(pem_bytes, multiple=False): + """ + Convert a PEM-encoded byte string into a DER-encoded byte string + + :param pem_bytes: + A byte string of the PEM-encoded data + + :param multiple: + If True, function will return a generator + + :raises: + ValueError - when the pem_bytes do not appear to be PEM-encoded bytes + + :return: + A 3-element tuple (object_name, headers, der_bytes). The object_name is + a unicode string of what is between "-----BEGIN " and "-----". Examples + include: "CERTIFICATE", "PUBLIC KEY", "PRIVATE KEY". The headers is a + dict containing any lines in the form "Name: Value" that are right + after the begin line. + """ + + generator = _unarmor(pem_bytes) + + if not multiple: + return next(generator) + + return generator diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/asn1crypto/pkcs12.py b/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/asn1crypto/pkcs12.py new file mode 100644 index 00000000..7ebcefeb --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/asn1crypto/pkcs12.py @@ -0,0 +1,193 @@ +# coding: utf-8 + +""" +ASN.1 type classes for PKCS#12 files. Exports the following items: + + - CertBag() + - CrlBag() + - Pfx() + - SafeBag() + - SecretBag() + +Other type classes are defined that help compose the types listed above. +""" + +from __future__ import unicode_literals, division, absolute_import, print_function + +from .algos import DigestInfo +from .cms import ContentInfo, SignedData +from .core import ( + Any, + BMPString, + Integer, + ObjectIdentifier, + OctetString, + ParsableOctetString, + Sequence, + SequenceOf, + SetOf, +) +from .keys import PrivateKeyInfo, EncryptedPrivateKeyInfo +from .x509 import Certificate, KeyPurposeId + + +# The structures in this file are taken from https://tools.ietf.org/html/rfc7292 + +class MacData(Sequence): + _fields = [ + ('mac', DigestInfo), + ('mac_salt', OctetString), + ('iterations', Integer, {'default': 1}), + ] + + +class Version(Integer): + _map = { + 3: 'v3' + } + + +class AttributeType(ObjectIdentifier): + _map = { + # https://tools.ietf.org/html/rfc2985#page-18 + '1.2.840.113549.1.9.20': 'friendly_name', + '1.2.840.113549.1.9.21': 'local_key_id', + # https://support.microsoft.com/en-us/kb/287547 + '1.3.6.1.4.1.311.17.1': 'microsoft_local_machine_keyset', + # https://github.com/frohoff/jdk8u-dev-jdk/blob/master/src/share/classes/sun/security/pkcs12/PKCS12KeyStore.java + # this is a set of OIDs, representing key usage, the usual value is a SET of one element OID 2.5.29.37.0 + '2.16.840.1.113894.746875.1.1': 'trusted_key_usage', + } + + +class SetOfAny(SetOf): + _child_spec = Any + + +class SetOfBMPString(SetOf): + _child_spec = BMPString + + +class SetOfOctetString(SetOf): + _child_spec = OctetString + + +class SetOfKeyPurposeId(SetOf): + _child_spec = KeyPurposeId + + +class Attribute(Sequence): + _fields = [ + ('type', AttributeType), + ('values', None), + ] + + _oid_specs = { + 'friendly_name': SetOfBMPString, + 'local_key_id': SetOfOctetString, + 'microsoft_csp_name': SetOfBMPString, + 'trusted_key_usage': SetOfKeyPurposeId, + } + + def _values_spec(self): + return self._oid_specs.get(self['type'].native, SetOfAny) + + _spec_callbacks = { + 'values': _values_spec + } + + +class Attributes(SetOf): + _child_spec = Attribute + + +class Pfx(Sequence): + _fields = [ + ('version', Version), + ('auth_safe', ContentInfo), + ('mac_data', MacData, {'optional': True}) + ] + + _authenticated_safe = None + + @property + def authenticated_safe(self): + if self._authenticated_safe is None: + content = self['auth_safe']['content'] + if isinstance(content, SignedData): + content = content['content_info']['content'] + self._authenticated_safe = AuthenticatedSafe.load(content.native) + return self._authenticated_safe + + +class AuthenticatedSafe(SequenceOf): + _child_spec = ContentInfo + + +class BagId(ObjectIdentifier): + _map = { + '1.2.840.113549.1.12.10.1.1': 'key_bag', + '1.2.840.113549.1.12.10.1.2': 'pkcs8_shrouded_key_bag', + '1.2.840.113549.1.12.10.1.3': 'cert_bag', + '1.2.840.113549.1.12.10.1.4': 'crl_bag', + '1.2.840.113549.1.12.10.1.5': 'secret_bag', + '1.2.840.113549.1.12.10.1.6': 'safe_contents', + } + + +class CertId(ObjectIdentifier): + _map = { + '1.2.840.113549.1.9.22.1': 'x509', + '1.2.840.113549.1.9.22.2': 'sdsi', + } + + +class CertBag(Sequence): + _fields = [ + ('cert_id', CertId), + ('cert_value', ParsableOctetString, {'explicit': 0}), + ] + + _oid_pair = ('cert_id', 'cert_value') + _oid_specs = { + 'x509': Certificate, + } + + +class CrlBag(Sequence): + _fields = [ + ('crl_id', ObjectIdentifier), + ('crl_value', OctetString, {'explicit': 0}), + ] + + +class SecretBag(Sequence): + _fields = [ + ('secret_type_id', ObjectIdentifier), + ('secret_value', OctetString, {'explicit': 0}), + ] + + +class SafeContents(SequenceOf): + pass + + +class SafeBag(Sequence): + _fields = [ + ('bag_id', BagId), + ('bag_value', Any, {'explicit': 0}), + ('bag_attributes', Attributes, {'optional': True}), + ] + + _oid_pair = ('bag_id', 'bag_value') + _oid_specs = { + 'key_bag': PrivateKeyInfo, + 'pkcs8_shrouded_key_bag': EncryptedPrivateKeyInfo, + 'cert_bag': CertBag, + 'crl_bag': CrlBag, + 'secret_bag': SecretBag, + 'safe_contents': SafeContents + } + + +SafeContents._child_spec = SafeBag diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/asn1crypto/tsp.py b/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/asn1crypto/tsp.py new file mode 100644 index 00000000..f006da99 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/asn1crypto/tsp.py @@ -0,0 +1,310 @@ +# coding: utf-8 + +""" +ASN.1 type classes for the time stamp protocol (TSP). Exports the following +items: + + - TimeStampReq() + - TimeStampResp() + +Also adds TimeStampedData() support to asn1crypto.cms.ContentInfo(), +TimeStampedData() and TSTInfo() support to +asn1crypto.cms.EncapsulatedContentInfo() and some oids and value parsers to +asn1crypto.cms.CMSAttribute(). + +Other type classes are defined that help compose the types listed above. +""" + +from __future__ import unicode_literals, division, absolute_import, print_function + +from .algos import DigestAlgorithm +from .cms import ( + CMSAttribute, + CMSAttributeType, + ContentInfo, + ContentType, + EncapsulatedContentInfo, +) +from .core import ( + Any, + BitString, + Boolean, + Choice, + GeneralizedTime, + IA5String, + Integer, + ObjectIdentifier, + OctetString, + Sequence, + SequenceOf, + SetOf, + UTF8String, +) +from .crl import CertificateList +from .x509 import ( + Attributes, + CertificatePolicies, + GeneralName, + GeneralNames, +) + + +# The structures in this file are based on https://tools.ietf.org/html/rfc3161, +# https://tools.ietf.org/html/rfc4998, https://tools.ietf.org/html/rfc5544, +# https://tools.ietf.org/html/rfc5035, https://tools.ietf.org/html/rfc2634 + +class Version(Integer): + _map = { + 0: 'v0', + 1: 'v1', + 2: 'v2', + 3: 'v3', + 4: 'v4', + 5: 'v5', + } + + +class MessageImprint(Sequence): + _fields = [ + ('hash_algorithm', DigestAlgorithm), + ('hashed_message', OctetString), + ] + + +class Accuracy(Sequence): + _fields = [ + ('seconds', Integer, {'optional': True}), + ('millis', Integer, {'implicit': 0, 'optional': True}), + ('micros', Integer, {'implicit': 1, 'optional': True}), + ] + + +class Extension(Sequence): + _fields = [ + ('extn_id', ObjectIdentifier), + ('critical', Boolean, {'default': False}), + ('extn_value', OctetString), + ] + + +class Extensions(SequenceOf): + _child_spec = Extension + + +class TSTInfo(Sequence): + _fields = [ + ('version', Version), + ('policy', ObjectIdentifier), + ('message_imprint', MessageImprint), + ('serial_number', Integer), + ('gen_time', GeneralizedTime), + ('accuracy', Accuracy, {'optional': True}), + ('ordering', Boolean, {'default': False}), + ('nonce', Integer, {'optional': True}), + ('tsa', GeneralName, {'explicit': 0, 'optional': True}), + ('extensions', Extensions, {'implicit': 1, 'optional': True}), + ] + + +class TimeStampReq(Sequence): + _fields = [ + ('version', Version), + ('message_imprint', MessageImprint), + ('req_policy', ObjectIdentifier, {'optional': True}), + ('nonce', Integer, {'optional': True}), + ('cert_req', Boolean, {'default': False}), + ('extensions', Extensions, {'implicit': 0, 'optional': True}), + ] + + +class PKIStatus(Integer): + _map = { + 0: 'granted', + 1: 'granted_with_mods', + 2: 'rejection', + 3: 'waiting', + 4: 'revocation_warning', + 5: 'revocation_notification', + } + + +class PKIFreeText(SequenceOf): + _child_spec = UTF8String + + +class PKIFailureInfo(BitString): + _map = { + 0: 'bad_alg', + 2: 'bad_request', + 5: 'bad_data_format', + 14: 'time_not_available', + 15: 'unaccepted_policy', + 16: 'unaccepted_extensions', + 17: 'add_info_not_available', + 25: 'system_failure', + } + + +class PKIStatusInfo(Sequence): + _fields = [ + ('status', PKIStatus), + ('status_string', PKIFreeText, {'optional': True}), + ('fail_info', PKIFailureInfo, {'optional': True}), + ] + + +class TimeStampResp(Sequence): + _fields = [ + ('status', PKIStatusInfo), + ('time_stamp_token', ContentInfo), + ] + + +class MetaData(Sequence): + _fields = [ + ('hash_protected', Boolean), + ('file_name', UTF8String, {'optional': True}), + ('media_type', IA5String, {'optional': True}), + ('other_meta_data', Attributes, {'optional': True}), + ] + + +class TimeStampAndCRL(Sequence): + _fields = [ + ('time_stamp', EncapsulatedContentInfo), + ('crl', CertificateList, {'optional': True}), + ] + + +class TimeStampTokenEvidence(SequenceOf): + _child_spec = TimeStampAndCRL + + +class DigestAlgorithms(SequenceOf): + _child_spec = DigestAlgorithm + + +class EncryptionInfo(Sequence): + _fields = [ + ('encryption_info_type', ObjectIdentifier), + ('encryption_info_value', Any), + ] + + +class PartialHashtree(SequenceOf): + _child_spec = OctetString + + +class PartialHashtrees(SequenceOf): + _child_spec = PartialHashtree + + +class ArchiveTimeStamp(Sequence): + _fields = [ + ('digest_algorithm', DigestAlgorithm, {'implicit': 0, 'optional': True}), + ('attributes', Attributes, {'implicit': 1, 'optional': True}), + ('reduced_hashtree', PartialHashtrees, {'implicit': 2, 'optional': True}), + ('time_stamp', ContentInfo), + ] + + +class ArchiveTimeStampSequence(SequenceOf): + _child_spec = ArchiveTimeStamp + + +class EvidenceRecord(Sequence): + _fields = [ + ('version', Version), + ('digest_algorithms', DigestAlgorithms), + ('crypto_infos', Attributes, {'implicit': 0, 'optional': True}), + ('encryption_info', EncryptionInfo, {'implicit': 1, 'optional': True}), + ('archive_time_stamp_sequence', ArchiveTimeStampSequence), + ] + + +class OtherEvidence(Sequence): + _fields = [ + ('oe_type', ObjectIdentifier), + ('oe_value', Any), + ] + + +class Evidence(Choice): + _alternatives = [ + ('tst_evidence', TimeStampTokenEvidence, {'implicit': 0}), + ('ers_evidence', EvidenceRecord, {'implicit': 1}), + ('other_evidence', OtherEvidence, {'implicit': 2}), + ] + + +class TimeStampedData(Sequence): + _fields = [ + ('version', Version), + ('data_uri', IA5String, {'optional': True}), + ('meta_data', MetaData, {'optional': True}), + ('content', OctetString, {'optional': True}), + ('temporal_evidence', Evidence), + ] + + +class IssuerSerial(Sequence): + _fields = [ + ('issuer', GeneralNames), + ('serial_number', Integer), + ] + + +class ESSCertID(Sequence): + _fields = [ + ('cert_hash', OctetString), + ('issuer_serial', IssuerSerial, {'optional': True}), + ] + + +class ESSCertIDs(SequenceOf): + _child_spec = ESSCertID + + +class SigningCertificate(Sequence): + _fields = [ + ('certs', ESSCertIDs), + ('policies', CertificatePolicies, {'optional': True}), + ] + + +class SetOfSigningCertificates(SetOf): + _child_spec = SigningCertificate + + +class ESSCertIDv2(Sequence): + _fields = [ + ('hash_algorithm', DigestAlgorithm, {'default': {'algorithm': 'sha256'}}), + ('cert_hash', OctetString), + ('issuer_serial', IssuerSerial, {'optional': True}), + ] + + +class ESSCertIDv2s(SequenceOf): + _child_spec = ESSCertIDv2 + + +class SigningCertificateV2(Sequence): + _fields = [ + ('certs', ESSCertIDv2s), + ('policies', CertificatePolicies, {'optional': True}), + ] + + +class SetOfSigningCertificatesV2(SetOf): + _child_spec = SigningCertificateV2 + + +EncapsulatedContentInfo._oid_specs['tst_info'] = TSTInfo +EncapsulatedContentInfo._oid_specs['timestamped_data'] = TimeStampedData +ContentInfo._oid_specs['timestamped_data'] = TimeStampedData +ContentType._map['1.2.840.113549.1.9.16.1.4'] = 'tst_info' +ContentType._map['1.2.840.113549.1.9.16.1.31'] = 'timestamped_data' +CMSAttributeType._map['1.2.840.113549.1.9.16.2.12'] = 'signing_certificate' +CMSAttribute._oid_specs['signing_certificate'] = SetOfSigningCertificates +CMSAttributeType._map['1.2.840.113549.1.9.16.2.47'] = 'signing_certificate_v2' +CMSAttribute._oid_specs['signing_certificate_v2'] = SetOfSigningCertificatesV2 diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/asn1crypto/util.py b/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/asn1crypto/util.py new file mode 100644 index 00000000..7196897c --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/asn1crypto/util.py @@ -0,0 +1,878 @@ +# coding: utf-8 + +""" +Miscellaneous data helpers, including functions for converting integers to and +from bytes and UTC timezone. Exports the following items: + + - OrderedDict() + - int_from_bytes() + - int_to_bytes() + - timezone.utc + - utc_with_dst + - create_timezone() + - inet_ntop() + - inet_pton() + - uri_to_iri() + - iri_to_uri() +""" + +from __future__ import unicode_literals, division, absolute_import, print_function + +import math +import sys +from datetime import datetime, date, timedelta, tzinfo + +from ._errors import unwrap +from ._iri import iri_to_uri, uri_to_iri # noqa +from ._ordereddict import OrderedDict # noqa +from ._types import type_name + +if sys.platform == 'win32': + from ._inet import inet_ntop, inet_pton +else: + from socket import inet_ntop, inet_pton # noqa + + +# Python 2 +if sys.version_info <= (3,): + + def int_to_bytes(value, signed=False, width=None): + """ + Converts an integer to a byte string + + :param value: + The integer to convert + + :param signed: + If the byte string should be encoded using two's complement + + :param width: + If None, the minimal possible size (but at least 1), + otherwise an integer of the byte width for the return value + + :return: + A byte string + """ + + if value == 0 and width == 0: + return b'' + + # Handle negatives in two's complement + is_neg = False + if signed and value < 0: + is_neg = True + bits = int(math.ceil(len('%x' % abs(value)) / 2.0) * 8) + value = (value + (1 << bits)) % (1 << bits) + + hex_str = '%x' % value + if len(hex_str) & 1: + hex_str = '0' + hex_str + + output = hex_str.decode('hex') + + if signed and not is_neg and ord(output[0:1]) & 0x80: + output = b'\x00' + output + + if width is not None: + if len(output) > width: + raise OverflowError('int too big to convert') + if is_neg: + pad_char = b'\xFF' + else: + pad_char = b'\x00' + output = (pad_char * (width - len(output))) + output + elif is_neg and ord(output[0:1]) & 0x80 == 0: + output = b'\xFF' + output + + return output + + def int_from_bytes(value, signed=False): + """ + Converts a byte string to an integer + + :param value: + The byte string to convert + + :param signed: + If the byte string should be interpreted using two's complement + + :return: + An integer + """ + + if value == b'': + return 0 + + num = long(value.encode("hex"), 16) # noqa + + if not signed: + return num + + # Check for sign bit and handle two's complement + if ord(value[0:1]) & 0x80: + bit_len = len(value) * 8 + return num - (1 << bit_len) + + return num + + class timezone(tzinfo): # noqa + """ + Implements datetime.timezone for py2. + Only full minute offsets are supported. + DST is not supported. + """ + + def __init__(self, offset, name=None): + """ + :param offset: + A timedelta with this timezone's offset from UTC + + :param name: + Name of the timezone; if None, generate one. + """ + + if not timedelta(hours=-24) < offset < timedelta(hours=24): + raise ValueError('Offset must be in [-23:59, 23:59]') + + if offset.seconds % 60 or offset.microseconds: + raise ValueError('Offset must be full minutes') + + self._offset = offset + + if name is not None: + self._name = name + elif not offset: + self._name = 'UTC' + else: + self._name = 'UTC' + _format_offset(offset) + + def __eq__(self, other): + """ + Compare two timezones + + :param other: + The other timezone to compare to + + :return: + A boolean + """ + + if type(other) != timezone: + return False + return self._offset == other._offset + + def __getinitargs__(self): + """ + Called by tzinfo.__reduce__ to support pickle and copy. + + :return: + offset and name, to be used for __init__ + """ + + return self._offset, self._name + + def tzname(self, dt): + """ + :param dt: + A datetime object; ignored. + + :return: + Name of this timezone + """ + + return self._name + + def utcoffset(self, dt): + """ + :param dt: + A datetime object; ignored. + + :return: + A timedelta object with the offset from UTC + """ + + return self._offset + + def dst(self, dt): + """ + :param dt: + A datetime object; ignored. + + :return: + Zero timedelta + """ + + return timedelta(0) + + timezone.utc = timezone(timedelta(0)) + +# Python 3 +else: + + from datetime import timezone # noqa + + def int_to_bytes(value, signed=False, width=None): + """ + Converts an integer to a byte string + + :param value: + The integer to convert + + :param signed: + If the byte string should be encoded using two's complement + + :param width: + If None, the minimal possible size (but at least 1), + otherwise an integer of the byte width for the return value + + :return: + A byte string + """ + + if width is None: + if signed: + if value < 0: + bits_required = abs(value + 1).bit_length() + else: + bits_required = value.bit_length() + if bits_required % 8 == 0: + bits_required += 1 + else: + bits_required = value.bit_length() + width = math.ceil(bits_required / 8) or 1 + return value.to_bytes(width, byteorder='big', signed=signed) + + def int_from_bytes(value, signed=False): + """ + Converts a byte string to an integer + + :param value: + The byte string to convert + + :param signed: + If the byte string should be interpreted using two's complement + + :return: + An integer + """ + + return int.from_bytes(value, 'big', signed=signed) + + +def _format_offset(off): + """ + Format a timedelta into "[+-]HH:MM" format or "" for None + """ + + if off is None: + return '' + mins = off.days * 24 * 60 + off.seconds // 60 + sign = '-' if mins < 0 else '+' + return sign + '%02d:%02d' % divmod(abs(mins), 60) + + +class _UtcWithDst(tzinfo): + """ + Utc class where dst does not return None; required for astimezone + """ + + def tzname(self, dt): + return 'UTC' + + def utcoffset(self, dt): + return timedelta(0) + + def dst(self, dt): + return timedelta(0) + + +utc_with_dst = _UtcWithDst() + +_timezone_cache = {} + + +def create_timezone(offset): + """ + Returns a new datetime.timezone object with the given offset. + Uses cached objects if possible. + + :param offset: + A datetime.timedelta object; It needs to be in full minutes and between -23:59 and +23:59. + + :return: + A datetime.timezone object + """ + + try: + tz = _timezone_cache[offset] + except KeyError: + tz = _timezone_cache[offset] = timezone(offset) + return tz + + +class extended_date(object): + """ + A datetime.datetime-like object that represents the year 0. This is just + to handle 0000-01-01 found in some certificates. Python's datetime does + not support year 0. + + The proleptic gregorian calendar repeats itself every 400 years. Therefore, + the simplest way to format is to substitute year 2000. + """ + + def __init__(self, year, month, day): + """ + :param year: + The integer 0 + + :param month: + An integer from 1 to 12 + + :param day: + An integer from 1 to 31 + """ + + if year != 0: + raise ValueError('year must be 0') + + self._y2k = date(2000, month, day) + + @property + def year(self): + """ + :return: + The integer 0 + """ + + return 0 + + @property + def month(self): + """ + :return: + An integer from 1 to 12 + """ + + return self._y2k.month + + @property + def day(self): + """ + :return: + An integer from 1 to 31 + """ + + return self._y2k.day + + def strftime(self, format): + """ + Formats the date using strftime() + + :param format: + A strftime() format string + + :return: + A str, the formatted date as a unicode string + in Python 3 and a byte string in Python 2 + """ + + # Format the date twice, once with year 2000, once with year 4000. + # The only differences in the result will be in the millennium. Find them and replace by zeros. + y2k = self._y2k.strftime(format) + y4k = self._y2k.replace(year=4000).strftime(format) + return ''.join('0' if (c2, c4) == ('2', '4') else c2 for c2, c4 in zip(y2k, y4k)) + + def isoformat(self): + """ + Formats the date as %Y-%m-%d + + :return: + The date formatted to %Y-%m-%d as a unicode string in Python 3 + and a byte string in Python 2 + """ + + return self.strftime('0000-%m-%d') + + def replace(self, year=None, month=None, day=None): + """ + Returns a new datetime.date or asn1crypto.util.extended_date + object with the specified components replaced + + :return: + A datetime.date or asn1crypto.util.extended_date object + """ + + if year is None: + year = self.year + if month is None: + month = self.month + if day is None: + day = self.day + + if year > 0: + cls = date + else: + cls = extended_date + + return cls( + year, + month, + day + ) + + def __str__(self): + """ + :return: + A str representing this extended_date, e.g. "0000-01-01" + """ + + return self.strftime('%Y-%m-%d') + + def __eq__(self, other): + """ + Compare two extended_date objects + + :param other: + The other extended_date to compare to + + :return: + A boolean + """ + + # datetime.date object wouldn't compare equal because it can't be year 0 + if not isinstance(other, self.__class__): + return False + return self.__cmp__(other) == 0 + + def __ne__(self, other): + """ + Compare two extended_date objects + + :param other: + The other extended_date to compare to + + :return: + A boolean + """ + + return not self.__eq__(other) + + def _comparison_error(self, other): + raise TypeError(unwrap( + ''' + An asn1crypto.util.extended_date object can only be compared to + an asn1crypto.util.extended_date or datetime.date object, not %s + ''', + type_name(other) + )) + + def __cmp__(self, other): + """ + Compare two extended_date or datetime.date objects + + :param other: + The other extended_date object to compare to + + :return: + An integer smaller than, equal to, or larger than 0 + """ + + # self is year 0, other is >= year 1 + if isinstance(other, date): + return -1 + + if not isinstance(other, self.__class__): + self._comparison_error(other) + + if self._y2k < other._y2k: + return -1 + if self._y2k > other._y2k: + return 1 + return 0 + + def __lt__(self, other): + return self.__cmp__(other) < 0 + + def __le__(self, other): + return self.__cmp__(other) <= 0 + + def __gt__(self, other): + return self.__cmp__(other) > 0 + + def __ge__(self, other): + return self.__cmp__(other) >= 0 + + +class extended_datetime(object): + """ + A datetime.datetime-like object that represents the year 0. This is just + to handle 0000-01-01 found in some certificates. Python's datetime does + not support year 0. + + The proleptic gregorian calendar repeats itself every 400 years. Therefore, + the simplest way to format is to substitute year 2000. + """ + + # There are 97 leap days during 400 years. + DAYS_IN_400_YEARS = 400 * 365 + 97 + DAYS_IN_2000_YEARS = 5 * DAYS_IN_400_YEARS + + def __init__(self, year, *args, **kwargs): + """ + :param year: + The integer 0 + + :param args: + Other positional arguments; see datetime.datetime. + + :param kwargs: + Other keyword arguments; see datetime.datetime. + """ + + if year != 0: + raise ValueError('year must be 0') + + self._y2k = datetime(2000, *args, **kwargs) + + @property + def year(self): + """ + :return: + The integer 0 + """ + + return 0 + + @property + def month(self): + """ + :return: + An integer from 1 to 12 + """ + + return self._y2k.month + + @property + def day(self): + """ + :return: + An integer from 1 to 31 + """ + + return self._y2k.day + + @property + def hour(self): + """ + :return: + An integer from 1 to 24 + """ + + return self._y2k.hour + + @property + def minute(self): + """ + :return: + An integer from 1 to 60 + """ + + return self._y2k.minute + + @property + def second(self): + """ + :return: + An integer from 1 to 60 + """ + + return self._y2k.second + + @property + def microsecond(self): + """ + :return: + An integer from 0 to 999999 + """ + + return self._y2k.microsecond + + @property + def tzinfo(self): + """ + :return: + If object is timezone aware, a datetime.tzinfo object, else None. + """ + + return self._y2k.tzinfo + + def utcoffset(self): + """ + :return: + If object is timezone aware, a datetime.timedelta object, else None. + """ + + return self._y2k.utcoffset() + + def time(self): + """ + :return: + A datetime.time object + """ + + return self._y2k.time() + + def date(self): + """ + :return: + An asn1crypto.util.extended_date of the date + """ + + return extended_date(0, self.month, self.day) + + def strftime(self, format): + """ + Performs strftime(), always returning a str + + :param format: + A strftime() format string + + :return: + A str of the formatted datetime + """ + + # Format the datetime twice, once with year 2000, once with year 4000. + # The only differences in the result will be in the millennium. Find them and replace by zeros. + y2k = self._y2k.strftime(format) + y4k = self._y2k.replace(year=4000).strftime(format) + return ''.join('0' if (c2, c4) == ('2', '4') else c2 for c2, c4 in zip(y2k, y4k)) + + def isoformat(self, sep='T'): + """ + Formats the date as "%Y-%m-%d %H:%M:%S" with the sep param between the + date and time portions + + :param set: + A single character of the separator to place between the date and + time + + :return: + The formatted datetime as a unicode string in Python 3 and a byte + string in Python 2 + """ + + s = '0000-%02d-%02d%c%02d:%02d:%02d' % (self.month, self.day, sep, self.hour, self.minute, self.second) + if self.microsecond: + s += '.%06d' % self.microsecond + return s + _format_offset(self.utcoffset()) + + def replace(self, year=None, *args, **kwargs): + """ + Returns a new datetime.datetime or asn1crypto.util.extended_datetime + object with the specified components replaced + + :param year: + The new year to substitute. None to keep it. + + :param args: + Other positional arguments; see datetime.datetime.replace. + + :param kwargs: + Other keyword arguments; see datetime.datetime.replace. + + :return: + A datetime.datetime or asn1crypto.util.extended_datetime object + """ + + if year: + return self._y2k.replace(year, *args, **kwargs) + + return extended_datetime.from_y2k(self._y2k.replace(2000, *args, **kwargs)) + + def astimezone(self, tz): + """ + Convert this extended_datetime to another timezone. + + :param tz: + A datetime.tzinfo object. + + :return: + A new extended_datetime or datetime.datetime object + """ + + return extended_datetime.from_y2k(self._y2k.astimezone(tz)) + + def timestamp(self): + """ + Return POSIX timestamp. Only supported in python >= 3.3 + + :return: + A float representing the seconds since 1970-01-01 UTC. This will be a negative value. + """ + + return self._y2k.timestamp() - self.DAYS_IN_2000_YEARS * 86400 + + def __str__(self): + """ + :return: + A str representing this extended_datetime, e.g. "0000-01-01 00:00:00.000001-10:00" + """ + + return self.isoformat(sep=' ') + + def __eq__(self, other): + """ + Compare two extended_datetime objects + + :param other: + The other extended_datetime to compare to + + :return: + A boolean + """ + + # Only compare against other datetime or extended_datetime objects + if not isinstance(other, (self.__class__, datetime)): + return False + + # Offset-naive and offset-aware datetimes are never the same + if (self.tzinfo is None) != (other.tzinfo is None): + return False + + return self.__cmp__(other) == 0 + + def __ne__(self, other): + """ + Compare two extended_datetime objects + + :param other: + The other extended_datetime to compare to + + :return: + A boolean + """ + + return not self.__eq__(other) + + def _comparison_error(self, other): + """ + Raises a TypeError about the other object not being suitable for + comparison + + :param other: + The object being compared to + """ + + raise TypeError(unwrap( + ''' + An asn1crypto.util.extended_datetime object can only be compared to + an asn1crypto.util.extended_datetime or datetime.datetime object, + not %s + ''', + type_name(other) + )) + + def __cmp__(self, other): + """ + Compare two extended_datetime or datetime.datetime objects + + :param other: + The other extended_datetime or datetime.datetime object to compare to + + :return: + An integer smaller than, equal to, or larger than 0 + """ + + if not isinstance(other, (self.__class__, datetime)): + self._comparison_error(other) + + if (self.tzinfo is None) != (other.tzinfo is None): + raise TypeError("can't compare offset-naive and offset-aware datetimes") + + diff = self - other + zero = timedelta(0) + if diff < zero: + return -1 + if diff > zero: + return 1 + return 0 + + def __lt__(self, other): + return self.__cmp__(other) < 0 + + def __le__(self, other): + return self.__cmp__(other) <= 0 + + def __gt__(self, other): + return self.__cmp__(other) > 0 + + def __ge__(self, other): + return self.__cmp__(other) >= 0 + + def __add__(self, other): + """ + Adds a timedelta + + :param other: + A datetime.timedelta object to add. + + :return: + A new extended_datetime or datetime.datetime object. + """ + + return extended_datetime.from_y2k(self._y2k + other) + + def __sub__(self, other): + """ + Subtracts a timedelta or another datetime. + + :param other: + A datetime.timedelta or datetime.datetime or extended_datetime object to subtract. + + :return: + If a timedelta is passed, a new extended_datetime or datetime.datetime object. + Else a datetime.timedelta object. + """ + + if isinstance(other, timedelta): + return extended_datetime.from_y2k(self._y2k - other) + + if isinstance(other, extended_datetime): + return self._y2k - other._y2k + + if isinstance(other, datetime): + return self._y2k - other - timedelta(days=self.DAYS_IN_2000_YEARS) + + return NotImplemented + + def __rsub__(self, other): + return -(self - other) + + @classmethod + def from_y2k(cls, value): + """ + Revert substitution of year 2000. + + :param value: + A datetime.datetime object which is 2000 years in the future. + :return: + A new extended_datetime or datetime.datetime object. + """ + + year = value.year - 2000 + + if year > 0: + new_cls = datetime + else: + new_cls = cls + + return new_cls( + year, + value.month, + value.day, + value.hour, + value.minute, + value.second, + value.microsecond, + value.tzinfo + ) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/asn1crypto/version.py b/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/asn1crypto/version.py new file mode 100644 index 00000000..3cf48923 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/asn1crypto/version.py @@ -0,0 +1,6 @@ +# coding: utf-8 +from __future__ import unicode_literals, division, absolute_import, print_function + + +__version__ = '1.4.0' +__version_info__ = (1, 4, 0) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/asn1crypto/x509.py b/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/asn1crypto/x509.py new file mode 100644 index 00000000..8cfb2c78 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/asn1crypto/x509.py @@ -0,0 +1,3036 @@ +# coding: utf-8 + +""" +ASN.1 type classes for X.509 certificates. Exports the following items: + + - Attributes() + - Certificate() + - Extensions() + - GeneralName() + - GeneralNames() + - Name() + +Other type classes are defined that help compose the types listed above. +""" + +from __future__ import unicode_literals, division, absolute_import, print_function + +from contextlib import contextmanager +from encodings import idna # noqa +import hashlib +import re +import socket +import stringprep +import sys +import unicodedata + +from ._errors import unwrap +from ._iri import iri_to_uri, uri_to_iri +from ._ordereddict import OrderedDict +from ._types import type_name, str_cls, bytes_to_list +from .algos import AlgorithmIdentifier, AnyAlgorithmIdentifier, DigestAlgorithm, SignedDigestAlgorithm +from .core import ( + Any, + BitString, + BMPString, + Boolean, + Choice, + Concat, + Enumerated, + GeneralizedTime, + GeneralString, + IA5String, + Integer, + Null, + NumericString, + ObjectIdentifier, + OctetBitString, + OctetString, + ParsableOctetString, + PrintableString, + Sequence, + SequenceOf, + Set, + SetOf, + TeletexString, + UniversalString, + UTCTime, + UTF8String, + VisibleString, + VOID, +) +from .keys import PublicKeyInfo +from .util import int_to_bytes, int_from_bytes, inet_ntop, inet_pton + + +# The structures in this file are taken from https://tools.ietf.org/html/rfc5280 +# and a few other supplementary sources, mostly due to extra supported +# extension and name OIDs + + +class DNSName(IA5String): + + _encoding = 'idna' + _bad_tag = (12, 19) + + def __ne__(self, other): + return not self == other + + def __eq__(self, other): + """ + Equality as defined by https://tools.ietf.org/html/rfc5280#section-7.2 + + :param other: + Another DNSName object + + :return: + A boolean + """ + + if not isinstance(other, DNSName): + return False + + return self.__unicode__().lower() == other.__unicode__().lower() + + def set(self, value): + """ + Sets the value of the DNS name + + :param value: + A unicode string + """ + + if not isinstance(value, str_cls): + raise TypeError(unwrap( + ''' + %s value must be a unicode string, not %s + ''', + type_name(self), + type_name(value) + )) + + if value.startswith('.'): + encoded_value = b'.' + value[1:].encode(self._encoding) + else: + encoded_value = value.encode(self._encoding) + + self._unicode = value + self.contents = encoded_value + self._header = None + if self._trailer != b'': + self._trailer = b'' + + +class URI(IA5String): + + def set(self, value): + """ + Sets the value of the string + + :param value: + A unicode string + """ + + if not isinstance(value, str_cls): + raise TypeError(unwrap( + ''' + %s value must be a unicode string, not %s + ''', + type_name(self), + type_name(value) + )) + + self._unicode = value + self.contents = iri_to_uri(value) + self._header = None + if self._trailer != b'': + self._trailer = b'' + + def __ne__(self, other): + return not self == other + + def __eq__(self, other): + """ + Equality as defined by https://tools.ietf.org/html/rfc5280#section-7.4 + + :param other: + Another URI object + + :return: + A boolean + """ + + if not isinstance(other, URI): + return False + + return iri_to_uri(self.native, True) == iri_to_uri(other.native, True) + + def __unicode__(self): + """ + :return: + A unicode string + """ + + if self.contents is None: + return '' + if self._unicode is None: + self._unicode = uri_to_iri(self._merge_chunks()) + return self._unicode + + +class EmailAddress(IA5String): + + _contents = None + + # If the value has gone through the .set() method, thus normalizing it + _normalized = False + + # In the wild we've seen this encoded as a UTF8String and PrintableString + _bad_tag = (12, 19) + + @property + def contents(self): + """ + :return: + A byte string of the DER-encoded contents of the sequence + """ + + return self._contents + + @contents.setter + def contents(self, value): + """ + :param value: + A byte string of the DER-encoded contents of the sequence + """ + + self._normalized = False + self._contents = value + + def set(self, value): + """ + Sets the value of the string + + :param value: + A unicode string + """ + + if not isinstance(value, str_cls): + raise TypeError(unwrap( + ''' + %s value must be a unicode string, not %s + ''', + type_name(self), + type_name(value) + )) + + if value.find('@') != -1: + mailbox, hostname = value.rsplit('@', 1) + encoded_value = mailbox.encode('ascii') + b'@' + hostname.encode('idna') + else: + encoded_value = value.encode('ascii') + + self._normalized = True + self._unicode = value + self.contents = encoded_value + self._header = None + if self._trailer != b'': + self._trailer = b'' + + def __unicode__(self): + """ + :return: + A unicode string + """ + + # We've seen this in the wild as a PrintableString, and since ascii is a + # subset of cp1252, we use the later for decoding to be more user friendly + if self._unicode is None: + contents = self._merge_chunks() + if contents.find(b'@') == -1: + self._unicode = contents.decode('cp1252') + else: + mailbox, hostname = contents.rsplit(b'@', 1) + self._unicode = mailbox.decode('cp1252') + '@' + hostname.decode('idna') + return self._unicode + + def __ne__(self, other): + return not self == other + + def __eq__(self, other): + """ + Equality as defined by https://tools.ietf.org/html/rfc5280#section-7.5 + + :param other: + Another EmailAddress object + + :return: + A boolean + """ + + if not isinstance(other, EmailAddress): + return False + + if not self._normalized: + self.set(self.native) + if not other._normalized: + other.set(other.native) + + if self._contents.find(b'@') == -1 or other._contents.find(b'@') == -1: + return self._contents == other._contents + + other_mailbox, other_hostname = other._contents.rsplit(b'@', 1) + mailbox, hostname = self._contents.rsplit(b'@', 1) + + if mailbox != other_mailbox: + return False + + if hostname.lower() != other_hostname.lower(): + return False + + return True + + +class IPAddress(OctetString): + def parse(self, spec=None, spec_params=None): + """ + This method is not applicable to IP addresses + """ + + raise ValueError(unwrap( + ''' + IP address values can not be parsed + ''' + )) + + def set(self, value): + """ + Sets the value of the object + + :param value: + A unicode string containing an IPv4 address, IPv4 address with CIDR, + an IPv6 address or IPv6 address with CIDR + """ + + if not isinstance(value, str_cls): + raise TypeError(unwrap( + ''' + %s value must be a unicode string, not %s + ''', + type_name(self), + type_name(value) + )) + + original_value = value + + has_cidr = value.find('/') != -1 + cidr = 0 + if has_cidr: + parts = value.split('/', 1) + value = parts[0] + cidr = int(parts[1]) + if cidr < 0: + raise ValueError(unwrap( + ''' + %s value contains a CIDR range less than 0 + ''', + type_name(self) + )) + + if value.find(':') != -1: + family = socket.AF_INET6 + if cidr > 128: + raise ValueError(unwrap( + ''' + %s value contains a CIDR range bigger than 128, the maximum + value for an IPv6 address + ''', + type_name(self) + )) + cidr_size = 128 + else: + family = socket.AF_INET + if cidr > 32: + raise ValueError(unwrap( + ''' + %s value contains a CIDR range bigger than 32, the maximum + value for an IPv4 address + ''', + type_name(self) + )) + cidr_size = 32 + + cidr_bytes = b'' + if has_cidr: + cidr_mask = '1' * cidr + cidr_mask += '0' * (cidr_size - len(cidr_mask)) + cidr_bytes = int_to_bytes(int(cidr_mask, 2)) + cidr_bytes = (b'\x00' * ((cidr_size // 8) - len(cidr_bytes))) + cidr_bytes + + self._native = original_value + self.contents = inet_pton(family, value) + cidr_bytes + self._bytes = self.contents + self._header = None + if self._trailer != b'': + self._trailer = b'' + + @property + def native(self): + """ + The native Python datatype representation of this value + + :return: + A unicode string or None + """ + + if self.contents is None: + return None + + if self._native is None: + byte_string = self.__bytes__() + byte_len = len(byte_string) + value = None + cidr_int = None + if byte_len in set([32, 16]): + value = inet_ntop(socket.AF_INET6, byte_string[0:16]) + if byte_len > 16: + cidr_int = int_from_bytes(byte_string[16:]) + elif byte_len in set([8, 4]): + value = inet_ntop(socket.AF_INET, byte_string[0:4]) + if byte_len > 4: + cidr_int = int_from_bytes(byte_string[4:]) + if cidr_int is not None: + cidr_bits = '{0:b}'.format(cidr_int) + cidr = len(cidr_bits.rstrip('0')) + value = value + '/' + str_cls(cidr) + self._native = value + return self._native + + def __ne__(self, other): + return not self == other + + def __eq__(self, other): + """ + :param other: + Another IPAddress object + + :return: + A boolean + """ + + if not isinstance(other, IPAddress): + return False + + return self.__bytes__() == other.__bytes__() + + +class Attribute(Sequence): + _fields = [ + ('type', ObjectIdentifier), + ('values', SetOf, {'spec': Any}), + ] + + +class Attributes(SequenceOf): + _child_spec = Attribute + + +class KeyUsage(BitString): + _map = { + 0: 'digital_signature', + 1: 'non_repudiation', + 2: 'key_encipherment', + 3: 'data_encipherment', + 4: 'key_agreement', + 5: 'key_cert_sign', + 6: 'crl_sign', + 7: 'encipher_only', + 8: 'decipher_only', + } + + +class PrivateKeyUsagePeriod(Sequence): + _fields = [ + ('not_before', GeneralizedTime, {'implicit': 0, 'optional': True}), + ('not_after', GeneralizedTime, {'implicit': 1, 'optional': True}), + ] + + +class NotReallyTeletexString(TeletexString): + """ + OpenSSL (and probably some other libraries) puts ISO-8859-1 + into TeletexString instead of ITU T.61. We use Windows-1252 when + decoding since it is a superset of ISO-8859-1, and less likely to + cause encoding issues, but we stay strict with encoding to prevent + us from creating bad data. + """ + + _decoding_encoding = 'cp1252' + + def __unicode__(self): + """ + :return: + A unicode string + """ + + if self.contents is None: + return '' + if self._unicode is None: + self._unicode = self._merge_chunks().decode(self._decoding_encoding) + return self._unicode + + +@contextmanager +def strict_teletex(): + try: + NotReallyTeletexString._decoding_encoding = 'teletex' + yield + finally: + NotReallyTeletexString._decoding_encoding = 'cp1252' + + +class DirectoryString(Choice): + _alternatives = [ + ('teletex_string', NotReallyTeletexString), + ('printable_string', PrintableString), + ('universal_string', UniversalString), + ('utf8_string', UTF8String), + ('bmp_string', BMPString), + # This is an invalid/bad alternative, but some broken certs use it + ('ia5_string', IA5String), + ] + + +class NameType(ObjectIdentifier): + _map = { + '2.5.4.3': 'common_name', + '2.5.4.4': 'surname', + '2.5.4.5': 'serial_number', + '2.5.4.6': 'country_name', + '2.5.4.7': 'locality_name', + '2.5.4.8': 'state_or_province_name', + '2.5.4.9': 'street_address', + '2.5.4.10': 'organization_name', + '2.5.4.11': 'organizational_unit_name', + '2.5.4.12': 'title', + '2.5.4.15': 'business_category', + '2.5.4.17': 'postal_code', + '2.5.4.20': 'telephone_number', + '2.5.4.41': 'name', + '2.5.4.42': 'given_name', + '2.5.4.43': 'initials', + '2.5.4.44': 'generation_qualifier', + '2.5.4.45': 'unique_identifier', + '2.5.4.46': 'dn_qualifier', + '2.5.4.65': 'pseudonym', + '2.5.4.97': 'organization_identifier', + # https://www.trustedcomputinggroup.org/wp-content/uploads/Credential_Profile_EK_V2.0_R14_published.pdf + '2.23.133.2.1': 'tpm_manufacturer', + '2.23.133.2.2': 'tpm_model', + '2.23.133.2.3': 'tpm_version', + '2.23.133.2.4': 'platform_manufacturer', + '2.23.133.2.5': 'platform_model', + '2.23.133.2.6': 'platform_version', + # https://tools.ietf.org/html/rfc2985#page-26 + '1.2.840.113549.1.9.1': 'email_address', + # Page 10 of https://cabforum.org/wp-content/uploads/EV-V1_5_5.pdf + '1.3.6.1.4.1.311.60.2.1.1': 'incorporation_locality', + '1.3.6.1.4.1.311.60.2.1.2': 'incorporation_state_or_province', + '1.3.6.1.4.1.311.60.2.1.3': 'incorporation_country', + # https://tools.ietf.org/html/rfc4519#section-2.39 + '0.9.2342.19200300.100.1.1': 'user_id', + # https://tools.ietf.org/html/rfc2247#section-4 + '0.9.2342.19200300.100.1.25': 'domain_component', + # http://www.alvestrand.no/objectid/0.2.262.1.10.7.20.html + '0.2.262.1.10.7.20': 'name_distinguisher', + } + + # This order is largely based on observed order seen in EV certs from + # Symantec and DigiCert. Some of the uncommon name-related fields are + # just placed in what seems like a reasonable order. + preferred_order = [ + 'incorporation_country', + 'incorporation_state_or_province', + 'incorporation_locality', + 'business_category', + 'serial_number', + 'country_name', + 'postal_code', + 'state_or_province_name', + 'locality_name', + 'street_address', + 'organization_name', + 'organizational_unit_name', + 'title', + 'common_name', + 'user_id', + 'initials', + 'generation_qualifier', + 'surname', + 'given_name', + 'name', + 'pseudonym', + 'dn_qualifier', + 'telephone_number', + 'email_address', + 'domain_component', + 'name_distinguisher', + 'organization_identifier', + 'tpm_manufacturer', + 'tpm_model', + 'tpm_version', + 'platform_manufacturer', + 'platform_model', + 'platform_version', + ] + + @classmethod + def preferred_ordinal(cls, attr_name): + """ + Returns an ordering value for a particular attribute key. + + Unrecognized attributes and OIDs will be sorted lexically at the end. + + :return: + An orderable value. + + """ + + attr_name = cls.map(attr_name) + if attr_name in cls.preferred_order: + ordinal = cls.preferred_order.index(attr_name) + else: + ordinal = len(cls.preferred_order) + + return (ordinal, attr_name) + + @property + def human_friendly(self): + """ + :return: + A human-friendly unicode string to display to users + """ + + return { + 'common_name': 'Common Name', + 'surname': 'Surname', + 'serial_number': 'Serial Number', + 'country_name': 'Country', + 'locality_name': 'Locality', + 'state_or_province_name': 'State/Province', + 'street_address': 'Street Address', + 'organization_name': 'Organization', + 'organizational_unit_name': 'Organizational Unit', + 'title': 'Title', + 'business_category': 'Business Category', + 'postal_code': 'Postal Code', + 'telephone_number': 'Telephone Number', + 'name': 'Name', + 'given_name': 'Given Name', + 'initials': 'Initials', + 'generation_qualifier': 'Generation Qualifier', + 'unique_identifier': 'Unique Identifier', + 'dn_qualifier': 'DN Qualifier', + 'pseudonym': 'Pseudonym', + 'email_address': 'Email Address', + 'incorporation_locality': 'Incorporation Locality', + 'incorporation_state_or_province': 'Incorporation State/Province', + 'incorporation_country': 'Incorporation Country', + 'domain_component': 'Domain Component', + 'name_distinguisher': 'Name Distinguisher', + 'organization_identifier': 'Organization Identifier', + 'tpm_manufacturer': 'TPM Manufacturer', + 'tpm_model': 'TPM Model', + 'tpm_version': 'TPM Version', + 'platform_manufacturer': 'Platform Manufacturer', + 'platform_model': 'Platform Model', + 'platform_version': 'Platform Version', + 'user_id': 'User ID', + }.get(self.native, self.native) + + +class NameTypeAndValue(Sequence): + _fields = [ + ('type', NameType), + ('value', Any), + ] + + _oid_pair = ('type', 'value') + _oid_specs = { + 'common_name': DirectoryString, + 'surname': DirectoryString, + 'serial_number': DirectoryString, + 'country_name': DirectoryString, + 'locality_name': DirectoryString, + 'state_or_province_name': DirectoryString, + 'street_address': DirectoryString, + 'organization_name': DirectoryString, + 'organizational_unit_name': DirectoryString, + 'title': DirectoryString, + 'business_category': DirectoryString, + 'postal_code': DirectoryString, + 'telephone_number': PrintableString, + 'name': DirectoryString, + 'given_name': DirectoryString, + 'initials': DirectoryString, + 'generation_qualifier': DirectoryString, + 'unique_identifier': OctetBitString, + 'dn_qualifier': DirectoryString, + 'pseudonym': DirectoryString, + # https://tools.ietf.org/html/rfc2985#page-26 + 'email_address': EmailAddress, + # Page 10 of https://cabforum.org/wp-content/uploads/EV-V1_5_5.pdf + 'incorporation_locality': DirectoryString, + 'incorporation_state_or_province': DirectoryString, + 'incorporation_country': DirectoryString, + 'domain_component': DNSName, + 'name_distinguisher': DirectoryString, + 'organization_identifier': DirectoryString, + 'tpm_manufacturer': UTF8String, + 'tpm_model': UTF8String, + 'tpm_version': UTF8String, + 'platform_manufacturer': UTF8String, + 'platform_model': UTF8String, + 'platform_version': UTF8String, + 'user_id': DirectoryString, + } + + _prepped = None + + @property + def prepped_value(self): + """ + Returns the value after being processed by the internationalized string + preparation as specified by RFC 5280 + + :return: + A unicode string + """ + + if self._prepped is None: + self._prepped = self._ldap_string_prep(self['value'].native) + return self._prepped + + def __ne__(self, other): + return not self == other + + def __eq__(self, other): + """ + Equality as defined by https://tools.ietf.org/html/rfc5280#section-7.1 + + :param other: + Another NameTypeAndValue object + + :return: + A boolean + """ + + if not isinstance(other, NameTypeAndValue): + return False + + if other['type'].native != self['type'].native: + return False + + return other.prepped_value == self.prepped_value + + def _ldap_string_prep(self, string): + """ + Implements the internationalized string preparation algorithm from + RFC 4518. https://tools.ietf.org/html/rfc4518#section-2 + + :param string: + A unicode string to prepare + + :return: + A prepared unicode string, ready for comparison + """ + + # Map step + string = re.sub('[\u00ad\u1806\u034f\u180b-\u180d\ufe0f-\uff00\ufffc]+', '', string) + string = re.sub('[\u0009\u000a\u000b\u000c\u000d\u0085]', ' ', string) + if sys.maxunicode == 0xffff: + # Some installs of Python 2.7 don't support 8-digit unicode escape + # ranges, so we have to break them into pieces + # Original was: \U0001D173-\U0001D17A and \U000E0020-\U000E007F + string = re.sub('\ud834[\udd73-\udd7a]|\udb40[\udc20-\udc7f]|\U000e0001', '', string) + else: + string = re.sub('[\U0001D173-\U0001D17A\U000E0020-\U000E007F\U000e0001]', '', string) + string = re.sub( + '[\u0000-\u0008\u000e-\u001f\u007f-\u0084\u0086-\u009f\u06dd\u070f\u180e\u200c-\u200f' + '\u202a-\u202e\u2060-\u2063\u206a-\u206f\ufeff\ufff9-\ufffb]+', + '', + string + ) + string = string.replace('\u200b', '') + string = re.sub('[\u00a0\u1680\u2000-\u200a\u2028-\u2029\u202f\u205f\u3000]', ' ', string) + + string = ''.join(map(stringprep.map_table_b2, string)) + + # Normalize step + string = unicodedata.normalize('NFKC', string) + + # Prohibit step + for char in string: + if stringprep.in_table_a1(char): + raise ValueError(unwrap( + ''' + X.509 Name objects may not contain unassigned code points + ''' + )) + + if stringprep.in_table_c8(char): + raise ValueError(unwrap( + ''' + X.509 Name objects may not contain change display or + zzzzdeprecated characters + ''' + )) + + if stringprep.in_table_c3(char): + raise ValueError(unwrap( + ''' + X.509 Name objects may not contain private use characters + ''' + )) + + if stringprep.in_table_c4(char): + raise ValueError(unwrap( + ''' + X.509 Name objects may not contain non-character code points + ''' + )) + + if stringprep.in_table_c5(char): + raise ValueError(unwrap( + ''' + X.509 Name objects may not contain surrogate code points + ''' + )) + + if char == '\ufffd': + raise ValueError(unwrap( + ''' + X.509 Name objects may not contain the replacement character + ''' + )) + + # Check bidirectional step - here we ensure that we are not mixing + # left-to-right and right-to-left text in the string + has_r_and_al_cat = False + has_l_cat = False + for char in string: + if stringprep.in_table_d1(char): + has_r_and_al_cat = True + elif stringprep.in_table_d2(char): + has_l_cat = True + + if has_r_and_al_cat: + first_is_r_and_al = stringprep.in_table_d1(string[0]) + last_is_r_and_al = stringprep.in_table_d1(string[-1]) + + if has_l_cat or not first_is_r_and_al or not last_is_r_and_al: + raise ValueError(unwrap( + ''' + X.509 Name object contains a malformed bidirectional + sequence + ''' + )) + + # Insignificant space handling step + string = ' ' + re.sub(' +', ' ', string).strip() + ' ' + + return string + + +class RelativeDistinguishedName(SetOf): + _child_spec = NameTypeAndValue + + @property + def hashable(self): + """ + :return: + A unicode string that can be used as a dict key or in a set + """ + + output = [] + values = self._get_values(self) + for key in sorted(values.keys()): + output.append('%s: %s' % (key, values[key])) + # Unit separator is used here since the normalization process for + # values moves any such character, and the keys are all dotted integers + # or under_score_words + return '\x1F'.join(output) + + def __ne__(self, other): + return not self == other + + def __eq__(self, other): + """ + Equality as defined by https://tools.ietf.org/html/rfc5280#section-7.1 + + :param other: + Another RelativeDistinguishedName object + + :return: + A boolean + """ + + if not isinstance(other, RelativeDistinguishedName): + return False + + if len(self) != len(other): + return False + + self_types = self._get_types(self) + other_types = self._get_types(other) + + if self_types != other_types: + return False + + self_values = self._get_values(self) + other_values = self._get_values(other) + + for type_name_ in self_types: + if self_values[type_name_] != other_values[type_name_]: + return False + + return True + + def _get_types(self, rdn): + """ + Returns a set of types contained in an RDN + + :param rdn: + A RelativeDistinguishedName object + + :return: + A set object with unicode strings of NameTypeAndValue type field + values + """ + + return set([ntv['type'].native for ntv in rdn]) + + def _get_values(self, rdn): + """ + Returns a dict of prepped values contained in an RDN + + :param rdn: + A RelativeDistinguishedName object + + :return: + A dict object with unicode strings of NameTypeAndValue value field + values that have been prepped for comparison + """ + + output = {} + [output.update([(ntv['type'].native, ntv.prepped_value)]) for ntv in rdn] + return output + + +class RDNSequence(SequenceOf): + _child_spec = RelativeDistinguishedName + + @property + def hashable(self): + """ + :return: + A unicode string that can be used as a dict key or in a set + """ + + # Record separator is used here since the normalization process for + # values moves any such character, and the keys are all dotted integers + # or under_score_words + return '\x1E'.join(rdn.hashable for rdn in self) + + def __ne__(self, other): + return not self == other + + def __eq__(self, other): + """ + Equality as defined by https://tools.ietf.org/html/rfc5280#section-7.1 + + :param other: + Another RDNSequence object + + :return: + A boolean + """ + + if not isinstance(other, RDNSequence): + return False + + if len(self) != len(other): + return False + + for index, self_rdn in enumerate(self): + if other[index] != self_rdn: + return False + + return True + + +class Name(Choice): + _alternatives = [ + ('', RDNSequence), + ] + + _human_friendly = None + _sha1 = None + _sha256 = None + + @classmethod + def build(cls, name_dict, use_printable=False): + """ + Creates a Name object from a dict of unicode string keys and values. + The keys should be from NameType._map, or a dotted-integer OID unicode + string. + + :param name_dict: + A dict of name information, e.g. {"common_name": "Will Bond", + "country_name": "US", "organization_name": "Codex Non Sufficit LC"} + + :param use_printable: + A bool - if PrintableString should be used for encoding instead of + UTF8String. This is for backwards compatibility with old software. + + :return: + An x509.Name object + """ + + rdns = [] + if not use_printable: + encoding_name = 'utf8_string' + encoding_class = UTF8String + else: + encoding_name = 'printable_string' + encoding_class = PrintableString + + # Sort the attributes according to NameType.preferred_order + name_dict = OrderedDict( + sorted( + name_dict.items(), + key=lambda item: NameType.preferred_ordinal(item[0]) + ) + ) + + for attribute_name, attribute_value in name_dict.items(): + attribute_name = NameType.map(attribute_name) + if attribute_name == 'email_address': + value = EmailAddress(attribute_value) + elif attribute_name == 'domain_component': + value = DNSName(attribute_value) + elif attribute_name in set(['dn_qualifier', 'country_name', 'serial_number']): + value = DirectoryString( + name='printable_string', + value=PrintableString(attribute_value) + ) + else: + value = DirectoryString( + name=encoding_name, + value=encoding_class(attribute_value) + ) + + rdns.append(RelativeDistinguishedName([ + NameTypeAndValue({ + 'type': attribute_name, + 'value': value + }) + ])) + + return cls(name='', value=RDNSequence(rdns)) + + @property + def hashable(self): + """ + :return: + A unicode string that can be used as a dict key or in a set + """ + + return self.chosen.hashable + + def __len__(self): + return len(self.chosen) + + def __ne__(self, other): + return not self == other + + def __eq__(self, other): + """ + Equality as defined by https://tools.ietf.org/html/rfc5280#section-7.1 + + :param other: + Another Name object + + :return: + A boolean + """ + + if not isinstance(other, Name): + return False + return self.chosen == other.chosen + + @property + def native(self): + if self._native is None: + self._native = OrderedDict() + for rdn in self.chosen.native: + for type_val in rdn: + field_name = type_val['type'] + if field_name in self._native: + existing = self._native[field_name] + if not isinstance(existing, list): + existing = self._native[field_name] = [existing] + existing.append(type_val['value']) + else: + self._native[field_name] = type_val['value'] + return self._native + + @property + def human_friendly(self): + """ + :return: + A human-friendly unicode string containing the parts of the name + """ + + if self._human_friendly is None: + data = OrderedDict() + last_field = None + for rdn in self.chosen: + for type_val in rdn: + field_name = type_val['type'].human_friendly + last_field = field_name + if field_name in data: + data[field_name] = [data[field_name]] + data[field_name].append(type_val['value']) + else: + data[field_name] = type_val['value'] + to_join = [] + keys = data.keys() + if last_field == 'Country': + keys = reversed(list(keys)) + for key in keys: + value = data[key] + native_value = self._recursive_humanize(value) + to_join.append('%s: %s' % (key, native_value)) + + has_comma = False + for element in to_join: + if element.find(',') != -1: + has_comma = True + break + + separator = ', ' if not has_comma else '; ' + self._human_friendly = separator.join(to_join[::-1]) + + return self._human_friendly + + def _recursive_humanize(self, value): + """ + Recursively serializes data compiled from the RDNSequence + + :param value: + An Asn1Value object, or a list of Asn1Value objects + + :return: + A unicode string + """ + + if isinstance(value, list): + return ', '.join( + reversed([self._recursive_humanize(sub_value) for sub_value in value]) + ) + return value.native + + @property + def sha1(self): + """ + :return: + The SHA1 hash of the DER-encoded bytes of this name + """ + + if self._sha1 is None: + self._sha1 = hashlib.sha1(self.dump()).digest() + return self._sha1 + + @property + def sha256(self): + """ + :return: + The SHA-256 hash of the DER-encoded bytes of this name + """ + + if self._sha256 is None: + self._sha256 = hashlib.sha256(self.dump()).digest() + return self._sha256 + + +class AnotherName(Sequence): + _fields = [ + ('type_id', ObjectIdentifier), + ('value', Any, {'explicit': 0}), + ] + + +class CountryName(Choice): + class_ = 1 + tag = 1 + + _alternatives = [ + ('x121_dcc_code', NumericString), + ('iso_3166_alpha2_code', PrintableString), + ] + + +class AdministrationDomainName(Choice): + class_ = 1 + tag = 2 + + _alternatives = [ + ('numeric', NumericString), + ('printable', PrintableString), + ] + + +class PrivateDomainName(Choice): + _alternatives = [ + ('numeric', NumericString), + ('printable', PrintableString), + ] + + +class PersonalName(Set): + _fields = [ + ('surname', PrintableString, {'implicit': 0}), + ('given_name', PrintableString, {'implicit': 1, 'optional': True}), + ('initials', PrintableString, {'implicit': 2, 'optional': True}), + ('generation_qualifier', PrintableString, {'implicit': 3, 'optional': True}), + ] + + +class TeletexPersonalName(Set): + _fields = [ + ('surname', TeletexString, {'implicit': 0}), + ('given_name', TeletexString, {'implicit': 1, 'optional': True}), + ('initials', TeletexString, {'implicit': 2, 'optional': True}), + ('generation_qualifier', TeletexString, {'implicit': 3, 'optional': True}), + ] + + +class OrganizationalUnitNames(SequenceOf): + _child_spec = PrintableString + + +class TeletexOrganizationalUnitNames(SequenceOf): + _child_spec = TeletexString + + +class BuiltInStandardAttributes(Sequence): + _fields = [ + ('country_name', CountryName, {'optional': True}), + ('administration_domain_name', AdministrationDomainName, {'optional': True}), + ('network_address', NumericString, {'implicit': 0, 'optional': True}), + ('terminal_identifier', PrintableString, {'implicit': 1, 'optional': True}), + ('private_domain_name', PrivateDomainName, {'explicit': 2, 'optional': True}), + ('organization_name', PrintableString, {'implicit': 3, 'optional': True}), + ('numeric_user_identifier', NumericString, {'implicit': 4, 'optional': True}), + ('personal_name', PersonalName, {'implicit': 5, 'optional': True}), + ('organizational_unit_names', OrganizationalUnitNames, {'implicit': 6, 'optional': True}), + ] + + +class BuiltInDomainDefinedAttribute(Sequence): + _fields = [ + ('type', PrintableString), + ('value', PrintableString), + ] + + +class BuiltInDomainDefinedAttributes(SequenceOf): + _child_spec = BuiltInDomainDefinedAttribute + + +class TeletexDomainDefinedAttribute(Sequence): + _fields = [ + ('type', TeletexString), + ('value', TeletexString), + ] + + +class TeletexDomainDefinedAttributes(SequenceOf): + _child_spec = TeletexDomainDefinedAttribute + + +class PhysicalDeliveryCountryName(Choice): + _alternatives = [ + ('x121_dcc_code', NumericString), + ('iso_3166_alpha2_code', PrintableString), + ] + + +class PostalCode(Choice): + _alternatives = [ + ('numeric_code', NumericString), + ('printable_code', PrintableString), + ] + + +class PDSParameter(Set): + _fields = [ + ('printable_string', PrintableString, {'optional': True}), + ('teletex_string', TeletexString, {'optional': True}), + ] + + +class PrintableAddress(SequenceOf): + _child_spec = PrintableString + + +class UnformattedPostalAddress(Set): + _fields = [ + ('printable_address', PrintableAddress, {'optional': True}), + ('teletex_string', TeletexString, {'optional': True}), + ] + + +class E1634Address(Sequence): + _fields = [ + ('number', NumericString, {'implicit': 0}), + ('sub_address', NumericString, {'implicit': 1, 'optional': True}), + ] + + +class NAddresses(SetOf): + _child_spec = OctetString + + +class PresentationAddress(Sequence): + _fields = [ + ('p_selector', OctetString, {'explicit': 0, 'optional': True}), + ('s_selector', OctetString, {'explicit': 1, 'optional': True}), + ('t_selector', OctetString, {'explicit': 2, 'optional': True}), + ('n_addresses', NAddresses, {'explicit': 3}), + ] + + +class ExtendedNetworkAddress(Choice): + _alternatives = [ + ('e163_4_address', E1634Address), + ('psap_address', PresentationAddress, {'implicit': 0}) + ] + + +class TerminalType(Integer): + _map = { + 3: 'telex', + 4: 'teletex', + 5: 'g3_facsimile', + 6: 'g4_facsimile', + 7: 'ia5_terminal', + 8: 'videotex', + } + + +class ExtensionAttributeType(Integer): + _map = { + 1: 'common_name', + 2: 'teletex_common_name', + 3: 'teletex_organization_name', + 4: 'teletex_personal_name', + 5: 'teletex_organization_unit_names', + 6: 'teletex_domain_defined_attributes', + 7: 'pds_name', + 8: 'physical_delivery_country_name', + 9: 'postal_code', + 10: 'physical_delivery_office_name', + 11: 'physical_delivery_office_number', + 12: 'extension_of_address_components', + 13: 'physical_delivery_personal_name', + 14: 'physical_delivery_organization_name', + 15: 'extension_physical_delivery_address_components', + 16: 'unformatted_postal_address', + 17: 'street_address', + 18: 'post_office_box_address', + 19: 'poste_restante_address', + 20: 'unique_postal_name', + 21: 'local_postal_attributes', + 22: 'extended_network_address', + 23: 'terminal_type', + } + + +class ExtensionAttribute(Sequence): + _fields = [ + ('extension_attribute_type', ExtensionAttributeType, {'implicit': 0}), + ('extension_attribute_value', Any, {'explicit': 1}), + ] + + _oid_pair = ('extension_attribute_type', 'extension_attribute_value') + _oid_specs = { + 'common_name': PrintableString, + 'teletex_common_name': TeletexString, + 'teletex_organization_name': TeletexString, + 'teletex_personal_name': TeletexPersonalName, + 'teletex_organization_unit_names': TeletexOrganizationalUnitNames, + 'teletex_domain_defined_attributes': TeletexDomainDefinedAttributes, + 'pds_name': PrintableString, + 'physical_delivery_country_name': PhysicalDeliveryCountryName, + 'postal_code': PostalCode, + 'physical_delivery_office_name': PDSParameter, + 'physical_delivery_office_number': PDSParameter, + 'extension_of_address_components': PDSParameter, + 'physical_delivery_personal_name': PDSParameter, + 'physical_delivery_organization_name': PDSParameter, + 'extension_physical_delivery_address_components': PDSParameter, + 'unformatted_postal_address': UnformattedPostalAddress, + 'street_address': PDSParameter, + 'post_office_box_address': PDSParameter, + 'poste_restante_address': PDSParameter, + 'unique_postal_name': PDSParameter, + 'local_postal_attributes': PDSParameter, + 'extended_network_address': ExtendedNetworkAddress, + 'terminal_type': TerminalType, + } + + +class ExtensionAttributes(SequenceOf): + _child_spec = ExtensionAttribute + + +class ORAddress(Sequence): + _fields = [ + ('built_in_standard_attributes', BuiltInStandardAttributes), + ('built_in_domain_defined_attributes', BuiltInDomainDefinedAttributes, {'optional': True}), + ('extension_attributes', ExtensionAttributes, {'optional': True}), + ] + + +class EDIPartyName(Sequence): + _fields = [ + ('name_assigner', DirectoryString, {'implicit': 0, 'optional': True}), + ('party_name', DirectoryString, {'implicit': 1}), + ] + + +class GeneralName(Choice): + _alternatives = [ + ('other_name', AnotherName, {'implicit': 0}), + ('rfc822_name', EmailAddress, {'implicit': 1}), + ('dns_name', DNSName, {'implicit': 2}), + ('x400_address', ORAddress, {'implicit': 3}), + ('directory_name', Name, {'explicit': 4}), + ('edi_party_name', EDIPartyName, {'implicit': 5}), + ('uniform_resource_identifier', URI, {'implicit': 6}), + ('ip_address', IPAddress, {'implicit': 7}), + ('registered_id', ObjectIdentifier, {'implicit': 8}), + ] + + def __ne__(self, other): + return not self == other + + def __eq__(self, other): + """ + Does not support other_name, x400_address or edi_party_name + + :param other: + The other GeneralName to compare to + + :return: + A boolean + """ + + if self.name in ('other_name', 'x400_address', 'edi_party_name'): + raise ValueError(unwrap( + ''' + Comparison is not supported for GeneralName objects of + choice %s + ''', + self.name + )) + + if other.name in ('other_name', 'x400_address', 'edi_party_name'): + raise ValueError(unwrap( + ''' + Comparison is not supported for GeneralName objects of choice + %s''', + other.name + )) + + if self.name != other.name: + return False + + return self.chosen == other.chosen + + +class GeneralNames(SequenceOf): + _child_spec = GeneralName + + +class Time(Choice): + _alternatives = [ + ('utc_time', UTCTime), + ('general_time', GeneralizedTime), + ] + + +class Validity(Sequence): + _fields = [ + ('not_before', Time), + ('not_after', Time), + ] + + +class BasicConstraints(Sequence): + _fields = [ + ('ca', Boolean, {'default': False}), + ('path_len_constraint', Integer, {'optional': True}), + ] + + +class AuthorityKeyIdentifier(Sequence): + _fields = [ + ('key_identifier', OctetString, {'implicit': 0, 'optional': True}), + ('authority_cert_issuer', GeneralNames, {'implicit': 1, 'optional': True}), + ('authority_cert_serial_number', Integer, {'implicit': 2, 'optional': True}), + ] + + +class DistributionPointName(Choice): + _alternatives = [ + ('full_name', GeneralNames, {'implicit': 0}), + ('name_relative_to_crl_issuer', RelativeDistinguishedName, {'implicit': 1}), + ] + + +class ReasonFlags(BitString): + _map = { + 0: 'unused', + 1: 'key_compromise', + 2: 'ca_compromise', + 3: 'affiliation_changed', + 4: 'superseded', + 5: 'cessation_of_operation', + 6: 'certificate_hold', + 7: 'privilege_withdrawn', + 8: 'aa_compromise', + } + + +class GeneralSubtree(Sequence): + _fields = [ + ('base', GeneralName), + ('minimum', Integer, {'implicit': 0, 'default': 0}), + ('maximum', Integer, {'implicit': 1, 'optional': True}), + ] + + +class GeneralSubtrees(SequenceOf): + _child_spec = GeneralSubtree + + +class NameConstraints(Sequence): + _fields = [ + ('permitted_subtrees', GeneralSubtrees, {'implicit': 0, 'optional': True}), + ('excluded_subtrees', GeneralSubtrees, {'implicit': 1, 'optional': True}), + ] + + +class DistributionPoint(Sequence): + _fields = [ + ('distribution_point', DistributionPointName, {'explicit': 0, 'optional': True}), + ('reasons', ReasonFlags, {'implicit': 1, 'optional': True}), + ('crl_issuer', GeneralNames, {'implicit': 2, 'optional': True}), + ] + + _url = False + + @property + def url(self): + """ + :return: + None or a unicode string of the distribution point's URL + """ + + if self._url is False: + self._url = None + name = self['distribution_point'] + if name.name != 'full_name': + raise ValueError(unwrap( + ''' + CRL distribution points that are relative to the issuer are + not supported + ''' + )) + + for general_name in name.chosen: + if general_name.name == 'uniform_resource_identifier': + url = general_name.native + if url.lower().startswith(('http://', 'https://', 'ldap://', 'ldaps://')): + self._url = url + break + + return self._url + + +class CRLDistributionPoints(SequenceOf): + _child_spec = DistributionPoint + + +class DisplayText(Choice): + _alternatives = [ + ('ia5_string', IA5String), + ('visible_string', VisibleString), + ('bmp_string', BMPString), + ('utf8_string', UTF8String), + ] + + +class NoticeNumbers(SequenceOf): + _child_spec = Integer + + +class NoticeReference(Sequence): + _fields = [ + ('organization', DisplayText), + ('notice_numbers', NoticeNumbers), + ] + + +class UserNotice(Sequence): + _fields = [ + ('notice_ref', NoticeReference, {'optional': True}), + ('explicit_text', DisplayText, {'optional': True}), + ] + + +class PolicyQualifierId(ObjectIdentifier): + _map = { + '1.3.6.1.5.5.7.2.1': 'certification_practice_statement', + '1.3.6.1.5.5.7.2.2': 'user_notice', + } + + +class PolicyQualifierInfo(Sequence): + _fields = [ + ('policy_qualifier_id', PolicyQualifierId), + ('qualifier', Any), + ] + + _oid_pair = ('policy_qualifier_id', 'qualifier') + _oid_specs = { + 'certification_practice_statement': IA5String, + 'user_notice': UserNotice, + } + + +class PolicyQualifierInfos(SequenceOf): + _child_spec = PolicyQualifierInfo + + +class PolicyIdentifier(ObjectIdentifier): + _map = { + '2.5.29.32.0': 'any_policy', + } + + +class PolicyInformation(Sequence): + _fields = [ + ('policy_identifier', PolicyIdentifier), + ('policy_qualifiers', PolicyQualifierInfos, {'optional': True}) + ] + + +class CertificatePolicies(SequenceOf): + _child_spec = PolicyInformation + + +class PolicyMapping(Sequence): + _fields = [ + ('issuer_domain_policy', PolicyIdentifier), + ('subject_domain_policy', PolicyIdentifier), + ] + + +class PolicyMappings(SequenceOf): + _child_spec = PolicyMapping + + +class PolicyConstraints(Sequence): + _fields = [ + ('require_explicit_policy', Integer, {'implicit': 0, 'optional': True}), + ('inhibit_policy_mapping', Integer, {'implicit': 1, 'optional': True}), + ] + + +class KeyPurposeId(ObjectIdentifier): + _map = { + # https://tools.ietf.org/html/rfc5280#page-45 + '2.5.29.37.0': 'any_extended_key_usage', + '1.3.6.1.5.5.7.3.1': 'server_auth', + '1.3.6.1.5.5.7.3.2': 'client_auth', + '1.3.6.1.5.5.7.3.3': 'code_signing', + '1.3.6.1.5.5.7.3.4': 'email_protection', + '1.3.6.1.5.5.7.3.5': 'ipsec_end_system', + '1.3.6.1.5.5.7.3.6': 'ipsec_tunnel', + '1.3.6.1.5.5.7.3.7': 'ipsec_user', + '1.3.6.1.5.5.7.3.8': 'time_stamping', + '1.3.6.1.5.5.7.3.9': 'ocsp_signing', + # http://tools.ietf.org/html/rfc3029.html#page-9 + '1.3.6.1.5.5.7.3.10': 'dvcs', + # http://tools.ietf.org/html/rfc6268.html#page-16 + '1.3.6.1.5.5.7.3.13': 'eap_over_ppp', + '1.3.6.1.5.5.7.3.14': 'eap_over_lan', + # https://tools.ietf.org/html/rfc5055#page-76 + '1.3.6.1.5.5.7.3.15': 'scvp_server', + '1.3.6.1.5.5.7.3.16': 'scvp_client', + # https://tools.ietf.org/html/rfc4945#page-31 + '1.3.6.1.5.5.7.3.17': 'ipsec_ike', + # https://tools.ietf.org/html/rfc5415#page-38 + '1.3.6.1.5.5.7.3.18': 'capwap_ac', + '1.3.6.1.5.5.7.3.19': 'capwap_wtp', + # https://tools.ietf.org/html/rfc5924#page-8 + '1.3.6.1.5.5.7.3.20': 'sip_domain', + # https://tools.ietf.org/html/rfc6187#page-7 + '1.3.6.1.5.5.7.3.21': 'secure_shell_client', + '1.3.6.1.5.5.7.3.22': 'secure_shell_server', + # https://tools.ietf.org/html/rfc6494#page-7 + '1.3.6.1.5.5.7.3.23': 'send_router', + '1.3.6.1.5.5.7.3.24': 'send_proxied_router', + '1.3.6.1.5.5.7.3.25': 'send_owner', + '1.3.6.1.5.5.7.3.26': 'send_proxied_owner', + # https://tools.ietf.org/html/rfc6402#page-10 + '1.3.6.1.5.5.7.3.27': 'cmc_ca', + '1.3.6.1.5.5.7.3.28': 'cmc_ra', + '1.3.6.1.5.5.7.3.29': 'cmc_archive', + # https://tools.ietf.org/html/draft-ietf-sidr-bgpsec-pki-profiles-15#page-6 + '1.3.6.1.5.5.7.3.30': 'bgpspec_router', + # https://www.ietf.org/proceedings/44/I-D/draft-ietf-ipsec-pki-req-01.txt + '1.3.6.1.5.5.8.2.2': 'ike_intermediate', + # https://msdn.microsoft.com/en-us/library/windows/desktop/aa378132(v=vs.85).aspx + # and https://support.microsoft.com/en-us/kb/287547 + '1.3.6.1.4.1.311.10.3.1': 'microsoft_trust_list_signing', + '1.3.6.1.4.1.311.10.3.2': 'microsoft_time_stamp_signing', + '1.3.6.1.4.1.311.10.3.3': 'microsoft_server_gated', + '1.3.6.1.4.1.311.10.3.3.1': 'microsoft_serialized', + '1.3.6.1.4.1.311.10.3.4': 'microsoft_efs', + '1.3.6.1.4.1.311.10.3.4.1': 'microsoft_efs_recovery', + '1.3.6.1.4.1.311.10.3.5': 'microsoft_whql', + '1.3.6.1.4.1.311.10.3.6': 'microsoft_nt5', + '1.3.6.1.4.1.311.10.3.7': 'microsoft_oem_whql', + '1.3.6.1.4.1.311.10.3.8': 'microsoft_embedded_nt', + '1.3.6.1.4.1.311.10.3.9': 'microsoft_root_list_signer', + '1.3.6.1.4.1.311.10.3.10': 'microsoft_qualified_subordination', + '1.3.6.1.4.1.311.10.3.11': 'microsoft_key_recovery', + '1.3.6.1.4.1.311.10.3.12': 'microsoft_document_signing', + '1.3.6.1.4.1.311.10.3.13': 'microsoft_lifetime_signing', + '1.3.6.1.4.1.311.10.3.14': 'microsoft_mobile_device_software', + # https://support.microsoft.com/en-us/help/287547/object-ids-associated-with-microsoft-cryptography + '1.3.6.1.4.1.311.20.2.2': 'microsoft_smart_card_logon', + # https://opensource.apple.com/source + # - /Security/Security-57031.40.6/Security/libsecurity_keychain/lib/SecPolicy.cpp + # - /libsecurity_cssm/libsecurity_cssm-36064/lib/oidsalg.c + '1.2.840.113635.100.1.2': 'apple_x509_basic', + '1.2.840.113635.100.1.3': 'apple_ssl', + '1.2.840.113635.100.1.4': 'apple_local_cert_gen', + '1.2.840.113635.100.1.5': 'apple_csr_gen', + '1.2.840.113635.100.1.6': 'apple_revocation_crl', + '1.2.840.113635.100.1.7': 'apple_revocation_ocsp', + '1.2.840.113635.100.1.8': 'apple_smime', + '1.2.840.113635.100.1.9': 'apple_eap', + '1.2.840.113635.100.1.10': 'apple_software_update_signing', + '1.2.840.113635.100.1.11': 'apple_ipsec', + '1.2.840.113635.100.1.12': 'apple_ichat', + '1.2.840.113635.100.1.13': 'apple_resource_signing', + '1.2.840.113635.100.1.14': 'apple_pkinit_client', + '1.2.840.113635.100.1.15': 'apple_pkinit_server', + '1.2.840.113635.100.1.16': 'apple_code_signing', + '1.2.840.113635.100.1.17': 'apple_package_signing', + '1.2.840.113635.100.1.18': 'apple_id_validation', + '1.2.840.113635.100.1.20': 'apple_time_stamping', + '1.2.840.113635.100.1.21': 'apple_revocation', + '1.2.840.113635.100.1.22': 'apple_passbook_signing', + '1.2.840.113635.100.1.23': 'apple_mobile_store', + '1.2.840.113635.100.1.24': 'apple_escrow_service', + '1.2.840.113635.100.1.25': 'apple_profile_signer', + '1.2.840.113635.100.1.26': 'apple_qa_profile_signer', + '1.2.840.113635.100.1.27': 'apple_test_mobile_store', + '1.2.840.113635.100.1.28': 'apple_otapki_signer', + '1.2.840.113635.100.1.29': 'apple_test_otapki_signer', + '1.2.840.113625.100.1.30': 'apple_id_validation_record_signing_policy', + '1.2.840.113625.100.1.31': 'apple_smp_encryption', + '1.2.840.113625.100.1.32': 'apple_test_smp_encryption', + '1.2.840.113635.100.1.33': 'apple_server_authentication', + '1.2.840.113635.100.1.34': 'apple_pcs_escrow_service', + # http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.201-2.pdf + '2.16.840.1.101.3.6.8': 'piv_card_authentication', + '2.16.840.1.101.3.6.7': 'piv_content_signing', + # https://tools.ietf.org/html/rfc4556.html + '1.3.6.1.5.2.3.4': 'pkinit_kpclientauth', + '1.3.6.1.5.2.3.5': 'pkinit_kpkdc', + # https://www.adobe.com/devnet-docs/acrobatetk/tools/DigSig/changes.html + '1.2.840.113583.1.1.5': 'adobe_authentic_documents_trust', + # https://www.idmanagement.gov/wp-content/uploads/sites/1171/uploads/fpki-pivi-cert-profiles.pdf + '2.16.840.1.101.3.8.7': 'fpki_pivi_content_signing' + } + + +class ExtKeyUsageSyntax(SequenceOf): + _child_spec = KeyPurposeId + + +class AccessMethod(ObjectIdentifier): + _map = { + '1.3.6.1.5.5.7.48.1': 'ocsp', + '1.3.6.1.5.5.7.48.2': 'ca_issuers', + '1.3.6.1.5.5.7.48.3': 'time_stamping', + '1.3.6.1.5.5.7.48.5': 'ca_repository', + } + + +class AccessDescription(Sequence): + _fields = [ + ('access_method', AccessMethod), + ('access_location', GeneralName), + ] + + +class AuthorityInfoAccessSyntax(SequenceOf): + _child_spec = AccessDescription + + +class SubjectInfoAccessSyntax(SequenceOf): + _child_spec = AccessDescription + + +# https://tools.ietf.org/html/rfc7633 +class Features(SequenceOf): + _child_spec = Integer + + +class EntrustVersionInfo(Sequence): + _fields = [ + ('entrust_vers', GeneralString), + ('entrust_info_flags', BitString) + ] + + +class NetscapeCertificateType(BitString): + _map = { + 0: 'ssl_client', + 1: 'ssl_server', + 2: 'email', + 3: 'object_signing', + 4: 'reserved', + 5: 'ssl_ca', + 6: 'email_ca', + 7: 'object_signing_ca', + } + + +class Version(Integer): + _map = { + 0: 'v1', + 1: 'v2', + 2: 'v3', + } + + +class TPMSpecification(Sequence): + _fields = [ + ('family', UTF8String), + ('level', Integer), + ('revision', Integer), + ] + + +class SetOfTPMSpecification(SetOf): + _child_spec = TPMSpecification + + +class TCGSpecificationVersion(Sequence): + _fields = [ + ('major_version', Integer), + ('minor_version', Integer), + ('revision', Integer), + ] + + +class TCGPlatformSpecification(Sequence): + _fields = [ + ('version', TCGSpecificationVersion), + ('platform_class', OctetString), + ] + + +class SetOfTCGPlatformSpecification(SetOf): + _child_spec = TCGPlatformSpecification + + +class EKGenerationType(Enumerated): + _map = { + 0: 'internal', + 1: 'injected', + 2: 'internal_revocable', + 3: 'injected_revocable', + } + + +class EKGenerationLocation(Enumerated): + _map = { + 0: 'tpm_manufacturer', + 1: 'platform_manufacturer', + 2: 'ek_cert_signer', + } + + +class EKCertificateGenerationLocation(Enumerated): + _map = { + 0: 'tpm_manufacturer', + 1: 'platform_manufacturer', + 2: 'ek_cert_signer', + } + + +class EvaluationAssuranceLevel(Enumerated): + _map = { + 1: 'level1', + 2: 'level2', + 3: 'level3', + 4: 'level4', + 5: 'level5', + 6: 'level6', + 7: 'level7', + } + + +class EvaluationStatus(Enumerated): + _map = { + 0: 'designed_to_meet', + 1: 'evaluation_in_progress', + 2: 'evaluation_completed', + } + + +class StrengthOfFunction(Enumerated): + _map = { + 0: 'basic', + 1: 'medium', + 2: 'high', + } + + +class URIReference(Sequence): + _fields = [ + ('uniform_resource_identifier', IA5String), + ('hash_algorithm', DigestAlgorithm, {'optional': True}), + ('hash_value', BitString, {'optional': True}), + ] + + +class CommonCriteriaMeasures(Sequence): + _fields = [ + ('version', IA5String), + ('assurance_level', EvaluationAssuranceLevel), + ('evaluation_status', EvaluationStatus), + ('plus', Boolean, {'default': False}), + ('strengh_of_function', StrengthOfFunction, {'implicit': 0, 'optional': True}), + ('profile_oid', ObjectIdentifier, {'implicit': 1, 'optional': True}), + ('profile_url', URIReference, {'implicit': 2, 'optional': True}), + ('target_oid', ObjectIdentifier, {'implicit': 3, 'optional': True}), + ('target_uri', URIReference, {'implicit': 4, 'optional': True}), + ] + + +class SecurityLevel(Enumerated): + _map = { + 1: 'level1', + 2: 'level2', + 3: 'level3', + 4: 'level4', + } + + +class FIPSLevel(Sequence): + _fields = [ + ('version', IA5String), + ('level', SecurityLevel), + ('plus', Boolean, {'default': False}), + ] + + +class TPMSecurityAssertions(Sequence): + _fields = [ + ('version', Version, {'default': 'v1'}), + ('field_upgradable', Boolean, {'default': False}), + ('ek_generation_type', EKGenerationType, {'implicit': 0, 'optional': True}), + ('ek_generation_location', EKGenerationLocation, {'implicit': 1, 'optional': True}), + ('ek_certificate_generation_location', EKCertificateGenerationLocation, {'implicit': 2, 'optional': True}), + ('cc_info', CommonCriteriaMeasures, {'implicit': 3, 'optional': True}), + ('fips_level', FIPSLevel, {'implicit': 4, 'optional': True}), + ('iso_9000_certified', Boolean, {'implicit': 5, 'default': False}), + ('iso_9000_uri', IA5String, {'optional': True}), + ] + + +class SetOfTPMSecurityAssertions(SetOf): + _child_spec = TPMSecurityAssertions + + +class SubjectDirectoryAttributeId(ObjectIdentifier): + _map = { + # https://tools.ietf.org/html/rfc2256#page-11 + '2.5.4.52': 'supported_algorithms', + # https://www.trustedcomputinggroup.org/wp-content/uploads/Credential_Profile_EK_V2.0_R14_published.pdf + '2.23.133.2.16': 'tpm_specification', + '2.23.133.2.17': 'tcg_platform_specification', + '2.23.133.2.18': 'tpm_security_assertions', + # https://tools.ietf.org/html/rfc3739#page-18 + '1.3.6.1.5.5.7.9.1': 'pda_date_of_birth', + '1.3.6.1.5.5.7.9.2': 'pda_place_of_birth', + '1.3.6.1.5.5.7.9.3': 'pda_gender', + '1.3.6.1.5.5.7.9.4': 'pda_country_of_citizenship', + '1.3.6.1.5.5.7.9.5': 'pda_country_of_residence', + # https://holtstrom.com/michael/tools/asn1decoder.php + '1.2.840.113533.7.68.29': 'entrust_user_role', + } + + +class SetOfGeneralizedTime(SetOf): + _child_spec = GeneralizedTime + + +class SetOfDirectoryString(SetOf): + _child_spec = DirectoryString + + +class SetOfPrintableString(SetOf): + _child_spec = PrintableString + + +class SupportedAlgorithm(Sequence): + _fields = [ + ('algorithm_identifier', AnyAlgorithmIdentifier), + ('intended_usage', KeyUsage, {'explicit': 0, 'optional': True}), + ('intended_certificate_policies', CertificatePolicies, {'explicit': 1, 'optional': True}), + ] + + +class SetOfSupportedAlgorithm(SetOf): + _child_spec = SupportedAlgorithm + + +class SubjectDirectoryAttribute(Sequence): + _fields = [ + ('type', SubjectDirectoryAttributeId), + ('values', Any), + ] + + _oid_pair = ('type', 'values') + _oid_specs = { + 'supported_algorithms': SetOfSupportedAlgorithm, + 'tpm_specification': SetOfTPMSpecification, + 'tcg_platform_specification': SetOfTCGPlatformSpecification, + 'tpm_security_assertions': SetOfTPMSecurityAssertions, + 'pda_date_of_birth': SetOfGeneralizedTime, + 'pda_place_of_birth': SetOfDirectoryString, + 'pda_gender': SetOfPrintableString, + 'pda_country_of_citizenship': SetOfPrintableString, + 'pda_country_of_residence': SetOfPrintableString, + } + + def _values_spec(self): + type_ = self['type'].native + if type_ in self._oid_specs: + return self._oid_specs[type_] + return SetOf + + _spec_callbacks = { + 'values': _values_spec + } + + +class SubjectDirectoryAttributes(SequenceOf): + _child_spec = SubjectDirectoryAttribute + + +class ExtensionId(ObjectIdentifier): + _map = { + '2.5.29.9': 'subject_directory_attributes', + '2.5.29.14': 'key_identifier', + '2.5.29.15': 'key_usage', + '2.5.29.16': 'private_key_usage_period', + '2.5.29.17': 'subject_alt_name', + '2.5.29.18': 'issuer_alt_name', + '2.5.29.19': 'basic_constraints', + '2.5.29.30': 'name_constraints', + '2.5.29.31': 'crl_distribution_points', + '2.5.29.32': 'certificate_policies', + '2.5.29.33': 'policy_mappings', + '2.5.29.35': 'authority_key_identifier', + '2.5.29.36': 'policy_constraints', + '2.5.29.37': 'extended_key_usage', + '2.5.29.46': 'freshest_crl', + '2.5.29.54': 'inhibit_any_policy', + '1.3.6.1.5.5.7.1.1': 'authority_information_access', + '1.3.6.1.5.5.7.1.11': 'subject_information_access', + # https://tools.ietf.org/html/rfc7633 + '1.3.6.1.5.5.7.1.24': 'tls_feature', + '1.3.6.1.5.5.7.48.1.5': 'ocsp_no_check', + '1.2.840.113533.7.65.0': 'entrust_version_extension', + '2.16.840.1.113730.1.1': 'netscape_certificate_type', + # https://tools.ietf.org/html/rfc6962.html#page-14 + '1.3.6.1.4.1.11129.2.4.2': 'signed_certificate_timestamp_list', + # https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-wcce/3aec3e50-511a-42f9-a5d5-240af503e470 + '1.3.6.1.4.1.311.20.2': 'microsoft_enroll_certtype', + } + + +class Extension(Sequence): + _fields = [ + ('extn_id', ExtensionId), + ('critical', Boolean, {'default': False}), + ('extn_value', ParsableOctetString), + ] + + _oid_pair = ('extn_id', 'extn_value') + _oid_specs = { + 'subject_directory_attributes': SubjectDirectoryAttributes, + 'key_identifier': OctetString, + 'key_usage': KeyUsage, + 'private_key_usage_period': PrivateKeyUsagePeriod, + 'subject_alt_name': GeneralNames, + 'issuer_alt_name': GeneralNames, + 'basic_constraints': BasicConstraints, + 'name_constraints': NameConstraints, + 'crl_distribution_points': CRLDistributionPoints, + 'certificate_policies': CertificatePolicies, + 'policy_mappings': PolicyMappings, + 'authority_key_identifier': AuthorityKeyIdentifier, + 'policy_constraints': PolicyConstraints, + 'extended_key_usage': ExtKeyUsageSyntax, + 'freshest_crl': CRLDistributionPoints, + 'inhibit_any_policy': Integer, + 'authority_information_access': AuthorityInfoAccessSyntax, + 'subject_information_access': SubjectInfoAccessSyntax, + 'tls_feature': Features, + 'ocsp_no_check': Null, + 'entrust_version_extension': EntrustVersionInfo, + 'netscape_certificate_type': NetscapeCertificateType, + 'signed_certificate_timestamp_list': OctetString, + # Not UTF8String as Microsofts docs claim, see: + # https://www.alvestrand.no/objectid/1.3.6.1.4.1.311.20.2.html + 'microsoft_enroll_certtype': BMPString, + } + + +class Extensions(SequenceOf): + _child_spec = Extension + + +class TbsCertificate(Sequence): + _fields = [ + ('version', Version, {'explicit': 0, 'default': 'v1'}), + ('serial_number', Integer), + ('signature', SignedDigestAlgorithm), + ('issuer', Name), + ('validity', Validity), + ('subject', Name), + ('subject_public_key_info', PublicKeyInfo), + ('issuer_unique_id', OctetBitString, {'implicit': 1, 'optional': True}), + ('subject_unique_id', OctetBitString, {'implicit': 2, 'optional': True}), + ('extensions', Extensions, {'explicit': 3, 'optional': True}), + ] + + +class Certificate(Sequence): + _fields = [ + ('tbs_certificate', TbsCertificate), + ('signature_algorithm', SignedDigestAlgorithm), + ('signature_value', OctetBitString), + ] + + _processed_extensions = False + _critical_extensions = None + _subject_directory_attributes_value = None + _key_identifier_value = None + _key_usage_value = None + _subject_alt_name_value = None + _issuer_alt_name_value = None + _basic_constraints_value = None + _name_constraints_value = None + _crl_distribution_points_value = None + _certificate_policies_value = None + _policy_mappings_value = None + _authority_key_identifier_value = None + _policy_constraints_value = None + _freshest_crl_value = None + _inhibit_any_policy_value = None + _extended_key_usage_value = None + _authority_information_access_value = None + _subject_information_access_value = None + _private_key_usage_period_value = None + _tls_feature_value = None + _ocsp_no_check_value = None + _issuer_serial = None + _authority_issuer_serial = False + _crl_distribution_points = None + _delta_crl_distribution_points = None + _valid_domains = None + _valid_ips = None + _self_issued = None + _self_signed = None + _sha1 = None + _sha256 = None + + def _set_extensions(self): + """ + Sets common named extensions to private attributes and creates a list + of critical extensions + """ + + self._critical_extensions = set() + + for extension in self['tbs_certificate']['extensions']: + name = extension['extn_id'].native + attribute_name = '_%s_value' % name + if hasattr(self, attribute_name): + setattr(self, attribute_name, extension['extn_value'].parsed) + if extension['critical'].native: + self._critical_extensions.add(name) + + self._processed_extensions = True + + @property + def critical_extensions(self): + """ + Returns a set of the names (or OID if not a known extension) of the + extensions marked as critical + + :return: + A set of unicode strings + """ + + if not self._processed_extensions: + self._set_extensions() + return self._critical_extensions + + @property + def private_key_usage_period_value(self): + """ + This extension is used to constrain the period over which the subject + private key may be used + + :return: + None or a PrivateKeyUsagePeriod object + """ + + if not self._processed_extensions: + self._set_extensions() + return self._private_key_usage_period_value + + @property + def subject_directory_attributes_value(self): + """ + This extension is used to contain additional identification attributes + about the subject. + + :return: + None or a SubjectDirectoryAttributes object + """ + + if not self._processed_extensions: + self._set_extensions() + return self._subject_directory_attributes_value + + @property + def key_identifier_value(self): + """ + This extension is used to help in creating certificate validation paths. + It contains an identifier that should generally, but is not guaranteed + to, be unique. + + :return: + None or an OctetString object + """ + + if not self._processed_extensions: + self._set_extensions() + return self._key_identifier_value + + @property + def key_usage_value(self): + """ + This extension is used to define the purpose of the public key + contained within the certificate. + + :return: + None or a KeyUsage + """ + + if not self._processed_extensions: + self._set_extensions() + return self._key_usage_value + + @property + def subject_alt_name_value(self): + """ + This extension allows for additional names to be associate with the + subject of the certificate. While it may contain a whole host of + possible names, it is usually used to allow certificates to be used + with multiple different domain names. + + :return: + None or a GeneralNames object + """ + + if not self._processed_extensions: + self._set_extensions() + return self._subject_alt_name_value + + @property + def issuer_alt_name_value(self): + """ + This extension allows associating one or more alternative names with + the issuer of the certificate. + + :return: + None or an x509.GeneralNames object + """ + + if not self._processed_extensions: + self._set_extensions() + return self._issuer_alt_name_value + + @property + def basic_constraints_value(self): + """ + This extension is used to determine if the subject of the certificate + is a CA, and if so, what the maximum number of intermediate CA certs + after this are, before an end-entity certificate is found. + + :return: + None or a BasicConstraints object + """ + + if not self._processed_extensions: + self._set_extensions() + return self._basic_constraints_value + + @property + def name_constraints_value(self): + """ + This extension is used in CA certificates, and is used to limit the + possible names of certificates issued. + + :return: + None or a NameConstraints object + """ + + if not self._processed_extensions: + self._set_extensions() + return self._name_constraints_value + + @property + def crl_distribution_points_value(self): + """ + This extension is used to help in locating the CRL for this certificate. + + :return: + None or a CRLDistributionPoints object + extension + """ + + if not self._processed_extensions: + self._set_extensions() + return self._crl_distribution_points_value + + @property + def certificate_policies_value(self): + """ + This extension defines policies in CA certificates under which + certificates may be issued. In end-entity certificates, the inclusion + of a policy indicates the issuance of the certificate follows the + policy. + + :return: + None or a CertificatePolicies object + """ + + if not self._processed_extensions: + self._set_extensions() + return self._certificate_policies_value + + @property + def policy_mappings_value(self): + """ + This extension allows mapping policy OIDs to other OIDs. This is used + to allow different policies to be treated as equivalent in the process + of validation. + + :return: + None or a PolicyMappings object + """ + + if not self._processed_extensions: + self._set_extensions() + return self._policy_mappings_value + + @property + def authority_key_identifier_value(self): + """ + This extension helps in identifying the public key with which to + validate the authenticity of the certificate. + + :return: + None or an AuthorityKeyIdentifier object + """ + + if not self._processed_extensions: + self._set_extensions() + return self._authority_key_identifier_value + + @property + def policy_constraints_value(self): + """ + This extension is used to control if policy mapping is allowed and + when policies are required. + + :return: + None or a PolicyConstraints object + """ + + if not self._processed_extensions: + self._set_extensions() + return self._policy_constraints_value + + @property + def freshest_crl_value(self): + """ + This extension is used to help locate any available delta CRLs + + :return: + None or an CRLDistributionPoints object + """ + + if not self._processed_extensions: + self._set_extensions() + return self._freshest_crl_value + + @property + def inhibit_any_policy_value(self): + """ + This extension is used to prevent mapping of the any policy to + specific requirements + + :return: + None or a Integer object + """ + + if not self._processed_extensions: + self._set_extensions() + return self._inhibit_any_policy_value + + @property + def extended_key_usage_value(self): + """ + This extension is used to define additional purposes for the public key + beyond what is contained in the basic constraints. + + :return: + None or an ExtKeyUsageSyntax object + """ + + if not self._processed_extensions: + self._set_extensions() + return self._extended_key_usage_value + + @property + def authority_information_access_value(self): + """ + This extension is used to locate the CA certificate used to sign this + certificate, or the OCSP responder for this certificate. + + :return: + None or an AuthorityInfoAccessSyntax object + """ + + if not self._processed_extensions: + self._set_extensions() + return self._authority_information_access_value + + @property + def subject_information_access_value(self): + """ + This extension is used to access information about the subject of this + certificate. + + :return: + None or a SubjectInfoAccessSyntax object + """ + + if not self._processed_extensions: + self._set_extensions() + return self._subject_information_access_value + + @property + def tls_feature_value(self): + """ + This extension is used to list the TLS features a server must respond + with if a client initiates a request supporting them. + + :return: + None or a Features object + """ + + if not self._processed_extensions: + self._set_extensions() + return self._tls_feature_value + + @property + def ocsp_no_check_value(self): + """ + This extension is used on certificates of OCSP responders, indicating + that revocation information for the certificate should never need to + be verified, thus preventing possible loops in path validation. + + :return: + None or a Null object (if present) + """ + + if not self._processed_extensions: + self._set_extensions() + return self._ocsp_no_check_value + + @property + def signature(self): + """ + :return: + A byte string of the signature + """ + + return self['signature_value'].native + + @property + def signature_algo(self): + """ + :return: + A unicode string of "rsassa_pkcs1v15", "rsassa_pss", "dsa", "ecdsa" + """ + + return self['signature_algorithm'].signature_algo + + @property + def hash_algo(self): + """ + :return: + A unicode string of "md2", "md5", "sha1", "sha224", "sha256", + "sha384", "sha512", "sha512_224", "sha512_256" + """ + + return self['signature_algorithm'].hash_algo + + @property + def public_key(self): + """ + :return: + The PublicKeyInfo object for this certificate + """ + + return self['tbs_certificate']['subject_public_key_info'] + + @property + def subject(self): + """ + :return: + The Name object for the subject of this certificate + """ + + return self['tbs_certificate']['subject'] + + @property + def issuer(self): + """ + :return: + The Name object for the issuer of this certificate + """ + + return self['tbs_certificate']['issuer'] + + @property + def serial_number(self): + """ + :return: + An integer of the certificate's serial number + """ + + return self['tbs_certificate']['serial_number'].native + + @property + def key_identifier(self): + """ + :return: + None or a byte string of the certificate's key identifier from the + key identifier extension + """ + + if not self.key_identifier_value: + return None + + return self.key_identifier_value.native + + @property + def issuer_serial(self): + """ + :return: + A byte string of the SHA-256 hash of the issuer concatenated with + the ascii character ":", concatenated with the serial number as + an ascii string + """ + + if self._issuer_serial is None: + self._issuer_serial = self.issuer.sha256 + b':' + str_cls(self.serial_number).encode('ascii') + return self._issuer_serial + + @property + def not_valid_after(self): + """ + :return: + A datetime of latest time when the certificate is still valid + """ + return self['tbs_certificate']['validity']['not_after'].native + + @property + def not_valid_before(self): + """ + :return: + A datetime of the earliest time when the certificate is valid + """ + return self['tbs_certificate']['validity']['not_before'].native + + @property + def authority_key_identifier(self): + """ + :return: + None or a byte string of the key_identifier from the authority key + identifier extension + """ + + if not self.authority_key_identifier_value: + return None + + return self.authority_key_identifier_value['key_identifier'].native + + @property + def authority_issuer_serial(self): + """ + :return: + None or a byte string of the SHA-256 hash of the isser from the + authority key identifier extension concatenated with the ascii + character ":", concatenated with the serial number from the + authority key identifier extension as an ascii string + """ + + if self._authority_issuer_serial is False: + akiv = self.authority_key_identifier_value + if akiv and akiv['authority_cert_issuer'].native: + issuer = self.authority_key_identifier_value['authority_cert_issuer'][0].chosen + # We untag the element since it is tagged via being a choice from GeneralName + issuer = issuer.untag() + authority_serial = self.authority_key_identifier_value['authority_cert_serial_number'].native + self._authority_issuer_serial = issuer.sha256 + b':' + str_cls(authority_serial).encode('ascii') + else: + self._authority_issuer_serial = None + return self._authority_issuer_serial + + @property + def crl_distribution_points(self): + """ + Returns complete CRL URLs - does not include delta CRLs + + :return: + A list of zero or more DistributionPoint objects + """ + + if self._crl_distribution_points is None: + self._crl_distribution_points = self._get_http_crl_distribution_points(self.crl_distribution_points_value) + return self._crl_distribution_points + + @property + def delta_crl_distribution_points(self): + """ + Returns delta CRL URLs - does not include complete CRLs + + :return: + A list of zero or more DistributionPoint objects + """ + + if self._delta_crl_distribution_points is None: + self._delta_crl_distribution_points = self._get_http_crl_distribution_points(self.freshest_crl_value) + return self._delta_crl_distribution_points + + def _get_http_crl_distribution_points(self, crl_distribution_points): + """ + Fetches the DistributionPoint object for non-relative, HTTP CRLs + referenced by the certificate + + :param crl_distribution_points: + A CRLDistributionPoints object to grab the DistributionPoints from + + :return: + A list of zero or more DistributionPoint objects + """ + + output = [] + + if crl_distribution_points is None: + return [] + + for distribution_point in crl_distribution_points: + distribution_point_name = distribution_point['distribution_point'] + if distribution_point_name is VOID: + continue + # RFC 5280 indicates conforming CA should not use the relative form + if distribution_point_name.name == 'name_relative_to_crl_issuer': + continue + # This library is currently only concerned with HTTP-based CRLs + for general_name in distribution_point_name.chosen: + if general_name.name == 'uniform_resource_identifier': + output.append(distribution_point) + + return output + + @property + def ocsp_urls(self): + """ + :return: + A list of zero or more unicode strings of the OCSP URLs for this + cert + """ + + if not self.authority_information_access_value: + return [] + + output = [] + for entry in self.authority_information_access_value: + if entry['access_method'].native == 'ocsp': + location = entry['access_location'] + if location.name != 'uniform_resource_identifier': + continue + url = location.native + if url.lower().startswith(('http://', 'https://', 'ldap://', 'ldaps://')): + output.append(url) + return output + + @property + def valid_domains(self): + """ + :return: + A list of unicode strings of valid domain names for the certificate. + Wildcard certificates will have a domain in the form: *.example.com + """ + + if self._valid_domains is None: + self._valid_domains = [] + + # For the subject alt name extension, we can look at the name of + # the choice selected since it distinguishes between domain names, + # email addresses, IPs, etc + if self.subject_alt_name_value: + for general_name in self.subject_alt_name_value: + if general_name.name == 'dns_name' and general_name.native not in self._valid_domains: + self._valid_domains.append(general_name.native) + + # If there was no subject alt name extension, and the common name + # in the subject looks like a domain, that is considered the valid + # list. This is done because according to + # https://tools.ietf.org/html/rfc6125#section-6.4.4, the common + # name should not be used if the subject alt name is present. + else: + pattern = re.compile('^(\\*\\.)?(?:[a-zA-Z0-9](?:[a-zA-Z0-9\\-]*[a-zA-Z0-9])?\\.)+[a-zA-Z]{2,}$') + for rdn in self.subject.chosen: + for name_type_value in rdn: + if name_type_value['type'].native == 'common_name': + value = name_type_value['value'].native + if pattern.match(value): + self._valid_domains.append(value) + + return self._valid_domains + + @property + def valid_ips(self): + """ + :return: + A list of unicode strings of valid IP addresses for the certificate + """ + + if self._valid_ips is None: + self._valid_ips = [] + + if self.subject_alt_name_value: + for general_name in self.subject_alt_name_value: + if general_name.name == 'ip_address': + self._valid_ips.append(general_name.native) + + return self._valid_ips + + @property + def ca(self): + """ + :return; + A boolean - if the certificate is marked as a CA + """ + + return self.basic_constraints_value and self.basic_constraints_value['ca'].native + + @property + def max_path_length(self): + """ + :return; + None or an integer of the maximum path length + """ + + if not self.ca: + return None + return self.basic_constraints_value['path_len_constraint'].native + + @property + def self_issued(self): + """ + :return: + A boolean - if the certificate is self-issued, as defined by RFC + 5280 + """ + + if self._self_issued is None: + self._self_issued = self.subject == self.issuer + return self._self_issued + + @property + def self_signed(self): + """ + :return: + A unicode string of "no" or "maybe". The "maybe" result will + be returned if the certificate issuer and subject are the same. + If a key identifier and authority key identifier are present, + they will need to match otherwise "no" will be returned. + + To verify is a certificate is truly self-signed, the signature + will need to be verified. See the certvalidator package for + one possible solution. + """ + + if self._self_signed is None: + self._self_signed = 'no' + if self.self_issued: + if self.key_identifier: + if not self.authority_key_identifier: + self._self_signed = 'maybe' + elif self.authority_key_identifier == self.key_identifier: + self._self_signed = 'maybe' + else: + self._self_signed = 'maybe' + return self._self_signed + + @property + def sha1(self): + """ + :return: + The SHA-1 hash of the DER-encoded bytes of this complete certificate + """ + + if self._sha1 is None: + self._sha1 = hashlib.sha1(self.dump()).digest() + return self._sha1 + + @property + def sha1_fingerprint(self): + """ + :return: + A unicode string of the SHA-1 hash, formatted using hex encoding + with a space between each pair of characters, all uppercase + """ + + return ' '.join('%02X' % c for c in bytes_to_list(self.sha1)) + + @property + def sha256(self): + """ + :return: + The SHA-256 hash of the DER-encoded bytes of this complete + certificate + """ + + if self._sha256 is None: + self._sha256 = hashlib.sha256(self.dump()).digest() + return self._sha256 + + @property + def sha256_fingerprint(self): + """ + :return: + A unicode string of the SHA-256 hash, formatted using hex encoding + with a space between each pair of characters, all uppercase + """ + + return ' '.join('%02X' % c for c in bytes_to_list(self.sha256)) + + def is_valid_domain_ip(self, domain_ip): + """ + Check if a domain name or IP address is valid according to the + certificate + + :param domain_ip: + A unicode string of a domain name or IP address + + :return: + A boolean - if the domain or IP is valid for the certificate + """ + + if not isinstance(domain_ip, str_cls): + raise TypeError(unwrap( + ''' + domain_ip must be a unicode string, not %s + ''', + type_name(domain_ip) + )) + + encoded_domain_ip = domain_ip.encode('idna').decode('ascii').lower() + + is_ipv6 = encoded_domain_ip.find(':') != -1 + is_ipv4 = not is_ipv6 and re.match('^\\d+\\.\\d+\\.\\d+\\.\\d+$', encoded_domain_ip) + is_domain = not is_ipv6 and not is_ipv4 + + # Handle domain name checks + if is_domain: + if not self.valid_domains: + return False + + domain_labels = encoded_domain_ip.split('.') + + for valid_domain in self.valid_domains: + encoded_valid_domain = valid_domain.encode('idna').decode('ascii').lower() + valid_domain_labels = encoded_valid_domain.split('.') + + # The domain must be equal in label length to match + if len(valid_domain_labels) != len(domain_labels): + continue + + if valid_domain_labels == domain_labels: + return True + + is_wildcard = self._is_wildcard_domain(encoded_valid_domain) + if is_wildcard and self._is_wildcard_match(domain_labels, valid_domain_labels): + return True + + return False + + # Handle IP address checks + if not self.valid_ips: + return False + + family = socket.AF_INET if is_ipv4 else socket.AF_INET6 + normalized_ip = inet_pton(family, encoded_domain_ip) + + for valid_ip in self.valid_ips: + valid_family = socket.AF_INET if valid_ip.find('.') != -1 else socket.AF_INET6 + normalized_valid_ip = inet_pton(valid_family, valid_ip) + + if normalized_valid_ip == normalized_ip: + return True + + return False + + def _is_wildcard_domain(self, domain): + """ + Checks if a domain is a valid wildcard according to + https://tools.ietf.org/html/rfc6125#section-6.4.3 + + :param domain: + A unicode string of the domain name, where any U-labels from an IDN + have been converted to A-labels + + :return: + A boolean - if the domain is a valid wildcard domain + """ + + # The * character must be present for a wildcard match, and if there is + # most than one, it is an invalid wildcard specification + if domain.count('*') != 1: + return False + + labels = domain.lower().split('.') + + if not labels: + return False + + # Wildcards may only appear in the left-most label + if labels[0].find('*') == -1: + return False + + # Wildcards may not be embedded in an A-label from an IDN + if labels[0][0:4] == 'xn--': + return False + + return True + + def _is_wildcard_match(self, domain_labels, valid_domain_labels): + """ + Determines if the labels in a domain are a match for labels from a + wildcard valid domain name + + :param domain_labels: + A list of unicode strings, with A-label form for IDNs, of the labels + in the domain name to check + + :param valid_domain_labels: + A list of unicode strings, with A-label form for IDNs, of the labels + in a wildcard domain pattern + + :return: + A boolean - if the domain matches the valid domain + """ + + first_domain_label = domain_labels[0] + other_domain_labels = domain_labels[1:] + + wildcard_label = valid_domain_labels[0] + other_valid_domain_labels = valid_domain_labels[1:] + + # The wildcard is only allowed in the first label, so if + # The subsequent labels are not equal, there is no match + if other_domain_labels != other_valid_domain_labels: + return False + + if wildcard_label == '*': + return True + + wildcard_regex = re.compile('^' + wildcard_label.replace('*', '.*') + '$') + if wildcard_regex.match(first_domain_label): + return True + + return False + + +# The structures are taken from the OpenSSL source file x_x509a.c, and specify +# extra information that is added to X.509 certificates to store trust +# information about the certificate. + +class KeyPurposeIdentifiers(SequenceOf): + _child_spec = KeyPurposeId + + +class SequenceOfAlgorithmIdentifiers(SequenceOf): + _child_spec = AlgorithmIdentifier + + +class CertificateAux(Sequence): + _fields = [ + ('trust', KeyPurposeIdentifiers, {'optional': True}), + ('reject', KeyPurposeIdentifiers, {'implicit': 0, 'optional': True}), + ('alias', UTF8String, {'optional': True}), + ('keyid', OctetString, {'optional': True}), + ('other', SequenceOfAlgorithmIdentifiers, {'implicit': 1, 'optional': True}), + ] + + +class TrustedCertificate(Concat): + _child_specs = [Certificate, CertificateAux] diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/changelog.md b/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/changelog.md new file mode 100644 index 00000000..46eb4591 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/changelog.md @@ -0,0 +1,458 @@ +# changelog + +## 1.4.0 + + - `core.ObjectIdentifier` and all derived classes now obey X.660 §7.6 and + thus restrict the first arc to 0 to 2, and the second arc to less than + 40 if the first arc is 0 or 1. This also fixes parsing of OIDs where the + first arc is 2 and the second arc is greater than 39. + - Fixed `keys.PublicKeyInfo.bit_size` to return an int rather than a float + on Python 3 when working with elliptic curve keys + - Fixed the `asn1crypto-tests` sdist on PyPi to work properly to generate a + .whl + +## 1.3.0 + + - Added `encrypt_key_pref` (`1.2.840.113549.1.9.16.2.11`) to + `cms.CMSAttributeType()`, along with related structures + - Added Brainpool curves from RFC 5639 to `keys.NamedCurve()` + - Fixed `x509.Certificate().subject_directory_attributes_value` + - Fixed some incorrectly computed minimum elliptic curve primary key + encoding sizes in `keys.NamedCurve()` + - Fixed a `TypeError` when trying to call `.untag()` or `.copy()` on a + `core.UTCTime()` or `core.GeneralizedTime()`, or a value containing one, + when using Python 2 + +## 1.2.0 + + - Added `asn1crypto.load_order()`, which returns a `list` of unicode strings + of the names of the fully-qualified module names for all of submodules of + the package. The module names are listed in their dependency load order. + This is primarily intended for the sake of implementing hot reloading. + +## 1.1.0 + + - Added User ID (`0.9.2342.19200300.100.1.1`) to `x509.NameType()` + - Added various EC named curves to `keys.NamedCurve()` + +## 1.0.1 + + - Fix an absolute import in `keys` to a relative import + +## 1.0.0 + + - Backwards Compatibility Breaks + - `cms.KeyEncryptionAlgorithmId().native` now returns the value + `"rsaes_pkcs1v15"` for OID `1.2.840.113549.1.1.1` instead of `"rsa"` + - Removed functionality to calculate public key values from private key + values. Alternatives have been added to oscrypto. + - `keys.PrivateKeyInfo().unwrap()` is now + `oscrypto.asymmetric.PrivateKey().unwrap()` + - `keys.PrivateKeyInfo().public_key` is now + `oscrypto.asymmetric.PrivateKey().public_key.unwrap()` + - `keys.PrivateKeyInfo().public_key_info` is now + `oscrypto.asymmetric.PrivateKey().public_key.asn1` + - `keys.PrivateKeyInfo().fingerprint` is now + `oscrypto.asymmetric.PrivateKey().fingerprint` + - `keys.PublicKeyInfo().unwrap()` is now + `oscrypto.asymmetric.PublicKey().unwrap()` + - `keys.PublicKeyInfo().fingerprint` is now + `oscrypto.asymmetric.PublicKey().fingerprint` + - Enhancements + - Significantly improved parsing of `core.UTCTime()` and + `core.GeneralizedTime()` values that include timezones and fractional + seconds + - `util.timezone` has a more complete implementation + - `core.Choice()` may now be constructed by a 2-element tuple or a 1-key + dict + - Added `x509.Certificate().not_valid_before` and + `x509.Certificate().not_valid_after` + - Added `core.BitString().unused_bits` + - Added `keys.NamedCurve.register()` for non-mainstream curve OIDs + - No longer try to load optional performance dependency, `libcrypto`, + on Mac or Linux + - `ocsp.CertStatus().native` will now return meaningful unicode string + values when the status choice is `"good"` or `"unknown"`. Previously + both returned `None` due to the way the structure was designed. + - Add support for explicit RSA SSA PSS (`1.2.840.113549.1.1.10`) to + `keys.PublicKeyInfo()` and `keys.PrivateKeyInfo()` + - Added structures for nested SHA-256 Windows PE signatures to + `cms.CMSAttribute()` + - Added RC4 (`1.2.840.113549.3.4`) to `algos.EncryptionAlgorithmId()` + - Added secp256k1 (`1.3.132.0.10`) to `keys.NamedCurve()` + - Added SHA-3 and SHAKE OIDs to `algos.DigestAlgorithmId()` and + `algos.HmacAlgorithmId()` + - Added RSA ES OAEP (`1.2.840.113549.1.1.7`) to + `cms.KeyEncryptionAlgorithmId()` + - Add IKE Intermediate (`1.3.6.1.5.5.8.2.2`) to `x509.KeyPurposeId()` + - `x509.EmailAddress()` and `x509.DNSName()` now handle invalidly-encoded + values using tags for `core.PrintableString()` and `core.UTF8String()` + - Add parameter structue from RFC 5084 for AES-CCM to + `algos.EncryptionAlgorithm()` + - Improved robustness of parsing broken `core.Sequence()` and + `core.SequenceOf()` values + - Bug Fixes + - Fixed encoding of tag values over 30 + - `core.IntegerBitString()` and `core.IntegerOctetString()` now restrict + values to non-negative integers since negative values are not + implemented + - When copying or dumping a BER-encoded indefinite-length value, + automatically force re-encoding to DER. *To ensure all nested values are + always DER-encoded, `.dump(True)` must be called.* + - Fix `UnboundLocalError` when calling `x509.IPAddress().native` on an + encoded value that has a length of zero + - Fixed passing `class_` via unicode string name to `core.Asn1Value()` + - Fixed a bug where EC private keys with leading null bytes would be + encoded in `keys.ECPrivateKey()` more narrowly than RFC 5915 requires + - Fixed some edge-case bugs in `util.int_to_bytes()` + - `x509.URI()` now only normalizes values when comparing + - Fixed BER-decoding of indefinite length `core.BitString()` + - Fixed DER-encoding of empty `core.BitString()` + - Fixed a missing return value for `core.Choice().parse()` + - Fixed `core.Choice().contents` working when the chosen alternative is a + `core.Choice()` also + - Fixed parsing and encoding of nested `core.Choice()` objects + - Fixed a bug causing `core.ObjectIdentifier().native` to sometimes not + map the OID + - Packaging + - `wheel`, `sdist` and `bdist_egg` releases now all include LICENSE, + `sdist` includes docs + - Added `asn1crypto_tests` package to PyPi + +## 0.24.0 + + - `x509.Certificate().self_signed` will no longer return `"yes"` under any + circumstances. This helps prevent confusion since the library does not + verify the signature. Instead a library like oscrypto should be used + to confirm if a certificate is self-signed. + - Added various OIDs to `x509.KeyPurposeId()` + - Added `x509.Certificate().private_key_usage_period_value` + - Added structures for parsing common subject directory attributes for + X.509 certificates, including `x509.SubjectDirectoryAttribute()` + - Added `algos.AnyAlgorithmIdentifier()` for situations where an + algorithm identifier may contain a digest, signed digest or encryption + algorithm OID + - Fixed a bug with `x509.Certificate().subject_directory_attributes_value` + not returning the correct value + - Fixed a bug where explicitly-tagged fields in a `core.Sequence()` would + not function properly when the field had a default value + - Fixed a bug with type checking in `pem.armor()` + +## 0.23.0 + + - Backwards compatibility break: the `tag_type`, `explicit_tag` and + `explicit_class` attributes on `core.Asn1Value` no longer exist and were + replaced by the `implicit` and `explicit` attributes. Field param dicts + may use the new `explicit` and `implicit` keys, or the old `tag_type` and + `tag` keys. The attribute changes will likely to have little to no impact + since they were primarily an implementation detail. + - Teletex strings used inside of X.509 certificates are now interpreted + using Windows-1252 (a superset of ISO-8859-1). This enables compatibility + with certificates generated by OpenSSL. Strict parsing of Teletex strings + can be retained by using the `x509.strict_teletex()` context manager. + - Added support for nested explicit tagging, supporting values that are + defined with explicit tagging and then added as a field of another + structure using explicit tagging. + - Fixed a `UnicodeDecodeError` when trying to find the (optional) dependency + OpenSSL on Python 2 + - Fixed `next_update` field of `crl.TbsCertList` to be optional + - Added the `x509.Certificate.sha256_fingerprint` property + - `x509.Certificate.ocsp_urls` and `x509.DistributionPoint.url` will now + return `https://`, `ldap://` and `ldaps://` URLs in addition to `http://`. + - Added CMS Attribute Protection definitions from RFC 6211 + - Added OIDs from RFC 6962 + +## 0.22.0 + + - Added `parser.peek()` + - Implemented proper support for BER-encoded indefinite length strings of + all kinds - `core.BitString`, `core.OctetString` and all of the `core` + classes that are natively represented as Python unicode strings + - Fixed a bug with encoding LDAP URLs in `x509.URI` + - Correct `x509.DNSName` to allow a leading `.`, such as when used with + `x509.NameConstraints` + - Fixed an issue with dumping the parsed contents of `core.Any` when + explicitly tagged + - Custom `setup.py clean` now accepts the short `-a` flag for compatibility + +## 0.21.1 + + - Fixed a regression where explicit tagging of a field containing a + `core.Choice` would result in an incorrect header + - Fixed a bug where an `IndexError` was being raised instead of a `ValueError` + when a value was truncated to not include enough bytes for the header + - Corrected the spec for the `value` field of `pkcs12.Attribute` + - Added support for `2.16.840.1.113894.746875.1.1` OID to + `pkcs12.AttributeType` + +## 0.21.0 + + - Added `core.load()` for loading standard, universal types without knowing + the spec beforehand + - Added a `strict` keyword arg to the various `load()` methods and functions in + `core` that checks for trailing data and raises a `ValueError` when found + - Added `asn1crypto.parser` submodule with `emit()` and `parse()` functions for + low-level integration + - Added `asn1crypto.version` for version introspection without side-effects + - Added `algos.DSASignature` + - Fixed a bug with the `_header` attribute of explicitly-tagged values only + containing the explicit tag header instead of both the explicit tag header + and the encapsulated value header + +## 0.20.0 + + - Added support for year 0 + - Added the OID for unique identifier to `x509.NameType` + - Fixed a bug creating the native representation of a `core.BitString` with + leading null bytes + - Added a `.cast()` method to allow converting between different + representations of the same data, e.g. `core.BitString` and + `core.OctetBitString` + +## 0.19.0 + + - Force `algos.DigestAlgorithm` to encoding `parameters` as `Null` when the + `algorithm` is `sha1`, `sha224`, `sha256`, `sha384` or `sha512` per RFC 4055 + - Resolved an issue where a BER-encoded indefinite-length value could not be + properly parsed when embedded inside of a `core.Sequence` or `core.Set` + - Fix `x509.Name.build()` to properly handle dotted OID type values + - `core.Choice` can now be constructed from a single-element `dict` or a + two-element `tuple` to allow for better usability when constructing values + from native Python values + - All `core` objects can now be passed to `print()` with an exception being + raised + +## 0.18.5 + + - Don't fail importing if `ctypes` or `_ctypes` is not available + +## 0.18.4 + + - `core.Sequence` will now raise an exception when an unknown field is provided + - Prevent `UnicodeDecodeError` on Python 2 when calling + `core.OctetString.debug()` + - Corrected the default value for the `hash_algorithm` field of + `tsp.ESSCertIDv2` + - Fixed a bug constructing a `cms.SignedData` object + - Ensure that specific RSA OIDs are always paired with `parameters` set to + `core.Null` + +## 0.18.3 + + - Fixed DER encoding of `core.BitString` when a `_map` is specified (i.e. a + "named bit list") to omit trailing zero bits. This fixes compliance of + various `x509` structures with RFC 5280. + - Corrected a side effect in `keys.PrivateKeyInfo.wrap()` that would cause the + original `keys.ECPrivateKey` structure to become corrupt + - `core.IntegerOctetString` now correctly encodes the integer as an unsigned + value when converting to bytes. Previously decoding was unsigned, but + encoding was signed. + - Fix `util.int_from_bytes()` on Python 2 to return `0` from an empty byte + string + +## 0.18.2 + + - Allow `_perf` submodule to be removed from source tree when embedding + +## 0.18.1 + + - Fixed DER encoding of `core.Set` and `core.SetOf` + - Fixed a bug in `x509.Name.build()` that could generate invalid DER encoding + - Improved exception messages when parsing nested structures via the `.native` + attribute + - `algos.SignedDigestAlgorithm` now ensures the `parameters` are set to + `Null` when `algorithm` is `sha224_rsa`, `sha256_rsa`, `sha384_rsa` or + `sha512_rsa`, per RFC 4055 + - Corrected the definition of `pdf.AdobeTimestamp` to mark the + `requires_auth` field as optional + - Add support for the OID `1.2.840.113549.1.9.16.2.14` to + `cms.CMSAttributeType` + - Improve attribute support for `cms.AttributeCertificateV2` + - Handle `cms.AttributeCertificateV2` when incorrectly tagged as + `cms.AttributeCertificateV1` in `cms.CertificateChoices` + +## 0.18.0 + + - Improved general parsing performance by 10-15% + - Add support for Windows XP + - Added `core.ObjectIdentifier.dotted` attribute to always return dotted + integer unicode string + - Added `core.ObjectIdentifier.map()` and `core.ObjectIdentifier.unmap()` + class methods to map dotted integer unicode strings to user-friendly unicode + strings and back + - Added various Apple OIDs to `x509.KeyPurposeId` + - Fixed a bug parsing nested indefinite-length-encoded values + - Fixed a bug with `x509.Certificate.issuer_alt_name_value` if it is the first + extension queried + - `keys.PublicKeyInfo.bit_size` and `keys.PrivateKeyInfo.bit_size` values are + now rounded up to the next closest multiple of 8 + +## 0.17.1 + + - Fix a bug in `x509.URI` parsing IRIs containing explicit port numbers on + Python 3.x + +## 0.17.0 + + - Added `x509.TrustedCertificate` for handling OpenSSL auxiliary certificate + information appended after a certificate + - Added `core.Concat` class for situations such as `x509.TrustedCertificate` + - Allow "broken" X.509 certificates to use `core.IA5String` where an + `x509.DirectoryString` should be used instead + - Added `keys.PrivateKeyInfo.public_key_info` attribute + - Added a bunch of OIDs to `x509.KeyPurposeId` + +## 0.16.0 + + - Added DH key exchange structures: `algos.KeyExchangeAlgorithm`, + `algos.KeyExchangeAlgorithmId` and `algos.DHParameters`. + - Added DH public key support to `keys.PublicKeyInfo`, + `keys.PublicKeyAlgorithm` and `keys.PublicKeyAlgorithmId`. New structures + include `keys.DomainParameters` and `keys.ValidationParms`. + +## 0.15.1 + + - Fixed `cms.CMSAttributes` to be a `core.SetOf` instead of `core.SequenceOf` + - `cms.CMSAttribute` can now parse unknown attribute contrustruct without an + exception being raised + - `x509.PolicyMapping` now uses `x509.PolicyIdentifier` for field types + - Fixed `pdf.RevocationInfoArchival` so that all fields are now of the type + `core.SequenceOf` instead of a single value + - Added support for the `name_distinguisher`, `telephone_number` and + `organization_identifier` OIDs to `x509.Name` + - Fixed `x509.Name.native` to not accidentally create nested lists when three + of more values for a single type are part of the name + - `x509.Name.human_friendly` now reverses the order of fields when the data + in an `x509.Name` was encoded in most-specific to least-specific order, which + is the opposite of the standard way of least-specific to most-specific. + - `x509.NameType.human_friendly` no longer raises an exception when an + unknown OID is encountered + - Raise a `ValueError` when parsing a `core.Set` and an unknown field is + encountered + +## 0.15.0 + + - Added support for the TLS feature extension from RFC 7633 + - `x509.Name.build()` now accepts a keyword parameter `use_printable` to force + string encoding to be `core.PrintableString` instead of `core.UTF8String` + - Added the functions `util.uri_to_iri()` and `util.iri_to_uri()` + - Changed `algos.SignedDigestAlgorithmId` to use the preferred OIDs when + mapping a unicode string name to an OID. Previously there were multiple OIDs + for some algorithms, and different OIDs would sometimes be selected due to + the fact that the `_map` `dict` is not ordered. + +## 0.14.1 + + - Fixed a bug generating `x509.Certificate.sha1_fingerprint` on Python 2 + +## 0.14.0 + + - Added the `x509.Certificate.sha1_fingerprint` attribute + +## 0.13.0 + + - Backwards compatibility break: the native representation of some + `algos.EncryptionAlgorithmId` values changed. `aes128` became `aes128_cbc`, + `aes192` became `aes192_cbc` and `aes256` became `aes256_cbc`. + - Added more OIDs to `algos.EncryptionAlgorithmId` + - Added more OIDs to `cms.KeyEncryptionAlgorithmId` + - `x509.Name.human_friendly` now properly supports multiple values per + `x509.NameTypeAndValue` object + - Added `ocsp.OCSPResponse.basic_ocsp_response` and + `ocsp.OCSPResponse.response_data` properties + - Added `algos.EncryptionAlgorithm.encryption_mode` property + - Fixed a bug with parsing times containing timezone offsets in Python 3 + - The `attributes` field of `csr.CertificationRequestInfo` is now optional, + for compatibility with other ASN.1 parsers + +## 0.12.2 + + - Correct `core.Sequence.__setitem__()` so set `core.VOID` to an optional + field when `None` is set + +## 0.12.1 + + - Fixed a `unicode`/`bytes` bug with `x509.URI.dump()` on Python 2 + +## 0.12.0 + + - Backwards Compatibility Break: `core.NoValue` was renamed to `core.Void` and + a singleton was added as `core.VOID` + - 20-30% improvement in parsing performance + - `core.Void` now implements `__nonzero__` + - `core.Asn1Value.copy()` now performs a deep copy + - All `core` value classes are now compatible with the `copy` module + - `core.SequenceOf` and `core.SetOf` now implement `__contains__` + - Added `x509.Name.__len__()` + - Fixed a bug where `core.Choice.validate()` would not properly account for + explicit tagging + - `core.Choice.load()` now properly passes itself as the spec when parsing + - `x509.Certificate.crl_distribution_points` no longer throws an exception if + the `DistributionPoint` does not have a value for the `distribution_point` + field + +## 0.11.1 + + - Corrected `core.UTCTime` to interpret year <= 49 as 20xx and >= 50 as 19xx + - `keys.PublicKeyInfo.hash_algo` can now handle DSA keys without parameters + - Added `crl.CertificateList.sha256` and `crl.CertificateList.sha1` + - Fixed `x509.Name.build()` to properly encode `country_name`, `serial_number` + and `dn_qualifier` as `core.PrintableString` as specified in RFC 5280, + instead of `core.UTF8String` + +## 0.11.0 + + - Added Python 2.6 support + - Added ability to compare primitive type objects + - Implemented proper support for internationalized domains, URLs and email + addresses in `x509.Certificate` + - Comparing `x509.Name` and `x509.GeneralName` objects adheres to RFC 5280 + - `x509.Certificate.self_signed` and `x509.Certificate.self_issued` no longer + require that certificate is for a CA + - Fixed `x509.Certificate.valid_domains` to adhere to RFC 6125 + - Added `x509.Certificate.is_valid_domain_ip()` + - Added `x509.Certificate.sha1` and `x509.Certificate.sha256` + - Exposed `util.inet_ntop()` and `util.inet_pton()` for IP address encoding + - Improved exception messages for improper types to include type's module name + +## 0.10.1 + + - Fixed bug in `core.Sequence` affecting Python 2.7 and pypy + +## 0.10.0 + + - Added PEM encoding/decoding functionality + - `core.BitString` now uses item access instead of attributes for named bit + access + - `core.BitString.native` now uses a `set` of unicode strings when `_map` is + present + - Removed `core.Asn1Value.pprint()` method + - Added `core.ParsableOctetString` class + - Added `core.ParsableOctetBitString` class + - Added `core.Asn1Value.copy()` method + - Added `core.Asn1Value.debug()` method + - Added `core.SequenceOf.append()` method + - Added `core.Sequence.spec()` and `core.SequenceOf.spec()` methods + - Added correct IP address parsing to `x509.GeneralName` + - `x509.Name` and `x509.GeneralName` are now compared according to rules in + RFC 5280 + - Added convenience attributes to: + - `algos.SignedDigestAlgorithm` + - `crl.CertificateList` + - `crl.RevokedCertificate` + - `keys.PublicKeyInfo` + - `ocsp.OCSPRequest` + - `ocsp.Request` + - `ocsp.OCSPResponse` + - `ocsp.SingleResponse` + - `x509.Certificate` + - `x509.Name` + - Added `asn1crypto.util` module with the following items: + - `int_to_bytes()` + - `int_from_bytes()` + - `timezone.utc` + - Added `setup.py clean` command + +## 0.9.0 + + - Initial release diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/dev/__init__.py b/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/dev/__init__.py new file mode 100644 index 00000000..a4b5cb47 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/dev/__init__.py @@ -0,0 +1,28 @@ +# coding: utf-8 +from __future__ import unicode_literals, division, absolute_import, print_function + +import os + + +package_name = "asn1crypto" + +other_packages = [ + "oscrypto", + "certbuilder", + "certvalidator", + "crlbuilder", + "csrbuilder", + "ocspbuilder" +] + +task_keyword_args = [] + +requires_oscrypto = False +has_tests_package = True + +package_root = os.path.abspath(os.path.join(os.path.dirname(__file__), '..')) +build_root = os.path.abspath(os.path.join(package_root, '..')) + +md_source_map = {} + +definition_replacements = {} diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/dev/_import.py b/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/dev/_import.py new file mode 100644 index 00000000..caad2190 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/dev/_import.py @@ -0,0 +1,116 @@ +# coding: utf-8 +from __future__ import unicode_literals, division, absolute_import, print_function + +import imp +import sys +import os + +from . import build_root, package_name, package_root + +if sys.version_info < (3,): + getcwd = os.getcwdu +else: + getcwd = os.getcwd + + +def _import_from(mod, path, mod_dir=None, allow_error=False): + """ + Imports a module from a specific path + + :param mod: + A unicode string of the module name + + :param path: + A unicode string to the directory containing the module + + :param mod_dir: + If the sub directory of "path" is different than the "mod" name, + pass the sub directory as a unicode string + + :param allow_error: + If an ImportError should be raised when the module can't be imported + + :return: + None if not loaded, otherwise the module + """ + + if mod_dir is None: + mod_dir = mod.replace('.', os.sep) + + if not os.path.exists(path): + return None + + if not os.path.exists(os.path.join(path, mod_dir)) \ + and not os.path.exists(os.path.join(path, mod_dir + '.py')): + return None + + if os.sep in mod_dir: + append, mod_dir = mod_dir.rsplit(os.sep, 1) + path = os.path.join(path, append) + + try: + mod_info = imp.find_module(mod_dir, [path]) + return imp.load_module(mod, *mod_info) + except ImportError: + if allow_error: + raise + return None + + +def _preload(require_oscrypto, print_info): + """ + Preloads asn1crypto and optionally oscrypto from a local source checkout, + or from a normal install + + :param require_oscrypto: + A bool if oscrypto needs to be preloaded + + :param print_info: + A bool if info about asn1crypto and oscrypto should be printed + """ + + if print_info: + print('Working dir: ' + getcwd()) + print('Python ' + sys.version.replace('\n', '')) + + asn1crypto = None + oscrypto = None + + if require_oscrypto: + # Some CI services don't use the package name for the dir + if package_name == 'oscrypto': + oscrypto_dir = package_root + else: + oscrypto_dir = os.path.join(build_root, 'oscrypto') + oscrypto_tests = None + if os.path.exists(oscrypto_dir): + oscrypto_tests = _import_from('oscrypto_tests', oscrypto_dir, 'tests') + if oscrypto_tests is None: + import oscrypto_tests + asn1crypto, oscrypto = oscrypto_tests.local_oscrypto() + + else: + if package_name == 'asn1crypto': + asn1crypto_dir = package_root + else: + asn1crypto_dir = os.path.join(build_root, 'asn1crypto') + if os.path.exists(asn1crypto_dir): + asn1crypto = _import_from('asn1crypto', asn1crypto_dir) + if asn1crypto is None: + import asn1crypto + + if print_info: + print( + '\nasn1crypto: %s, %s' % ( + asn1crypto.__version__, + os.path.dirname(asn1crypto.__file__) + ) + ) + if require_oscrypto: + print( + 'oscrypto: %s backend, %s, %s' % ( + oscrypto.backend(), + oscrypto.__version__, + os.path.dirname(oscrypto.__file__) + ) + ) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/dev/_pep425.py b/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/dev/_pep425.py new file mode 100644 index 00000000..9591b472 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/dev/_pep425.py @@ -0,0 +1,205 @@ +# coding: utf-8 + +""" +This file was originally derived from +https://github.com/pypa/pip/blob/3e713708088aedb1cde32f3c94333d6e29aaf86e/src/pip/_internal/pep425tags.py + +The following license covers that code: + +Copyright (c) 2008-2018 The pip developers (see AUTHORS.txt file) + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +""" + +from __future__ import unicode_literals, division, absolute_import, print_function + +import sys +import os +import ctypes +import re +import platform + +if sys.version_info >= (2, 7): + import sysconfig + +if sys.version_info < (3,): + str_cls = unicode # noqa +else: + str_cls = str + + +def _pep425_implementation(): + """ + :return: + A 2 character unicode string of the implementation - 'cp' for cpython + or 'pp' for PyPy + """ + + return 'pp' if hasattr(sys, 'pypy_version_info') else 'cp' + + +def _pep425_version(): + """ + :return: + A tuple of integers representing the Python version number + """ + + if hasattr(sys, 'pypy_version_info'): + return (sys.version_info[0], sys.pypy_version_info.major, + sys.pypy_version_info.minor) + else: + return (sys.version_info[0], sys.version_info[1]) + + +def _pep425_supports_manylinux(): + """ + :return: + A boolean indicating if the machine can use manylinux1 packages + """ + + try: + import _manylinux + return bool(_manylinux.manylinux1_compatible) + except (ImportError, AttributeError): + pass + + # Check for glibc 2.5 + try: + proc = ctypes.CDLL(None) + gnu_get_libc_version = proc.gnu_get_libc_version + gnu_get_libc_version.restype = ctypes.c_char_p + + ver = gnu_get_libc_version() + if not isinstance(ver, str_cls): + ver = ver.decode('ascii') + match = re.match(r'(\d+)\.(\d+)', ver) + return match and match.group(1) == '2' and int(match.group(2)) >= 5 + + except (AttributeError): + return False + + +def _pep425_get_abi(): + """ + :return: + A unicode string of the system abi. Will be something like: "cp27m", + "cp33m", etc. + """ + + try: + soabi = sysconfig.get_config_var('SOABI') + if soabi: + if soabi.startswith('cpython-'): + return 'cp%s' % soabi.split('-')[1] + return soabi.replace('.', '_').replace('-', '_') + except (IOError, NameError): + pass + + impl = _pep425_implementation() + suffix = '' + if impl == 'cp': + suffix += 'm' + if sys.maxunicode == 0x10ffff and sys.version_info < (3, 3): + suffix += 'u' + return '%s%s%s' % (impl, ''.join(map(str_cls, _pep425_version())), suffix) + + +def _pep425tags(): + """ + :return: + A list of 3-element tuples with unicode strings or None: + [0] implementation tag - cp33, pp27, cp26, py2, py2.py3 + [1] abi tag - cp26m, None + [2] arch tag - linux_x86_64, macosx_10_10_x85_64, etc + """ + + tags = [] + + versions = [] + version_info = _pep425_version() + major = version_info[:-1] + for minor in range(version_info[-1], -1, -1): + versions.append(''.join(map(str, major + (minor,)))) + + impl = _pep425_implementation() + + abis = [] + abi = _pep425_get_abi() + if abi: + abis.append(abi) + abi3 = _pep425_implementation() == 'cp' and sys.version_info >= (3,) + if abi3: + abis.append('abi3') + abis.append('none') + + if sys.platform == 'darwin': + plat_ver = platform.mac_ver() + ver_parts = plat_ver[0].split('.') + minor = int(ver_parts[1]) + arch = plat_ver[2] + if sys.maxsize == 2147483647: + arch = 'i386' + arches = [] + while minor > 5: + arches.append('macosx_10_%s_%s' % (minor, arch)) + arches.append('macosx_10_%s_intel' % (minor,)) + arches.append('macosx_10_%s_universal' % (minor,)) + minor -= 1 + else: + if sys.platform == 'win32': + if 'amd64' in sys.version.lower(): + arches = ['win_amd64'] + else: + arches = [sys.platform] + elif hasattr(os, 'uname'): + (plat, _, _, _, machine) = os.uname() + plat = plat.lower().replace('/', '') + machine.replace(' ', '_').replace('/', '_') + if plat == 'linux' and sys.maxsize == 2147483647 and 'arm' not in machine: + machine = 'i686' + arch = '%s_%s' % (plat, machine) + if _pep425_supports_manylinux(): + arches = [arch.replace('linux', 'manylinux1'), arch] + else: + arches = [arch] + + for abi in abis: + for arch in arches: + tags.append(('%s%s' % (impl, versions[0]), abi, arch)) + + if abi3: + for version in versions[1:]: + for arch in arches: + tags.append(('%s%s' % (impl, version), 'abi3', arch)) + + for arch in arches: + tags.append(('py%s' % (versions[0][0]), 'none', arch)) + + tags.append(('%s%s' % (impl, versions[0]), 'none', 'any')) + tags.append(('%s%s' % (impl, versions[0][0]), 'none', 'any')) + + for i, version in enumerate(versions): + tags.append(('py%s' % (version,), 'none', 'any')) + if i == 0: + tags.append(('py%s' % (version[0]), 'none', 'any')) + + tags.append(('py2.py3', 'none', 'any')) + + return tags diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/dev/_task.py b/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/dev/_task.py new file mode 100644 index 00000000..5cc257a8 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/dev/_task.py @@ -0,0 +1,163 @@ +# coding: utf-8 +from __future__ import unicode_literals, division, absolute_import, print_function + +import ast +import _ast +import os +import sys + +from . import package_root, task_keyword_args +from ._import import _import_from + + +if sys.version_info < (3,): + byte_cls = str +else: + byte_cls = bytes + + +def _list_tasks(): + """ + Fetches a list of all valid tasks that may be run, and the args they + accept. Does not actually import the task module to prevent errors if a + user does not have the dependencies installed for every task. + + :return: + A list of 2-element tuples: + 0: a unicode string of the task name + 1: a list of dicts containing the parameter definitions + """ + + out = [] + dev_path = os.path.join(package_root, 'dev') + for fname in sorted(os.listdir(dev_path)): + if fname.startswith('.') or fname.startswith('_'): + continue + if not fname.endswith('.py'): + continue + name = fname[:-3] + args = () + + full_path = os.path.join(package_root, 'dev', fname) + with open(full_path, 'rb') as f: + full_code = f.read() + if sys.version_info >= (3,): + full_code = full_code.decode('utf-8') + + task_node = ast.parse(full_code, filename=full_path) + for node in ast.iter_child_nodes(task_node): + if isinstance(node, _ast.Assign): + if len(node.targets) == 1 \ + and isinstance(node.targets[0], _ast.Name) \ + and node.targets[0].id == 'run_args': + args = ast.literal_eval(node.value) + break + + out.append((name, args)) + return out + + +def show_usage(): + """ + Prints to stderr the valid options for invoking tasks + """ + + valid_tasks = [] + for task in _list_tasks(): + usage = task[0] + for run_arg in task[1]: + usage += ' ' + name = run_arg.get('name', '') + if run_arg.get('required', False): + usage += '{%s}' % name + else: + usage += '[%s]' % name + valid_tasks.append(usage) + + out = 'Usage: run.py' + for karg in task_keyword_args: + out += ' [%s=%s]' % (karg['name'], karg['placeholder']) + out += ' (%s)' % ' | '.join(valid_tasks) + + print(out, file=sys.stderr) + sys.exit(1) + + +def _get_arg(num): + """ + :return: + A unicode string of the requested command line arg + """ + + if len(sys.argv) < num + 1: + return None + arg = sys.argv[num] + if isinstance(arg, byte_cls): + arg = arg.decode('utf-8') + return arg + + +def run_task(): + """ + Parses the command line args, invoking the requested task + """ + + arg_num = 1 + task = None + args = [] + kwargs = {} + + # We look for the task name, processing any global task keyword args + # by setting the appropriate env var + while True: + val = _get_arg(arg_num) + if val is None: + break + + next_arg = False + for karg in task_keyword_args: + if val.startswith(karg['name'] + '='): + os.environ[karg['env_var']] = val[len(karg['name']) + 1:] + next_arg = True + break + + if next_arg: + arg_num += 1 + continue + + task = val + break + + if task is None: + show_usage() + + task_mod = _import_from('dev.%s' % task, package_root, allow_error=True) + if task_mod is None: + show_usage() + + run_args = task_mod.__dict__.get('run_args', []) + max_args = arg_num + 1 + len(run_args) + + if len(sys.argv) > max_args: + show_usage() + + for i, run_arg in enumerate(run_args): + val = _get_arg(arg_num + 1 + i) + if val is None: + if run_arg.get('required', False): + show_usage() + break + + if run_arg.get('cast') == 'int' and val.isdigit(): + val = int(val) + + kwarg = run_arg.get('kwarg') + if kwarg: + kwargs[kwarg] = val + else: + args.append(val) + + run = task_mod.__dict__.get('run') + + result = run(*args, **kwargs) + sys.exit(int(not result)) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/dev/build.py b/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/dev/build.py new file mode 100644 index 00000000..48995947 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/dev/build.py @@ -0,0 +1,89 @@ +# coding: utf-8 +from __future__ import unicode_literals, division, absolute_import, print_function + +import imp +import os +import tarfile +import zipfile + +import setuptools.sandbox + +from . import package_root, package_name, has_tests_package + + +def _list_zip(filename): + """ + Prints all of the files in a .zip file + """ + + zf = zipfile.ZipFile(filename, 'r') + for name in zf.namelist(): + print(' %s' % name) + + +def _list_tgz(filename): + """ + Prints all of the files in a .tar.gz file + """ + + tf = tarfile.open(filename, 'r:gz') + for name in tf.getnames(): + print(' %s' % name) + + +def run(): + """ + Creates a sdist .tar.gz and a bdist_wheel --univeral .whl + + :return: + A bool - if the packaging process was successful + """ + + setup = os.path.join(package_root, 'setup.py') + tests_root = os.path.join(package_root, 'tests') + tests_setup = os.path.join(tests_root, 'setup.py') + + # Trying to call setuptools.sandbox.run_setup(setup, ['--version']) + # resulted in a segfault, so we do this instead + module_info = imp.find_module('version', [os.path.join(package_root, package_name)]) + version_mod = imp.load_module('%s.version' % package_name, *module_info) + + pkg_name_info = (package_name, version_mod.__version__) + print('Building %s-%s' % pkg_name_info) + + sdist = '%s-%s.tar.gz' % pkg_name_info + whl = '%s-%s-py2.py3-none-any.whl' % pkg_name_info + setuptools.sandbox.run_setup(setup, ['-q', 'sdist']) + print(' - created %s' % sdist) + _list_tgz(os.path.join(package_root, 'dist', sdist)) + setuptools.sandbox.run_setup(setup, ['-q', 'bdist_wheel', '--universal']) + print(' - created %s' % whl) + _list_zip(os.path.join(package_root, 'dist', whl)) + setuptools.sandbox.run_setup(setup, ['-q', 'clean']) + + if has_tests_package: + print('Building %s_tests-%s' % (package_name, version_mod.__version__)) + + tests_sdist = '%s_tests-%s.tar.gz' % pkg_name_info + tests_whl = '%s_tests-%s-py2.py3-none-any.whl' % pkg_name_info + setuptools.sandbox.run_setup(tests_setup, ['-q', 'sdist']) + print(' - created %s' % tests_sdist) + _list_tgz(os.path.join(tests_root, 'dist', tests_sdist)) + setuptools.sandbox.run_setup(tests_setup, ['-q', 'bdist_wheel', '--universal']) + print(' - created %s' % tests_whl) + _list_zip(os.path.join(tests_root, 'dist', tests_whl)) + setuptools.sandbox.run_setup(tests_setup, ['-q', 'clean']) + + dist_dir = os.path.join(package_root, 'dist') + tests_dist_dir = os.path.join(tests_root, 'dist') + os.rename( + os.path.join(tests_dist_dir, tests_sdist), + os.path.join(dist_dir, tests_sdist) + ) + os.rename( + os.path.join(tests_dist_dir, tests_whl), + os.path.join(dist_dir, tests_whl) + ) + os.rmdir(tests_dist_dir) + + return True diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/dev/ci-driver.py b/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/dev/ci-driver.py new file mode 100644 index 00000000..af9d7e4c --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/dev/ci-driver.py @@ -0,0 +1,73 @@ +# coding: utf-8 +from __future__ import unicode_literals, division, absolute_import, print_function + +import os +import platform +import sys +import subprocess + + +run_args = [ + { + 'name': 'cffi', + 'kwarg': 'cffi', + }, + { + 'name': 'openssl', + 'kwarg': 'openssl', + }, + { + 'name': 'winlegacy', + 'kwarg': 'winlegacy', + }, +] + + +def _write_env(env, key, value): + sys.stdout.write("%s: %s\n" % (key, value)) + sys.stdout.flush() + if sys.version_info < (3,): + env[key.encode('utf-8')] = value.encode('utf-8') + else: + env[key] = value + + +def run(**_): + """ + Runs CI, setting various env vars + + :return: + A bool - if the CI ran successfully + """ + + env = os.environ.copy() + options = set(sys.argv[2:]) + + newline = False + if 'cffi' not in options: + _write_env(env, 'OSCRYPTO_USE_CTYPES', 'true') + newline = True + if 'openssl' in options and sys.platform == 'darwin': + mac_version_info = tuple(map(int, platform.mac_ver()[0].split('.')[:2])) + if mac_version_info < (10, 15): + _write_env(env, 'OSCRYPTO_USE_OPENSSL', '/usr/lib/libcrypto.dylib,/usr/lib/libssl.dylib') + else: + _write_env(env, 'OSCRYPTO_USE_OPENSSL', '/usr/lib/libcrypto.35.dylib,/usr/lib/libssl.35.dylib') + newline = True + if 'winlegacy' in options: + _write_env(env, 'OSCRYPTO_USE_WINLEGACY', 'true') + newline = True + + if newline: + sys.stdout.write("\n") + + proc = subprocess.Popen( + [ + sys.executable, + 'run.py', + 'ci', + ], + env=env + ) + proc.communicate() + return proc.returncode == 0 diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/dev/ci.py b/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/dev/ci.py new file mode 100644 index 00000000..946d5b83 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/dev/ci.py @@ -0,0 +1,57 @@ +# coding: utf-8 +from __future__ import unicode_literals, division, absolute_import, print_function + +import os +import site +import sys + +from . import build_root, requires_oscrypto +from ._import import _preload + + +deps_dir = os.path.join(build_root, 'modularcrypto-deps') +if os.path.exists(deps_dir): + site.addsitedir(deps_dir) + +if sys.version_info[0:2] not in [(2, 6), (3, 2)]: + from .lint import run as run_lint +else: + run_lint = None + +if sys.version_info[0:2] != (3, 2): + from .coverage import run as run_coverage + from .coverage import coverage + run_tests = None + +else: + from .tests import run as run_tests + run_coverage = None + + +def run(): + """ + Runs the linter and tests + + :return: + A bool - if the linter and tests ran successfully + """ + + _preload(requires_oscrypto, True) + + if run_lint: + print('') + lint_result = run_lint() + else: + lint_result = True + + if run_coverage: + print('\nRunning tests (via coverage.py %s)' % coverage.__version__) + sys.stdout.flush() + tests_result = run_coverage(ci=True) + else: + print('\nRunning tests') + sys.stdout.flush() + tests_result = run_tests(ci=True) + sys.stdout.flush() + + return lint_result and tests_result diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/dev/codecov.json b/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/dev/codecov.json new file mode 100644 index 00000000..ad045a7d --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/dev/codecov.json @@ -0,0 +1,5 @@ +{ + "slug": "wbond/asn1crypto", + "token": "98876f5e-6517-4def-85ce-c6e508eee35a", + "disabled": true +} diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/dev/coverage.py b/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/dev/coverage.py new file mode 100644 index 00000000..bb99a4f5 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/dev/coverage.py @@ -0,0 +1,677 @@ +# coding: utf-8 +from __future__ import unicode_literals, division, absolute_import, print_function + +import cgi +import codecs +import coverage +import imp +import json +import os +import unittest +import re +import sys +import tempfile +import time +import platform as _plat +import subprocess +from fnmatch import fnmatch + +from . import package_name, package_root, other_packages + +if sys.version_info < (3,): + str_cls = unicode # noqa + from urllib2 import URLError + from urllib import urlencode + from io import open +else: + str_cls = str + from urllib.error import URLError + from urllib.parse import urlencode + +if sys.version_info < (3, 7): + Pattern = re._pattern_type +else: + Pattern = re.Pattern + + +def run(ci=False): + """ + Runs the tests while measuring coverage + + :param ci: + If coverage is being run in a CI environment - this triggers trying to + run the tests for the rest of modularcrypto and uploading coverage data + + :return: + A bool - if the tests ran successfully + """ + + xml_report_path = os.path.join(package_root, 'coverage.xml') + if os.path.exists(xml_report_path): + os.unlink(xml_report_path) + + cov = coverage.Coverage(include='%s/*.py' % package_name) + cov.start() + + from .tests import run as run_tests + result = run_tests(ci=ci) + print() + + if ci: + suite = unittest.TestSuite() + loader = unittest.TestLoader() + for other_package in other_packages: + for test_class in _load_package_tests(other_package): + suite.addTest(loader.loadTestsFromTestCase(test_class)) + + if suite.countTestCases() > 0: + print('Running tests from other modularcrypto packages') + sys.stdout.flush() + runner_result = unittest.TextTestRunner(stream=sys.stdout, verbosity=1).run(suite) + result = runner_result.wasSuccessful() and result + print() + sys.stdout.flush() + + cov.stop() + cov.save() + + cov.report(show_missing=False) + print() + sys.stdout.flush() + if ci: + cov.xml_report() + + if ci and result and os.path.exists(xml_report_path): + _codecov_submit() + print() + + return result + + +def _load_package_tests(name): + """ + Load the test classes from another modularcrypto package + + :param name: + A unicode string of the other package name + + :return: + A list of unittest.TestCase classes of the tests for the package + """ + + package_dir = os.path.join('..', name) + if not os.path.exists(package_dir): + return [] + + tests_module_info = imp.find_module('tests', [package_dir]) + tests_module = imp.load_module('%s.tests' % name, *tests_module_info) + return tests_module.test_classes() + + +def _env_info(): + """ + :return: + A two-element tuple of unicode strings. The first is the name of the + environment, the second the root of the repo. The environment name + will be one of: "ci-travis", "ci-circle", "ci-appveyor", + "ci-github-actions", "local" + """ + + if os.getenv('CI') == 'true' and os.getenv('TRAVIS') == 'true': + return ('ci-travis', os.getenv('TRAVIS_BUILD_DIR')) + + if os.getenv('CI') == 'True' and os.getenv('APPVEYOR') == 'True': + return ('ci-appveyor', os.getenv('APPVEYOR_BUILD_FOLDER')) + + if os.getenv('CI') == 'true' and os.getenv('CIRCLECI') == 'true': + return ('ci-circle', os.getcwdu() if sys.version_info < (3,) else os.getcwd()) + + if os.getenv('GITHUB_ACTIONS') == 'true': + return ('ci-github-actions', os.getenv('GITHUB_WORKSPACE')) + + return ('local', package_root) + + +def _codecov_submit(): + env_name, root = _env_info() + + try: + with open(os.path.join(root, 'dev/codecov.json'), 'rb') as f: + json_data = json.loads(f.read().decode('utf-8')) + except (OSError, ValueError, UnicodeDecodeError, KeyError): + print('error reading codecov.json') + return + + if json_data.get('disabled'): + return + + if env_name == 'ci-travis': + # http://docs.travis-ci.com/user/environment-variables/#Default-Environment-Variables + build_url = 'https://travis-ci.org/%s/jobs/%s' % (os.getenv('TRAVIS_REPO_SLUG'), os.getenv('TRAVIS_JOB_ID')) + query = { + 'service': 'travis', + 'branch': os.getenv('TRAVIS_BRANCH'), + 'build': os.getenv('TRAVIS_JOB_NUMBER'), + 'pr': os.getenv('TRAVIS_PULL_REQUEST'), + 'job': os.getenv('TRAVIS_JOB_ID'), + 'tag': os.getenv('TRAVIS_TAG'), + 'slug': os.getenv('TRAVIS_REPO_SLUG'), + 'commit': os.getenv('TRAVIS_COMMIT'), + 'build_url': build_url, + } + + elif env_name == 'ci-appveyor': + # http://www.appveyor.com/docs/environment-variables + build_url = 'https://ci.appveyor.com/project/%s/build/%s' % ( + os.getenv('APPVEYOR_REPO_NAME'), + os.getenv('APPVEYOR_BUILD_VERSION') + ) + query = { + 'service': "appveyor", + 'branch': os.getenv('APPVEYOR_REPO_BRANCH'), + 'build': os.getenv('APPVEYOR_JOB_ID'), + 'pr': os.getenv('APPVEYOR_PULL_REQUEST_NUMBER'), + 'job': '/'.join(( + os.getenv('APPVEYOR_ACCOUNT_NAME'), + os.getenv('APPVEYOR_PROJECT_SLUG'), + os.getenv('APPVEYOR_BUILD_VERSION') + )), + 'tag': os.getenv('APPVEYOR_REPO_TAG_NAME'), + 'slug': os.getenv('APPVEYOR_REPO_NAME'), + 'commit': os.getenv('APPVEYOR_REPO_COMMIT'), + 'build_url': build_url, + } + + elif env_name == 'ci-circle': + # https://circleci.com/docs/environment-variables + query = { + 'service': 'circleci', + 'branch': os.getenv('CIRCLE_BRANCH'), + 'build': os.getenv('CIRCLE_BUILD_NUM'), + 'pr': os.getenv('CIRCLE_PR_NUMBER'), + 'job': os.getenv('CIRCLE_BUILD_NUM') + "." + os.getenv('CIRCLE_NODE_INDEX'), + 'tag': os.getenv('CIRCLE_TAG'), + 'slug': os.getenv('CIRCLE_PROJECT_USERNAME') + "/" + os.getenv('CIRCLE_PROJECT_REPONAME'), + 'commit': os.getenv('CIRCLE_SHA1'), + 'build_url': os.getenv('CIRCLE_BUILD_URL'), + } + + elif env_name == 'ci-github-actions': + branch = '' + tag = '' + ref = os.getenv('GITHUB_REF', '') + if ref.startswith('refs/tags/'): + tag = ref[10:] + elif ref.startswith('refs/heads/'): + branch = ref[11:] + + impl = _plat.python_implementation() + major, minor = _plat.python_version_tuple()[0:2] + build_name = '%s %s %s.%s' % (_platform_name(), impl, major, minor) + + query = { + 'service': 'custom', + 'token': json_data['token'], + 'branch': branch, + 'tag': tag, + 'slug': os.getenv('GITHUB_REPOSITORY'), + 'commit': os.getenv('GITHUB_SHA'), + 'build_url': 'https://github.com/wbond/oscrypto/commit/%s/checks' % os.getenv('GITHUB_SHA'), + 'name': 'GitHub Actions %s on %s' % (build_name, os.getenv('RUNNER_OS')) + } + + else: + if not os.path.exists(os.path.join(root, '.git')): + print('git repository not found, not submitting coverage data') + return + git_status = _git_command(['status', '--porcelain'], root) + if git_status != '': + print('git repository has uncommitted changes, not submitting coverage data') + return + + branch = _git_command(['rev-parse', '--abbrev-ref', 'HEAD'], root) + commit = _git_command(['rev-parse', '--verify', 'HEAD'], root) + tag = _git_command(['name-rev', '--tags', '--name-only', commit], root) + impl = _plat.python_implementation() + major, minor = _plat.python_version_tuple()[0:2] + build_name = '%s %s %s.%s' % (_platform_name(), impl, major, minor) + query = { + 'branch': branch, + 'commit': commit, + 'slug': json_data['slug'], + 'token': json_data['token'], + 'build': build_name, + } + if tag != 'undefined': + query['tag'] = tag + + payload = 'PLATFORM=%s\n' % _platform_name() + payload += 'PYTHON_VERSION=%s %s\n' % (_plat.python_version(), _plat.python_implementation()) + if 'oscrypto' in sys.modules: + payload += 'OSCRYPTO_BACKEND=%s\n' % sys.modules['oscrypto'].backend() + payload += '<<<<<< ENV\n' + + for path in _list_files(root): + payload += path + '\n' + payload += '<<<<<< network\n' + + payload += '# path=coverage.xml\n' + with open(os.path.join(root, 'coverage.xml'), 'r', encoding='utf-8') as f: + payload += f.read() + '\n' + payload += '<<<<<< EOF\n' + + url = 'https://codecov.io/upload/v4' + headers = { + 'Accept': 'text/plain' + } + filtered_query = {} + for key in query: + value = query[key] + if value == '' or value is None: + continue + filtered_query[key] = value + + print('Submitting coverage info to codecov.io') + info = _do_request( + 'POST', + url, + headers, + query_params=filtered_query + ) + + encoding = info[1] or 'utf-8' + text = info[2].decode(encoding).strip() + parts = text.split() + upload_url = parts[1] + + headers = { + 'Content-Type': 'text/plain', + 'x-amz-acl': 'public-read', + 'x-amz-storage-class': 'REDUCED_REDUNDANCY' + } + + print('Uploading coverage data to codecov.io S3 bucket') + _do_request( + 'PUT', + upload_url, + headers, + data=payload.encode('utf-8') + ) + + +def _git_command(params, cwd): + """ + Executes a git command, returning the output + + :param params: + A list of the parameters to pass to git + + :param cwd: + The working directory to execute git in + + :return: + A 2-element tuple of (stdout, stderr) + """ + + proc = subprocess.Popen( + ['git'] + params, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + cwd=cwd + ) + stdout, stderr = proc.communicate() + code = proc.wait() + if code != 0: + e = OSError('git exit code was non-zero') + e.stdout = stdout + raise e + return stdout.decode('utf-8').strip() + + +def _parse_env_var_file(data): + """ + Parses a basic VAR="value data" file contents into a dict + + :param data: + A unicode string of the file data + + :return: + A dict of parsed name/value data + """ + + output = {} + for line in data.splitlines(): + line = line.strip() + if not line or '=' not in line: + continue + parts = line.split('=') + if len(parts) != 2: + continue + name = parts[0] + value = parts[1] + if len(value) > 1: + if value[0] == '"' and value[-1] == '"': + value = value[1:-1] + output[name] = value + return output + + +def _platform_name(): + """ + Returns information about the current operating system and version + + :return: + A unicode string containing the OS name and version + """ + + if sys.platform == 'darwin': + version = _plat.mac_ver()[0] + _plat_ver_info = tuple(map(int, version.split('.'))) + if _plat_ver_info < (10, 12): + name = 'OS X' + else: + name = 'macOS' + return '%s %s' % (name, version) + + elif sys.platform == 'win32': + _win_ver = sys.getwindowsversion() + _plat_ver_info = (_win_ver[0], _win_ver[1]) + return 'Windows %s' % _plat.win32_ver()[0] + + elif sys.platform in ['linux', 'linux2']: + if os.path.exists('/etc/os-release'): + with open('/etc/os-release', 'r', encoding='utf-8') as f: + pairs = _parse_env_var_file(f.read()) + if 'NAME' in pairs and 'VERSION_ID' in pairs: + return '%s %s' % (pairs['NAME'], pairs['VERSION_ID']) + version = pairs['VERSION_ID'] + elif 'PRETTY_NAME' in pairs: + return pairs['PRETTY_NAME'] + elif 'NAME' in pairs: + return pairs['NAME'] + else: + raise ValueError('No suitable version info found in /etc/os-release') + elif os.path.exists('/etc/lsb-release'): + with open('/etc/lsb-release', 'r', encoding='utf-8') as f: + pairs = _parse_env_var_file(f.read()) + if 'DISTRIB_DESCRIPTION' in pairs: + return pairs['DISTRIB_DESCRIPTION'] + else: + raise ValueError('No suitable version info found in /etc/lsb-release') + else: + return 'Linux' + + else: + return '%s %s' % (_plat.system(), _plat.release()) + + +def _list_files(root): + """ + Lists all of the files in a directory, taking into account any .gitignore + file that is present + + :param root: + A unicode filesystem path + + :return: + A list of unicode strings, containing paths of all files not ignored + by .gitignore with root, using relative paths + """ + + dir_patterns, file_patterns = _gitignore(root) + paths = [] + prefix = os.path.abspath(root) + os.sep + for base, dirs, files in os.walk(root): + for d in dirs: + for dir_pattern in dir_patterns: + if fnmatch(d, dir_pattern): + dirs.remove(d) + break + for f in files: + skip = False + for file_pattern in file_patterns: + if fnmatch(f, file_pattern): + skip = True + break + if skip: + continue + full_path = os.path.join(base, f) + if full_path[:len(prefix)] == prefix: + full_path = full_path[len(prefix):] + paths.append(full_path) + return sorted(paths) + + +def _gitignore(root): + """ + Parses a .gitignore file and returns patterns to match dirs and files. + Only basic gitignore patterns are supported. Pattern negation, ** wildcards + and anchored patterns are not currently implemented. + + :param root: + A unicode string of the path to the git repository + + :return: + A 2-element tuple: + - 0: a list of unicode strings to match against dirs + - 1: a list of unicode strings to match against dirs and files + """ + + gitignore_path = os.path.join(root, '.gitignore') + + dir_patterns = ['.git'] + file_patterns = [] + + if not os.path.exists(gitignore_path): + return (dir_patterns, file_patterns) + + with open(gitignore_path, 'r', encoding='utf-8') as f: + for line in f.readlines(): + line = line.strip() + if not line: + continue + if line.startswith('#'): + continue + if '**' in line: + raise NotImplementedError('gitignore ** wildcards are not implemented') + if line.startswith('!'): + raise NotImplementedError('gitignore pattern negation is not implemented') + if line.startswith('/'): + raise NotImplementedError('gitignore anchored patterns are not implemented') + if line.startswith('\\#'): + line = '#' + line[2:] + if line.startswith('\\!'): + line = '!' + line[2:] + if line.endswith('/'): + dir_patterns.append(line[:-1]) + else: + file_patterns.append(line) + + return (dir_patterns, file_patterns) + + +def _do_request(method, url, headers, data=None, query_params=None, timeout=20): + """ + Performs an HTTP request + + :param method: + A unicode string of 'POST' or 'PUT' + + :param url; + A unicode string of the URL to request + + :param headers: + A dict of unicode strings, where keys are header names and values are + the header values. + + :param data: + A dict of unicode strings (to be encoded as + application/x-www-form-urlencoded), or a byte string of data. + + :param query_params: + A dict of unicode keys and values to pass as query params + + :param timeout: + An integer number of seconds to use as the timeout + + :return: + A 3-element tuple: + - 0: A unicode string of the response content-type + - 1: A unicode string of the response encoding, or None + - 2: A byte string of the response body + """ + + if query_params: + url += '?' + urlencode(query_params).replace('+', '%20') + + if isinstance(data, dict): + data_bytes = {} + for key in data: + data_bytes[key.encode('utf-8')] = data[key].encode('utf-8') + data = urlencode(data_bytes) + headers['Content-Type'] = 'application/x-www-form-urlencoded' + if isinstance(data, str_cls): + raise TypeError('data must be a byte string') + + try: + tempfd, tempf_path = tempfile.mkstemp('-coverage') + os.write(tempfd, data or b'') + os.close(tempfd) + + if sys.platform == 'win32': + powershell_exe = os.path.join('system32\\WindowsPowerShell\\v1.0\\powershell.exe') + code = "[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12;" + code += "$wc = New-Object Net.WebClient;" + for key in headers: + code += "$wc.Headers.add('%s','%s');" % (key, headers[key]) + code += "$out = $wc.UploadFile('%s', '%s', '%s');" % (url, method, tempf_path) + code += "[System.Text.Encoding]::GetEncoding('ISO-8859-1').GetString($wc.ResponseHeaders.ToByteArray())" + + # To properly obtain bytes, we use BitConverter to get hex dash + # encoding (e.g. AE-09-3F) and they decode in python + code += " + [System.BitConverter]::ToString($out);" + stdout, stderr = _execute( + [powershell_exe, '-Command', code], + os.getcwd(), + re.compile(r'Unable to connect to|TLS|Internal Server Error'), + 6 + ) + if stdout[-2:] == b'\r\n' and b'\r\n\r\n' in stdout: + # An extra trailing crlf is added at the end by powershell + stdout = stdout[0:-2] + parts = stdout.split(b'\r\n\r\n', 1) + if len(parts) == 2: + stdout = parts[0] + b'\r\n\r\n' + codecs.decode(parts[1].replace(b'-', b''), 'hex_codec') + + else: + args = [ + 'curl', + '--http1.1', + '--connect-timeout', '5', + '--request', + method, + '--location', + '--silent', + '--show-error', + '--include', + # Prevent curl from asking for an HTTP "100 Continue" response + '--header', 'Expect:' + ] + for key in headers: + args.append('--header') + args.append("%s: %s" % (key, headers[key])) + args.append('--data-binary') + args.append('@%s' % tempf_path) + args.append(url) + stdout, stderr = _execute( + args, + os.getcwd(), + re.compile(r'Failed to connect to|TLS|SSLRead|outstanding|cleanly|timed out'), + 6 + ) + finally: + if tempf_path and os.path.exists(tempf_path): + os.remove(tempf_path) + + if len(stderr) > 0: + raise URLError("Error %sing %s:\n%s" % (method, url, stderr)) + + parts = stdout.split(b'\r\n\r\n', 1) + if len(parts) != 2: + raise URLError("Error %sing %s, response data malformed:\n%s" % (method, url, stdout)) + header_block, body = parts + + content_type_header = None + content_len_header = None + for hline in header_block.decode('iso-8859-1').splitlines(): + hline_parts = hline.split(':', 1) + if len(hline_parts) != 2: + continue + name, val = hline_parts + name = name.strip().lower() + val = val.strip() + if name == 'content-type': + content_type_header = val + if name == 'content-length': + content_len_header = val + + if content_type_header is None and content_len_header != '0': + raise URLError("Error %sing %s, no content-type header:\n%s" % (method, url, stdout)) + + if content_type_header is None: + content_type = 'text/plain' + encoding = 'utf-8' + else: + content_type, params = cgi.parse_header(content_type_header) + encoding = params.get('charset') + + return (content_type, encoding, body) + + +def _execute(params, cwd, retry=None, retries=0, backoff=2): + """ + Executes a subprocess + + :param params: + A list of the executable and arguments to pass to it + + :param cwd: + The working directory to execute the command in + + :param retry: + If this string is present in stderr, or regex pattern matches stderr, retry the operation + + :param retries: + An integer number of times to retry + + :return: + A 2-element tuple of (stdout, stderr) + """ + + proc = subprocess.Popen( + params, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + cwd=cwd + ) + stdout, stderr = proc.communicate() + code = proc.wait() + if code != 0: + if retry and retries > 0: + stderr_str = stderr.decode('utf-8') + if isinstance(retry, Pattern): + if retry.search(stderr_str) is not None: + time.sleep(backoff) + return _execute(params, cwd, retry, retries - 1, backoff * 2) + elif retry in stderr_str: + time.sleep(backoff) + return _execute(params, cwd, retry, retries - 1, backoff * 2) + e = OSError('subprocess exit code for "%s" was %d: %s' % (' '.join(params), code, stderr)) + e.stdout = stdout + e.stderr = stderr + raise e + return (stdout, stderr) + + +if __name__ == '__main__': + _codecov_submit() diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/dev/deps.py b/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/dev/deps.py new file mode 100644 index 00000000..a4c641b3 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/dev/deps.py @@ -0,0 +1,712 @@ +# coding: utf-8 +from __future__ import unicode_literals, division, absolute_import, print_function + +import os +import subprocess +import sys +import shutil +import re +import json +import tarfile +import zipfile + +from . import package_root, build_root, other_packages +from ._pep425 import _pep425tags, _pep425_implementation + +if sys.version_info < (3,): + str_cls = unicode # noqa +else: + str_cls = str + + +def run(): + """ + Installs required development dependencies. Uses git to checkout other + modularcrypto repos for more accurate coverage data. + """ + + deps_dir = os.path.join(build_root, 'modularcrypto-deps') + if os.path.exists(deps_dir): + shutil.rmtree(deps_dir, ignore_errors=True) + os.mkdir(deps_dir) + + try: + print("Staging ci dependencies") + _stage_requirements(deps_dir, os.path.join(package_root, 'requires', 'ci')) + + print("Checking out modularcrypto packages for coverage") + for other_package in other_packages: + pkg_url = 'https://github.com/wbond/%s.git' % other_package + pkg_dir = os.path.join(build_root, other_package) + if os.path.exists(pkg_dir): + print("%s is already present" % other_package) + continue + print("Cloning %s" % pkg_url) + _execute(['git', 'clone', pkg_url], build_root) + print() + + except (Exception): + if os.path.exists(deps_dir): + shutil.rmtree(deps_dir, ignore_errors=True) + raise + + return True + + +def _download(url, dest): + """ + Downloads a URL to a directory + + :param url: + The URL to download + + :param dest: + The path to the directory to save the file in + + :return: + The filesystem path to the saved file + """ + + print('Downloading %s' % url) + filename = os.path.basename(url) + dest_path = os.path.join(dest, filename) + + if sys.platform == 'win32': + powershell_exe = os.path.join('system32\\WindowsPowerShell\\v1.0\\powershell.exe') + code = "[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12;" + code += "(New-Object Net.WebClient).DownloadFile('%s', '%s');" % (url, dest_path) + _execute([powershell_exe, '-Command', code], dest, 'Unable to connect to') + + else: + _execute( + ['curl', '-L', '--silent', '--show-error', '-O', url], + dest, + 'Failed to connect to' + ) + + return dest_path + + +def _tuple_from_ver(version_string): + """ + :param version_string: + A unicode dotted version string + + :return: + A tuple of integers + """ + + match = re.search( + r'(\d+(?:\.\d+)*)' + r'([-._]?(?:alpha|a|beta|b|preview|pre|c|rc)\.?\d*)?' + r'(-\d+|(?:[-._]?(?:rev|r|post)\.?\d*))?' + r'([-._]?dev\.?\d*)?', + version_string + ) + if not match: + return tuple() + + nums = tuple(map(int, match.group(1).split('.'))) + + pre = match.group(2) + if pre: + pre = pre.replace('alpha', 'a') + pre = pre.replace('beta', 'b') + pre = pre.replace('preview', 'rc') + pre = pre.replace('pre', 'rc') + pre = re.sub(r'(?<!r)c', 'rc', pre) + pre = pre.lstrip('._-') + pre_dig_match = re.search(r'\d+', pre) + if pre_dig_match: + pre_dig = int(pre_dig_match.group(0)) + else: + pre_dig = 0 + pre = pre.rstrip('0123456789') + + pre_num = { + 'a': -3, + 'b': -2, + 'rc': -1, + }[pre] + + pre_tup = (pre_num, pre_dig) + else: + pre_tup = tuple() + + post = match.group(3) + if post: + post_dig_match = re.search(r'\d+', post) + if post_dig_match: + post_dig = int(post_dig_match.group(0)) + else: + post_dig = 0 + post_tup = (1, post_dig) + else: + post_tup = tuple() + + dev = match.group(4) + if dev: + dev_dig_match = re.search(r'\d+', dev) + if dev_dig_match: + dev_dig = int(dev_dig_match.group(0)) + else: + dev_dig = 0 + dev_tup = (-4, dev_dig) + else: + dev_tup = tuple() + + normalized = [nums] + if pre_tup: + normalized.append(pre_tup) + if post_tup: + normalized.append(post_tup) + if dev_tup: + normalized.append(dev_tup) + # This ensures regular releases happen after dev and prerelease, but + # before post releases + if not pre_tup and not post_tup and not dev_tup: + normalized.append((0, 0)) + + return tuple(normalized) + + +def _open_archive(path): + """ + :param path: + A unicode string of the filesystem path to the archive + + :return: + An archive object + """ + + if path.endswith('.zip'): + return zipfile.ZipFile(path, 'r') + return tarfile.open(path, 'r') + + +def _list_archive_members(archive): + """ + :param archive: + An archive from _open_archive() + + :return: + A list of info objects to be used with _info_name() and _extract_info() + """ + + if isinstance(archive, zipfile.ZipFile): + return archive.infolist() + return archive.getmembers() + + +def _archive_single_dir(archive): + """ + Check if all members of the archive are in a single top-level directory + + :param archive: + An archive from _open_archive() + + :return: + None if not a single top level directory in archive, otherwise a + unicode string of the top level directory name + """ + + common_root = None + for info in _list_archive_members(archive): + fn = _info_name(info) + if fn in set(['.', '/']): + continue + sep = None + if '/' in fn: + sep = '/' + elif '\\' in fn: + sep = '\\' + if sep is None: + root_dir = fn + else: + root_dir, _ = fn.split(sep, 1) + if common_root is None: + common_root = root_dir + else: + if common_root != root_dir: + return None + return common_root + + +def _info_name(info): + """ + Returns a normalized file path for an archive info object + + :param info: + An info object from _list_archive_members() + + :return: + A unicode string with all directory separators normalized to "/" + """ + + if isinstance(info, zipfile.ZipInfo): + return info.filename.replace('\\', '/') + return info.name.replace('\\', '/') + + +def _extract_info(archive, info): + """ + Extracts the contents of an archive info object + + ;param archive: + An archive from _open_archive() + + :param info: + An info object from _list_archive_members() + + :return: + None, or a byte string of the file contents + """ + + if isinstance(archive, zipfile.ZipFile): + fn = info.filename + is_dir = fn.endswith('/') or fn.endswith('\\') + out = archive.read(info) + if is_dir and out == b'': + return None + return out + + info_file = archive.extractfile(info) + if info_file: + return info_file.read() + return None + + +def _extract_package(deps_dir, pkg_path, pkg_dir): + """ + Extract a .whl, .zip, .tar.gz or .tar.bz2 into a package path to + use when running CI tasks + + :param deps_dir: + A unicode string of the directory the package should be extracted to + + :param pkg_path: + A unicode string of the path to the archive + + :param pkg_dir: + If running setup.py, change to this dir first - a unicode string + """ + + if pkg_path.endswith('.exe'): + try: + zf = None + zf = zipfile.ZipFile(pkg_path, 'r') + # Exes have a PLATLIB folder containing everything we want + for zi in zf.infolist(): + if not zi.filename.startswith('PLATLIB'): + continue + data = _extract_info(zf, zi) + if data is not None: + dst_path = os.path.join(deps_dir, zi.filename[8:]) + dst_dir = os.path.dirname(dst_path) + if not os.path.exists(dst_dir): + os.makedirs(dst_dir) + with open(dst_path, 'wb') as f: + f.write(data) + finally: + if zf: + zf.close() + return + + if pkg_path.endswith('.whl'): + try: + zf = None + zf = zipfile.ZipFile(pkg_path, 'r') + # Wheels contain exactly what we need and nothing else + zf.extractall(deps_dir) + finally: + if zf: + zf.close() + return + + # Source archives may contain a bunch of other things, including mutliple + # packages, so we must use setup.py/setuptool to install/extract it + + ar = None + staging_dir = os.path.join(deps_dir, '_staging') + try: + ar = _open_archive(pkg_path) + + common_root = _archive_single_dir(ar) + + members = [] + for info in _list_archive_members(ar): + dst_rel_path = _info_name(info) + if common_root is not None: + dst_rel_path = dst_rel_path[len(common_root) + 1:] + members.append((info, dst_rel_path)) + + if not os.path.exists(staging_dir): + os.makedirs(staging_dir) + + for info, rel_path in members: + info_data = _extract_info(ar, info) + # Dirs won't return a file + if info_data is not None: + dst_path = os.path.join(staging_dir, rel_path) + dst_dir = os.path.dirname(dst_path) + if not os.path.exists(dst_dir): + os.makedirs(dst_dir) + with open(dst_path, 'wb') as f: + f.write(info_data) + + setup_dir = staging_dir + if pkg_dir: + setup_dir = os.path.join(staging_dir, pkg_dir) + + root = os.path.abspath(os.path.join(deps_dir, '..')) + install_lib = os.path.basename(deps_dir) + + # Ensure we pick up previously installed packages when running + # setup.py. This is important for things like setuptools. + env = os.environ.copy() + if sys.version_info >= (3,): + env['PYTHONPATH'] = deps_dir + else: + env[b'PYTHONPATH'] = deps_dir.encode('utf-8') + + _execute( + [ + sys.executable, + 'setup.py', + 'install', + '--root=%s' % root, + '--install-lib=%s' % install_lib, + '--no-compile' + ], + setup_dir, + env=env + ) + + finally: + if ar: + ar.close() + if staging_dir: + shutil.rmtree(staging_dir) + + +def _sort_pep440_versions(releases, include_prerelease): + """ + :param releases: + A list of unicode string PEP 440 version numbers + + :param include_prerelease: + A boolean indicating if prerelease versions should be included + + :return: + A sorted generator of 2-element tuples: + 0: A unicode string containing a PEP 440 version number + 1: A tuple of tuples containing integers - this is the output of + _tuple_from_ver() for the PEP 440 version number and is intended + for comparing versions + """ + + parsed_versions = [] + for v in releases: + t = _tuple_from_ver(v) + if not include_prerelease and t[1][0] < 0: + continue + parsed_versions.append((v, t)) + + return sorted(parsed_versions, key=lambda v: v[1]) + + +def _is_valid_python_version(python_version, requires_python): + """ + Verifies the "python_version" and "requires_python" keys from a PyPi + download record are applicable to the current version of Python + + :param python_version: + The "python_version" value from a PyPi download JSON structure. This + should be one of: "py2", "py3", "py2.py3" or "source". + + :param requires_python: + The "requires_python" value from a PyPi download JSON structure. This + will be None, or a comma-separated list of conditions that must be + true. Ex: ">=3.5", "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" + """ + + if python_version == "py2" and sys.version_info >= (3,): + return False + if python_version == "py3" and sys.version_info < (3,): + return False + + if requires_python is not None: + + def _ver_tuples(ver_str): + ver_str = ver_str.strip() + if ver_str.endswith('.*'): + ver_str = ver_str[:-2] + cond_tup = tuple(map(int, ver_str.split('.'))) + return (sys.version_info[:len(cond_tup)], cond_tup) + + for part in map(str_cls.strip, requires_python.split(',')): + if part.startswith('!='): + sys_tup, cond_tup = _ver_tuples(part[2:]) + if sys_tup == cond_tup: + return False + elif part.startswith('>='): + sys_tup, cond_tup = _ver_tuples(part[2:]) + if sys_tup < cond_tup: + return False + elif part.startswith('>'): + sys_tup, cond_tup = _ver_tuples(part[1:]) + if sys_tup <= cond_tup: + return False + elif part.startswith('<='): + sys_tup, cond_tup = _ver_tuples(part[2:]) + if sys_tup > cond_tup: + return False + elif part.startswith('<'): + sys_tup, cond_tup = _ver_tuples(part[1:]) + if sys_tup >= cond_tup: + return False + elif part.startswith('=='): + sys_tup, cond_tup = _ver_tuples(part[2:]) + if sys_tup != cond_tup: + return False + + return True + + +def _locate_suitable_download(downloads): + """ + :param downloads: + A list of dicts containing a key "url", "python_version" and + "requires_python" + + :return: + A unicode string URL, or None if not a valid release for the current + version of Python + """ + + valid_tags = _pep425tags() + + exe_suffix = None + if sys.platform == 'win32' and _pep425_implementation() == 'cp': + win_arch = 'win32' if sys.maxsize == 2147483647 else 'win-amd64' + version_info = sys.version_info + exe_suffix = '.%s-py%d.%d.exe' % (win_arch, version_info[0], version_info[1]) + + wheels = {} + whl = None + tar_bz2 = None + tar_gz = None + exe = None + for download in downloads: + if not _is_valid_python_version(download.get('python_version'), download.get('requires_python')): + continue + + if exe_suffix and download['url'].endswith(exe_suffix): + exe = download['url'] + if download['url'].endswith('.whl'): + parts = os.path.basename(download['url']).split('-') + tag_impl = parts[-3] + tag_abi = parts[-2] + tag_arch = parts[-1].split('.')[0] + wheels[(tag_impl, tag_abi, tag_arch)] = download['url'] + if download['url'].endswith('.tar.bz2'): + tar_bz2 = download['url'] + if download['url'].endswith('.tar.gz'): + tar_gz = download['url'] + + # Find the most-specific wheel possible + for tag in valid_tags: + if tag in wheels: + whl = wheels[tag] + break + + if exe_suffix and exe: + url = exe + elif whl: + url = whl + elif tar_bz2: + url = tar_bz2 + elif tar_gz: + url = tar_gz + else: + return None + + return url + + +def _stage_requirements(deps_dir, path): + """ + Installs requirements without using Python to download, since + different services are limiting to TLS 1.2, and older version of + Python do not support that + + :param deps_dir: + A unicode path to a temporary diretory to use for downloads + + :param path: + A unicode filesystem path to a requirements file + """ + + packages = _parse_requires(path) + for p in packages: + url = None + pkg = p['pkg'] + pkg_sub_dir = None + if p['type'] == 'url': + anchor = None + if '#' in pkg: + pkg, anchor = pkg.split('#', 1) + if '&' in anchor: + parts = anchor.split('&') + else: + parts = [anchor] + for part in parts: + param, value = part.split('=') + if param == 'subdirectory': + pkg_sub_dir = value + + if pkg.endswith('.zip') or pkg.endswith('.tar.gz') or pkg.endswith('.tar.bz2') or pkg.endswith('.whl'): + url = pkg + else: + raise Exception('Unable to install package from URL that is not an archive') + else: + pypi_json_url = 'https://pypi.org/pypi/%s/json' % pkg + json_dest = _download(pypi_json_url, deps_dir) + with open(json_dest, 'rb') as f: + pkg_info = json.loads(f.read().decode('utf-8')) + if os.path.exists(json_dest): + os.remove(json_dest) + + if p['type'] == '==': + if p['ver'] not in pkg_info['releases']: + raise Exception('Unable to find version %s of %s' % (p['ver'], pkg)) + url = _locate_suitable_download(pkg_info['releases'][p['ver']]) + if not url: + raise Exception('Unable to find a compatible download of %s == %s' % (pkg, p['ver'])) + else: + p_ver_tup = _tuple_from_ver(p['ver']) + for ver_str, ver_tup in reversed(_sort_pep440_versions(pkg_info['releases'], False)): + if p['type'] == '>=' and ver_tup < p_ver_tup: + break + url = _locate_suitable_download(pkg_info['releases'][ver_str]) + if url: + break + if not url: + if p['type'] == '>=': + raise Exception('Unable to find a compatible download of %s >= %s' % (pkg, p['ver'])) + else: + raise Exception('Unable to find a compatible download of %s' % pkg) + + local_path = _download(url, deps_dir) + + _extract_package(deps_dir, local_path, pkg_sub_dir) + + os.remove(local_path) + + +def _parse_requires(path): + """ + Does basic parsing of pip requirements files, to allow for + using something other than Python to do actual TLS requests + + :param path: + A path to a requirements file + + :return: + A list of dict objects containing the keys: + - 'type' ('any', 'url', '==', '>=') + - 'pkg' + - 'ver' (if 'type' == '==' or 'type' == '>=') + """ + + python_version = '.'.join(map(str_cls, sys.version_info[0:2])) + sys_platform = sys.platform + + packages = [] + + with open(path, 'rb') as f: + contents = f.read().decode('utf-8') + + for line in re.split(r'\r?\n', contents): + line = line.strip() + if not len(line): + continue + if re.match(r'^\s*#', line): + continue + if ';' in line: + package, cond = line.split(';', 1) + package = package.strip() + cond = cond.strip() + cond = cond.replace('sys_platform', repr(sys_platform)) + cond = cond.replace('python_version', repr(python_version)) + if not eval(cond): + continue + else: + package = line.strip() + + if re.match(r'^\s*-r\s*', package): + sub_req_file = re.sub(r'^\s*-r\s*', '', package) + sub_req_file = os.path.abspath(os.path.join(os.path.dirname(path), sub_req_file)) + packages.extend(_parse_requires(sub_req_file)) + continue + + if re.match(r'https?://', package): + packages.append({'type': 'url', 'pkg': package}) + continue + + if '>=' in package: + parts = package.split('>=') + package = parts[0].strip() + ver = parts[1].strip() + packages.append({'type': '>=', 'pkg': package, 'ver': ver}) + continue + + if '==' in package: + parts = package.split('==') + package = parts[0].strip() + ver = parts[1].strip() + packages.append({'type': '==', 'pkg': package, 'ver': ver}) + continue + + if re.search(r'[^ a-zA-Z0-9\-]', package): + raise Exception('Unsupported requirements format version constraint: %s' % package) + + packages.append({'type': 'any', 'pkg': package}) + + return packages + + +def _execute(params, cwd, retry=None, env=None): + """ + Executes a subprocess + + :param params: + A list of the executable and arguments to pass to it + + :param cwd: + The working directory to execute the command in + + :param retry: + If this string is present in stderr, retry the operation + + :return: + A 2-element tuple of (stdout, stderr) + """ + + proc = subprocess.Popen( + params, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + cwd=cwd, + env=env + ) + stdout, stderr = proc.communicate() + code = proc.wait() + if code != 0: + if retry and retry in stderr.decode('utf-8'): + return _execute(params, cwd) + e = OSError('subprocess exit code for "%s" was %d: %s' % (' '.join(params), code, stderr)) + e.stdout = stdout + e.stderr = stderr + raise e + return (stdout, stderr) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/dev/lint.py b/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/dev/lint.py new file mode 100644 index 00000000..cbfa9a7c --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/dev/lint.py @@ -0,0 +1,38 @@ +# coding: utf-8 +from __future__ import unicode_literals, division, absolute_import, print_function + +import os + +from . import package_name, package_root + +import flake8 +if not hasattr(flake8, '__version_info__') or flake8.__version_info__ < (3,): + from flake8.engine import get_style_guide +else: + from flake8.api.legacy import get_style_guide + + +def run(): + """ + Runs flake8 lint + + :return: + A bool - if flake8 did not find any errors + """ + + print('Running flake8 %s' % flake8.__version__) + + flake8_style = get_style_guide(config_file=os.path.join(package_root, 'tox.ini')) + + paths = [] + for _dir in [package_name, 'dev', 'tests']: + for root, _, filenames in os.walk(_dir): + for filename in filenames: + if not filename.endswith('.py'): + continue + paths.append(os.path.join(root, filename)) + report = flake8_style.check_files(paths) + success = report.total_errors == 0 + if success: + print('OK') + return success diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/dev/pyenv-install.py b/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/dev/pyenv-install.py new file mode 100644 index 00000000..f43d6ded --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/dev/pyenv-install.py @@ -0,0 +1,144 @@ +# coding: utf-8 +from __future__ import unicode_literals, division, absolute_import, print_function + +import os +import subprocess +import sys + + +run_args = [ + { + 'name': 'version', + 'kwarg': 'version', + }, +] + + +def _write_env(env, key, value): + sys.stdout.write("%s: %s\n" % (key, value)) + sys.stdout.flush() + if sys.version_info < (3,): + env[key.encode('utf-8')] = value.encode('utf-8') + else: + env[key] = value + + +def run(version=None): + """ + Installs a version of Python on Mac using pyenv + + :return: + A bool - if Python was installed successfully + """ + + if sys.platform == 'win32': + raise ValueError('pyenv-install is not designed for Windows') + + if version not in set(['2.6', '3.3']): + raise ValueError('Invalid version: %r' % version) + + python_path = os.path.expanduser('~/.pyenv/versions/%s/bin' % version) + if os.path.exists(os.path.join(python_path, 'python')): + print(python_path) + return True + + stdout = "" + stderr = "" + + proc = subprocess.Popen( + 'command -v pyenv', + shell=True, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE + ) + proc.communicate() + if proc.returncode != 0: + proc = subprocess.Popen( + ['brew', 'install', 'pyenv'], + stdout=subprocess.PIPE, + stderr=subprocess.PIPE + ) + so, se = proc.communicate() + stdout += so.decode('utf-8') + stderr += se.decode('utf-8') + if proc.returncode != 0: + print(stdout) + print(stderr, file=sys.stderr) + return False + + pyenv_script = './%s' % version + try: + with open(pyenv_script, 'wb') as f: + if version == '2.6': + contents = '#require_gcc\n' \ + 'install_package "openssl-1.0.2k" "https://www.openssl.org/source/old/1.0.2/openssl-1.0.2k.tar.gz' \ + '#6b3977c61f2aedf0f96367dcfb5c6e578cf37e7b8d913b4ecb6643c3cb88d8c0" mac_openssl\n' \ + 'install_package "readline-8.0" "https://ftpmirror.gnu.org/readline/readline-8.0.tar.gz' \ + '#e339f51971478d369f8a053a330a190781acb9864cf4c541060f12078948e461" mac_readline' \ + ' --if has_broken_mac_readline\n' \ + 'install_package "Python-2.6.9" "https://www.python.org/ftp/python/2.6.9/Python-2.6.9.tgz' \ + '#7277b1285d8a82f374ef6ebaac85b003266f7939b3f2a24a3af52f9523ac94db" standard verify_py26' + elif version == '3.3': + contents = '#require_gcc\n' \ + 'install_package "openssl-1.0.2k" "https://www.openssl.org/source/old/1.0.2/openssl-1.0.2k.tar.gz' \ + '#6b3977c61f2aedf0f96367dcfb5c6e578cf37e7b8d913b4ecb6643c3cb88d8c0" mac_openssl\n' \ + 'install_package "readline-8.0" "https://ftpmirror.gnu.org/readline/readline-8.0.tar.gz' \ + '#e339f51971478d369f8a053a330a190781acb9864cf4c541060f12078948e461" mac_readline' \ + ' --if has_broken_mac_readline\n' \ + 'install_package "Python-3.3.7" "https://www.python.org/ftp/python/3.3.7/Python-3.3.7.tar.xz' \ + '#85f60c327501c36bc18c33370c14d472801e6af2f901dafbba056f61685429fe" standard verify_py33' + f.write(contents.encode('utf-8')) + + args = ['pyenv', 'install', pyenv_script] + stdin = None + stdin_contents = None + env = os.environ.copy() + + if version == '2.6': + _write_env(env, 'PYTHON_CONFIGURE_OPTS', '--enable-ipv6') + stdin = subprocess.PIPE + stdin_contents = '--- configure 2021-08-05 20:17:26.000000000 -0400\n' \ + '+++ configure 2021-08-05 20:21:30.000000000 -0400\n' \ + '@@ -10300,17 +10300,8 @@\n' \ + ' rm -f core conftest.err conftest.$ac_objext \\\n' \ + ' conftest$ac_exeext conftest.$ac_ext\n' \ + ' \n' \ + '-if test "$buggygetaddrinfo" = "yes"; then\n' \ + '-\tif test "$ipv6" = "yes"; then\n' \ + '-\t\techo \'Fatal: You must get working getaddrinfo() function.\'\n' \ + '-\t\techo \' or you can specify "--disable-ipv6"\'.\n' \ + '-\t\texit 1\n' \ + '-\tfi\n' \ + '-else\n' \ + '-\n' \ + ' $as_echo "#define HAVE_GETADDRINFO 1" >>confdefs.h\n' \ + ' \n' \ + '-fi\n' \ + ' for ac_func in getnameinfo\n' \ + ' do :\n' \ + ' ac_fn_c_check_func "$LINENO" "getnameinfo" "ac_cv_func_getnameinfo"' + stdin_contents = stdin_contents.encode('ascii') + args.append('--patch') + + proc = subprocess.Popen( + args, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + stdin=stdin, + env=env + ) + so, se = proc.communicate(stdin_contents) + stdout += so.decode('utf-8') + stderr += se.decode('utf-8') + + if proc.returncode != 0: + print(stdout) + print(stderr, file=sys.stderr) + return False + + finally: + if os.path.exists(pyenv_script): + os.unlink(pyenv_script) + + print(python_path) + return True diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/dev/python-install.py b/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/dev/python-install.py new file mode 100644 index 00000000..99302aea --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/dev/python-install.py @@ -0,0 +1,77 @@ +# coding: utf-8 +from __future__ import unicode_literals, division, absolute_import, print_function + +import os +import shutil +import subprocess +import sys +from urllib.parse import urlparse +from urllib.request import urlopen + + +run_args = [ + { + 'name': 'version', + 'kwarg': 'version', + }, + { + 'name': 'arch', + 'kwarg': 'arch', + }, +] + + +def run(version=None, arch=None): + """ + Installs a version of Python on Windows + + :return: + A bool - if Python was installed successfully + """ + + if sys.platform != 'win32': + raise ValueError('python-install is only designed for Windows') + + if version not in set(['2.6', '3.3']): + raise ValueError('Invalid version: %r' % version) + + if arch not in set(['x86', 'x64']): + raise ValueError('Invalid arch: %r' % arch) + + if version == '2.6': + if arch == 'x64': + url = 'https://www.python.org/ftp/python/2.6.6/python-2.6.6.amd64.msi' + else: + url = 'https://www.python.org/ftp/python/2.6.6/python-2.6.6.msi' + else: + if arch == 'x64': + url = 'https://www.python.org/ftp/python/3.3.5/python-3.3.5.amd64.msi' + else: + url = 'https://www.python.org/ftp/python/3.3.5/python-3.3.5.msi' + + home = os.environ.get('USERPROFILE') + msi_filename = os.path.basename(urlparse(url).path) + msi_path = os.path.join(home, msi_filename) + install_path = os.path.join(os.environ.get('LOCALAPPDATA'), 'Python%s-%s' % (version, arch)) + + if os.path.exists(os.path.join(install_path, 'python.exe')): + print(install_path) + return True + + try: + with urlopen(url) as r, open(msi_path, 'wb') as f: + shutil.copyfileobj(r, f) + + proc = subprocess.Popen( + 'msiexec /passive /a %s TARGETDIR=%s' % (msi_filename, install_path), + shell=True, + cwd=home + ) + proc.communicate() + + finally: + if os.path.exists(msi_path): + os.unlink(msi_path) + + print(install_path) + return True diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/dev/release.py b/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/dev/release.py new file mode 100644 index 00000000..a854196b --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/dev/release.py @@ -0,0 +1,60 @@ +# coding: utf-8 +from __future__ import unicode_literals, division, absolute_import, print_function + +import subprocess +import sys + +import twine.cli + +from . import package_name, package_root, has_tests_package +from .build import run as build + + +def run(): + """ + Creates a sdist .tar.gz and a bdist_wheel --univeral .whl and uploads + them to pypi + + :return: + A bool - if the packaging and upload process was successful + """ + + git_wc_proc = subprocess.Popen( + ['git', 'status', '--porcelain', '-uno'], + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + cwd=package_root + ) + git_wc_status, _ = git_wc_proc.communicate() + + if len(git_wc_status) > 0: + print(git_wc_status.decode('utf-8').rstrip(), file=sys.stderr) + print('Unable to perform release since working copy is not clean', file=sys.stderr) + return False + + git_tag_proc = subprocess.Popen( + ['git', 'tag', '-l', '--contains', 'HEAD'], + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + cwd=package_root + ) + tag, tag_error = git_tag_proc.communicate() + + if len(tag_error) > 0: + print(tag_error.decode('utf-8').rstrip(), file=sys.stderr) + print('Error looking for current git tag', file=sys.stderr) + return False + + if len(tag) == 0: + print('No git tag found on HEAD', file=sys.stderr) + return False + + tag = tag.decode('ascii').strip() + + build() + + twine.cli.dispatch(['upload', 'dist/%s-%s*' % (package_name, tag)]) + if has_tests_package: + twine.cli.dispatch(['upload', 'dist/%s_tests-%s*' % (package_name, tag)]) + + return True diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/dev/tests.py b/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/dev/tests.py new file mode 100644 index 00000000..101c6917 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/dev/tests.py @@ -0,0 +1,91 @@ +# coding: utf-8 +from __future__ import unicode_literals, division, absolute_import, print_function + +import unittest +import re +import sys +import warnings + +from . import requires_oscrypto +from ._import import _preload + +from tests import test_classes + +if sys.version_info < (3,): + range = xrange # noqa + from cStringIO import StringIO +else: + from io import StringIO + + +run_args = [ + { + 'name': 'regex', + 'kwarg': 'matcher', + }, + { + 'name': 'repeat_count', + 'kwarg': 'repeat', + 'cast': 'int', + }, +] + + +def run(matcher=None, repeat=1, ci=False): + """ + Runs the tests + + :param matcher: + A unicode string containing a regular expression to use to filter test + names by. A value of None will cause no filtering. + + :param repeat: + An integer - the number of times to run the tests + + :param ci: + A bool, indicating if the tests are being run as part of CI + + :return: + A bool - if the tests succeeded + """ + + _preload(requires_oscrypto, not ci) + + warnings.filterwarnings("error") + + loader = unittest.TestLoader() + # We have to manually track the list of applicable tests because for + # some reason with Python 3.4 on Windows, the tests in a suite are replaced + # with None after being executed. This breaks the repeat functionality. + test_list = [] + for test_class in test_classes(): + if matcher: + names = loader.getTestCaseNames(test_class) + for name in names: + if re.search(matcher, name): + test_list.append(test_class(name)) + else: + test_list.append(loader.loadTestsFromTestCase(test_class)) + + stream = sys.stdout + verbosity = 1 + if matcher and repeat == 1: + verbosity = 2 + elif repeat > 1: + stream = StringIO() + + for _ in range(0, repeat): + suite = unittest.TestSuite() + for test in test_list: + suite.addTest(test) + result = unittest.TextTestRunner(stream=stream, verbosity=verbosity).run(suite) + + if len(result.errors) > 0 or len(result.failures) > 0: + if repeat > 1: + print(stream.getvalue()) + return False + + if repeat > 1: + stream.truncate(0) + + return True diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/dev/version.py b/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/dev/version.py new file mode 100644 index 00000000..fe37d3d4 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/dev/version.py @@ -0,0 +1,88 @@ +# coding: utf-8 +from __future__ import unicode_literals, division, absolute_import, print_function + +import codecs +import os +import re + +from . import package_root, package_name, has_tests_package + + +run_args = [ + { + 'name': 'pep440_version', + 'required': True + }, +] + + +def run(new_version): + """ + Updates the package version in the various locations + + :param new_version: + A unicode string of the new library version as a PEP 440 version + + :return: + A bool - if the version number was successfully bumped + """ + + # We use a restricted form of PEP 440 versions + version_match = re.match( + r'(\d+)\.(\d+)\.(\d)+(?:\.((?:dev|a|b|rc)\d+))?$', + new_version + ) + if not version_match: + raise ValueError('Invalid PEP 440 version: %s' % new_version) + + new_version_info = ( + int(version_match.group(1)), + int(version_match.group(2)), + int(version_match.group(3)), + ) + if version_match.group(4): + new_version_info += (version_match.group(4),) + + version_path = os.path.join(package_root, package_name, 'version.py') + setup_path = os.path.join(package_root, 'setup.py') + setup_tests_path = os.path.join(package_root, 'tests', 'setup.py') + tests_path = os.path.join(package_root, 'tests', '__init__.py') + + file_paths = [version_path, setup_path] + if has_tests_package: + file_paths.extend([setup_tests_path, tests_path]) + + for file_path in file_paths: + orig_source = '' + with codecs.open(file_path, 'r', encoding='utf-8') as f: + orig_source = f.read() + + found = 0 + new_source = '' + for line in orig_source.splitlines(True): + if line.startswith('__version__ = '): + found += 1 + new_source += '__version__ = %r\n' % new_version + elif line.startswith('__version_info__ = '): + found += 1 + new_source += '__version_info__ = %r\n' % (new_version_info,) + elif line.startswith('PACKAGE_VERSION = '): + found += 1 + new_source += 'PACKAGE_VERSION = %r\n' % new_version + else: + new_source += line + + if found == 0: + raise ValueError('Did not find any versions in %s' % file_path) + + s = 's' if found > 1 else '' + rel_path = file_path[len(package_root) + 1:] + was_were = 'was' if found == 1 else 'were' + if new_source != orig_source: + print('Updated %d version%s in %s' % (found, s, rel_path)) + with codecs.open(file_path, 'w', encoding='utf-8') as f: + f.write(new_source) + else: + print('%d version%s in %s %s up-to-date' % (found, s, rel_path, was_were)) + + return True diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/readme.md b/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/readme.md new file mode 100644 index 00000000..0477fde5 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/readme.md @@ -0,0 +1,267 @@ +# asn1crypto + +A fast, pure Python library for parsing and serializing ASN.1 structures. + + - [Features](#features) + - [Why Another Python ASN.1 Library?](#why-another-python-asn1-library) + - [Related Crypto Libraries](#related-crypto-libraries) + - [Current Release](#current-release) + - [Dependencies](#dependencies) + - [Installation](#installation) + - [License](#license) + - [Documentation](#documentation) + - [Continuous Integration](#continuous-integration) + - [Testing](#testing) + - [Development](#development) + - [CI Tasks](#ci-tasks) + +[![GitHub Actions CI](https://github.com/wbond/asn1crypto/workflows/CI/badge.svg)](https://github.com/wbond/asn1crypto/actions?workflow=CI) +[![CircleCI](https://circleci.com/gh/wbond/asn1crypto.svg?style=shield)](https://circleci.com/gh/wbond/asn1crypto) +[![PyPI](https://img.shields.io/pypi/v/asn1crypto.svg)](https://pypi.org/project/asn1crypto/) + +## Features + +In addition to an ASN.1 BER/DER decoder and DER serializer, the project includes +a bunch of ASN.1 structures for use with various common cryptography standards: + +| Standard | Module | Source | +| ---------------------- | ------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------- | +| X.509 | [`asn1crypto.x509`](asn1crypto/x509.py) | [RFC 5280](https://tools.ietf.org/html/rfc5280) | +| CRL | [`asn1crypto.crl`](asn1crypto/crl.py) | [RFC 5280](https://tools.ietf.org/html/rfc5280) | +| CSR | [`asn1crypto.csr`](asn1crypto/csr.py) | [RFC 2986](https://tools.ietf.org/html/rfc2986), [RFC 2985](https://tools.ietf.org/html/rfc2985) | +| OCSP | [`asn1crypto.ocsp`](asn1crypto/ocsp.py) | [RFC 6960](https://tools.ietf.org/html/rfc6960) | +| PKCS#12 | [`asn1crypto.pkcs12`](asn1crypto/pkcs12.py) | [RFC 7292](https://tools.ietf.org/html/rfc7292) | +| PKCS#8 | [`asn1crypto.keys`](asn1crypto/keys.py) | [RFC 5208](https://tools.ietf.org/html/rfc5208) | +| PKCS#1 v2.1 (RSA keys) | [`asn1crypto.keys`](asn1crypto/keys.py) | [RFC 3447](https://tools.ietf.org/html/rfc3447) | +| DSA keys | [`asn1crypto.keys`](asn1crypto/keys.py) | [RFC 3279](https://tools.ietf.org/html/rfc3279) | +| Elliptic curve keys | [`asn1crypto.keys`](asn1crypto/keys.py) | [SECG SEC1 V2](http://www.secg.org/sec1-v2.pdf) | +| PKCS#3 v1.4 | [`asn1crypto.algos`](asn1crypto/algos.py) | [PKCS#3 v1.4](ftp://ftp.rsasecurity.com/pub/pkcs/ascii/pkcs-3.asc) | +| PKCS#5 v2.1 | [`asn1crypto.algos`](asn1crypto/algos.py) | [PKCS#5 v2.1](http://www.emc.com/collateral/white-papers/h11302-pkcs5v2-1-password-based-cryptography-standard-wp.pdf) | +| CMS (and PKCS#7) | [`asn1crypto.cms`](asn1crypto/cms.py) | [RFC 5652](https://tools.ietf.org/html/rfc5652), [RFC 2315](https://tools.ietf.org/html/rfc2315) | +| TSP | [`asn1crypto.tsp`](asn1crypto/tsp.py) | [RFC 3161](https://tools.ietf.org/html/rfc3161) | +| PDF signatures | [`asn1crypto.pdf`](asn1crypto/pdf.py) | [PDF 1.7](http://wwwimages.adobe.com/content/dam/Adobe/en/devnet/pdf/pdfs/PDF32000_2008.pdf) | + +## Why Another Python ASN.1 Library? + +Python has long had the [pyasn1](https://pypi.org/project/pyasn1/) and +[pyasn1_modules](https://pypi.org/project/pyasn1-modules/) available for +parsing and serializing ASN.1 structures. While the project does include a +comprehensive set of tools for parsing and serializing, the performance of the +library can be very poor, especially when dealing with bit fields and parsing +large structures such as CRLs. + +After spending extensive time using *pyasn1*, the following issues were +identified: + + 1. Poor performance + 2. Verbose, non-pythonic API + 3. Out-dated and incomplete definitions in *pyasn1-modules* + 4. No simple way to map data to native Python data structures + 5. No mechanism for overridden universal ASN.1 types + +The *pyasn1* API is largely method driven, and uses extensive configuration +objects and lowerCamelCase names. There were no consistent options for +converting types of native Python data structures. Since the project supports +out-dated versions of Python, many newer language features are unavailable +for use. + +Time was spent trying to profile issues with the performance, however the +architecture made it hard to pin down the primary source of the poor +performance. Attempts were made to improve performance by utilizing unreleased +patches and delaying parsing using the `Any` type. Even with such changes, the +performance was still unacceptably slow. + +Finally, a number of structures in the cryptographic space use universal data +types such as `BitString` and `OctetString`, but interpret the data as other +types. For instance, signatures are really byte strings, but are encoded as +`BitString`. Elliptic curve keys use both `BitString` and `OctetString` to +represent integers. Parsing these structures as the base universal types and +then re-interpreting them wastes computation. + +*asn1crypto* uses the following techniques to improve performance, especially +when extracting one or two fields from large, complex structures: + + - Delayed parsing of byte string values + - Persistence of original ASN.1 encoded data until a value is changed + - Lazy loading of child fields + - Utilization of high-level Python stdlib modules + +While there is no extensive performance test suite, the +`CRLTests.test_parse_crl` test case was used to parse a 21MB CRL file on a +late 2013 rMBP. *asn1crypto* parsed the certificate serial numbers in just +under 8 seconds. With *pyasn1*, using definitions from *pyasn1-modules*, the +same parsing took over 4,100 seconds. + +For smaller structures the performance difference can range from a few times +faster to an order of magnitude or more. + +## Related Crypto Libraries + +*asn1crypto* is part of the modularcrypto family of Python packages: + + - [asn1crypto](https://github.com/wbond/asn1crypto) + - [oscrypto](https://github.com/wbond/oscrypto) + - [csrbuilder](https://github.com/wbond/csrbuilder) + - [certbuilder](https://github.com/wbond/certbuilder) + - [crlbuilder](https://github.com/wbond/crlbuilder) + - [ocspbuilder](https://github.com/wbond/ocspbuilder) + - [certvalidator](https://github.com/wbond/certvalidator) + +## Current Release + +1.4.0 - [changelog](changelog.md) + +## Dependencies + +Python 2.6, 2.7, 3.2, 3.3, 3.4, 3.5, 3.6, 3.7, 3.8, 3.9 or pypy. *No third-party +packages required.* + +## Installation + +```bash +pip install asn1crypto +``` + +## License + +*asn1crypto* is licensed under the terms of the MIT license. See the +[LICENSE](LICENSE) file for the exact license text. + +## Documentation + +The documentation for *asn1crypto* is composed of tutorials on basic usage and +links to the source for the various pre-defined type classes. + +### Tutorials + + - [Universal Types with BER/DER Decoder and DER Encoder](docs/universal_types.md) + - [PEM Encoder and Decoder](docs/pem.md) + +### Reference + + - [Universal types](asn1crypto/core.py), `asn1crypto.core` + - [Digest, HMAC, signed digest and encryption algorithms](asn1crypto/algos.py), `asn1crypto.algos` + - [Private and public keys](asn1crypto/keys.py), `asn1crypto.keys` + - [X509 certificates](asn1crypto/x509.py), `asn1crypto.x509` + - [Certificate revocation lists (CRLs)](asn1crypto/crl.py), `asn1crypto.crl` + - [Online certificate status protocol (OCSP)](asn1crypto/ocsp.py), `asn1crypto.ocsp` + - [Certificate signing requests (CSRs)](asn1crypto/csr.py), `asn1crypto.csr` + - [Private key/certificate containers (PKCS#12)](asn1crypto/pkcs12.py), `asn1crypto.pkcs12` + - [Cryptographic message syntax (CMS, PKCS#7)](asn1crypto/cms.py), `asn1crypto.cms` + - [Time stamp protocol (TSP)](asn1crypto/tsp.py), `asn1crypto.tsp` + - [PDF signatures](asn1crypto/pdf.py), `asn1crypto.pdf` + +## Continuous Integration + +Various combinations of platforms and versions of Python are tested via: + + - [macOS, Linux, Windows](https://github.com/wbond/asn1crypto/actions/workflows/ci.yml) via GitHub Actions + - [arm64](https://circleci.com/gh/wbond/asn1crypto) via CircleCI + +## Testing + +Tests are written using `unittest` and require no third-party packages. + +Depending on what type of source is available for the package, the following +commands can be used to run the test suite. + +### Git Repository + +When working within a Git working copy, or an archive of the Git repository, +the full test suite is run via: + +```bash +python run.py tests +``` + +To run only some tests, pass a regular expression as a parameter to `tests`. + +```bash +python run.py tests ocsp +``` + +### PyPi Source Distribution + +When working within an extracted source distribution (aka `.tar.gz`) from +PyPi, the full test suite is run via: + +```bash +python setup.py test +``` + +### Package + +When the package has been installed via pip (or another method), the package +`asn1crypto_tests` may be installed and invoked to run the full test suite: + +```bash +pip install asn1crypto_tests +python -m asn1crypto_tests +``` + +## Development + +To install the package used for linting, execute: + +```bash +pip install --user -r requires/lint +``` + +The following command will run the linter: + +```bash +python run.py lint +``` + +Support for code coverage can be installed via: + +```bash +pip install --user -r requires/coverage +``` + +Coverage is measured by running: + +```bash +python run.py coverage +``` + +To change the version number of the package, run: + +```bash +python run.py version {pep440_version} +``` + +To install the necessary packages for releasing a new version on PyPI, run: + +```bash +pip install --user -r requires/release +``` + +Releases are created by: + + - Making a git tag in [PEP 440](https://www.python.org/dev/peps/pep-0440/#examples-of-compliant-version-schemes) format + - Running the command: + + ```bash + python run.py release + ``` + +Existing releases can be found at https://pypi.org/project/asn1crypto/. + +## CI Tasks + +A task named `deps` exists to download and stage all necessary testing +dependencies. On posix platforms, `curl` is used for downloads and on Windows +PowerShell with `Net.WebClient` is used. This configuration sidesteps issues +related to getting pip to work properly and messing with `site-packages` for +the version of Python being used. + +The `ci` task runs `lint` (if flake8 is available for the version of Python) and +`coverage` (or `tests` if coverage is not available for the version of Python). +If the current directory is a clean git working copy, the coverage data is +submitted to codecov.io. + +```bash +python run.py deps +python run.py ci +``` diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/requires/ci b/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/requires/ci new file mode 100644 index 00000000..e7503fb3 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/requires/ci @@ -0,0 +1,2 @@ +-r ./coverage +-r ./lint diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/requires/coverage b/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/requires/coverage new file mode 100644 index 00000000..52ac5292 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/requires/coverage @@ -0,0 +1,5 @@ +setuptools == 39.2.0 ; python_version == '3.3' +coverage == 4.4.1 ; python_version == '2.6' +coverage == 4.2 ; python_version == '3.3' and sys_platform == "win32" +coverage == 4.5.4 ; (python_version == '3.3' and sys_platform != "win32") or python_version == '3.4' +coverage == 5.5 ; python_version == '2.7' or python_version >= '3.5' diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/requires/lint b/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/requires/lint new file mode 100644 index 00000000..121788bb --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/requires/lint @@ -0,0 +1,14 @@ +setuptools >= 39.0.1 ; python_version == '2.7' or python_version >= '3.3' +enum34 == 1.1.6 ; python_version == '2.7' or python_version == '3.3' +configparser == 3.5.0 ; python_version == '2.7' +mccabe == 0.6.1 ; python_version == '3.3' +pycodestyle == 2.3.1 ; python_version == '3.3' +pyflakes == 1.6.0 ; python_version == '3.3' +flake8 == 3.5.0 ; python_version == '3.3' +mccabe == 0.6.1 ; python_version == '2.7' or python_version >= '3.4' +pycodestyle == 2.5.0 ; python_version == '2.7' or python_version >= '3.4' +pyflakes == 2.1.1 ; python_version == '2.7' or python_version >= '3.4' +functools32 == 3.2.3-2 ; python_version == '2.7' +typing == 3.7.4.1 ; python_version == '2.7' or python_version == '3.4' +entrypoints == 0.3 ; python_version == '2.7' or python_version >= '3.4' +flake8 == 3.7.9 ; python_version == '2.7' or python_version >= '3.4' diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/requires/release b/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/requires/release new file mode 100644 index 00000000..3b816554 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/requires/release @@ -0,0 +1,3 @@ +wheel >= 0.31.0 +twine >= 1.11.0 +setuptools >= 38.6.0 diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/run.py b/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/run.py new file mode 100644 index 00000000..2f532214 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/run.py @@ -0,0 +1,8 @@ +#!/usr/bin/env python +# coding: utf-8 +from __future__ import unicode_literals, division, absolute_import, print_function + +from dev._task import run_task + + +run_task() diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/setup.py b/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/setup.py new file mode 100644 index 00000000..fd0193a9 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/setup.py @@ -0,0 +1,159 @@ +import codecs +import os +import shutil +import sys +import warnings + +import setuptools +from setuptools import setup, Command +from setuptools.command.egg_info import egg_info + + +PACKAGE_NAME = 'asn1crypto' +PACKAGE_VERSION = '1.4.0' +PACKAGE_ROOT = os.path.dirname(os.path.abspath(__file__)) + + +# setuptools 38.6.0 and newer know about long_description_content_type, but +# distutils still complains about it, so silence the warning +sv = setuptools.__version__ +svi = tuple(int(o) if o.isdigit() else o for o in sv.split('.')) +if svi >= (38, 6): + warnings.filterwarnings( + 'ignore', + "Unknown distribution option: 'long_description_content_type'", + module='distutils.dist' + ) + + +# Try to load the tests first from the source repository layout. If that +# doesn't work, we assume this file is in the release package, and the tests +# are part of the package {PACKAGE_NAME}_tests. +if os.path.exists(os.path.join(PACKAGE_ROOT, 'tests')): + tests_require = [] + test_suite = 'tests.make_suite' +else: + tests_require = ['%s_tests' % PACKAGE_NAME] + test_suite = '%s_tests.make_suite' % PACKAGE_NAME + + +# This allows us to send the LICENSE and docs when creating a sdist. Wheels +# automatically include the LICENSE, and don't need the docs. For these +# to be included, the command must be "python setup.py sdist". +package_data = {} +if sys.argv[1:] == ['sdist'] or sorted(sys.argv[1:]) == ['-q', 'sdist']: + package_data[PACKAGE_NAME] = [ + '../LICENSE', + '../*.md', + '../docs/*.md', + ] + + +# Ensures a copy of the LICENSE is included with the egg-info for +# install and bdist_egg commands +class EggInfoCommand(egg_info): + def run(self): + egg_info_path = os.path.join( + PACKAGE_ROOT, + '%s.egg-info' % PACKAGE_NAME + ) + if not os.path.exists(egg_info_path): + os.mkdir(egg_info_path) + shutil.copy2( + os.path.join(PACKAGE_ROOT, 'LICENSE'), + os.path.join(egg_info_path, 'LICENSE') + ) + egg_info.run(self) + + +class CleanCommand(Command): + user_options = [ + ('all', 'a', '(Compatibility with original clean command)'), + ] + + def initialize_options(self): + self.all = False + + def finalize_options(self): + pass + + def run(self): + sub_folders = ['build', 'temp', '%s.egg-info' % PACKAGE_NAME] + if self.all: + sub_folders.append('dist') + for sub_folder in sub_folders: + full_path = os.path.join(PACKAGE_ROOT, sub_folder) + if os.path.exists(full_path): + shutil.rmtree(full_path) + for root, dirs, files in os.walk(os.path.join(PACKAGE_ROOT, PACKAGE_NAME)): + for filename in files: + if filename[-4:] == '.pyc': + os.unlink(os.path.join(root, filename)) + for dirname in list(dirs): + if dirname == '__pycache__': + shutil.rmtree(os.path.join(root, dirname)) + + +readme = '' +with codecs.open(os.path.join(PACKAGE_ROOT, 'readme.md'), 'r', 'utf-8') as f: + readme = f.read() + + +setup( + name=PACKAGE_NAME, + version=PACKAGE_VERSION, + + description=( + 'Fast ASN.1 parser and serializer with definitions for private keys, ' + 'public keys, certificates, CRL, OCSP, CMS, PKCS#3, PKCS#7, PKCS#8, ' + 'PKCS#12, PKCS#5, X.509 and TSP' + ), + long_description=readme, + long_description_content_type='text/markdown', + + url='https://github.com/wbond/asn1crypto', + + author='wbond', + author_email='will@wbond.net', + + license='MIT', + + classifiers=[ + 'Development Status :: 5 - Production/Stable', + + 'Intended Audience :: Developers', + + 'License :: OSI Approved :: MIT License', + + 'Programming Language :: Python', + 'Programming Language :: Python :: 2', + 'Programming Language :: Python :: 2.6', + 'Programming Language :: Python :: 2.7', + 'Programming Language :: Python :: 3', + 'Programming Language :: Python :: 3.2', + 'Programming Language :: Python :: 3.3', + 'Programming Language :: Python :: 3.4', + 'Programming Language :: Python :: 3.5', + 'Programming Language :: Python :: 3.6', + 'Programming Language :: Python :: 3.7', + 'Programming Language :: Python :: 3.8', + 'Programming Language :: Python :: 3.9', + 'Programming Language :: Python :: Implementation :: CPython', + 'Programming Language :: Python :: Implementation :: PyPy', + + 'Topic :: Security :: Cryptography', + ], + + keywords='asn1 crypto pki x509 certificate rsa dsa ec dh', + + packages=[PACKAGE_NAME], + package_data=package_data, + + tests_require=tests_require, + test_suite=test_suite, + + cmdclass={ + 'clean': CleanCommand, + 'egg_info': EggInfoCommand, + } +) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/tox.ini b/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/tox.ini new file mode 100644 index 00000000..48202f41 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/asn1crypto/tox.ini @@ -0,0 +1,13 @@ +[tox] +envlist = py26,py27,py32,py33,py34,py35,py36,py37,py38,py39,pypy + +[testenv] +deps = -rrequires/ci +commands = {envpython} run.py ci + +[pep8] +max-line-length = 120 + +[flake8] +max-line-length = 120 +jobs = 1 diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/__about__.py b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/__about__.py new file mode 100644 index 00000000..8848a196 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/__about__.py @@ -0,0 +1,15 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + + +__all__ = [ + "__version__", + "__author__", + "__copyright__", +] + +__version__ = "36.0.1" + +__author__ = "The Python Cryptographic Authority and individual contributors" +__copyright__ = "Copyright 2013-2021 {}".format(__author__) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/__init__.py b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/__init__.py new file mode 100644 index 00000000..983b6018 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/__init__.py @@ -0,0 +1,17 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + + +from cryptography.__about__ import ( + __author__, + __copyright__, + __version__, +) + + +__all__ = [ + "__version__", + "__author__", + "__copyright__", +] diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/exceptions.py b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/exceptions.py new file mode 100644 index 00000000..3bd98d82 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/exceptions.py @@ -0,0 +1,57 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + + +from cryptography import utils + + +class _Reasons(utils.Enum): + BACKEND_MISSING_INTERFACE = 0 + UNSUPPORTED_HASH = 1 + UNSUPPORTED_CIPHER = 2 + UNSUPPORTED_PADDING = 3 + UNSUPPORTED_MGF = 4 + UNSUPPORTED_PUBLIC_KEY_ALGORITHM = 5 + UNSUPPORTED_ELLIPTIC_CURVE = 6 + UNSUPPORTED_SERIALIZATION = 7 + UNSUPPORTED_X509 = 8 + UNSUPPORTED_EXCHANGE_ALGORITHM = 9 + UNSUPPORTED_DIFFIE_HELLMAN = 10 + UNSUPPORTED_MAC = 11 + + +class UnsupportedAlgorithm(Exception): + def __init__(self, message, reason=None): + super(UnsupportedAlgorithm, self).__init__(message) + self._reason = reason + + +class AlreadyFinalized(Exception): + pass + + +class AlreadyUpdated(Exception): + pass + + +class NotYetFinalized(Exception): + pass + + +class InvalidTag(Exception): + pass + + +class InvalidSignature(Exception): + pass + + +class InternalError(Exception): + def __init__(self, msg, err_code): + super(InternalError, self).__init__(msg) + self.err_code = err_code + + +class InvalidKey(Exception): + pass diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/fernet.py b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/fernet.py new file mode 100644 index 00000000..c2e01fc5 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/fernet.py @@ -0,0 +1,205 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + + +import base64 +import binascii +import os +import struct +import time +import typing + +from cryptography import utils +from cryptography.exceptions import InvalidSignature +from cryptography.hazmat.primitives import hashes, padding +from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes +from cryptography.hazmat.primitives.hmac import HMAC + + +class InvalidToken(Exception): + pass + + +_MAX_CLOCK_SKEW = 60 + + +class Fernet(object): + def __init__( + self, + key: typing.Union[bytes, str], + backend: typing.Any = None, + ): + key = base64.urlsafe_b64decode(key) + if len(key) != 32: + raise ValueError( + "Fernet key must be 32 url-safe base64-encoded bytes." + ) + + self._signing_key = key[:16] + self._encryption_key = key[16:] + + @classmethod + def generate_key(cls) -> bytes: + return base64.urlsafe_b64encode(os.urandom(32)) + + def encrypt(self, data: bytes) -> bytes: + return self.encrypt_at_time(data, int(time.time())) + + def encrypt_at_time(self, data: bytes, current_time: int) -> bytes: + iv = os.urandom(16) + return self._encrypt_from_parts(data, current_time, iv) + + def _encrypt_from_parts( + self, data: bytes, current_time: int, iv: bytes + ) -> bytes: + utils._check_bytes("data", data) + + padder = padding.PKCS7(algorithms.AES.block_size).padder() + padded_data = padder.update(data) + padder.finalize() + encryptor = Cipher( + algorithms.AES(self._encryption_key), + modes.CBC(iv), + ).encryptor() + ciphertext = encryptor.update(padded_data) + encryptor.finalize() + + basic_parts = ( + b"\x80" + struct.pack(">Q", current_time) + iv + ciphertext + ) + + h = HMAC(self._signing_key, hashes.SHA256()) + h.update(basic_parts) + hmac = h.finalize() + return base64.urlsafe_b64encode(basic_parts + hmac) + + def decrypt(self, token: bytes, ttl: typing.Optional[int] = None) -> bytes: + timestamp, data = Fernet._get_unverified_token_data(token) + if ttl is None: + time_info = None + else: + time_info = (ttl, int(time.time())) + return self._decrypt_data(data, timestamp, time_info) + + def decrypt_at_time( + self, token: bytes, ttl: int, current_time: int + ) -> bytes: + if ttl is None: + raise ValueError( + "decrypt_at_time() can only be used with a non-None ttl" + ) + timestamp, data = Fernet._get_unverified_token_data(token) + return self._decrypt_data(data, timestamp, (ttl, current_time)) + + def extract_timestamp(self, token: bytes) -> int: + timestamp, data = Fernet._get_unverified_token_data(token) + # Verify the token was not tampered with. + self._verify_signature(data) + return timestamp + + @staticmethod + def _get_unverified_token_data(token: bytes) -> typing.Tuple[int, bytes]: + utils._check_bytes("token", token) + try: + data = base64.urlsafe_b64decode(token) + except (TypeError, binascii.Error): + raise InvalidToken + + if not data or data[0] != 0x80: + raise InvalidToken + + try: + (timestamp,) = struct.unpack(">Q", data[1:9]) + except struct.error: + raise InvalidToken + return timestamp, data + + def _verify_signature(self, data: bytes) -> None: + h = HMAC(self._signing_key, hashes.SHA256()) + h.update(data[:-32]) + try: + h.verify(data[-32:]) + except InvalidSignature: + raise InvalidToken + + def _decrypt_data( + self, + data: bytes, + timestamp: int, + time_info: typing.Optional[typing.Tuple[int, int]], + ) -> bytes: + if time_info is not None: + ttl, current_time = time_info + if timestamp + ttl < current_time: + raise InvalidToken + + if current_time + _MAX_CLOCK_SKEW < timestamp: + raise InvalidToken + + self._verify_signature(data) + + iv = data[9:25] + ciphertext = data[25:-32] + decryptor = Cipher( + algorithms.AES(self._encryption_key), modes.CBC(iv) + ).decryptor() + plaintext_padded = decryptor.update(ciphertext) + try: + plaintext_padded += decryptor.finalize() + except ValueError: + raise InvalidToken + unpadder = padding.PKCS7(algorithms.AES.block_size).unpadder() + + unpadded = unpadder.update(plaintext_padded) + try: + unpadded += unpadder.finalize() + except ValueError: + raise InvalidToken + return unpadded + + +class MultiFernet(object): + def __init__(self, fernets: typing.Iterable[Fernet]): + fernets = list(fernets) + if not fernets: + raise ValueError( + "MultiFernet requires at least one Fernet instance" + ) + self._fernets = fernets + + def encrypt(self, msg: bytes) -> bytes: + return self.encrypt_at_time(msg, int(time.time())) + + def encrypt_at_time(self, msg: bytes, current_time: int) -> bytes: + return self._fernets[0].encrypt_at_time(msg, current_time) + + def rotate(self, msg: bytes) -> bytes: + timestamp, data = Fernet._get_unverified_token_data(msg) + for f in self._fernets: + try: + p = f._decrypt_data(data, timestamp, None) + break + except InvalidToken: + pass + else: + raise InvalidToken + + iv = os.urandom(16) + return self._fernets[0]._encrypt_from_parts(p, timestamp, iv) + + def decrypt(self, msg: bytes, ttl: typing.Optional[int] = None) -> bytes: + for f in self._fernets: + try: + return f.decrypt(msg, ttl) + except InvalidToken: + pass + raise InvalidToken + + def decrypt_at_time( + self, msg: bytes, ttl: int, current_time: int + ) -> bytes: + for f in self._fernets: + try: + return f.decrypt_at_time(msg, ttl, current_time) + except InvalidToken: + pass + raise InvalidToken diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/__init__.py b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/__init__.py new file mode 100644 index 00000000..007694bc --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/__init__.py @@ -0,0 +1,10 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. +""" +Hazardous Materials + +This is a "Hazardous Materials" module. You should ONLY use it if you're +100% absolutely sure that you know what you're doing because this module +is full of land mines, dragons, and dinosaurs with laser guns. +""" diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/_oid.py b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/_oid.py new file mode 100644 index 00000000..07f53d2f --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/_oid.py @@ -0,0 +1,341 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +import typing + +from cryptography.hazmat.primitives import hashes + + +class ObjectIdentifier(object): + def __init__(self, dotted_string: str) -> None: + self._dotted_string = dotted_string + + nodes = self._dotted_string.split(".") + intnodes = [] + + # There must be at least 2 nodes, the first node must be 0..2, and + # if less than 2, the second node cannot have a value outside the + # range 0..39. All nodes must be integers. + for node in nodes: + try: + node_value = int(node, 10) + except ValueError: + raise ValueError( + "Malformed OID: %s (non-integer nodes)" + % (self._dotted_string) + ) + if node_value < 0: + raise ValueError( + "Malformed OID: %s (negative-integer nodes)" + % (self._dotted_string) + ) + intnodes.append(node_value) + + if len(nodes) < 2: + raise ValueError( + "Malformed OID: %s (insufficient number of nodes)" + % (self._dotted_string) + ) + + if intnodes[0] > 2: + raise ValueError( + "Malformed OID: %s (first node outside valid range)" + % (self._dotted_string) + ) + + if intnodes[0] < 2 and intnodes[1] >= 40: + raise ValueError( + "Malformed OID: %s (second node outside valid range)" + % (self._dotted_string) + ) + + def __eq__(self, other: typing.Any) -> bool: + if not isinstance(other, ObjectIdentifier): + return NotImplemented + + return self.dotted_string == other.dotted_string + + def __ne__(self, other: typing.Any) -> bool: + return not self == other + + def __repr__(self) -> str: + return "<ObjectIdentifier(oid={}, name={})>".format( + self.dotted_string, self._name + ) + + def __hash__(self) -> int: + return hash(self.dotted_string) + + @property + def _name(self) -> str: + return _OID_NAMES.get(self, "Unknown OID") + + @property + def dotted_string(self) -> str: + return self._dotted_string + + +class ExtensionOID(object): + SUBJECT_DIRECTORY_ATTRIBUTES = ObjectIdentifier("2.5.29.9") + SUBJECT_KEY_IDENTIFIER = ObjectIdentifier("2.5.29.14") + KEY_USAGE = ObjectIdentifier("2.5.29.15") + SUBJECT_ALTERNATIVE_NAME = ObjectIdentifier("2.5.29.17") + ISSUER_ALTERNATIVE_NAME = ObjectIdentifier("2.5.29.18") + BASIC_CONSTRAINTS = ObjectIdentifier("2.5.29.19") + NAME_CONSTRAINTS = ObjectIdentifier("2.5.29.30") + CRL_DISTRIBUTION_POINTS = ObjectIdentifier("2.5.29.31") + CERTIFICATE_POLICIES = ObjectIdentifier("2.5.29.32") + POLICY_MAPPINGS = ObjectIdentifier("2.5.29.33") + AUTHORITY_KEY_IDENTIFIER = ObjectIdentifier("2.5.29.35") + POLICY_CONSTRAINTS = ObjectIdentifier("2.5.29.36") + EXTENDED_KEY_USAGE = ObjectIdentifier("2.5.29.37") + FRESHEST_CRL = ObjectIdentifier("2.5.29.46") + INHIBIT_ANY_POLICY = ObjectIdentifier("2.5.29.54") + ISSUING_DISTRIBUTION_POINT = ObjectIdentifier("2.5.29.28") + AUTHORITY_INFORMATION_ACCESS = ObjectIdentifier("1.3.6.1.5.5.7.1.1") + SUBJECT_INFORMATION_ACCESS = ObjectIdentifier("1.3.6.1.5.5.7.1.11") + OCSP_NO_CHECK = ObjectIdentifier("1.3.6.1.5.5.7.48.1.5") + TLS_FEATURE = ObjectIdentifier("1.3.6.1.5.5.7.1.24") + CRL_NUMBER = ObjectIdentifier("2.5.29.20") + DELTA_CRL_INDICATOR = ObjectIdentifier("2.5.29.27") + PRECERT_SIGNED_CERTIFICATE_TIMESTAMPS = ObjectIdentifier( + "1.3.6.1.4.1.11129.2.4.2" + ) + PRECERT_POISON = ObjectIdentifier("1.3.6.1.4.1.11129.2.4.3") + SIGNED_CERTIFICATE_TIMESTAMPS = ObjectIdentifier("1.3.6.1.4.1.11129.2.4.5") + + +class OCSPExtensionOID(object): + NONCE = ObjectIdentifier("1.3.6.1.5.5.7.48.1.2") + + +class CRLEntryExtensionOID(object): + CERTIFICATE_ISSUER = ObjectIdentifier("2.5.29.29") + CRL_REASON = ObjectIdentifier("2.5.29.21") + INVALIDITY_DATE = ObjectIdentifier("2.5.29.24") + + +class NameOID(object): + COMMON_NAME = ObjectIdentifier("2.5.4.3") + COUNTRY_NAME = ObjectIdentifier("2.5.4.6") + LOCALITY_NAME = ObjectIdentifier("2.5.4.7") + STATE_OR_PROVINCE_NAME = ObjectIdentifier("2.5.4.8") + STREET_ADDRESS = ObjectIdentifier("2.5.4.9") + ORGANIZATION_NAME = ObjectIdentifier("2.5.4.10") + ORGANIZATIONAL_UNIT_NAME = ObjectIdentifier("2.5.4.11") + SERIAL_NUMBER = ObjectIdentifier("2.5.4.5") + SURNAME = ObjectIdentifier("2.5.4.4") + GIVEN_NAME = ObjectIdentifier("2.5.4.42") + TITLE = ObjectIdentifier("2.5.4.12") + GENERATION_QUALIFIER = ObjectIdentifier("2.5.4.44") + X500_UNIQUE_IDENTIFIER = ObjectIdentifier("2.5.4.45") + DN_QUALIFIER = ObjectIdentifier("2.5.4.46") + PSEUDONYM = ObjectIdentifier("2.5.4.65") + USER_ID = ObjectIdentifier("0.9.2342.19200300.100.1.1") + DOMAIN_COMPONENT = ObjectIdentifier("0.9.2342.19200300.100.1.25") + EMAIL_ADDRESS = ObjectIdentifier("1.2.840.113549.1.9.1") + JURISDICTION_COUNTRY_NAME = ObjectIdentifier("1.3.6.1.4.1.311.60.2.1.3") + JURISDICTION_LOCALITY_NAME = ObjectIdentifier("1.3.6.1.4.1.311.60.2.1.1") + JURISDICTION_STATE_OR_PROVINCE_NAME = ObjectIdentifier( + "1.3.6.1.4.1.311.60.2.1.2" + ) + BUSINESS_CATEGORY = ObjectIdentifier("2.5.4.15") + POSTAL_ADDRESS = ObjectIdentifier("2.5.4.16") + POSTAL_CODE = ObjectIdentifier("2.5.4.17") + INN = ObjectIdentifier("1.2.643.3.131.1.1") + OGRN = ObjectIdentifier("1.2.643.100.1") + SNILS = ObjectIdentifier("1.2.643.100.3") + UNSTRUCTURED_NAME = ObjectIdentifier("1.2.840.113549.1.9.2") + + +class SignatureAlgorithmOID(object): + RSA_WITH_MD5 = ObjectIdentifier("1.2.840.113549.1.1.4") + RSA_WITH_SHA1 = ObjectIdentifier("1.2.840.113549.1.1.5") + # This is an alternate OID for RSA with SHA1 that is occasionally seen + _RSA_WITH_SHA1 = ObjectIdentifier("1.3.14.3.2.29") + RSA_WITH_SHA224 = ObjectIdentifier("1.2.840.113549.1.1.14") + RSA_WITH_SHA256 = ObjectIdentifier("1.2.840.113549.1.1.11") + RSA_WITH_SHA384 = ObjectIdentifier("1.2.840.113549.1.1.12") + RSA_WITH_SHA512 = ObjectIdentifier("1.2.840.113549.1.1.13") + RSASSA_PSS = ObjectIdentifier("1.2.840.113549.1.1.10") + ECDSA_WITH_SHA1 = ObjectIdentifier("1.2.840.10045.4.1") + ECDSA_WITH_SHA224 = ObjectIdentifier("1.2.840.10045.4.3.1") + ECDSA_WITH_SHA256 = ObjectIdentifier("1.2.840.10045.4.3.2") + ECDSA_WITH_SHA384 = ObjectIdentifier("1.2.840.10045.4.3.3") + ECDSA_WITH_SHA512 = ObjectIdentifier("1.2.840.10045.4.3.4") + DSA_WITH_SHA1 = ObjectIdentifier("1.2.840.10040.4.3") + DSA_WITH_SHA224 = ObjectIdentifier("2.16.840.1.101.3.4.3.1") + DSA_WITH_SHA256 = ObjectIdentifier("2.16.840.1.101.3.4.3.2") + DSA_WITH_SHA384 = ObjectIdentifier("2.16.840.1.101.3.4.3.3") + DSA_WITH_SHA512 = ObjectIdentifier("2.16.840.1.101.3.4.3.4") + ED25519 = ObjectIdentifier("1.3.101.112") + ED448 = ObjectIdentifier("1.3.101.113") + GOSTR3411_94_WITH_3410_2001 = ObjectIdentifier("1.2.643.2.2.3") + GOSTR3410_2012_WITH_3411_2012_256 = ObjectIdentifier("1.2.643.7.1.1.3.2") + GOSTR3410_2012_WITH_3411_2012_512 = ObjectIdentifier("1.2.643.7.1.1.3.3") + + +_SIG_OIDS_TO_HASH: typing.Dict[ + ObjectIdentifier, typing.Optional[hashes.HashAlgorithm] +] = { + SignatureAlgorithmOID.RSA_WITH_MD5: hashes.MD5(), + SignatureAlgorithmOID.RSA_WITH_SHA1: hashes.SHA1(), + SignatureAlgorithmOID._RSA_WITH_SHA1: hashes.SHA1(), + SignatureAlgorithmOID.RSA_WITH_SHA224: hashes.SHA224(), + SignatureAlgorithmOID.RSA_WITH_SHA256: hashes.SHA256(), + SignatureAlgorithmOID.RSA_WITH_SHA384: hashes.SHA384(), + SignatureAlgorithmOID.RSA_WITH_SHA512: hashes.SHA512(), + SignatureAlgorithmOID.ECDSA_WITH_SHA1: hashes.SHA1(), + SignatureAlgorithmOID.ECDSA_WITH_SHA224: hashes.SHA224(), + SignatureAlgorithmOID.ECDSA_WITH_SHA256: hashes.SHA256(), + SignatureAlgorithmOID.ECDSA_WITH_SHA384: hashes.SHA384(), + SignatureAlgorithmOID.ECDSA_WITH_SHA512: hashes.SHA512(), + SignatureAlgorithmOID.DSA_WITH_SHA1: hashes.SHA1(), + SignatureAlgorithmOID.DSA_WITH_SHA224: hashes.SHA224(), + SignatureAlgorithmOID.DSA_WITH_SHA256: hashes.SHA256(), + SignatureAlgorithmOID.ED25519: None, + SignatureAlgorithmOID.ED448: None, + SignatureAlgorithmOID.GOSTR3411_94_WITH_3410_2001: None, + SignatureAlgorithmOID.GOSTR3410_2012_WITH_3411_2012_256: None, + SignatureAlgorithmOID.GOSTR3410_2012_WITH_3411_2012_512: None, +} + + +class ExtendedKeyUsageOID(object): + SERVER_AUTH = ObjectIdentifier("1.3.6.1.5.5.7.3.1") + CLIENT_AUTH = ObjectIdentifier("1.3.6.1.5.5.7.3.2") + CODE_SIGNING = ObjectIdentifier("1.3.6.1.5.5.7.3.3") + EMAIL_PROTECTION = ObjectIdentifier("1.3.6.1.5.5.7.3.4") + TIME_STAMPING = ObjectIdentifier("1.3.6.1.5.5.7.3.8") + OCSP_SIGNING = ObjectIdentifier("1.3.6.1.5.5.7.3.9") + ANY_EXTENDED_KEY_USAGE = ObjectIdentifier("2.5.29.37.0") + SMARTCARD_LOGON = ObjectIdentifier("1.3.6.1.4.1.311.20.2.2") + KERBEROS_PKINIT_KDC = ObjectIdentifier("1.3.6.1.5.2.3.5") + + +class AuthorityInformationAccessOID(object): + CA_ISSUERS = ObjectIdentifier("1.3.6.1.5.5.7.48.2") + OCSP = ObjectIdentifier("1.3.6.1.5.5.7.48.1") + + +class SubjectInformationAccessOID(object): + CA_REPOSITORY = ObjectIdentifier("1.3.6.1.5.5.7.48.5") + + +class CertificatePoliciesOID(object): + CPS_QUALIFIER = ObjectIdentifier("1.3.6.1.5.5.7.2.1") + CPS_USER_NOTICE = ObjectIdentifier("1.3.6.1.5.5.7.2.2") + ANY_POLICY = ObjectIdentifier("2.5.29.32.0") + + +class AttributeOID(object): + CHALLENGE_PASSWORD = ObjectIdentifier("1.2.840.113549.1.9.7") + UNSTRUCTURED_NAME = ObjectIdentifier("1.2.840.113549.1.9.2") + + +_OID_NAMES = { + NameOID.COMMON_NAME: "commonName", + NameOID.COUNTRY_NAME: "countryName", + NameOID.LOCALITY_NAME: "localityName", + NameOID.STATE_OR_PROVINCE_NAME: "stateOrProvinceName", + NameOID.STREET_ADDRESS: "streetAddress", + NameOID.ORGANIZATION_NAME: "organizationName", + NameOID.ORGANIZATIONAL_UNIT_NAME: "organizationalUnitName", + NameOID.SERIAL_NUMBER: "serialNumber", + NameOID.SURNAME: "surname", + NameOID.GIVEN_NAME: "givenName", + NameOID.TITLE: "title", + NameOID.GENERATION_QUALIFIER: "generationQualifier", + NameOID.X500_UNIQUE_IDENTIFIER: "x500UniqueIdentifier", + NameOID.DN_QUALIFIER: "dnQualifier", + NameOID.PSEUDONYM: "pseudonym", + NameOID.USER_ID: "userID", + NameOID.DOMAIN_COMPONENT: "domainComponent", + NameOID.EMAIL_ADDRESS: "emailAddress", + NameOID.JURISDICTION_COUNTRY_NAME: "jurisdictionCountryName", + NameOID.JURISDICTION_LOCALITY_NAME: "jurisdictionLocalityName", + NameOID.JURISDICTION_STATE_OR_PROVINCE_NAME: ( + "jurisdictionStateOrProvinceName" + ), + NameOID.BUSINESS_CATEGORY: "businessCategory", + NameOID.POSTAL_ADDRESS: "postalAddress", + NameOID.POSTAL_CODE: "postalCode", + NameOID.INN: "INN", + NameOID.OGRN: "OGRN", + NameOID.SNILS: "SNILS", + NameOID.UNSTRUCTURED_NAME: "unstructuredName", + SignatureAlgorithmOID.RSA_WITH_MD5: "md5WithRSAEncryption", + SignatureAlgorithmOID.RSA_WITH_SHA1: "sha1WithRSAEncryption", + SignatureAlgorithmOID.RSA_WITH_SHA224: "sha224WithRSAEncryption", + SignatureAlgorithmOID.RSA_WITH_SHA256: "sha256WithRSAEncryption", + SignatureAlgorithmOID.RSA_WITH_SHA384: "sha384WithRSAEncryption", + SignatureAlgorithmOID.RSA_WITH_SHA512: "sha512WithRSAEncryption", + SignatureAlgorithmOID.RSASSA_PSS: "RSASSA-PSS", + SignatureAlgorithmOID.ECDSA_WITH_SHA1: "ecdsa-with-SHA1", + SignatureAlgorithmOID.ECDSA_WITH_SHA224: "ecdsa-with-SHA224", + SignatureAlgorithmOID.ECDSA_WITH_SHA256: "ecdsa-with-SHA256", + SignatureAlgorithmOID.ECDSA_WITH_SHA384: "ecdsa-with-SHA384", + SignatureAlgorithmOID.ECDSA_WITH_SHA512: "ecdsa-with-SHA512", + SignatureAlgorithmOID.DSA_WITH_SHA1: "dsa-with-sha1", + SignatureAlgorithmOID.DSA_WITH_SHA224: "dsa-with-sha224", + SignatureAlgorithmOID.DSA_WITH_SHA256: "dsa-with-sha256", + SignatureAlgorithmOID.ED25519: "ed25519", + SignatureAlgorithmOID.ED448: "ed448", + SignatureAlgorithmOID.GOSTR3411_94_WITH_3410_2001: ( + "GOST R 34.11-94 with GOST R 34.10-2001" + ), + SignatureAlgorithmOID.GOSTR3410_2012_WITH_3411_2012_256: ( + "GOST R 34.10-2012 with GOST R 34.11-2012 (256 bit)" + ), + SignatureAlgorithmOID.GOSTR3410_2012_WITH_3411_2012_512: ( + "GOST R 34.10-2012 with GOST R 34.11-2012 (512 bit)" + ), + ExtendedKeyUsageOID.SERVER_AUTH: "serverAuth", + ExtendedKeyUsageOID.CLIENT_AUTH: "clientAuth", + ExtendedKeyUsageOID.CODE_SIGNING: "codeSigning", + ExtendedKeyUsageOID.EMAIL_PROTECTION: "emailProtection", + ExtendedKeyUsageOID.TIME_STAMPING: "timeStamping", + ExtendedKeyUsageOID.OCSP_SIGNING: "OCSPSigning", + ExtendedKeyUsageOID.SMARTCARD_LOGON: "msSmartcardLogin", + ExtendedKeyUsageOID.KERBEROS_PKINIT_KDC: "pkInitKDC", + ExtensionOID.SUBJECT_DIRECTORY_ATTRIBUTES: "subjectDirectoryAttributes", + ExtensionOID.SUBJECT_KEY_IDENTIFIER: "subjectKeyIdentifier", + ExtensionOID.KEY_USAGE: "keyUsage", + ExtensionOID.SUBJECT_ALTERNATIVE_NAME: "subjectAltName", + ExtensionOID.ISSUER_ALTERNATIVE_NAME: "issuerAltName", + ExtensionOID.BASIC_CONSTRAINTS: "basicConstraints", + ExtensionOID.PRECERT_SIGNED_CERTIFICATE_TIMESTAMPS: ( + "signedCertificateTimestampList" + ), + ExtensionOID.SIGNED_CERTIFICATE_TIMESTAMPS: ( + "signedCertificateTimestampList" + ), + ExtensionOID.PRECERT_POISON: "ctPoison", + CRLEntryExtensionOID.CRL_REASON: "cRLReason", + CRLEntryExtensionOID.INVALIDITY_DATE: "invalidityDate", + CRLEntryExtensionOID.CERTIFICATE_ISSUER: "certificateIssuer", + ExtensionOID.NAME_CONSTRAINTS: "nameConstraints", + ExtensionOID.CRL_DISTRIBUTION_POINTS: "cRLDistributionPoints", + ExtensionOID.CERTIFICATE_POLICIES: "certificatePolicies", + ExtensionOID.POLICY_MAPPINGS: "policyMappings", + ExtensionOID.AUTHORITY_KEY_IDENTIFIER: "authorityKeyIdentifier", + ExtensionOID.POLICY_CONSTRAINTS: "policyConstraints", + ExtensionOID.EXTENDED_KEY_USAGE: "extendedKeyUsage", + ExtensionOID.FRESHEST_CRL: "freshestCRL", + ExtensionOID.INHIBIT_ANY_POLICY: "inhibitAnyPolicy", + ExtensionOID.ISSUING_DISTRIBUTION_POINT: ("issuingDistributionPoint"), + ExtensionOID.AUTHORITY_INFORMATION_ACCESS: "authorityInfoAccess", + ExtensionOID.SUBJECT_INFORMATION_ACCESS: "subjectInfoAccess", + ExtensionOID.OCSP_NO_CHECK: "OCSPNoCheck", + ExtensionOID.CRL_NUMBER: "cRLNumber", + ExtensionOID.DELTA_CRL_INDICATOR: "deltaCRLIndicator", + ExtensionOID.TLS_FEATURE: "TLSFeature", + AuthorityInformationAccessOID.OCSP: "OCSP", + AuthorityInformationAccessOID.CA_ISSUERS: "caIssuers", + SubjectInformationAccessOID.CA_REPOSITORY: "caRepository", + CertificatePoliciesOID.CPS_QUALIFIER: "id-qt-cps", + CertificatePoliciesOID.CPS_USER_NOTICE: "id-qt-unotice", + OCSPExtensionOID.NONCE: "OCSPNonce", + AttributeOID.CHALLENGE_PASSWORD: "challengePassword", +} diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/backends/__init__.py b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/backends/__init__.py new file mode 100644 index 00000000..775689cb --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/backends/__init__.py @@ -0,0 +1,11 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from cryptography.hazmat.backends.interfaces import Backend + + +def default_backend() -> Backend: + from cryptography.hazmat.backends.openssl.backend import backend + + return backend diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/backends/interfaces.py b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/backends/interfaces.py new file mode 100644 index 00000000..1e7a2131 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/backends/interfaces.py @@ -0,0 +1,384 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + + +import abc + + +class CipherBackend(metaclass=abc.ABCMeta): + @abc.abstractmethod + def cipher_supported(self, cipher, mode): + """ + Return True if the given cipher and mode are supported. + """ + + @abc.abstractmethod + def create_symmetric_encryption_ctx(self, cipher, mode): + """ + Get a CipherContext that can be used for encryption. + """ + + @abc.abstractmethod + def create_symmetric_decryption_ctx(self, cipher, mode): + """ + Get a CipherContext that can be used for decryption. + """ + + +class HashBackend(metaclass=abc.ABCMeta): + @abc.abstractmethod + def hash_supported(self, algorithm): + """ + Return True if the hash algorithm is supported by this backend. + """ + + @abc.abstractmethod + def create_hash_ctx(self, algorithm): + """ + Create a HashContext for calculating a message digest. + """ + + +class HMACBackend(metaclass=abc.ABCMeta): + @abc.abstractmethod + def hmac_supported(self, algorithm): + """ + Return True if the hash algorithm is supported for HMAC by this + backend. + """ + + @abc.abstractmethod + def create_hmac_ctx(self, key, algorithm): + """ + Create a context for calculating a message authentication code. + """ + + +class CMACBackend(metaclass=abc.ABCMeta): + @abc.abstractmethod + def cmac_algorithm_supported(self, algorithm): + """ + Returns True if the block cipher is supported for CMAC by this backend + """ + + @abc.abstractmethod + def create_cmac_ctx(self, algorithm): + """ + Create a context for calculating a message authentication code. + """ + + +class PBKDF2HMACBackend(metaclass=abc.ABCMeta): + @abc.abstractmethod + def pbkdf2_hmac_supported(self, algorithm): + """ + Return True if the hash algorithm is supported for PBKDF2 by this + backend. + """ + + @abc.abstractmethod + def derive_pbkdf2_hmac( + self, algorithm, length, salt, iterations, key_material + ): + """ + Return length bytes derived from provided PBKDF2 parameters. + """ + + +class RSABackend(metaclass=abc.ABCMeta): + @abc.abstractmethod + def generate_rsa_private_key(self, public_exponent, key_size): + """ + Generate an RSAPrivateKey instance with public_exponent and a modulus + of key_size bits. + """ + + @abc.abstractmethod + def rsa_padding_supported(self, padding): + """ + Returns True if the backend supports the given padding options. + """ + + @abc.abstractmethod + def generate_rsa_parameters_supported(self, public_exponent, key_size): + """ + Returns True if the backend supports the given parameters for key + generation. + """ + + @abc.abstractmethod + def load_rsa_private_numbers(self, numbers): + """ + Returns an RSAPrivateKey provider. + """ + + @abc.abstractmethod + def load_rsa_public_numbers(self, numbers): + """ + Returns an RSAPublicKey provider. + """ + + +class DSABackend(metaclass=abc.ABCMeta): + @abc.abstractmethod + def generate_dsa_parameters(self, key_size): + """ + Generate a DSAParameters instance with a modulus of key_size bits. + """ + + @abc.abstractmethod + def generate_dsa_private_key(self, parameters): + """ + Generate a DSAPrivateKey instance with parameters as a DSAParameters + object. + """ + + @abc.abstractmethod + def generate_dsa_private_key_and_parameters(self, key_size): + """ + Generate a DSAPrivateKey instance using key size only. + """ + + @abc.abstractmethod + def dsa_hash_supported(self, algorithm): + """ + Return True if the hash algorithm is supported by the backend for DSA. + """ + + @abc.abstractmethod + def dsa_parameters_supported(self, p, q, g): + """ + Return True if the parameters are supported by the backend for DSA. + """ + + @abc.abstractmethod + def load_dsa_private_numbers(self, numbers): + """ + Returns a DSAPrivateKey provider. + """ + + @abc.abstractmethod + def load_dsa_public_numbers(self, numbers): + """ + Returns a DSAPublicKey provider. + """ + + @abc.abstractmethod + def load_dsa_parameter_numbers(self, numbers): + """ + Returns a DSAParameters provider. + """ + + +class EllipticCurveBackend(metaclass=abc.ABCMeta): + @abc.abstractmethod + def elliptic_curve_signature_algorithm_supported( + self, signature_algorithm, curve + ): + """ + Returns True if the backend supports the named elliptic curve with the + specified signature algorithm. + """ + + @abc.abstractmethod + def elliptic_curve_supported(self, curve): + """ + Returns True if the backend supports the named elliptic curve. + """ + + @abc.abstractmethod + def generate_elliptic_curve_private_key(self, curve): + """ + Return an object conforming to the EllipticCurvePrivateKey interface. + """ + + @abc.abstractmethod + def load_elliptic_curve_public_numbers(self, numbers): + """ + Return an EllipticCurvePublicKey provider using the given numbers. + """ + + @abc.abstractmethod + def load_elliptic_curve_private_numbers(self, numbers): + """ + Return an EllipticCurvePrivateKey provider using the given numbers. + """ + + @abc.abstractmethod + def elliptic_curve_exchange_algorithm_supported(self, algorithm, curve): + """ + Returns whether the exchange algorithm is supported by this backend. + """ + + @abc.abstractmethod + def derive_elliptic_curve_private_key(self, private_value, curve): + """ + Compute the private key given the private value and curve. + """ + + +class PEMSerializationBackend(metaclass=abc.ABCMeta): + @abc.abstractmethod + def load_pem_private_key(self, data, password): + """ + Loads a private key from PEM encoded data, using the provided password + if the data is encrypted. + """ + + @abc.abstractmethod + def load_pem_public_key(self, data): + """ + Loads a public key from PEM encoded data. + """ + + @abc.abstractmethod + def load_pem_parameters(self, data): + """ + Load encryption parameters from PEM encoded data. + """ + + +class DERSerializationBackend(metaclass=abc.ABCMeta): + @abc.abstractmethod + def load_der_private_key(self, data, password): + """ + Loads a private key from DER encoded data. Uses the provided password + if the data is encrypted. + """ + + @abc.abstractmethod + def load_der_public_key(self, data): + """ + Loads a public key from DER encoded data. + """ + + @abc.abstractmethod + def load_der_parameters(self, data): + """ + Load encryption parameters from DER encoded data. + """ + + +class DHBackend(metaclass=abc.ABCMeta): + @abc.abstractmethod + def generate_dh_parameters(self, generator, key_size): + """ + Generate a DHParameters instance with a modulus of key_size bits. + Using the given generator. Often 2 or 5. + """ + + @abc.abstractmethod + def generate_dh_private_key(self, parameters): + """ + Generate a DHPrivateKey instance with parameters as a DHParameters + object. + """ + + @abc.abstractmethod + def generate_dh_private_key_and_parameters(self, generator, key_size): + """ + Generate a DHPrivateKey instance using key size only. + Using the given generator. Often 2 or 5. + """ + + @abc.abstractmethod + def load_dh_private_numbers(self, numbers): + """ + Load a DHPrivateKey from DHPrivateNumbers + """ + + @abc.abstractmethod + def load_dh_public_numbers(self, numbers): + """ + Load a DHPublicKey from DHPublicNumbers. + """ + + @abc.abstractmethod + def load_dh_parameter_numbers(self, numbers): + """ + Load DHParameters from DHParameterNumbers. + """ + + @abc.abstractmethod + def dh_parameters_supported(self, p, g, q=None): + """ + Returns whether the backend supports DH with these parameter values. + """ + + @abc.abstractmethod + def dh_x942_serialization_supported(self): + """ + Returns True if the backend supports the serialization of DH objects + with subgroup order (q). + """ + + +class ScryptBackend(metaclass=abc.ABCMeta): + @abc.abstractmethod + def derive_scrypt(self, key_material, salt, length, n, r, p): + """ + Return bytes derived from provided Scrypt parameters. + """ + + @abc.abstractmethod + def scrypt_supported(self): + """ + Return True if Scrypt is supported. + """ + + +# This is the catch-all for future backend methods and inherits all the +# other interfaces as well so we can just use Backend for typing. +class Backend( + CipherBackend, + CMACBackend, + DERSerializationBackend, + DHBackend, + DSABackend, + EllipticCurveBackend, + HashBackend, + HMACBackend, + PBKDF2HMACBackend, + RSABackend, + PEMSerializationBackend, + ScryptBackend, + metaclass=abc.ABCMeta, +): + @abc.abstractmethod + def load_pem_pkcs7_certificates(self, data): + """ + Returns a list of x509.Certificate + """ + + @abc.abstractmethod + def load_der_pkcs7_certificates(self, data): + """ + Returns a list of x509.Certificate + """ + + @abc.abstractmethod + def pkcs7_sign(self, builder, encoding, options): + """ + Returns bytes + """ + + @abc.abstractmethod + def load_key_and_certificates_from_pkcs12(self, data, password): + """ + Returns a tuple of (key, cert, [certs]) + """ + + @abc.abstractmethod + def load_pkcs12(self, data, password): + """ + Returns a PKCS12KeyAndCertificates object + """ + + @abc.abstractmethod + def serialize_key_and_certificates_to_pkcs12( + self, name, key, cert, cas, encryption_algorithm + ): + """ + Returns bytes + """ diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/backends/openssl/__init__.py b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/backends/openssl/__init__.py new file mode 100644 index 00000000..31fd17c3 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/backends/openssl/__init__.py @@ -0,0 +1,9 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + + +from cryptography.hazmat.backends.openssl.backend import backend + + +__all__ = ["backend"] diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/backends/openssl/aead.py b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/backends/openssl/aead.py new file mode 100644 index 00000000..43f642cc --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/backends/openssl/aead.py @@ -0,0 +1,175 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + + +from cryptography.exceptions import InvalidTag + + +_ENCRYPT = 1 +_DECRYPT = 0 + + +def _aead_cipher_name(cipher): + from cryptography.hazmat.primitives.ciphers.aead import ( + AESCCM, + AESGCM, + AESOCB3, + ChaCha20Poly1305, + ) + + if isinstance(cipher, ChaCha20Poly1305): + return b"chacha20-poly1305" + elif isinstance(cipher, AESCCM): + return "aes-{}-ccm".format(len(cipher._key) * 8).encode("ascii") + elif isinstance(cipher, AESOCB3): + return "aes-{}-ocb".format(len(cipher._key) * 8).encode("ascii") + else: + assert isinstance(cipher, AESGCM) + return "aes-{}-gcm".format(len(cipher._key) * 8).encode("ascii") + + +def _aead_setup(backend, cipher_name, key, nonce, tag, tag_len, operation): + evp_cipher = backend._lib.EVP_get_cipherbyname(cipher_name) + backend.openssl_assert(evp_cipher != backend._ffi.NULL) + ctx = backend._lib.EVP_CIPHER_CTX_new() + ctx = backend._ffi.gc(ctx, backend._lib.EVP_CIPHER_CTX_free) + res = backend._lib.EVP_CipherInit_ex( + ctx, + evp_cipher, + backend._ffi.NULL, + backend._ffi.NULL, + backend._ffi.NULL, + int(operation == _ENCRYPT), + ) + backend.openssl_assert(res != 0) + res = backend._lib.EVP_CIPHER_CTX_set_key_length(ctx, len(key)) + backend.openssl_assert(res != 0) + res = backend._lib.EVP_CIPHER_CTX_ctrl( + ctx, + backend._lib.EVP_CTRL_AEAD_SET_IVLEN, + len(nonce), + backend._ffi.NULL, + ) + backend.openssl_assert(res != 0) + if operation == _DECRYPT: + res = backend._lib.EVP_CIPHER_CTX_ctrl( + ctx, backend._lib.EVP_CTRL_AEAD_SET_TAG, len(tag), tag + ) + backend.openssl_assert(res != 0) + elif cipher_name.endswith(b"-ccm"): + res = backend._lib.EVP_CIPHER_CTX_ctrl( + ctx, backend._lib.EVP_CTRL_AEAD_SET_TAG, tag_len, backend._ffi.NULL + ) + backend.openssl_assert(res != 0) + + nonce_ptr = backend._ffi.from_buffer(nonce) + key_ptr = backend._ffi.from_buffer(key) + res = backend._lib.EVP_CipherInit_ex( + ctx, + backend._ffi.NULL, + backend._ffi.NULL, + key_ptr, + nonce_ptr, + int(operation == _ENCRYPT), + ) + backend.openssl_assert(res != 0) + return ctx + + +def _set_length(backend, ctx, data_len): + intptr = backend._ffi.new("int *") + res = backend._lib.EVP_CipherUpdate( + ctx, backend._ffi.NULL, intptr, backend._ffi.NULL, data_len + ) + backend.openssl_assert(res != 0) + + +def _process_aad(backend, ctx, associated_data): + outlen = backend._ffi.new("int *") + res = backend._lib.EVP_CipherUpdate( + ctx, backend._ffi.NULL, outlen, associated_data, len(associated_data) + ) + backend.openssl_assert(res != 0) + + +def _process_data(backend, ctx, data): + outlen = backend._ffi.new("int *") + buf = backend._ffi.new("unsigned char[]", len(data)) + res = backend._lib.EVP_CipherUpdate(ctx, buf, outlen, data, len(data)) + backend.openssl_assert(res != 0) + return backend._ffi.buffer(buf, outlen[0])[:] + + +def _encrypt(backend, cipher, nonce, data, associated_data, tag_length): + from cryptography.hazmat.primitives.ciphers.aead import AESCCM + + cipher_name = _aead_cipher_name(cipher) + ctx = _aead_setup( + backend, cipher_name, cipher._key, nonce, None, tag_length, _ENCRYPT + ) + # CCM requires us to pass the length of the data before processing anything + # However calling this with any other AEAD results in an error + if isinstance(cipher, AESCCM): + _set_length(backend, ctx, len(data)) + + _process_aad(backend, ctx, associated_data) + processed_data = _process_data(backend, ctx, data) + outlen = backend._ffi.new("int *") + # All AEADs we support besides OCB are streaming so they return nothing + # in finalization. OCB can return up to (16 byte block - 1) bytes so + # we need a buffer here too. + buf = backend._ffi.new("unsigned char[]", 16) + res = backend._lib.EVP_CipherFinal_ex(ctx, buf, outlen) + backend.openssl_assert(res != 0) + processed_data += backend._ffi.buffer(buf, outlen[0])[:] + tag_buf = backend._ffi.new("unsigned char[]", tag_length) + res = backend._lib.EVP_CIPHER_CTX_ctrl( + ctx, backend._lib.EVP_CTRL_AEAD_GET_TAG, tag_length, tag_buf + ) + backend.openssl_assert(res != 0) + tag = backend._ffi.buffer(tag_buf)[:] + + return processed_data + tag + + +def _decrypt(backend, cipher, nonce, data, associated_data, tag_length): + from cryptography.hazmat.primitives.ciphers.aead import AESCCM + + if len(data) < tag_length: + raise InvalidTag + tag = data[-tag_length:] + data = data[:-tag_length] + cipher_name = _aead_cipher_name(cipher) + ctx = _aead_setup( + backend, cipher_name, cipher._key, nonce, tag, tag_length, _DECRYPT + ) + # CCM requires us to pass the length of the data before processing anything + # However calling this with any other AEAD results in an error + if isinstance(cipher, AESCCM): + _set_length(backend, ctx, len(data)) + + _process_aad(backend, ctx, associated_data) + # CCM has a different error path if the tag doesn't match. Errors are + # raised in Update and Final is irrelevant. + if isinstance(cipher, AESCCM): + outlen = backend._ffi.new("int *") + buf = backend._ffi.new("unsigned char[]", len(data)) + res = backend._lib.EVP_CipherUpdate(ctx, buf, outlen, data, len(data)) + if res != 1: + backend._consume_errors() + raise InvalidTag + + processed_data = backend._ffi.buffer(buf, outlen[0])[:] + else: + processed_data = _process_data(backend, ctx, data) + outlen = backend._ffi.new("int *") + # OCB can return up to 15 bytes (16 byte block - 1) in finalization + buf = backend._ffi.new("unsigned char[]", 16) + res = backend._lib.EVP_CipherFinal_ex(ctx, buf, outlen) + processed_data += backend._ffi.buffer(buf, outlen[0])[:] + if res == 0: + backend._consume_errors() + raise InvalidTag + + return processed_data diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/backends/openssl/backend.py b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/backends/openssl/backend.py new file mode 100644 index 00000000..73645239 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/backends/openssl/backend.py @@ -0,0 +1,2311 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + + +import collections +import contextlib +import itertools +import typing +import warnings +from contextlib import contextmanager + +from cryptography import utils, x509 +from cryptography.exceptions import UnsupportedAlgorithm, _Reasons +from cryptography.hazmat.backends.interfaces import Backend as BackendInterface +from cryptography.hazmat.backends.openssl import aead +from cryptography.hazmat.backends.openssl.ciphers import _CipherContext +from cryptography.hazmat.backends.openssl.cmac import _CMACContext +from cryptography.hazmat.backends.openssl.dh import ( + _DHParameters, + _DHPrivateKey, + _DHPublicKey, + _dh_params_dup, +) +from cryptography.hazmat.backends.openssl.dsa import ( + _DSAParameters, + _DSAPrivateKey, + _DSAPublicKey, +) +from cryptography.hazmat.backends.openssl.ec import ( + _EllipticCurvePrivateKey, + _EllipticCurvePublicKey, +) +from cryptography.hazmat.backends.openssl.ed25519 import ( + _Ed25519PrivateKey, + _Ed25519PublicKey, +) +from cryptography.hazmat.backends.openssl.ed448 import ( + _ED448_KEY_SIZE, + _Ed448PrivateKey, + _Ed448PublicKey, +) +from cryptography.hazmat.backends.openssl.hashes import _HashContext +from cryptography.hazmat.backends.openssl.hmac import _HMACContext +from cryptography.hazmat.backends.openssl.poly1305 import ( + _POLY1305_KEY_SIZE, + _Poly1305Context, +) +from cryptography.hazmat.backends.openssl.rsa import ( + _RSAPrivateKey, + _RSAPublicKey, +) +from cryptography.hazmat.backends.openssl.x25519 import ( + _X25519PrivateKey, + _X25519PublicKey, +) +from cryptography.hazmat.backends.openssl.x448 import ( + _X448PrivateKey, + _X448PublicKey, +) +from cryptography.hazmat.bindings._rust import ( + x509 as rust_x509, +) +from cryptography.hazmat.bindings.openssl import binding +from cryptography.hazmat.primitives import hashes, serialization +from cryptography.hazmat.primitives.asymmetric import ( + dh, + dsa, + ec, + ed25519, + rsa, +) +from cryptography.hazmat.primitives.asymmetric.padding import ( + MGF1, + OAEP, + PKCS1v15, + PSS, +) +from cryptography.hazmat.primitives.ciphers.algorithms import ( + AES, + ARC4, + Blowfish, + CAST5, + Camellia, + ChaCha20, + IDEA, + SEED, + SM4, + TripleDES, +) +from cryptography.hazmat.primitives.ciphers.modes import ( + CBC, + CFB, + CFB8, + CTR, + ECB, + GCM, + OFB, + XTS, +) +from cryptography.hazmat.primitives.kdf import scrypt +from cryptography.hazmat.primitives.serialization import pkcs7, ssh +from cryptography.hazmat.primitives.serialization.pkcs12 import ( + PKCS12Certificate, + PKCS12KeyAndCertificates, +) +from cryptography.x509.base import PUBLIC_KEY_TYPES + + +_MemoryBIO = collections.namedtuple("_MemoryBIO", ["bio", "char_ptr"]) + + +# Not actually supported, just used as a marker for some serialization tests. +class _RC2(object): + pass + + +class Backend(BackendInterface): + """ + OpenSSL API binding interfaces. + """ + + name = "openssl" + + # FIPS has opinions about acceptable algorithms and key sizes, but the + # disallowed algorithms are still present in OpenSSL. They just error if + # you try to use them. To avoid that we allowlist the algorithms in + # FIPS 140-3. This isn't ideal, but FIPS 140-3 is trash so here we are. + _fips_aead = { + b"aes-128-ccm", + b"aes-192-ccm", + b"aes-256-ccm", + b"aes-128-gcm", + b"aes-192-gcm", + b"aes-256-gcm", + } + _fips_ciphers = (AES, TripleDES) + # Sometimes SHA1 is still permissible. That logic is contained + # within the various *_supported methods. + _fips_hashes = ( + hashes.SHA224, + hashes.SHA256, + hashes.SHA384, + hashes.SHA512, + hashes.SHA512_224, + hashes.SHA512_256, + hashes.SHA3_224, + hashes.SHA3_256, + hashes.SHA3_384, + hashes.SHA3_512, + hashes.SHAKE128, + hashes.SHAKE256, + ) + _fips_ecdh_curves = ( + ec.SECP224R1, + ec.SECP256R1, + ec.SECP384R1, + ec.SECP521R1, + ) + _fips_rsa_min_key_size = 2048 + _fips_rsa_min_public_exponent = 65537 + _fips_dsa_min_modulus = 1 << 2048 + _fips_dh_min_key_size = 2048 + _fips_dh_min_modulus = 1 << _fips_dh_min_key_size + + def __init__(self): + self._binding = binding.Binding() + self._ffi = self._binding.ffi + self._lib = self._binding.lib + self._rsa_skip_check_key = False + self._fips_enabled = self._is_fips_enabled() + + self._cipher_registry = {} + self._register_default_ciphers() + if self._fips_enabled and self._lib.CRYPTOGRAPHY_NEEDS_OSRANDOM_ENGINE: + warnings.warn( + "OpenSSL FIPS mode is enabled. Can't enable DRBG fork safety.", + UserWarning, + ) + else: + self.activate_osrandom_engine() + self._dh_types = [self._lib.EVP_PKEY_DH] + if self._lib.Cryptography_HAS_EVP_PKEY_DHX: + self._dh_types.append(self._lib.EVP_PKEY_DHX) + + def __repr__(self): + return "<OpenSSLBackend(version: {}, FIPS: {})>".format( + self.openssl_version_text(), self._fips_enabled + ) + + def openssl_assert(self, ok, errors=None): + return binding._openssl_assert(self._lib, ok, errors=errors) + + def _is_fips_enabled(self): + if self._lib.Cryptography_HAS_300_FIPS: + mode = self._lib.EVP_default_properties_is_fips_enabled( + self._ffi.NULL + ) + else: + mode = getattr(self._lib, "FIPS_mode", lambda: 0)() + + if mode == 0: + # OpenSSL without FIPS pushes an error on the error stack + self._lib.ERR_clear_error() + return bool(mode) + + def _enable_fips(self): + # This function enables FIPS mode for OpenSSL 3.0.0 on installs that + # have the FIPS provider installed properly. + self._binding._enable_fips() + assert self._is_fips_enabled() + self._fips_enabled = self._is_fips_enabled() + + def activate_builtin_random(self): + if self._lib.CRYPTOGRAPHY_NEEDS_OSRANDOM_ENGINE: + # Obtain a new structural reference. + e = self._lib.ENGINE_get_default_RAND() + if e != self._ffi.NULL: + self._lib.ENGINE_unregister_RAND(e) + # Reset the RNG to use the built-in. + res = self._lib.RAND_set_rand_method(self._ffi.NULL) + self.openssl_assert(res == 1) + # decrement the structural reference from get_default_RAND + res = self._lib.ENGINE_finish(e) + self.openssl_assert(res == 1) + + @contextlib.contextmanager + def _get_osurandom_engine(self): + # Fetches an engine by id and returns it. This creates a structural + # reference. + e = self._lib.ENGINE_by_id(self._lib.Cryptography_osrandom_engine_id) + self.openssl_assert(e != self._ffi.NULL) + # Initialize the engine for use. This adds a functional reference. + res = self._lib.ENGINE_init(e) + self.openssl_assert(res == 1) + + try: + yield e + finally: + # Decrement the structural ref incremented by ENGINE_by_id. + res = self._lib.ENGINE_free(e) + self.openssl_assert(res == 1) + # Decrement the functional ref incremented by ENGINE_init. + res = self._lib.ENGINE_finish(e) + self.openssl_assert(res == 1) + + def activate_osrandom_engine(self): + if self._lib.CRYPTOGRAPHY_NEEDS_OSRANDOM_ENGINE: + # Unregister and free the current engine. + self.activate_builtin_random() + with self._get_osurandom_engine() as e: + # Set the engine as the default RAND provider. + res = self._lib.ENGINE_set_default_RAND(e) + self.openssl_assert(res == 1) + # Reset the RNG to use the engine + res = self._lib.RAND_set_rand_method(self._ffi.NULL) + self.openssl_assert(res == 1) + + def osrandom_engine_implementation(self): + buf = self._ffi.new("char[]", 64) + with self._get_osurandom_engine() as e: + res = self._lib.ENGINE_ctrl_cmd( + e, b"get_implementation", len(buf), buf, self._ffi.NULL, 0 + ) + self.openssl_assert(res > 0) + return self._ffi.string(buf).decode("ascii") + + def openssl_version_text(self): + """ + Friendly string name of the loaded OpenSSL library. This is not + necessarily the same version as it was compiled against. + + Example: OpenSSL 1.1.1d 10 Sep 2019 + """ + return self._ffi.string( + self._lib.OpenSSL_version(self._lib.OPENSSL_VERSION) + ).decode("ascii") + + def openssl_version_number(self): + return self._lib.OpenSSL_version_num() + + def create_hmac_ctx(self, key, algorithm): + return _HMACContext(self, key, algorithm) + + def _evp_md_from_algorithm(self, algorithm): + if algorithm.name == "blake2b" or algorithm.name == "blake2s": + alg = "{}{}".format( + algorithm.name, algorithm.digest_size * 8 + ).encode("ascii") + else: + alg = algorithm.name.encode("ascii") + + evp_md = self._lib.EVP_get_digestbyname(alg) + return evp_md + + def _evp_md_non_null_from_algorithm(self, algorithm): + evp_md = self._evp_md_from_algorithm(algorithm) + self.openssl_assert(evp_md != self._ffi.NULL) + return evp_md + + def hash_supported(self, algorithm): + if self._fips_enabled and not isinstance(algorithm, self._fips_hashes): + return False + + evp_md = self._evp_md_from_algorithm(algorithm) + return evp_md != self._ffi.NULL + + def scrypt_supported(self): + if self._fips_enabled: + return False + else: + return self._lib.Cryptography_HAS_SCRYPT == 1 + + def hmac_supported(self, algorithm): + # FIPS mode still allows SHA1 for HMAC + if self._fips_enabled and isinstance(algorithm, hashes.SHA1): + return True + + return self.hash_supported(algorithm) + + def create_hash_ctx(self, algorithm): + return _HashContext(self, algorithm) + + def cipher_supported(self, cipher, mode): + if self._fips_enabled: + # FIPS mode requires AES or TripleDES, but only CBC/ECB allowed + # in TripleDES mode. + if not isinstance(cipher, self._fips_ciphers) or ( + isinstance(cipher, TripleDES) + and not isinstance(mode, (CBC, ECB)) + ): + return False + + try: + adapter = self._cipher_registry[type(cipher), type(mode)] + except KeyError: + return False + evp_cipher = adapter(self, cipher, mode) + return self._ffi.NULL != evp_cipher + + def register_cipher_adapter(self, cipher_cls, mode_cls, adapter): + if (cipher_cls, mode_cls) in self._cipher_registry: + raise ValueError( + "Duplicate registration for: {} {}.".format( + cipher_cls, mode_cls + ) + ) + self._cipher_registry[cipher_cls, mode_cls] = adapter + + def _register_default_ciphers(self): + for mode_cls in [CBC, CTR, ECB, OFB, CFB, CFB8, GCM]: + self.register_cipher_adapter( + AES, + mode_cls, + GetCipherByName("{cipher.name}-{cipher.key_size}-{mode.name}"), + ) + for mode_cls in [CBC, CTR, ECB, OFB, CFB]: + self.register_cipher_adapter( + Camellia, + mode_cls, + GetCipherByName("{cipher.name}-{cipher.key_size}-{mode.name}"), + ) + for mode_cls in [CBC, CFB, CFB8, OFB]: + self.register_cipher_adapter( + TripleDES, mode_cls, GetCipherByName("des-ede3-{mode.name}") + ) + self.register_cipher_adapter( + TripleDES, ECB, GetCipherByName("des-ede3") + ) + for mode_cls in [CBC, CFB, OFB, ECB]: + self.register_cipher_adapter( + Blowfish, mode_cls, GetCipherByName("bf-{mode.name}") + ) + for mode_cls in [CBC, CFB, OFB, ECB]: + self.register_cipher_adapter( + SEED, mode_cls, GetCipherByName("seed-{mode.name}") + ) + for cipher_cls, mode_cls in itertools.product( + [CAST5, IDEA], + [CBC, OFB, CFB, ECB], + ): + self.register_cipher_adapter( + cipher_cls, + mode_cls, + GetCipherByName("{cipher.name}-{mode.name}"), + ) + self.register_cipher_adapter(ARC4, type(None), GetCipherByName("rc4")) + # We don't actually support RC2, this is just used by some tests. + self.register_cipher_adapter(_RC2, type(None), GetCipherByName("rc2")) + self.register_cipher_adapter( + ChaCha20, type(None), GetCipherByName("chacha20") + ) + self.register_cipher_adapter(AES, XTS, _get_xts_cipher) + for mode_cls in [ECB, CBC, OFB, CFB, CTR]: + self.register_cipher_adapter( + SM4, mode_cls, GetCipherByName("sm4-{mode.name}") + ) + + def create_symmetric_encryption_ctx(self, cipher, mode): + return _CipherContext(self, cipher, mode, _CipherContext._ENCRYPT) + + def create_symmetric_decryption_ctx(self, cipher, mode): + return _CipherContext(self, cipher, mode, _CipherContext._DECRYPT) + + def pbkdf2_hmac_supported(self, algorithm): + return self.hmac_supported(algorithm) + + def derive_pbkdf2_hmac( + self, algorithm, length, salt, iterations, key_material + ): + buf = self._ffi.new("unsigned char[]", length) + evp_md = self._evp_md_non_null_from_algorithm(algorithm) + key_material_ptr = self._ffi.from_buffer(key_material) + res = self._lib.PKCS5_PBKDF2_HMAC( + key_material_ptr, + len(key_material), + salt, + len(salt), + iterations, + evp_md, + length, + buf, + ) + self.openssl_assert(res == 1) + return self._ffi.buffer(buf)[:] + + def _consume_errors(self): + return binding._consume_errors(self._lib) + + def _consume_errors_with_text(self): + return binding._consume_errors_with_text(self._lib) + + def _bn_to_int(self, bn): + assert bn != self._ffi.NULL + self.openssl_assert(not self._lib.BN_is_negative(bn)) + + bn_num_bytes = self._lib.BN_num_bytes(bn) + bin_ptr = self._ffi.new("unsigned char[]", bn_num_bytes) + bin_len = self._lib.BN_bn2bin(bn, bin_ptr) + # A zero length means the BN has value 0 + self.openssl_assert(bin_len >= 0) + val = int.from_bytes(self._ffi.buffer(bin_ptr)[:bin_len], "big") + return val + + def _int_to_bn(self, num, bn=None): + """ + Converts a python integer to a BIGNUM. The returned BIGNUM will not + be garbage collected (to support adding them to structs that take + ownership of the object). Be sure to register it for GC if it will + be discarded after use. + """ + assert bn is None or bn != self._ffi.NULL + + if bn is None: + bn = self._ffi.NULL + + binary = num.to_bytes(int(num.bit_length() / 8.0 + 1), "big") + bn_ptr = self._lib.BN_bin2bn(binary, len(binary), bn) + self.openssl_assert(bn_ptr != self._ffi.NULL) + return bn_ptr + + def generate_rsa_private_key(self, public_exponent, key_size): + rsa._verify_rsa_parameters(public_exponent, key_size) + + rsa_cdata = self._lib.RSA_new() + self.openssl_assert(rsa_cdata != self._ffi.NULL) + rsa_cdata = self._ffi.gc(rsa_cdata, self._lib.RSA_free) + + bn = self._int_to_bn(public_exponent) + bn = self._ffi.gc(bn, self._lib.BN_free) + + res = self._lib.RSA_generate_key_ex( + rsa_cdata, key_size, bn, self._ffi.NULL + ) + self.openssl_assert(res == 1) + evp_pkey = self._rsa_cdata_to_evp_pkey(rsa_cdata) + + return _RSAPrivateKey( + self, rsa_cdata, evp_pkey, self._rsa_skip_check_key + ) + + def generate_rsa_parameters_supported(self, public_exponent, key_size): + return ( + public_exponent >= 3 + and public_exponent & 1 != 0 + and key_size >= 512 + ) + + def load_rsa_private_numbers(self, numbers): + rsa._check_private_key_components( + numbers.p, + numbers.q, + numbers.d, + numbers.dmp1, + numbers.dmq1, + numbers.iqmp, + numbers.public_numbers.e, + numbers.public_numbers.n, + ) + rsa_cdata = self._lib.RSA_new() + self.openssl_assert(rsa_cdata != self._ffi.NULL) + rsa_cdata = self._ffi.gc(rsa_cdata, self._lib.RSA_free) + p = self._int_to_bn(numbers.p) + q = self._int_to_bn(numbers.q) + d = self._int_to_bn(numbers.d) + dmp1 = self._int_to_bn(numbers.dmp1) + dmq1 = self._int_to_bn(numbers.dmq1) + iqmp = self._int_to_bn(numbers.iqmp) + e = self._int_to_bn(numbers.public_numbers.e) + n = self._int_to_bn(numbers.public_numbers.n) + res = self._lib.RSA_set0_factors(rsa_cdata, p, q) + self.openssl_assert(res == 1) + res = self._lib.RSA_set0_key(rsa_cdata, n, e, d) + self.openssl_assert(res == 1) + res = self._lib.RSA_set0_crt_params(rsa_cdata, dmp1, dmq1, iqmp) + self.openssl_assert(res == 1) + evp_pkey = self._rsa_cdata_to_evp_pkey(rsa_cdata) + + return _RSAPrivateKey( + self, rsa_cdata, evp_pkey, self._rsa_skip_check_key + ) + + def load_rsa_public_numbers(self, numbers): + rsa._check_public_key_components(numbers.e, numbers.n) + rsa_cdata = self._lib.RSA_new() + self.openssl_assert(rsa_cdata != self._ffi.NULL) + rsa_cdata = self._ffi.gc(rsa_cdata, self._lib.RSA_free) + e = self._int_to_bn(numbers.e) + n = self._int_to_bn(numbers.n) + res = self._lib.RSA_set0_key(rsa_cdata, n, e, self._ffi.NULL) + self.openssl_assert(res == 1) + evp_pkey = self._rsa_cdata_to_evp_pkey(rsa_cdata) + + return _RSAPublicKey(self, rsa_cdata, evp_pkey) + + def _create_evp_pkey_gc(self): + evp_pkey = self._lib.EVP_PKEY_new() + self.openssl_assert(evp_pkey != self._ffi.NULL) + evp_pkey = self._ffi.gc(evp_pkey, self._lib.EVP_PKEY_free) + return evp_pkey + + def _rsa_cdata_to_evp_pkey(self, rsa_cdata): + evp_pkey = self._create_evp_pkey_gc() + res = self._lib.EVP_PKEY_set1_RSA(evp_pkey, rsa_cdata) + self.openssl_assert(res == 1) + return evp_pkey + + def _bytes_to_bio(self, data): + """ + Return a _MemoryBIO namedtuple of (BIO, char*). + + The char* is the storage for the BIO and it must stay alive until the + BIO is finished with. + """ + data_ptr = self._ffi.from_buffer(data) + bio = self._lib.BIO_new_mem_buf(data_ptr, len(data)) + self.openssl_assert(bio != self._ffi.NULL) + + return _MemoryBIO(self._ffi.gc(bio, self._lib.BIO_free), data_ptr) + + def _create_mem_bio_gc(self): + """ + Creates an empty memory BIO. + """ + bio_method = self._lib.BIO_s_mem() + self.openssl_assert(bio_method != self._ffi.NULL) + bio = self._lib.BIO_new(bio_method) + self.openssl_assert(bio != self._ffi.NULL) + bio = self._ffi.gc(bio, self._lib.BIO_free) + return bio + + def _read_mem_bio(self, bio): + """ + Reads a memory BIO. This only works on memory BIOs. + """ + buf = self._ffi.new("char **") + buf_len = self._lib.BIO_get_mem_data(bio, buf) + self.openssl_assert(buf_len > 0) + self.openssl_assert(buf[0] != self._ffi.NULL) + bio_data = self._ffi.buffer(buf[0], buf_len)[:] + return bio_data + + def _evp_pkey_to_private_key(self, evp_pkey): + """ + Return the appropriate type of PrivateKey given an evp_pkey cdata + pointer. + """ + + key_type = self._lib.EVP_PKEY_id(evp_pkey) + + if key_type == self._lib.EVP_PKEY_RSA: + rsa_cdata = self._lib.EVP_PKEY_get1_RSA(evp_pkey) + self.openssl_assert(rsa_cdata != self._ffi.NULL) + rsa_cdata = self._ffi.gc(rsa_cdata, self._lib.RSA_free) + return _RSAPrivateKey( + self, rsa_cdata, evp_pkey, self._rsa_skip_check_key + ) + elif key_type == self._lib.EVP_PKEY_DSA: + dsa_cdata = self._lib.EVP_PKEY_get1_DSA(evp_pkey) + self.openssl_assert(dsa_cdata != self._ffi.NULL) + dsa_cdata = self._ffi.gc(dsa_cdata, self._lib.DSA_free) + return _DSAPrivateKey(self, dsa_cdata, evp_pkey) + elif key_type == self._lib.EVP_PKEY_EC: + ec_cdata = self._lib.EVP_PKEY_get1_EC_KEY(evp_pkey) + self.openssl_assert(ec_cdata != self._ffi.NULL) + ec_cdata = self._ffi.gc(ec_cdata, self._lib.EC_KEY_free) + return _EllipticCurvePrivateKey(self, ec_cdata, evp_pkey) + elif key_type in self._dh_types: + dh_cdata = self._lib.EVP_PKEY_get1_DH(evp_pkey) + self.openssl_assert(dh_cdata != self._ffi.NULL) + dh_cdata = self._ffi.gc(dh_cdata, self._lib.DH_free) + return _DHPrivateKey(self, dh_cdata, evp_pkey) + elif key_type == getattr(self._lib, "EVP_PKEY_ED25519", None): + # EVP_PKEY_ED25519 is not present in OpenSSL < 1.1.1 + return _Ed25519PrivateKey(self, evp_pkey) + elif key_type == getattr(self._lib, "EVP_PKEY_X448", None): + # EVP_PKEY_X448 is not present in OpenSSL < 1.1.1 + return _X448PrivateKey(self, evp_pkey) + elif key_type == getattr(self._lib, "EVP_PKEY_X25519", None): + # EVP_PKEY_X25519 is not present in OpenSSL < 1.1.0 + return _X25519PrivateKey(self, evp_pkey) + elif key_type == getattr(self._lib, "EVP_PKEY_ED448", None): + # EVP_PKEY_ED448 is not present in OpenSSL < 1.1.1 + return _Ed448PrivateKey(self, evp_pkey) + else: + raise UnsupportedAlgorithm("Unsupported key type.") + + def _evp_pkey_to_public_key(self, evp_pkey): + """ + Return the appropriate type of PublicKey given an evp_pkey cdata + pointer. + """ + + key_type = self._lib.EVP_PKEY_id(evp_pkey) + + if key_type == self._lib.EVP_PKEY_RSA: + rsa_cdata = self._lib.EVP_PKEY_get1_RSA(evp_pkey) + self.openssl_assert(rsa_cdata != self._ffi.NULL) + rsa_cdata = self._ffi.gc(rsa_cdata, self._lib.RSA_free) + return _RSAPublicKey(self, rsa_cdata, evp_pkey) + elif key_type == self._lib.EVP_PKEY_DSA: + dsa_cdata = self._lib.EVP_PKEY_get1_DSA(evp_pkey) + self.openssl_assert(dsa_cdata != self._ffi.NULL) + dsa_cdata = self._ffi.gc(dsa_cdata, self._lib.DSA_free) + return _DSAPublicKey(self, dsa_cdata, evp_pkey) + elif key_type == self._lib.EVP_PKEY_EC: + ec_cdata = self._lib.EVP_PKEY_get1_EC_KEY(evp_pkey) + self.openssl_assert(ec_cdata != self._ffi.NULL) + ec_cdata = self._ffi.gc(ec_cdata, self._lib.EC_KEY_free) + return _EllipticCurvePublicKey(self, ec_cdata, evp_pkey) + elif key_type in self._dh_types: + dh_cdata = self._lib.EVP_PKEY_get1_DH(evp_pkey) + self.openssl_assert(dh_cdata != self._ffi.NULL) + dh_cdata = self._ffi.gc(dh_cdata, self._lib.DH_free) + return _DHPublicKey(self, dh_cdata, evp_pkey) + elif key_type == getattr(self._lib, "EVP_PKEY_ED25519", None): + # EVP_PKEY_ED25519 is not present in OpenSSL < 1.1.1 + return _Ed25519PublicKey(self, evp_pkey) + elif key_type == getattr(self._lib, "EVP_PKEY_X448", None): + # EVP_PKEY_X448 is not present in OpenSSL < 1.1.1 + return _X448PublicKey(self, evp_pkey) + elif key_type == getattr(self._lib, "EVP_PKEY_X25519", None): + # EVP_PKEY_X25519 is not present in OpenSSL < 1.1.0 + return _X25519PublicKey(self, evp_pkey) + elif key_type == getattr(self._lib, "EVP_PKEY_ED448", None): + # EVP_PKEY_X25519 is not present in OpenSSL < 1.1.1 + return _Ed448PublicKey(self, evp_pkey) + else: + raise UnsupportedAlgorithm("Unsupported key type.") + + def _oaep_hash_supported(self, algorithm): + if self._lib.Cryptography_HAS_RSA_OAEP_MD: + return isinstance( + algorithm, + ( + hashes.SHA1, + hashes.SHA224, + hashes.SHA256, + hashes.SHA384, + hashes.SHA512, + ), + ) + else: + return isinstance(algorithm, hashes.SHA1) + + def rsa_padding_supported(self, padding): + if isinstance(padding, PKCS1v15): + return True + elif isinstance(padding, PSS) and isinstance(padding._mgf, MGF1): + # SHA1 is permissible in MGF1 in FIPS + if self._fips_enabled and isinstance( + padding._mgf._algorithm, hashes.SHA1 + ): + return True + else: + return self.hash_supported(padding._mgf._algorithm) + elif isinstance(padding, OAEP) and isinstance(padding._mgf, MGF1): + return ( + self._oaep_hash_supported(padding._mgf._algorithm) + and self._oaep_hash_supported(padding._algorithm) + and ( + (padding._label is None or len(padding._label) == 0) + or self._lib.Cryptography_HAS_RSA_OAEP_LABEL == 1 + ) + ) + else: + return False + + def generate_dsa_parameters(self, key_size): + if key_size not in (1024, 2048, 3072, 4096): + raise ValueError( + "Key size must be 1024, 2048, 3072, or 4096 bits." + ) + + ctx = self._lib.DSA_new() + self.openssl_assert(ctx != self._ffi.NULL) + ctx = self._ffi.gc(ctx, self._lib.DSA_free) + + res = self._lib.DSA_generate_parameters_ex( + ctx, + key_size, + self._ffi.NULL, + 0, + self._ffi.NULL, + self._ffi.NULL, + self._ffi.NULL, + ) + + self.openssl_assert(res == 1) + + return _DSAParameters(self, ctx) + + def generate_dsa_private_key(self, parameters): + ctx = self._lib.DSAparams_dup(parameters._dsa_cdata) + self.openssl_assert(ctx != self._ffi.NULL) + ctx = self._ffi.gc(ctx, self._lib.DSA_free) + self._lib.DSA_generate_key(ctx) + evp_pkey = self._dsa_cdata_to_evp_pkey(ctx) + + return _DSAPrivateKey(self, ctx, evp_pkey) + + def generate_dsa_private_key_and_parameters(self, key_size): + parameters = self.generate_dsa_parameters(key_size) + return self.generate_dsa_private_key(parameters) + + def _dsa_cdata_set_values(self, dsa_cdata, p, q, g, pub_key, priv_key): + res = self._lib.DSA_set0_pqg(dsa_cdata, p, q, g) + self.openssl_assert(res == 1) + res = self._lib.DSA_set0_key(dsa_cdata, pub_key, priv_key) + self.openssl_assert(res == 1) + + def load_dsa_private_numbers(self, numbers): + dsa._check_dsa_private_numbers(numbers) + parameter_numbers = numbers.public_numbers.parameter_numbers + + dsa_cdata = self._lib.DSA_new() + self.openssl_assert(dsa_cdata != self._ffi.NULL) + dsa_cdata = self._ffi.gc(dsa_cdata, self._lib.DSA_free) + + p = self._int_to_bn(parameter_numbers.p) + q = self._int_to_bn(parameter_numbers.q) + g = self._int_to_bn(parameter_numbers.g) + pub_key = self._int_to_bn(numbers.public_numbers.y) + priv_key = self._int_to_bn(numbers.x) + self._dsa_cdata_set_values(dsa_cdata, p, q, g, pub_key, priv_key) + + evp_pkey = self._dsa_cdata_to_evp_pkey(dsa_cdata) + + return _DSAPrivateKey(self, dsa_cdata, evp_pkey) + + def load_dsa_public_numbers(self, numbers): + dsa._check_dsa_parameters(numbers.parameter_numbers) + dsa_cdata = self._lib.DSA_new() + self.openssl_assert(dsa_cdata != self._ffi.NULL) + dsa_cdata = self._ffi.gc(dsa_cdata, self._lib.DSA_free) + + p = self._int_to_bn(numbers.parameter_numbers.p) + q = self._int_to_bn(numbers.parameter_numbers.q) + g = self._int_to_bn(numbers.parameter_numbers.g) + pub_key = self._int_to_bn(numbers.y) + priv_key = self._ffi.NULL + self._dsa_cdata_set_values(dsa_cdata, p, q, g, pub_key, priv_key) + + evp_pkey = self._dsa_cdata_to_evp_pkey(dsa_cdata) + + return _DSAPublicKey(self, dsa_cdata, evp_pkey) + + def load_dsa_parameter_numbers(self, numbers): + dsa._check_dsa_parameters(numbers) + dsa_cdata = self._lib.DSA_new() + self.openssl_assert(dsa_cdata != self._ffi.NULL) + dsa_cdata = self._ffi.gc(dsa_cdata, self._lib.DSA_free) + + p = self._int_to_bn(numbers.p) + q = self._int_to_bn(numbers.q) + g = self._int_to_bn(numbers.g) + res = self._lib.DSA_set0_pqg(dsa_cdata, p, q, g) + self.openssl_assert(res == 1) + + return _DSAParameters(self, dsa_cdata) + + def _dsa_cdata_to_evp_pkey(self, dsa_cdata): + evp_pkey = self._create_evp_pkey_gc() + res = self._lib.EVP_PKEY_set1_DSA(evp_pkey, dsa_cdata) + self.openssl_assert(res == 1) + return evp_pkey + + def dsa_hash_supported(self, algorithm): + return self.hash_supported(algorithm) + + def dsa_parameters_supported(self, p, q, g): + return True + + def cmac_algorithm_supported(self, algorithm): + return self.cipher_supported( + algorithm, CBC(b"\x00" * algorithm.block_size) + ) + + def create_cmac_ctx(self, algorithm): + return _CMACContext(self, algorithm) + + def load_pem_private_key(self, data, password): + return self._load_key( + self._lib.PEM_read_bio_PrivateKey, + self._evp_pkey_to_private_key, + data, + password, + ) + + def load_pem_public_key(self, data): + mem_bio = self._bytes_to_bio(data) + evp_pkey = self._lib.PEM_read_bio_PUBKEY( + mem_bio.bio, self._ffi.NULL, self._ffi.NULL, self._ffi.NULL + ) + if evp_pkey != self._ffi.NULL: + evp_pkey = self._ffi.gc(evp_pkey, self._lib.EVP_PKEY_free) + return self._evp_pkey_to_public_key(evp_pkey) + else: + # It's not a (RSA/DSA/ECDSA) subjectPublicKeyInfo, but we still + # need to check to see if it is a pure PKCS1 RSA public key (not + # embedded in a subjectPublicKeyInfo) + self._consume_errors() + res = self._lib.BIO_reset(mem_bio.bio) + self.openssl_assert(res == 1) + rsa_cdata = self._lib.PEM_read_bio_RSAPublicKey( + mem_bio.bio, self._ffi.NULL, self._ffi.NULL, self._ffi.NULL + ) + if rsa_cdata != self._ffi.NULL: + rsa_cdata = self._ffi.gc(rsa_cdata, self._lib.RSA_free) + evp_pkey = self._rsa_cdata_to_evp_pkey(rsa_cdata) + return _RSAPublicKey(self, rsa_cdata, evp_pkey) + else: + self._handle_key_loading_error() + + def load_pem_parameters(self, data): + mem_bio = self._bytes_to_bio(data) + # only DH is supported currently + dh_cdata = self._lib.PEM_read_bio_DHparams( + mem_bio.bio, self._ffi.NULL, self._ffi.NULL, self._ffi.NULL + ) + if dh_cdata != self._ffi.NULL: + dh_cdata = self._ffi.gc(dh_cdata, self._lib.DH_free) + return _DHParameters(self, dh_cdata) + else: + self._handle_key_loading_error() + + def load_der_private_key(self, data, password): + # OpenSSL has a function called d2i_AutoPrivateKey that in theory + # handles this automatically, however it doesn't handle encrypted + # private keys. Instead we try to load the key two different ways. + # First we'll try to load it as a traditional key. + bio_data = self._bytes_to_bio(data) + key = self._evp_pkey_from_der_traditional_key(bio_data, password) + if key: + return self._evp_pkey_to_private_key(key) + else: + # Finally we try to load it with the method that handles encrypted + # PKCS8 properly. + return self._load_key( + self._lib.d2i_PKCS8PrivateKey_bio, + self._evp_pkey_to_private_key, + data, + password, + ) + + def _evp_pkey_from_der_traditional_key(self, bio_data, password): + key = self._lib.d2i_PrivateKey_bio(bio_data.bio, self._ffi.NULL) + if key != self._ffi.NULL: + # In OpenSSL 3.0.0-alpha15 there exist scenarios where the key will + # successfully load but errors are still put on the stack. Tracked + # as https://github.com/openssl/openssl/issues/14996 + self._consume_errors() + + key = self._ffi.gc(key, self._lib.EVP_PKEY_free) + if password is not None: + raise TypeError( + "Password was given but private key is not encrypted." + ) + + return key + else: + self._consume_errors() + return None + + def load_der_public_key(self, data): + mem_bio = self._bytes_to_bio(data) + evp_pkey = self._lib.d2i_PUBKEY_bio(mem_bio.bio, self._ffi.NULL) + if evp_pkey != self._ffi.NULL: + evp_pkey = self._ffi.gc(evp_pkey, self._lib.EVP_PKEY_free) + return self._evp_pkey_to_public_key(evp_pkey) + else: + # It's not a (RSA/DSA/ECDSA) subjectPublicKeyInfo, but we still + # need to check to see if it is a pure PKCS1 RSA public key (not + # embedded in a subjectPublicKeyInfo) + self._consume_errors() + res = self._lib.BIO_reset(mem_bio.bio) + self.openssl_assert(res == 1) + rsa_cdata = self._lib.d2i_RSAPublicKey_bio( + mem_bio.bio, self._ffi.NULL + ) + if rsa_cdata != self._ffi.NULL: + rsa_cdata = self._ffi.gc(rsa_cdata, self._lib.RSA_free) + evp_pkey = self._rsa_cdata_to_evp_pkey(rsa_cdata) + return _RSAPublicKey(self, rsa_cdata, evp_pkey) + else: + self._handle_key_loading_error() + + def load_der_parameters(self, data): + mem_bio = self._bytes_to_bio(data) + dh_cdata = self._lib.d2i_DHparams_bio(mem_bio.bio, self._ffi.NULL) + if dh_cdata != self._ffi.NULL: + dh_cdata = self._ffi.gc(dh_cdata, self._lib.DH_free) + return _DHParameters(self, dh_cdata) + elif self._lib.Cryptography_HAS_EVP_PKEY_DHX: + # We check to see if the is dhx. + self._consume_errors() + res = self._lib.BIO_reset(mem_bio.bio) + self.openssl_assert(res == 1) + dh_cdata = self._lib.Cryptography_d2i_DHxparams_bio( + mem_bio.bio, self._ffi.NULL + ) + if dh_cdata != self._ffi.NULL: + dh_cdata = self._ffi.gc(dh_cdata, self._lib.DH_free) + return _DHParameters(self, dh_cdata) + + self._handle_key_loading_error() + + def _cert2ossl(self, cert: x509.Certificate) -> typing.Any: + data = cert.public_bytes(serialization.Encoding.DER) + mem_bio = self._bytes_to_bio(data) + x509 = self._lib.d2i_X509_bio(mem_bio.bio, self._ffi.NULL) + self.openssl_assert(x509 != self._ffi.NULL) + x509 = self._ffi.gc(x509, self._lib.X509_free) + return x509 + + def _ossl2cert(self, x509: typing.Any) -> x509.Certificate: + bio = self._create_mem_bio_gc() + res = self._lib.i2d_X509_bio(bio, x509) + self.openssl_assert(res == 1) + return rust_x509.load_der_x509_certificate(self._read_mem_bio(bio)) + + def _csr2ossl(self, csr: x509.CertificateSigningRequest) -> typing.Any: + data = csr.public_bytes(serialization.Encoding.DER) + mem_bio = self._bytes_to_bio(data) + x509_req = self._lib.d2i_X509_REQ_bio(mem_bio.bio, self._ffi.NULL) + self.openssl_assert(x509_req != self._ffi.NULL) + x509_req = self._ffi.gc(x509_req, self._lib.X509_REQ_free) + return x509_req + + def _ossl2csr( + self, x509_req: typing.Any + ) -> x509.CertificateSigningRequest: + bio = self._create_mem_bio_gc() + res = self._lib.i2d_X509_REQ_bio(bio, x509_req) + self.openssl_assert(res == 1) + return rust_x509.load_der_x509_csr(self._read_mem_bio(bio)) + + def _crl2ossl(self, crl: x509.CertificateRevocationList) -> typing.Any: + data = crl.public_bytes(serialization.Encoding.DER) + mem_bio = self._bytes_to_bio(data) + x509_crl = self._lib.d2i_X509_CRL_bio(mem_bio.bio, self._ffi.NULL) + self.openssl_assert(x509_crl != self._ffi.NULL) + x509_crl = self._ffi.gc(x509_crl, self._lib.X509_CRL_free) + return x509_crl + + def _ossl2crl( + self, x509_crl: typing.Any + ) -> x509.CertificateRevocationList: + bio = self._create_mem_bio_gc() + res = self._lib.i2d_X509_CRL_bio(bio, x509_crl) + self.openssl_assert(res == 1) + return rust_x509.load_der_x509_crl(self._read_mem_bio(bio)) + + def _crl_is_signature_valid( + self, crl: x509.CertificateRevocationList, public_key: PUBLIC_KEY_TYPES + ) -> bool: + if not isinstance( + public_key, + ( + _DSAPublicKey, + _RSAPublicKey, + _EllipticCurvePublicKey, + ), + ): + raise TypeError( + "Expecting one of DSAPublicKey, RSAPublicKey," + " or EllipticCurvePublicKey." + ) + x509_crl = self._crl2ossl(crl) + res = self._lib.X509_CRL_verify(x509_crl, public_key._evp_pkey) + + if res != 1: + self._consume_errors() + return False + + return True + + def _csr_is_signature_valid( + self, csr: x509.CertificateSigningRequest + ) -> bool: + x509_req = self._csr2ossl(csr) + pkey = self._lib.X509_REQ_get_pubkey(x509_req) + self.openssl_assert(pkey != self._ffi.NULL) + pkey = self._ffi.gc(pkey, self._lib.EVP_PKEY_free) + res = self._lib.X509_REQ_verify(x509_req, pkey) + + if res != 1: + self._consume_errors() + return False + + return True + + def _check_keys_correspond(self, key1, key2): + if self._lib.EVP_PKEY_cmp(key1._evp_pkey, key2._evp_pkey) != 1: + raise ValueError("Keys do not correspond") + + def _load_key(self, openssl_read_func, convert_func, data, password): + mem_bio = self._bytes_to_bio(data) + + userdata = self._ffi.new("CRYPTOGRAPHY_PASSWORD_DATA *") + if password is not None: + utils._check_byteslike("password", password) + password_ptr = self._ffi.from_buffer(password) + userdata.password = password_ptr + userdata.length = len(password) + + evp_pkey = openssl_read_func( + mem_bio.bio, + self._ffi.NULL, + self._ffi.addressof( + self._lib._original_lib, "Cryptography_pem_password_cb" + ), + userdata, + ) + + if evp_pkey == self._ffi.NULL: + if userdata.error != 0: + self._consume_errors() + if userdata.error == -1: + raise TypeError( + "Password was not given but private key is encrypted" + ) + else: + assert userdata.error == -2 + raise ValueError( + "Passwords longer than {} bytes are not supported " + "by this backend.".format(userdata.maxsize - 1) + ) + else: + self._handle_key_loading_error() + + # In OpenSSL 3.0.0-alpha15 there exist scenarios where the key will + # successfully load but errors are still put on the stack. Tracked + # as https://github.com/openssl/openssl/issues/14996 + self._consume_errors() + + evp_pkey = self._ffi.gc(evp_pkey, self._lib.EVP_PKEY_free) + + if password is not None and userdata.called == 0: + raise TypeError( + "Password was given but private key is not encrypted." + ) + + assert ( + password is not None and userdata.called == 1 + ) or password is None + + return convert_func(evp_pkey) + + def _handle_key_loading_error(self): + errors = self._consume_errors() + + if not errors: + raise ValueError( + "Could not deserialize key data. The data may be in an " + "incorrect format or it may be encrypted with an unsupported " + "algorithm." + ) + + elif ( + errors[0]._lib_reason_match( + self._lib.ERR_LIB_EVP, self._lib.EVP_R_BAD_DECRYPT + ) + or errors[0]._lib_reason_match( + self._lib.ERR_LIB_PKCS12, + self._lib.PKCS12_R_PKCS12_CIPHERFINAL_ERROR, + ) + or ( + self._lib.Cryptography_HAS_PROVIDERS + and errors[0]._lib_reason_match( + self._lib.ERR_LIB_PROV, + self._lib.PROV_R_BAD_DECRYPT, + ) + ) + ): + raise ValueError("Bad decrypt. Incorrect password?") + + elif any( + error._lib_reason_match( + self._lib.ERR_LIB_EVP, + self._lib.EVP_R_UNSUPPORTED_PRIVATE_KEY_ALGORITHM, + ) + for error in errors + ): + raise ValueError("Unsupported public key algorithm.") + + else: + errors = binding._errors_with_text(errors) + raise ValueError( + "Could not deserialize key data. The data may be in an " + "incorrect format, it may be encrypted with an unsupported " + "algorithm, or it may be an unsupported key type (e.g. EC " + "curves with explicit parameters).", + errors, + ) + + def elliptic_curve_supported(self, curve): + try: + curve_nid = self._elliptic_curve_to_nid(curve) + except UnsupportedAlgorithm: + curve_nid = self._lib.NID_undef + + group = self._lib.EC_GROUP_new_by_curve_name(curve_nid) + + if group == self._ffi.NULL: + self._consume_errors() + return False + else: + self.openssl_assert(curve_nid != self._lib.NID_undef) + self._lib.EC_GROUP_free(group) + return True + + def elliptic_curve_signature_algorithm_supported( + self, signature_algorithm, curve + ): + # We only support ECDSA right now. + if not isinstance(signature_algorithm, ec.ECDSA): + return False + + return self.elliptic_curve_supported(curve) + + def generate_elliptic_curve_private_key(self, curve): + """ + Generate a new private key on the named curve. + """ + + if self.elliptic_curve_supported(curve): + ec_cdata = self._ec_key_new_by_curve(curve) + + res = self._lib.EC_KEY_generate_key(ec_cdata) + self.openssl_assert(res == 1) + + evp_pkey = self._ec_cdata_to_evp_pkey(ec_cdata) + + return _EllipticCurvePrivateKey(self, ec_cdata, evp_pkey) + else: + raise UnsupportedAlgorithm( + "Backend object does not support {}.".format(curve.name), + _Reasons.UNSUPPORTED_ELLIPTIC_CURVE, + ) + + def load_elliptic_curve_private_numbers(self, numbers): + public = numbers.public_numbers + + ec_cdata = self._ec_key_new_by_curve(public.curve) + + private_value = self._ffi.gc( + self._int_to_bn(numbers.private_value), self._lib.BN_clear_free + ) + res = self._lib.EC_KEY_set_private_key(ec_cdata, private_value) + if res != 1: + self._consume_errors() + raise ValueError("Invalid EC key.") + + ec_cdata = self._ec_key_set_public_key_affine_coordinates( + ec_cdata, public.x, public.y + ) + + evp_pkey = self._ec_cdata_to_evp_pkey(ec_cdata) + + return _EllipticCurvePrivateKey(self, ec_cdata, evp_pkey) + + def load_elliptic_curve_public_numbers(self, numbers): + ec_cdata = self._ec_key_new_by_curve(numbers.curve) + ec_cdata = self._ec_key_set_public_key_affine_coordinates( + ec_cdata, numbers.x, numbers.y + ) + evp_pkey = self._ec_cdata_to_evp_pkey(ec_cdata) + + return _EllipticCurvePublicKey(self, ec_cdata, evp_pkey) + + def load_elliptic_curve_public_bytes(self, curve, point_bytes): + ec_cdata = self._ec_key_new_by_curve(curve) + group = self._lib.EC_KEY_get0_group(ec_cdata) + self.openssl_assert(group != self._ffi.NULL) + point = self._lib.EC_POINT_new(group) + self.openssl_assert(point != self._ffi.NULL) + point = self._ffi.gc(point, self._lib.EC_POINT_free) + with self._tmp_bn_ctx() as bn_ctx: + res = self._lib.EC_POINT_oct2point( + group, point, point_bytes, len(point_bytes), bn_ctx + ) + if res != 1: + self._consume_errors() + raise ValueError("Invalid public bytes for the given curve") + + res = self._lib.EC_KEY_set_public_key(ec_cdata, point) + self.openssl_assert(res == 1) + evp_pkey = self._ec_cdata_to_evp_pkey(ec_cdata) + return _EllipticCurvePublicKey(self, ec_cdata, evp_pkey) + + def derive_elliptic_curve_private_key(self, private_value, curve): + ec_cdata = self._ec_key_new_by_curve(curve) + + get_func, group = self._ec_key_determine_group_get_func(ec_cdata) + + point = self._lib.EC_POINT_new(group) + self.openssl_assert(point != self._ffi.NULL) + point = self._ffi.gc(point, self._lib.EC_POINT_free) + + value = self._int_to_bn(private_value) + value = self._ffi.gc(value, self._lib.BN_clear_free) + + with self._tmp_bn_ctx() as bn_ctx: + res = self._lib.EC_POINT_mul( + group, point, value, self._ffi.NULL, self._ffi.NULL, bn_ctx + ) + self.openssl_assert(res == 1) + + bn_x = self._lib.BN_CTX_get(bn_ctx) + bn_y = self._lib.BN_CTX_get(bn_ctx) + + res = get_func(group, point, bn_x, bn_y, bn_ctx) + if res != 1: + self._consume_errors() + raise ValueError("Unable to derive key from private_value") + + res = self._lib.EC_KEY_set_public_key(ec_cdata, point) + self.openssl_assert(res == 1) + private = self._int_to_bn(private_value) + private = self._ffi.gc(private, self._lib.BN_clear_free) + res = self._lib.EC_KEY_set_private_key(ec_cdata, private) + self.openssl_assert(res == 1) + + evp_pkey = self._ec_cdata_to_evp_pkey(ec_cdata) + + return _EllipticCurvePrivateKey(self, ec_cdata, evp_pkey) + + def _ec_key_new_by_curve(self, curve): + curve_nid = self._elliptic_curve_to_nid(curve) + return self._ec_key_new_by_curve_nid(curve_nid) + + def _ec_key_new_by_curve_nid(self, curve_nid): + ec_cdata = self._lib.EC_KEY_new_by_curve_name(curve_nid) + self.openssl_assert(ec_cdata != self._ffi.NULL) + return self._ffi.gc(ec_cdata, self._lib.EC_KEY_free) + + def elliptic_curve_exchange_algorithm_supported(self, algorithm, curve): + if self._fips_enabled and not isinstance( + curve, self._fips_ecdh_curves + ): + return False + + return self.elliptic_curve_supported(curve) and isinstance( + algorithm, ec.ECDH + ) + + def _ec_cdata_to_evp_pkey(self, ec_cdata): + evp_pkey = self._create_evp_pkey_gc() + res = self._lib.EVP_PKEY_set1_EC_KEY(evp_pkey, ec_cdata) + self.openssl_assert(res == 1) + return evp_pkey + + def _elliptic_curve_to_nid(self, curve): + """ + Get the NID for a curve name. + """ + + curve_aliases = {"secp192r1": "prime192v1", "secp256r1": "prime256v1"} + + curve_name = curve_aliases.get(curve.name, curve.name) + + curve_nid = self._lib.OBJ_sn2nid(curve_name.encode()) + if curve_nid == self._lib.NID_undef: + raise UnsupportedAlgorithm( + "{} is not a supported elliptic curve".format(curve.name), + _Reasons.UNSUPPORTED_ELLIPTIC_CURVE, + ) + return curve_nid + + @contextmanager + def _tmp_bn_ctx(self): + bn_ctx = self._lib.BN_CTX_new() + self.openssl_assert(bn_ctx != self._ffi.NULL) + bn_ctx = self._ffi.gc(bn_ctx, self._lib.BN_CTX_free) + self._lib.BN_CTX_start(bn_ctx) + try: + yield bn_ctx + finally: + self._lib.BN_CTX_end(bn_ctx) + + def _ec_key_determine_group_get_func(self, ctx): + """ + Given an EC_KEY determine the group and what function is required to + get point coordinates. + """ + self.openssl_assert(ctx != self._ffi.NULL) + + nid_two_field = self._lib.OBJ_sn2nid(b"characteristic-two-field") + self.openssl_assert(nid_two_field != self._lib.NID_undef) + + group = self._lib.EC_KEY_get0_group(ctx) + self.openssl_assert(group != self._ffi.NULL) + + method = self._lib.EC_GROUP_method_of(group) + self.openssl_assert(method != self._ffi.NULL) + + nid = self._lib.EC_METHOD_get_field_type(method) + self.openssl_assert(nid != self._lib.NID_undef) + + if nid == nid_two_field and self._lib.Cryptography_HAS_EC2M: + get_func = self._lib.EC_POINT_get_affine_coordinates_GF2m + else: + get_func = self._lib.EC_POINT_get_affine_coordinates_GFp + + assert get_func + + return get_func, group + + def _ec_key_set_public_key_affine_coordinates(self, ctx, x, y): + """ + Sets the public key point in the EC_KEY context to the affine x and y + values. + """ + + if x < 0 or y < 0: + raise ValueError( + "Invalid EC key. Both x and y must be non-negative." + ) + + x = self._ffi.gc(self._int_to_bn(x), self._lib.BN_free) + y = self._ffi.gc(self._int_to_bn(y), self._lib.BN_free) + res = self._lib.EC_KEY_set_public_key_affine_coordinates(ctx, x, y) + if res != 1: + self._consume_errors() + raise ValueError("Invalid EC key.") + + return ctx + + def _private_key_bytes( + self, encoding, format, encryption_algorithm, key, evp_pkey, cdata + ): + # validate argument types + if not isinstance(encoding, serialization.Encoding): + raise TypeError("encoding must be an item from the Encoding enum") + if not isinstance(format, serialization.PrivateFormat): + raise TypeError( + "format must be an item from the PrivateFormat enum" + ) + if not isinstance( + encryption_algorithm, serialization.KeySerializationEncryption + ): + raise TypeError( + "Encryption algorithm must be a KeySerializationEncryption " + "instance" + ) + + # validate password + if isinstance(encryption_algorithm, serialization.NoEncryption): + password = b"" + elif isinstance( + encryption_algorithm, serialization.BestAvailableEncryption + ): + password = encryption_algorithm.password + if len(password) > 1023: + raise ValueError( + "Passwords longer than 1023 bytes are not supported by " + "this backend" + ) + else: + raise ValueError("Unsupported encryption type") + + # PKCS8 + PEM/DER + if format is serialization.PrivateFormat.PKCS8: + if encoding is serialization.Encoding.PEM: + write_bio = self._lib.PEM_write_bio_PKCS8PrivateKey + elif encoding is serialization.Encoding.DER: + write_bio = self._lib.i2d_PKCS8PrivateKey_bio + else: + raise ValueError("Unsupported encoding for PKCS8") + return self._private_key_bytes_via_bio( + write_bio, evp_pkey, password + ) + + # TraditionalOpenSSL + PEM/DER + if format is serialization.PrivateFormat.TraditionalOpenSSL: + if self._fips_enabled and not isinstance( + encryption_algorithm, serialization.NoEncryption + ): + raise ValueError( + "Encrypted traditional OpenSSL format is not " + "supported in FIPS mode." + ) + key_type = self._lib.EVP_PKEY_id(evp_pkey) + + if encoding is serialization.Encoding.PEM: + if key_type == self._lib.EVP_PKEY_RSA: + write_bio = self._lib.PEM_write_bio_RSAPrivateKey + elif key_type == self._lib.EVP_PKEY_DSA: + write_bio = self._lib.PEM_write_bio_DSAPrivateKey + elif key_type == self._lib.EVP_PKEY_EC: + write_bio = self._lib.PEM_write_bio_ECPrivateKey + else: + raise ValueError( + "Unsupported key type for TraditionalOpenSSL" + ) + return self._private_key_bytes_via_bio( + write_bio, cdata, password + ) + + if encoding is serialization.Encoding.DER: + if password: + raise ValueError( + "Encryption is not supported for DER encoded " + "traditional OpenSSL keys" + ) + if key_type == self._lib.EVP_PKEY_RSA: + write_bio = self._lib.i2d_RSAPrivateKey_bio + elif key_type == self._lib.EVP_PKEY_EC: + write_bio = self._lib.i2d_ECPrivateKey_bio + elif key_type == self._lib.EVP_PKEY_DSA: + write_bio = self._lib.i2d_DSAPrivateKey_bio + else: + raise ValueError( + "Unsupported key type for TraditionalOpenSSL" + ) + return self._bio_func_output(write_bio, cdata) + + raise ValueError("Unsupported encoding for TraditionalOpenSSL") + + # OpenSSH + PEM + if format is serialization.PrivateFormat.OpenSSH: + if encoding is serialization.Encoding.PEM: + return ssh.serialize_ssh_private_key(key, password) + + raise ValueError( + "OpenSSH private key format can only be used" + " with PEM encoding" + ) + + # Anything that key-specific code was supposed to handle earlier, + # like Raw. + raise ValueError("format is invalid with this key") + + def _private_key_bytes_via_bio(self, write_bio, evp_pkey, password): + if not password: + evp_cipher = self._ffi.NULL + else: + # This is a curated value that we will update over time. + evp_cipher = self._lib.EVP_get_cipherbyname(b"aes-256-cbc") + + return self._bio_func_output( + write_bio, + evp_pkey, + evp_cipher, + password, + len(password), + self._ffi.NULL, + self._ffi.NULL, + ) + + def _bio_func_output(self, write_bio, *args): + bio = self._create_mem_bio_gc() + res = write_bio(bio, *args) + self.openssl_assert(res == 1) + return self._read_mem_bio(bio) + + def _public_key_bytes(self, encoding, format, key, evp_pkey, cdata): + if not isinstance(encoding, serialization.Encoding): + raise TypeError("encoding must be an item from the Encoding enum") + if not isinstance(format, serialization.PublicFormat): + raise TypeError( + "format must be an item from the PublicFormat enum" + ) + + # SubjectPublicKeyInfo + PEM/DER + if format is serialization.PublicFormat.SubjectPublicKeyInfo: + if encoding is serialization.Encoding.PEM: + write_bio = self._lib.PEM_write_bio_PUBKEY + elif encoding is serialization.Encoding.DER: + write_bio = self._lib.i2d_PUBKEY_bio + else: + raise ValueError( + "SubjectPublicKeyInfo works only with PEM or DER encoding" + ) + return self._bio_func_output(write_bio, evp_pkey) + + # PKCS1 + PEM/DER + if format is serialization.PublicFormat.PKCS1: + # Only RSA is supported here. + key_type = self._lib.EVP_PKEY_id(evp_pkey) + if key_type != self._lib.EVP_PKEY_RSA: + raise ValueError("PKCS1 format is supported only for RSA keys") + + if encoding is serialization.Encoding.PEM: + write_bio = self._lib.PEM_write_bio_RSAPublicKey + elif encoding is serialization.Encoding.DER: + write_bio = self._lib.i2d_RSAPublicKey_bio + else: + raise ValueError("PKCS1 works only with PEM or DER encoding") + return self._bio_func_output(write_bio, cdata) + + # OpenSSH + OpenSSH + if format is serialization.PublicFormat.OpenSSH: + if encoding is serialization.Encoding.OpenSSH: + return ssh.serialize_ssh_public_key(key) + + raise ValueError( + "OpenSSH format must be used with OpenSSH encoding" + ) + + # Anything that key-specific code was supposed to handle earlier, + # like Raw, CompressedPoint, UncompressedPoint + raise ValueError("format is invalid with this key") + + def _parameter_bytes(self, encoding, format, cdata): + if encoding is serialization.Encoding.OpenSSH: + raise TypeError("OpenSSH encoding is not supported") + + # Only DH is supported here currently. + q = self._ffi.new("BIGNUM **") + self._lib.DH_get0_pqg(cdata, self._ffi.NULL, q, self._ffi.NULL) + if encoding is serialization.Encoding.PEM: + if q[0] != self._ffi.NULL: + write_bio = self._lib.PEM_write_bio_DHxparams + else: + write_bio = self._lib.PEM_write_bio_DHparams + elif encoding is serialization.Encoding.DER: + if q[0] != self._ffi.NULL: + write_bio = self._lib.Cryptography_i2d_DHxparams_bio + else: + write_bio = self._lib.i2d_DHparams_bio + else: + raise TypeError("encoding must be an item from the Encoding enum") + + bio = self._create_mem_bio_gc() + res = write_bio(bio, cdata) + self.openssl_assert(res == 1) + return self._read_mem_bio(bio) + + def dh_supported(self): + return not self._lib.CRYPTOGRAPHY_IS_BORINGSSL + + def generate_dh_parameters(self, generator, key_size): + if key_size < dh._MIN_MODULUS_SIZE: + raise ValueError( + "DH key_size must be at least {} bits".format( + dh._MIN_MODULUS_SIZE + ) + ) + + if generator not in (2, 5): + raise ValueError("DH generator must be 2 or 5") + + dh_param_cdata = self._lib.DH_new() + self.openssl_assert(dh_param_cdata != self._ffi.NULL) + dh_param_cdata = self._ffi.gc(dh_param_cdata, self._lib.DH_free) + + res = self._lib.DH_generate_parameters_ex( + dh_param_cdata, key_size, generator, self._ffi.NULL + ) + self.openssl_assert(res == 1) + + return _DHParameters(self, dh_param_cdata) + + def _dh_cdata_to_evp_pkey(self, dh_cdata): + evp_pkey = self._create_evp_pkey_gc() + res = self._lib.EVP_PKEY_set1_DH(evp_pkey, dh_cdata) + self.openssl_assert(res == 1) + return evp_pkey + + def generate_dh_private_key(self, parameters): + dh_key_cdata = _dh_params_dup(parameters._dh_cdata, self) + + res = self._lib.DH_generate_key(dh_key_cdata) + self.openssl_assert(res == 1) + + evp_pkey = self._dh_cdata_to_evp_pkey(dh_key_cdata) + + return _DHPrivateKey(self, dh_key_cdata, evp_pkey) + + def generate_dh_private_key_and_parameters(self, generator, key_size): + return self.generate_dh_private_key( + self.generate_dh_parameters(generator, key_size) + ) + + def load_dh_private_numbers(self, numbers): + parameter_numbers = numbers.public_numbers.parameter_numbers + + dh_cdata = self._lib.DH_new() + self.openssl_assert(dh_cdata != self._ffi.NULL) + dh_cdata = self._ffi.gc(dh_cdata, self._lib.DH_free) + + p = self._int_to_bn(parameter_numbers.p) + g = self._int_to_bn(parameter_numbers.g) + + if parameter_numbers.q is not None: + q = self._int_to_bn(parameter_numbers.q) + else: + q = self._ffi.NULL + + pub_key = self._int_to_bn(numbers.public_numbers.y) + priv_key = self._int_to_bn(numbers.x) + + res = self._lib.DH_set0_pqg(dh_cdata, p, q, g) + self.openssl_assert(res == 1) + + res = self._lib.DH_set0_key(dh_cdata, pub_key, priv_key) + self.openssl_assert(res == 1) + + codes = self._ffi.new("int[]", 1) + res = self._lib.Cryptography_DH_check(dh_cdata, codes) + self.openssl_assert(res == 1) + + # DH_check will return DH_NOT_SUITABLE_GENERATOR if p % 24 does not + # equal 11 when the generator is 2 (a quadratic nonresidue). + # We want to ignore that error because p % 24 == 23 is also fine. + # Specifically, g is then a quadratic residue. Within the context of + # Diffie-Hellman this means it can only generate half the possible + # values. That sounds bad, but quadratic nonresidues leak a bit of + # the key to the attacker in exchange for having the full key space + # available. See: https://crypto.stackexchange.com/questions/12961 + if codes[0] != 0 and not ( + parameter_numbers.g == 2 + and codes[0] ^ self._lib.DH_NOT_SUITABLE_GENERATOR == 0 + ): + raise ValueError("DH private numbers did not pass safety checks.") + + evp_pkey = self._dh_cdata_to_evp_pkey(dh_cdata) + + return _DHPrivateKey(self, dh_cdata, evp_pkey) + + def load_dh_public_numbers(self, numbers): + dh_cdata = self._lib.DH_new() + self.openssl_assert(dh_cdata != self._ffi.NULL) + dh_cdata = self._ffi.gc(dh_cdata, self._lib.DH_free) + + parameter_numbers = numbers.parameter_numbers + + p = self._int_to_bn(parameter_numbers.p) + g = self._int_to_bn(parameter_numbers.g) + + if parameter_numbers.q is not None: + q = self._int_to_bn(parameter_numbers.q) + else: + q = self._ffi.NULL + + pub_key = self._int_to_bn(numbers.y) + + res = self._lib.DH_set0_pqg(dh_cdata, p, q, g) + self.openssl_assert(res == 1) + + res = self._lib.DH_set0_key(dh_cdata, pub_key, self._ffi.NULL) + self.openssl_assert(res == 1) + + evp_pkey = self._dh_cdata_to_evp_pkey(dh_cdata) + + return _DHPublicKey(self, dh_cdata, evp_pkey) + + def load_dh_parameter_numbers(self, numbers): + dh_cdata = self._lib.DH_new() + self.openssl_assert(dh_cdata != self._ffi.NULL) + dh_cdata = self._ffi.gc(dh_cdata, self._lib.DH_free) + + p = self._int_to_bn(numbers.p) + g = self._int_to_bn(numbers.g) + + if numbers.q is not None: + q = self._int_to_bn(numbers.q) + else: + q = self._ffi.NULL + + res = self._lib.DH_set0_pqg(dh_cdata, p, q, g) + self.openssl_assert(res == 1) + + return _DHParameters(self, dh_cdata) + + def dh_parameters_supported(self, p, g, q=None): + dh_cdata = self._lib.DH_new() + self.openssl_assert(dh_cdata != self._ffi.NULL) + dh_cdata = self._ffi.gc(dh_cdata, self._lib.DH_free) + + p = self._int_to_bn(p) + g = self._int_to_bn(g) + + if q is not None: + q = self._int_to_bn(q) + else: + q = self._ffi.NULL + + res = self._lib.DH_set0_pqg(dh_cdata, p, q, g) + self.openssl_assert(res == 1) + + codes = self._ffi.new("int[]", 1) + res = self._lib.Cryptography_DH_check(dh_cdata, codes) + self.openssl_assert(res == 1) + + return codes[0] == 0 + + def dh_x942_serialization_supported(self): + return self._lib.Cryptography_HAS_EVP_PKEY_DHX == 1 + + def x25519_load_public_bytes(self, data): + # When we drop support for CRYPTOGRAPHY_OPENSSL_LESS_THAN_111 we can + # switch this to EVP_PKEY_new_raw_public_key + if len(data) != 32: + raise ValueError("An X25519 public key is 32 bytes long") + + evp_pkey = self._create_evp_pkey_gc() + res = self._lib.EVP_PKEY_set_type(evp_pkey, self._lib.NID_X25519) + self.openssl_assert(res == 1) + res = self._lib.EVP_PKEY_set1_tls_encodedpoint( + evp_pkey, data, len(data) + ) + self.openssl_assert(res == 1) + return _X25519PublicKey(self, evp_pkey) + + def x25519_load_private_bytes(self, data): + # When we drop support for CRYPTOGRAPHY_OPENSSL_LESS_THAN_111 we can + # switch this to EVP_PKEY_new_raw_private_key and drop the + # zeroed_bytearray garbage. + # OpenSSL only has facilities for loading PKCS8 formatted private + # keys using the algorithm identifiers specified in + # https://tools.ietf.org/html/draft-ietf-curdle-pkix-09. + # This is the standard PKCS8 prefix for a 32 byte X25519 key. + # The form is: + # 0:d=0 hl=2 l= 46 cons: SEQUENCE + # 2:d=1 hl=2 l= 1 prim: INTEGER :00 + # 5:d=1 hl=2 l= 5 cons: SEQUENCE + # 7:d=2 hl=2 l= 3 prim: OBJECT :1.3.101.110 + # 12:d=1 hl=2 l= 34 prim: OCTET STRING (the key) + # Of course there's a bit more complexity. In reality OCTET STRING + # contains an OCTET STRING of length 32! So the last two bytes here + # are \x04\x20, which is an OCTET STRING of length 32. + if len(data) != 32: + raise ValueError("An X25519 private key is 32 bytes long") + + pkcs8_prefix = b'0.\x02\x01\x000\x05\x06\x03+en\x04"\x04 ' + with self._zeroed_bytearray(48) as ba: + ba[0:16] = pkcs8_prefix + ba[16:] = data + bio = self._bytes_to_bio(ba) + evp_pkey = self._lib.d2i_PrivateKey_bio(bio.bio, self._ffi.NULL) + + self.openssl_assert(evp_pkey != self._ffi.NULL) + evp_pkey = self._ffi.gc(evp_pkey, self._lib.EVP_PKEY_free) + self.openssl_assert( + self._lib.EVP_PKEY_id(evp_pkey) == self._lib.EVP_PKEY_X25519 + ) + return _X25519PrivateKey(self, evp_pkey) + + def _evp_pkey_keygen_gc(self, nid): + evp_pkey_ctx = self._lib.EVP_PKEY_CTX_new_id(nid, self._ffi.NULL) + self.openssl_assert(evp_pkey_ctx != self._ffi.NULL) + evp_pkey_ctx = self._ffi.gc(evp_pkey_ctx, self._lib.EVP_PKEY_CTX_free) + res = self._lib.EVP_PKEY_keygen_init(evp_pkey_ctx) + self.openssl_assert(res == 1) + evp_ppkey = self._ffi.new("EVP_PKEY **") + res = self._lib.EVP_PKEY_keygen(evp_pkey_ctx, evp_ppkey) + self.openssl_assert(res == 1) + self.openssl_assert(evp_ppkey[0] != self._ffi.NULL) + evp_pkey = self._ffi.gc(evp_ppkey[0], self._lib.EVP_PKEY_free) + return evp_pkey + + def x25519_generate_key(self): + evp_pkey = self._evp_pkey_keygen_gc(self._lib.NID_X25519) + return _X25519PrivateKey(self, evp_pkey) + + def x25519_supported(self): + if self._fips_enabled: + return False + return not self._lib.CRYPTOGRAPHY_IS_LIBRESSL + + def x448_load_public_bytes(self, data): + if len(data) != 56: + raise ValueError("An X448 public key is 56 bytes long") + + evp_pkey = self._lib.EVP_PKEY_new_raw_public_key( + self._lib.NID_X448, self._ffi.NULL, data, len(data) + ) + self.openssl_assert(evp_pkey != self._ffi.NULL) + evp_pkey = self._ffi.gc(evp_pkey, self._lib.EVP_PKEY_free) + return _X448PublicKey(self, evp_pkey) + + def x448_load_private_bytes(self, data): + if len(data) != 56: + raise ValueError("An X448 private key is 56 bytes long") + + data_ptr = self._ffi.from_buffer(data) + evp_pkey = self._lib.EVP_PKEY_new_raw_private_key( + self._lib.NID_X448, self._ffi.NULL, data_ptr, len(data) + ) + self.openssl_assert(evp_pkey != self._ffi.NULL) + evp_pkey = self._ffi.gc(evp_pkey, self._lib.EVP_PKEY_free) + return _X448PrivateKey(self, evp_pkey) + + def x448_generate_key(self): + evp_pkey = self._evp_pkey_keygen_gc(self._lib.NID_X448) + return _X448PrivateKey(self, evp_pkey) + + def x448_supported(self): + if self._fips_enabled: + return False + return ( + not self._lib.CRYPTOGRAPHY_OPENSSL_LESS_THAN_111 + and not self._lib.CRYPTOGRAPHY_IS_BORINGSSL + ) + + def ed25519_supported(self): + if self._fips_enabled: + return False + return not self._lib.CRYPTOGRAPHY_OPENSSL_LESS_THAN_111B + + def ed25519_load_public_bytes(self, data): + utils._check_bytes("data", data) + + if len(data) != ed25519._ED25519_KEY_SIZE: + raise ValueError("An Ed25519 public key is 32 bytes long") + + evp_pkey = self._lib.EVP_PKEY_new_raw_public_key( + self._lib.NID_ED25519, self._ffi.NULL, data, len(data) + ) + self.openssl_assert(evp_pkey != self._ffi.NULL) + evp_pkey = self._ffi.gc(evp_pkey, self._lib.EVP_PKEY_free) + + return _Ed25519PublicKey(self, evp_pkey) + + def ed25519_load_private_bytes(self, data): + if len(data) != ed25519._ED25519_KEY_SIZE: + raise ValueError("An Ed25519 private key is 32 bytes long") + + utils._check_byteslike("data", data) + data_ptr = self._ffi.from_buffer(data) + evp_pkey = self._lib.EVP_PKEY_new_raw_private_key( + self._lib.NID_ED25519, self._ffi.NULL, data_ptr, len(data) + ) + self.openssl_assert(evp_pkey != self._ffi.NULL) + evp_pkey = self._ffi.gc(evp_pkey, self._lib.EVP_PKEY_free) + + return _Ed25519PrivateKey(self, evp_pkey) + + def ed25519_generate_key(self): + evp_pkey = self._evp_pkey_keygen_gc(self._lib.NID_ED25519) + return _Ed25519PrivateKey(self, evp_pkey) + + def ed448_supported(self): + if self._fips_enabled: + return False + return ( + not self._lib.CRYPTOGRAPHY_OPENSSL_LESS_THAN_111B + and not self._lib.CRYPTOGRAPHY_IS_BORINGSSL + ) + + def ed448_load_public_bytes(self, data): + utils._check_bytes("data", data) + if len(data) != _ED448_KEY_SIZE: + raise ValueError("An Ed448 public key is 57 bytes long") + + evp_pkey = self._lib.EVP_PKEY_new_raw_public_key( + self._lib.NID_ED448, self._ffi.NULL, data, len(data) + ) + self.openssl_assert(evp_pkey != self._ffi.NULL) + evp_pkey = self._ffi.gc(evp_pkey, self._lib.EVP_PKEY_free) + + return _Ed448PublicKey(self, evp_pkey) + + def ed448_load_private_bytes(self, data): + utils._check_byteslike("data", data) + if len(data) != _ED448_KEY_SIZE: + raise ValueError("An Ed448 private key is 57 bytes long") + + data_ptr = self._ffi.from_buffer(data) + evp_pkey = self._lib.EVP_PKEY_new_raw_private_key( + self._lib.NID_ED448, self._ffi.NULL, data_ptr, len(data) + ) + self.openssl_assert(evp_pkey != self._ffi.NULL) + evp_pkey = self._ffi.gc(evp_pkey, self._lib.EVP_PKEY_free) + + return _Ed448PrivateKey(self, evp_pkey) + + def ed448_generate_key(self): + evp_pkey = self._evp_pkey_keygen_gc(self._lib.NID_ED448) + return _Ed448PrivateKey(self, evp_pkey) + + def derive_scrypt(self, key_material, salt, length, n, r, p): + buf = self._ffi.new("unsigned char[]", length) + key_material_ptr = self._ffi.from_buffer(key_material) + res = self._lib.EVP_PBE_scrypt( + key_material_ptr, + len(key_material), + salt, + len(salt), + n, + r, + p, + scrypt._MEM_LIMIT, + buf, + length, + ) + if res != 1: + errors = self._consume_errors_with_text() + # memory required formula explained here: + # https://blog.filippo.io/the-scrypt-parameters/ + min_memory = 128 * n * r // (1024 ** 2) + raise MemoryError( + "Not enough memory to derive key. These parameters require" + " {} MB of memory.".format(min_memory), + errors, + ) + return self._ffi.buffer(buf)[:] + + def aead_cipher_supported(self, cipher): + cipher_name = aead._aead_cipher_name(cipher) + if self._fips_enabled and cipher_name not in self._fips_aead: + return False + return self._lib.EVP_get_cipherbyname(cipher_name) != self._ffi.NULL + + @contextlib.contextmanager + def _zeroed_bytearray(self, length): + """ + This method creates a bytearray, which we copy data into (hopefully + also from a mutable buffer that can be dynamically erased!), and then + zero when we're done. + """ + ba = bytearray(length) + try: + yield ba + finally: + self._zero_data(ba, length) + + def _zero_data(self, data, length): + # We clear things this way because at the moment we're not + # sure of a better way that can guarantee it overwrites the + # memory of a bytearray and doesn't just replace the underlying char *. + for i in range(length): + data[i] = 0 + + @contextlib.contextmanager + def _zeroed_null_terminated_buf(self, data): + """ + This method takes bytes, which can be a bytestring or a mutable + buffer like a bytearray, and yields a null-terminated version of that + data. This is required because PKCS12_parse doesn't take a length with + its password char * and ffi.from_buffer doesn't provide null + termination. So, to support zeroing the data via bytearray we + need to build this ridiculous construct that copies the memory, but + zeroes it after use. + """ + if data is None: + yield self._ffi.NULL + else: + data_len = len(data) + buf = self._ffi.new("char[]", data_len + 1) + self._ffi.memmove(buf, data, data_len) + try: + yield buf + finally: + # Cast to a uint8_t * so we can assign by integer + self._zero_data(self._ffi.cast("uint8_t *", buf), data_len) + + def load_key_and_certificates_from_pkcs12(self, data, password): + pkcs12 = self.load_pkcs12(data, password) + return ( + pkcs12.key, + pkcs12.cert.certificate if pkcs12.cert else None, + [cert.certificate for cert in pkcs12.additional_certs], + ) + + def load_pkcs12(self, data, password): + if password is not None: + utils._check_byteslike("password", password) + + bio = self._bytes_to_bio(data) + p12 = self._lib.d2i_PKCS12_bio(bio.bio, self._ffi.NULL) + if p12 == self._ffi.NULL: + self._consume_errors() + raise ValueError("Could not deserialize PKCS12 data") + + p12 = self._ffi.gc(p12, self._lib.PKCS12_free) + evp_pkey_ptr = self._ffi.new("EVP_PKEY **") + x509_ptr = self._ffi.new("X509 **") + sk_x509_ptr = self._ffi.new("Cryptography_STACK_OF_X509 **") + with self._zeroed_null_terminated_buf(password) as password_buf: + res = self._lib.PKCS12_parse( + p12, password_buf, evp_pkey_ptr, x509_ptr, sk_x509_ptr + ) + + # Workaround for + # https://github.com/libressl-portable/portable/issues/659 + # TODO: Once 3.4.0 is released, add branch. + if self._lib.CRYPTOGRAPHY_IS_LIBRESSL: + self._consume_errors() + + if res == 0: + self._consume_errors() + raise ValueError("Invalid password or PKCS12 data") + + cert = None + key = None + additional_certificates = [] + + if evp_pkey_ptr[0] != self._ffi.NULL: + evp_pkey = self._ffi.gc(evp_pkey_ptr[0], self._lib.EVP_PKEY_free) + key = self._evp_pkey_to_private_key(evp_pkey) + + if x509_ptr[0] != self._ffi.NULL: + x509 = self._ffi.gc(x509_ptr[0], self._lib.X509_free) + cert_obj = self._ossl2cert(x509) + name = None + maybe_name = self._lib.X509_alias_get0(x509, self._ffi.NULL) + if maybe_name != self._ffi.NULL: + name = self._ffi.string(maybe_name) + cert = PKCS12Certificate(cert_obj, name) + + if sk_x509_ptr[0] != self._ffi.NULL: + sk_x509 = self._ffi.gc(sk_x509_ptr[0], self._lib.sk_X509_free) + num = self._lib.sk_X509_num(sk_x509_ptr[0]) + + # In OpenSSL < 3.0.0 PKCS12 parsing reverses the order of the + # certificates. + indices: typing.Iterable[int] + if ( + self._lib.CRYPTOGRAPHY_OPENSSL_300_OR_GREATER + or self._lib.CRYPTOGRAPHY_IS_BORINGSSL + ): + indices = range(num) + else: + indices = reversed(range(num)) + + for i in indices: + x509 = self._lib.sk_X509_value(sk_x509, i) + self.openssl_assert(x509 != self._ffi.NULL) + x509 = self._ffi.gc(x509, self._lib.X509_free) + addl_cert = self._ossl2cert(x509) + addl_name = None + maybe_name = self._lib.X509_alias_get0(x509, self._ffi.NULL) + if maybe_name != self._ffi.NULL: + addl_name = self._ffi.string(maybe_name) + additional_certificates.append( + PKCS12Certificate(addl_cert, addl_name) + ) + + return PKCS12KeyAndCertificates(key, cert, additional_certificates) + + def serialize_key_and_certificates_to_pkcs12( + self, name, key, cert, cas, encryption_algorithm + ): + password = None + if name is not None: + utils._check_bytes("name", name) + + if isinstance(encryption_algorithm, serialization.NoEncryption): + nid_cert = -1 + nid_key = -1 + pkcs12_iter = 0 + mac_iter = 0 + elif isinstance( + encryption_algorithm, serialization.BestAvailableEncryption + ): + # PKCS12 encryption is hopeless trash and can never be fixed. + # This is the least terrible option. + nid_cert = self._lib.NID_pbe_WithSHA1And3_Key_TripleDES_CBC + nid_key = self._lib.NID_pbe_WithSHA1And3_Key_TripleDES_CBC + # At least we can set this higher than OpenSSL's default + pkcs12_iter = 20000 + # mac_iter chosen for compatibility reasons, see: + # https://www.openssl.org/docs/man1.1.1/man3/PKCS12_create.html + # Did we mention how lousy PKCS12 encryption is? + mac_iter = 1 + password = encryption_algorithm.password + else: + raise ValueError("Unsupported key encryption type") + + if cas is None or len(cas) == 0: + sk_x509 = self._ffi.NULL + else: + sk_x509 = self._lib.sk_X509_new_null() + sk_x509 = self._ffi.gc(sk_x509, self._lib.sk_X509_free) + + # This list is to keep the x509 values alive until end of function + ossl_cas = [] + for ca in cas: + ossl_ca = self._cert2ossl(ca) + ossl_cas.append(ossl_ca) + res = self._lib.sk_X509_push(sk_x509, ossl_ca) + backend.openssl_assert(res >= 1) + + with self._zeroed_null_terminated_buf(password) as password_buf: + with self._zeroed_null_terminated_buf(name) as name_buf: + ossl_cert = self._cert2ossl(cert) if cert else self._ffi.NULL + evp_pkey = key._evp_pkey if key else self._ffi.NULL + p12 = self._lib.PKCS12_create( + password_buf, + name_buf, + evp_pkey, + ossl_cert, + sk_x509, + nid_key, + nid_cert, + pkcs12_iter, + mac_iter, + 0, + ) + + self.openssl_assert(p12 != self._ffi.NULL) + p12 = self._ffi.gc(p12, self._lib.PKCS12_free) + + bio = self._create_mem_bio_gc() + res = self._lib.i2d_PKCS12_bio(bio, p12) + self.openssl_assert(res > 0) + return self._read_mem_bio(bio) + + def poly1305_supported(self): + if self._fips_enabled: + return False + return self._lib.Cryptography_HAS_POLY1305 == 1 + + def create_poly1305_ctx(self, key): + utils._check_byteslike("key", key) + if len(key) != _POLY1305_KEY_SIZE: + raise ValueError("A poly1305 key is 32 bytes long") + + return _Poly1305Context(self, key) + + def pkcs7_supported(self): + return not self._lib.CRYPTOGRAPHY_IS_BORINGSSL + + def load_pem_pkcs7_certificates(self, data): + utils._check_bytes("data", data) + bio = self._bytes_to_bio(data) + p7 = self._lib.PEM_read_bio_PKCS7( + bio.bio, self._ffi.NULL, self._ffi.NULL, self._ffi.NULL + ) + if p7 == self._ffi.NULL: + self._consume_errors() + raise ValueError("Unable to parse PKCS7 data") + + p7 = self._ffi.gc(p7, self._lib.PKCS7_free) + return self._load_pkcs7_certificates(p7) + + def load_der_pkcs7_certificates(self, data): + utils._check_bytes("data", data) + bio = self._bytes_to_bio(data) + p7 = self._lib.d2i_PKCS7_bio(bio.bio, self._ffi.NULL) + if p7 == self._ffi.NULL: + self._consume_errors() + raise ValueError("Unable to parse PKCS7 data") + + p7 = self._ffi.gc(p7, self._lib.PKCS7_free) + return self._load_pkcs7_certificates(p7) + + def _load_pkcs7_certificates(self, p7): + nid = self._lib.OBJ_obj2nid(p7.type) + self.openssl_assert(nid != self._lib.NID_undef) + if nid != self._lib.NID_pkcs7_signed: + raise UnsupportedAlgorithm( + "Only basic signed structures are currently supported. NID" + " for this data was {}".format(nid), + _Reasons.UNSUPPORTED_SERIALIZATION, + ) + + sk_x509 = p7.d.sign.cert + num = self._lib.sk_X509_num(sk_x509) + certs = [] + for i in range(num): + x509 = self._lib.sk_X509_value(sk_x509, i) + self.openssl_assert(x509 != self._ffi.NULL) + res = self._lib.X509_up_ref(x509) + # When OpenSSL is less than 1.1.0 up_ref returns the current + # refcount. On 1.1.0+ it returns 1 for success. + self.openssl_assert(res >= 1) + x509 = self._ffi.gc(x509, self._lib.X509_free) + cert = self._ossl2cert(x509) + certs.append(cert) + + return certs + + def pkcs7_sign(self, builder, encoding, options): + bio = self._bytes_to_bio(builder._data) + init_flags = self._lib.PKCS7_PARTIAL + final_flags = 0 + + if len(builder._additional_certs) == 0: + certs = self._ffi.NULL + else: + certs = self._lib.sk_X509_new_null() + certs = self._ffi.gc(certs, self._lib.sk_X509_free) + # This list is to keep the x509 values alive until end of function + ossl_certs = [] + for cert in builder._additional_certs: + ossl_cert = self._cert2ossl(cert) + ossl_certs.append(ossl_cert) + res = self._lib.sk_X509_push(certs, ossl_cert) + self.openssl_assert(res >= 1) + + if pkcs7.PKCS7Options.DetachedSignature in options: + # Don't embed the data in the PKCS7 structure + init_flags |= self._lib.PKCS7_DETACHED + final_flags |= self._lib.PKCS7_DETACHED + + # This just inits a structure for us. However, there + # are flags we need to set, joy. + p7 = self._lib.PKCS7_sign( + self._ffi.NULL, + self._ffi.NULL, + certs, + self._ffi.NULL, + init_flags, + ) + self.openssl_assert(p7 != self._ffi.NULL) + p7 = self._ffi.gc(p7, self._lib.PKCS7_free) + signer_flags = 0 + # These flags are configurable on a per-signature basis + # but we've deliberately chosen to make the API only allow + # setting it across all signatures for now. + if pkcs7.PKCS7Options.NoCapabilities in options: + signer_flags |= self._lib.PKCS7_NOSMIMECAP + elif pkcs7.PKCS7Options.NoAttributes in options: + signer_flags |= self._lib.PKCS7_NOATTR + + if pkcs7.PKCS7Options.NoCerts in options: + signer_flags |= self._lib.PKCS7_NOCERTS + + for certificate, private_key, hash_algorithm in builder._signers: + ossl_cert = self._cert2ossl(certificate) + md = self._evp_md_non_null_from_algorithm(hash_algorithm) + p7signerinfo = self._lib.PKCS7_sign_add_signer( + p7, ossl_cert, private_key._evp_pkey, md, signer_flags + ) + self.openssl_assert(p7signerinfo != self._ffi.NULL) + + for option in options: + # DetachedSignature, NoCapabilities, and NoAttributes are already + # handled so we just need to check these last two options. + if option is pkcs7.PKCS7Options.Text: + final_flags |= self._lib.PKCS7_TEXT + elif option is pkcs7.PKCS7Options.Binary: + final_flags |= self._lib.PKCS7_BINARY + + bio_out = self._create_mem_bio_gc() + if encoding is serialization.Encoding.SMIME: + # This finalizes the structure + res = self._lib.SMIME_write_PKCS7( + bio_out, p7, bio.bio, final_flags + ) + elif encoding is serialization.Encoding.PEM: + res = self._lib.PKCS7_final(p7, bio.bio, final_flags) + self.openssl_assert(res == 1) + res = self._lib.PEM_write_bio_PKCS7_stream( + bio_out, p7, bio.bio, final_flags + ) + else: + assert encoding is serialization.Encoding.DER + # We need to call finalize here becauase i2d_PKCS7_bio does not + # finalize. + res = self._lib.PKCS7_final(p7, bio.bio, final_flags) + self.openssl_assert(res == 1) + # OpenSSL 3.0 leaves a random bio error on the stack: + # https://github.com/openssl/openssl/issues/16681 + if self._lib.CRYPTOGRAPHY_OPENSSL_300_OR_GREATER: + self._consume_errors() + res = self._lib.i2d_PKCS7_bio(bio_out, p7) + self.openssl_assert(res == 1) + return self._read_mem_bio(bio_out) + + +class GetCipherByName(object): + def __init__(self, fmt): + self._fmt = fmt + + def __call__(self, backend, cipher, mode): + cipher_name = self._fmt.format(cipher=cipher, mode=mode).lower() + return backend._lib.EVP_get_cipherbyname(cipher_name.encode("ascii")) + + +def _get_xts_cipher(backend, cipher, mode): + cipher_name = "aes-{}-xts".format(cipher.key_size // 2) + return backend._lib.EVP_get_cipherbyname(cipher_name.encode("ascii")) + + +backend = Backend() diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/backends/openssl/ciphers.py b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/backends/openssl/ciphers.py new file mode 100644 index 00000000..d5b60102 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/backends/openssl/ciphers.py @@ -0,0 +1,278 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + + +from cryptography import utils +from cryptography.exceptions import InvalidTag, UnsupportedAlgorithm, _Reasons +from cryptography.hazmat.primitives import ciphers +from cryptography.hazmat.primitives.ciphers import modes + + +@utils.register_interface(ciphers.CipherContext) +@utils.register_interface(ciphers.AEADCipherContext) +@utils.register_interface(ciphers.AEADEncryptionContext) +@utils.register_interface(ciphers.AEADDecryptionContext) +class _CipherContext(object): + _ENCRYPT = 1 + _DECRYPT = 0 + _MAX_CHUNK_SIZE = 2 ** 30 - 1 + + def __init__(self, backend, cipher, mode, operation): + self._backend = backend + self._cipher = cipher + self._mode = mode + self._operation = operation + self._tag = None + + if isinstance(self._cipher, ciphers.BlockCipherAlgorithm): + self._block_size_bytes = self._cipher.block_size // 8 + else: + self._block_size_bytes = 1 + + ctx = self._backend._lib.EVP_CIPHER_CTX_new() + ctx = self._backend._ffi.gc( + ctx, self._backend._lib.EVP_CIPHER_CTX_free + ) + + registry = self._backend._cipher_registry + try: + adapter = registry[type(cipher), type(mode)] + except KeyError: + raise UnsupportedAlgorithm( + "cipher {} in {} mode is not supported " + "by this backend.".format( + cipher.name, mode.name if mode else mode + ), + _Reasons.UNSUPPORTED_CIPHER, + ) + + evp_cipher = adapter(self._backend, cipher, mode) + if evp_cipher == self._backend._ffi.NULL: + msg = "cipher {0.name} ".format(cipher) + if mode is not None: + msg += "in {0.name} mode ".format(mode) + msg += ( + "is not supported by this backend (Your version of OpenSSL " + "may be too old. Current version: {}.)" + ).format(self._backend.openssl_version_text()) + raise UnsupportedAlgorithm(msg, _Reasons.UNSUPPORTED_CIPHER) + + if isinstance(mode, modes.ModeWithInitializationVector): + iv_nonce = self._backend._ffi.from_buffer( + mode.initialization_vector + ) + elif isinstance(mode, modes.ModeWithTweak): + iv_nonce = self._backend._ffi.from_buffer(mode.tweak) + elif isinstance(mode, modes.ModeWithNonce): + iv_nonce = self._backend._ffi.from_buffer(mode.nonce) + elif isinstance(cipher, modes.ModeWithNonce): + iv_nonce = self._backend._ffi.from_buffer(cipher.nonce) + else: + iv_nonce = self._backend._ffi.NULL + # begin init with cipher and operation type + res = self._backend._lib.EVP_CipherInit_ex( + ctx, + evp_cipher, + self._backend._ffi.NULL, + self._backend._ffi.NULL, + self._backend._ffi.NULL, + operation, + ) + self._backend.openssl_assert(res != 0) + # set the key length to handle variable key ciphers + res = self._backend._lib.EVP_CIPHER_CTX_set_key_length( + ctx, len(cipher.key) + ) + self._backend.openssl_assert(res != 0) + if isinstance(mode, modes.GCM): + res = self._backend._lib.EVP_CIPHER_CTX_ctrl( + ctx, + self._backend._lib.EVP_CTRL_AEAD_SET_IVLEN, + len(iv_nonce), + self._backend._ffi.NULL, + ) + self._backend.openssl_assert(res != 0) + if mode.tag is not None: + res = self._backend._lib.EVP_CIPHER_CTX_ctrl( + ctx, + self._backend._lib.EVP_CTRL_AEAD_SET_TAG, + len(mode.tag), + mode.tag, + ) + self._backend.openssl_assert(res != 0) + self._tag = mode.tag + + # pass key/iv + res = self._backend._lib.EVP_CipherInit_ex( + ctx, + self._backend._ffi.NULL, + self._backend._ffi.NULL, + self._backend._ffi.from_buffer(cipher.key), + iv_nonce, + operation, + ) + + # Check for XTS mode duplicate keys error + errors = self._backend._consume_errors() + lib = self._backend._lib + if res == 0 and ( + ( + lib.CRYPTOGRAPHY_OPENSSL_111D_OR_GREATER + and errors[0]._lib_reason_match( + lib.ERR_LIB_EVP, lib.EVP_R_XTS_DUPLICATED_KEYS + ) + ) + or ( + lib.Cryptography_HAS_PROVIDERS + and errors[0]._lib_reason_match( + lib.ERR_LIB_PROV, lib.PROV_R_XTS_DUPLICATED_KEYS + ) + ) + ): + raise ValueError("In XTS mode duplicated keys are not allowed") + + self._backend.openssl_assert(res != 0, errors=errors) + + # We purposely disable padding here as it's handled higher up in the + # API. + self._backend._lib.EVP_CIPHER_CTX_set_padding(ctx, 0) + self._ctx = ctx + + def update(self, data: bytes) -> bytes: + buf = bytearray(len(data) + self._block_size_bytes - 1) + n = self.update_into(data, buf) + return bytes(buf[:n]) + + def update_into(self, data: bytes, buf) -> int: + total_data_len = len(data) + if len(buf) < (total_data_len + self._block_size_bytes - 1): + raise ValueError( + "buffer must be at least {} bytes for this " + "payload".format(len(data) + self._block_size_bytes - 1) + ) + + data_processed = 0 + total_out = 0 + outlen = self._backend._ffi.new("int *") + baseoutbuf = self._backend._ffi.from_buffer(buf) + baseinbuf = self._backend._ffi.from_buffer(data) + + while data_processed != total_data_len: + outbuf = baseoutbuf + total_out + inbuf = baseinbuf + data_processed + inlen = min(self._MAX_CHUNK_SIZE, total_data_len - data_processed) + + res = self._backend._lib.EVP_CipherUpdate( + self._ctx, outbuf, outlen, inbuf, inlen + ) + if res == 0 and isinstance(self._mode, modes.XTS): + self._backend._consume_errors() + raise ValueError( + "In XTS mode you must supply at least a full block in the " + "first update call. For AES this is 16 bytes." + ) + else: + self._backend.openssl_assert(res != 0) + data_processed += inlen + total_out += outlen[0] + + return total_out + + def finalize(self) -> bytes: + if ( + self._operation == self._DECRYPT + and isinstance(self._mode, modes.ModeWithAuthenticationTag) + and self.tag is None + ): + raise ValueError( + "Authentication tag must be provided when decrypting." + ) + + buf = self._backend._ffi.new("unsigned char[]", self._block_size_bytes) + outlen = self._backend._ffi.new("int *") + res = self._backend._lib.EVP_CipherFinal_ex(self._ctx, buf, outlen) + if res == 0: + errors = self._backend._consume_errors() + + if not errors and isinstance(self._mode, modes.GCM): + raise InvalidTag + + lib = self._backend._lib + self._backend.openssl_assert( + errors[0]._lib_reason_match( + lib.ERR_LIB_EVP, + lib.EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH, + ) + or ( + lib.Cryptography_HAS_PROVIDERS + and errors[0]._lib_reason_match( + lib.ERR_LIB_PROV, + lib.PROV_R_WRONG_FINAL_BLOCK_LENGTH, + ) + ) + or ( + lib.CRYPTOGRAPHY_IS_BORINGSSL + and errors[0].reason + == lib.CIPHER_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH + ), + errors=errors, + ) + raise ValueError( + "The length of the provided data is not a multiple of " + "the block length." + ) + + if ( + isinstance(self._mode, modes.GCM) + and self._operation == self._ENCRYPT + ): + tag_buf = self._backend._ffi.new( + "unsigned char[]", self._block_size_bytes + ) + res = self._backend._lib.EVP_CIPHER_CTX_ctrl( + self._ctx, + self._backend._lib.EVP_CTRL_AEAD_GET_TAG, + self._block_size_bytes, + tag_buf, + ) + self._backend.openssl_assert(res != 0) + self._tag = self._backend._ffi.buffer(tag_buf)[:] + + res = self._backend._lib.EVP_CIPHER_CTX_reset(self._ctx) + self._backend.openssl_assert(res == 1) + return self._backend._ffi.buffer(buf)[: outlen[0]] + + def finalize_with_tag(self, tag: bytes) -> bytes: + tag_len = len(tag) + if tag_len < self._mode._min_tag_length: + raise ValueError( + "Authentication tag must be {} bytes or longer.".format( + self._mode._min_tag_length + ) + ) + elif tag_len > self._block_size_bytes: + raise ValueError( + "Authentication tag cannot be more than {} bytes.".format( + self._block_size_bytes + ) + ) + res = self._backend._lib.EVP_CIPHER_CTX_ctrl( + self._ctx, self._backend._lib.EVP_CTRL_AEAD_SET_TAG, len(tag), tag + ) + self._backend.openssl_assert(res != 0) + self._tag = tag + return self.finalize() + + def authenticate_additional_data(self, data: bytes) -> None: + outlen = self._backend._ffi.new("int *") + res = self._backend._lib.EVP_CipherUpdate( + self._ctx, + self._backend._ffi.NULL, + outlen, + self._backend._ffi.from_buffer(data), + len(data), + ) + self._backend.openssl_assert(res != 0) + + tag = utils.read_only_property("_tag") diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/backends/openssl/cmac.py b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/backends/openssl/cmac.py new file mode 100644 index 00000000..a00c10cf --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/backends/openssl/cmac.py @@ -0,0 +1,80 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + + +from cryptography import utils +from cryptography.exceptions import ( + InvalidSignature, + UnsupportedAlgorithm, + _Reasons, +) +from cryptography.hazmat.primitives import constant_time +from cryptography.hazmat.primitives.ciphers.modes import CBC + + +class _CMACContext(object): + def __init__(self, backend, algorithm, ctx=None): + if not backend.cmac_algorithm_supported(algorithm): + raise UnsupportedAlgorithm( + "This backend does not support CMAC.", + _Reasons.UNSUPPORTED_CIPHER, + ) + + self._backend = backend + self._key = algorithm.key + self._algorithm = algorithm + self._output_length = algorithm.block_size // 8 + + if ctx is None: + registry = self._backend._cipher_registry + adapter = registry[type(algorithm), CBC] + + evp_cipher = adapter(self._backend, algorithm, CBC) + + ctx = self._backend._lib.CMAC_CTX_new() + + self._backend.openssl_assert(ctx != self._backend._ffi.NULL) + ctx = self._backend._ffi.gc(ctx, self._backend._lib.CMAC_CTX_free) + + key_ptr = self._backend._ffi.from_buffer(self._key) + res = self._backend._lib.CMAC_Init( + ctx, + key_ptr, + len(self._key), + evp_cipher, + self._backend._ffi.NULL, + ) + self._backend.openssl_assert(res == 1) + + self._ctx = ctx + + algorithm = utils.read_only_property("_algorithm") + + def update(self, data: bytes) -> None: + res = self._backend._lib.CMAC_Update(self._ctx, data, len(data)) + self._backend.openssl_assert(res == 1) + + def finalize(self) -> bytes: + buf = self._backend._ffi.new("unsigned char[]", self._output_length) + length = self._backend._ffi.new("size_t *", self._output_length) + res = self._backend._lib.CMAC_Final(self._ctx, buf, length) + self._backend.openssl_assert(res == 1) + + self._ctx = None + + return self._backend._ffi.buffer(buf)[:] + + def copy(self) -> "_CMACContext": + copied_ctx = self._backend._lib.CMAC_CTX_new() + copied_ctx = self._backend._ffi.gc( + copied_ctx, self._backend._lib.CMAC_CTX_free + ) + res = self._backend._lib.CMAC_CTX_copy(copied_ctx, self._ctx) + self._backend.openssl_assert(res == 1) + return _CMACContext(self._backend, self._algorithm, ctx=copied_ctx) + + def verify(self, signature: bytes) -> None: + digest = self.finalize() + if not constant_time.bytes_eq(digest, signature): + raise InvalidSignature("Signature did not match digest.") diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/backends/openssl/decode_asn1.py b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/backends/openssl/decode_asn1.py new file mode 100644 index 00000000..df91d6d8 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/backends/openssl/decode_asn1.py @@ -0,0 +1,31 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + + +from cryptography import x509 + +# CRLReason ::= ENUMERATED { +# unspecified (0), +# keyCompromise (1), +# cACompromise (2), +# affiliationChanged (3), +# superseded (4), +# cessationOfOperation (5), +# certificateHold (6), +# -- value 7 is not used +# removeFromCRL (8), +# privilegeWithdrawn (9), +# aACompromise (10) } +_CRL_ENTRY_REASON_ENUM_TO_CODE = { + x509.ReasonFlags.unspecified: 0, + x509.ReasonFlags.key_compromise: 1, + x509.ReasonFlags.ca_compromise: 2, + x509.ReasonFlags.affiliation_changed: 3, + x509.ReasonFlags.superseded: 4, + x509.ReasonFlags.cessation_of_operation: 5, + x509.ReasonFlags.certificate_hold: 6, + x509.ReasonFlags.remove_from_crl: 8, + x509.ReasonFlags.privilege_withdrawn: 9, + x509.ReasonFlags.aa_compromise: 10, +} diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/backends/openssl/dh.py b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/backends/openssl/dh.py new file mode 100644 index 00000000..b928f024 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/backends/openssl/dh.py @@ -0,0 +1,293 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + + +from cryptography.exceptions import UnsupportedAlgorithm, _Reasons +from cryptography.hazmat.primitives import serialization +from cryptography.hazmat.primitives.asymmetric import dh + + +def _dh_params_dup(dh_cdata, backend): + lib = backend._lib + ffi = backend._ffi + + param_cdata = lib.DHparams_dup(dh_cdata) + backend.openssl_assert(param_cdata != ffi.NULL) + param_cdata = ffi.gc(param_cdata, lib.DH_free) + if lib.CRYPTOGRAPHY_IS_LIBRESSL: + # In libressl DHparams_dup don't copy q + q = ffi.new("BIGNUM **") + lib.DH_get0_pqg(dh_cdata, ffi.NULL, q, ffi.NULL) + q_dup = lib.BN_dup(q[0]) + res = lib.DH_set0_pqg(param_cdata, ffi.NULL, q_dup, ffi.NULL) + backend.openssl_assert(res == 1) + + return param_cdata + + +def _dh_cdata_to_parameters(dh_cdata, backend): + param_cdata = _dh_params_dup(dh_cdata, backend) + return _DHParameters(backend, param_cdata) + + +class _DHParameters(dh.DHParameters): + def __init__(self, backend, dh_cdata): + self._backend = backend + self._dh_cdata = dh_cdata + + def parameter_numbers(self) -> dh.DHParameterNumbers: + p = self._backend._ffi.new("BIGNUM **") + g = self._backend._ffi.new("BIGNUM **") + q = self._backend._ffi.new("BIGNUM **") + self._backend._lib.DH_get0_pqg(self._dh_cdata, p, q, g) + self._backend.openssl_assert(p[0] != self._backend._ffi.NULL) + self._backend.openssl_assert(g[0] != self._backend._ffi.NULL) + if q[0] == self._backend._ffi.NULL: + q_val = None + else: + q_val = self._backend._bn_to_int(q[0]) + return dh.DHParameterNumbers( + p=self._backend._bn_to_int(p[0]), + g=self._backend._bn_to_int(g[0]), + q=q_val, + ) + + def generate_private_key(self) -> dh.DHPrivateKey: + return self._backend.generate_dh_private_key(self) + + def parameter_bytes( + self, + encoding: serialization.Encoding, + format: serialization.ParameterFormat, + ) -> bytes: + if format is not serialization.ParameterFormat.PKCS3: + raise ValueError("Only PKCS3 serialization is supported") + if not self._backend._lib.Cryptography_HAS_EVP_PKEY_DHX: + q = self._backend._ffi.new("BIGNUM **") + self._backend._lib.DH_get0_pqg( + self._dh_cdata, + self._backend._ffi.NULL, + q, + self._backend._ffi.NULL, + ) + if q[0] != self._backend._ffi.NULL: + raise UnsupportedAlgorithm( + "DH X9.42 serialization is not supported", + _Reasons.UNSUPPORTED_SERIALIZATION, + ) + + return self._backend._parameter_bytes(encoding, format, self._dh_cdata) + + +def _get_dh_num_bits(backend, dh_cdata) -> int: + p = backend._ffi.new("BIGNUM **") + backend._lib.DH_get0_pqg(dh_cdata, p, backend._ffi.NULL, backend._ffi.NULL) + backend.openssl_assert(p[0] != backend._ffi.NULL) + return backend._lib.BN_num_bits(p[0]) + + +class _DHPrivateKey(dh.DHPrivateKey): + def __init__(self, backend, dh_cdata, evp_pkey): + self._backend = backend + self._dh_cdata = dh_cdata + self._evp_pkey = evp_pkey + self._key_size_bytes = self._backend._lib.DH_size(dh_cdata) + + @property + def key_size(self) -> int: + return _get_dh_num_bits(self._backend, self._dh_cdata) + + def private_numbers(self) -> dh.DHPrivateNumbers: + p = self._backend._ffi.new("BIGNUM **") + g = self._backend._ffi.new("BIGNUM **") + q = self._backend._ffi.new("BIGNUM **") + self._backend._lib.DH_get0_pqg(self._dh_cdata, p, q, g) + self._backend.openssl_assert(p[0] != self._backend._ffi.NULL) + self._backend.openssl_assert(g[0] != self._backend._ffi.NULL) + if q[0] == self._backend._ffi.NULL: + q_val = None + else: + q_val = self._backend._bn_to_int(q[0]) + pub_key = self._backend._ffi.new("BIGNUM **") + priv_key = self._backend._ffi.new("BIGNUM **") + self._backend._lib.DH_get0_key(self._dh_cdata, pub_key, priv_key) + self._backend.openssl_assert(pub_key[0] != self._backend._ffi.NULL) + self._backend.openssl_assert(priv_key[0] != self._backend._ffi.NULL) + return dh.DHPrivateNumbers( + public_numbers=dh.DHPublicNumbers( + parameter_numbers=dh.DHParameterNumbers( + p=self._backend._bn_to_int(p[0]), + g=self._backend._bn_to_int(g[0]), + q=q_val, + ), + y=self._backend._bn_to_int(pub_key[0]), + ), + x=self._backend._bn_to_int(priv_key[0]), + ) + + def exchange(self, peer_public_key: dh.DHPublicKey) -> bytes: + if not isinstance(peer_public_key, _DHPublicKey): + raise TypeError("peer_public_key must be a DHPublicKey") + + ctx = self._backend._lib.EVP_PKEY_CTX_new( + self._evp_pkey, self._backend._ffi.NULL + ) + self._backend.openssl_assert(ctx != self._backend._ffi.NULL) + ctx = self._backend._ffi.gc(ctx, self._backend._lib.EVP_PKEY_CTX_free) + res = self._backend._lib.EVP_PKEY_derive_init(ctx) + self._backend.openssl_assert(res == 1) + res = self._backend._lib.EVP_PKEY_derive_set_peer( + ctx, peer_public_key._evp_pkey + ) + # Invalid kex errors here in OpenSSL 3.0 because checks were moved + # to EVP_PKEY_derive_set_peer + self._exchange_assert(res == 1) + keylen = self._backend._ffi.new("size_t *") + res = self._backend._lib.EVP_PKEY_derive( + ctx, self._backend._ffi.NULL, keylen + ) + # Invalid kex errors here in OpenSSL < 3 + self._exchange_assert(res == 1) + self._backend.openssl_assert(keylen[0] > 0) + buf = self._backend._ffi.new("unsigned char[]", keylen[0]) + res = self._backend._lib.EVP_PKEY_derive(ctx, buf, keylen) + self._backend.openssl_assert(res == 1) + + key = self._backend._ffi.buffer(buf, keylen[0])[:] + pad = self._key_size_bytes - len(key) + + if pad > 0: + key = (b"\x00" * pad) + key + + return key + + def _exchange_assert(self, ok): + if not ok: + errors_with_text = self._backend._consume_errors_with_text() + raise ValueError( + "Error computing shared key.", + errors_with_text, + ) + + def public_key(self) -> dh.DHPublicKey: + dh_cdata = _dh_params_dup(self._dh_cdata, self._backend) + pub_key = self._backend._ffi.new("BIGNUM **") + self._backend._lib.DH_get0_key( + self._dh_cdata, pub_key, self._backend._ffi.NULL + ) + self._backend.openssl_assert(pub_key[0] != self._backend._ffi.NULL) + pub_key_dup = self._backend._lib.BN_dup(pub_key[0]) + self._backend.openssl_assert(pub_key_dup != self._backend._ffi.NULL) + + res = self._backend._lib.DH_set0_key( + dh_cdata, pub_key_dup, self._backend._ffi.NULL + ) + self._backend.openssl_assert(res == 1) + evp_pkey = self._backend._dh_cdata_to_evp_pkey(dh_cdata) + return _DHPublicKey(self._backend, dh_cdata, evp_pkey) + + def parameters(self) -> dh.DHParameters: + return _dh_cdata_to_parameters(self._dh_cdata, self._backend) + + def private_bytes( + self, + encoding: serialization.Encoding, + format: serialization.PrivateFormat, + encryption_algorithm: serialization.KeySerializationEncryption, + ) -> bytes: + if format is not serialization.PrivateFormat.PKCS8: + raise ValueError( + "DH private keys support only PKCS8 serialization" + ) + if not self._backend._lib.Cryptography_HAS_EVP_PKEY_DHX: + q = self._backend._ffi.new("BIGNUM **") + self._backend._lib.DH_get0_pqg( + self._dh_cdata, + self._backend._ffi.NULL, + q, + self._backend._ffi.NULL, + ) + if q[0] != self._backend._ffi.NULL: + raise UnsupportedAlgorithm( + "DH X9.42 serialization is not supported", + _Reasons.UNSUPPORTED_SERIALIZATION, + ) + + return self._backend._private_key_bytes( + encoding, + format, + encryption_algorithm, + self, + self._evp_pkey, + self._dh_cdata, + ) + + +class _DHPublicKey(dh.DHPublicKey): + def __init__(self, backend, dh_cdata, evp_pkey): + self._backend = backend + self._dh_cdata = dh_cdata + self._evp_pkey = evp_pkey + self._key_size_bits = _get_dh_num_bits(self._backend, self._dh_cdata) + + @property + def key_size(self) -> int: + return self._key_size_bits + + def public_numbers(self) -> dh.DHPublicNumbers: + p = self._backend._ffi.new("BIGNUM **") + g = self._backend._ffi.new("BIGNUM **") + q = self._backend._ffi.new("BIGNUM **") + self._backend._lib.DH_get0_pqg(self._dh_cdata, p, q, g) + self._backend.openssl_assert(p[0] != self._backend._ffi.NULL) + self._backend.openssl_assert(g[0] != self._backend._ffi.NULL) + if q[0] == self._backend._ffi.NULL: + q_val = None + else: + q_val = self._backend._bn_to_int(q[0]) + pub_key = self._backend._ffi.new("BIGNUM **") + self._backend._lib.DH_get0_key( + self._dh_cdata, pub_key, self._backend._ffi.NULL + ) + self._backend.openssl_assert(pub_key[0] != self._backend._ffi.NULL) + return dh.DHPublicNumbers( + parameter_numbers=dh.DHParameterNumbers( + p=self._backend._bn_to_int(p[0]), + g=self._backend._bn_to_int(g[0]), + q=q_val, + ), + y=self._backend._bn_to_int(pub_key[0]), + ) + + def parameters(self) -> dh.DHParameters: + return _dh_cdata_to_parameters(self._dh_cdata, self._backend) + + def public_bytes( + self, + encoding: serialization.Encoding, + format: serialization.PublicFormat, + ) -> bytes: + if format is not serialization.PublicFormat.SubjectPublicKeyInfo: + raise ValueError( + "DH public keys support only " + "SubjectPublicKeyInfo serialization" + ) + + if not self._backend._lib.Cryptography_HAS_EVP_PKEY_DHX: + q = self._backend._ffi.new("BIGNUM **") + self._backend._lib.DH_get0_pqg( + self._dh_cdata, + self._backend._ffi.NULL, + q, + self._backend._ffi.NULL, + ) + if q[0] != self._backend._ffi.NULL: + raise UnsupportedAlgorithm( + "DH X9.42 serialization is not supported", + _Reasons.UNSUPPORTED_SERIALIZATION, + ) + + return self._backend._public_key_bytes( + encoding, format, self, self._evp_pkey, None + ) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/backends/openssl/dsa.py b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/backends/openssl/dsa.py new file mode 100644 index 00000000..fbce96c2 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/backends/openssl/dsa.py @@ -0,0 +1,289 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + + +import typing + +from cryptography import utils +from cryptography.exceptions import InvalidSignature +from cryptography.hazmat.backends.openssl.utils import ( + _calculate_digest_and_algorithm, + _check_not_prehashed, + _warn_sign_verify_deprecated, +) +from cryptography.hazmat.primitives import hashes, serialization +from cryptography.hazmat.primitives.asymmetric import ( + AsymmetricSignatureContext, + AsymmetricVerificationContext, + dsa, + utils as asym_utils, +) + + +def _dsa_sig_sign(backend, private_key, data): + sig_buf_len = backend._lib.DSA_size(private_key._dsa_cdata) + sig_buf = backend._ffi.new("unsigned char[]", sig_buf_len) + buflen = backend._ffi.new("unsigned int *") + + # The first parameter passed to DSA_sign is unused by OpenSSL but + # must be an integer. + res = backend._lib.DSA_sign( + 0, data, len(data), sig_buf, buflen, private_key._dsa_cdata + ) + backend.openssl_assert(res == 1) + backend.openssl_assert(buflen[0]) + + return backend._ffi.buffer(sig_buf)[: buflen[0]] + + +def _dsa_sig_verify(backend, public_key, signature, data): + # The first parameter passed to DSA_verify is unused by OpenSSL but + # must be an integer. + res = backend._lib.DSA_verify( + 0, data, len(data), signature, len(signature), public_key._dsa_cdata + ) + + if res != 1: + backend._consume_errors() + raise InvalidSignature + + +class _DSAVerificationContext(AsymmetricVerificationContext): + def __init__(self, backend, public_key, signature, algorithm): + self._backend = backend + self._public_key = public_key + self._signature = signature + self._algorithm = algorithm + + self._hash_ctx = hashes.Hash(self._algorithm, self._backend) + + def update(self, data: bytes): + self._hash_ctx.update(data) + + def verify(self) -> None: + data_to_verify = self._hash_ctx.finalize() + + _dsa_sig_verify( + self._backend, self._public_key, self._signature, data_to_verify + ) + + +class _DSASignatureContext(AsymmetricSignatureContext): + def __init__( + self, + backend, + private_key: dsa.DSAPrivateKey, + algorithm: hashes.HashAlgorithm, + ): + self._backend = backend + self._private_key = private_key + self._algorithm = algorithm + self._hash_ctx = hashes.Hash(self._algorithm, self._backend) + + def update(self, data: bytes) -> None: + self._hash_ctx.update(data) + + def finalize(self) -> bytes: + data_to_sign = self._hash_ctx.finalize() + return _dsa_sig_sign(self._backend, self._private_key, data_to_sign) + + +class _DSAParameters(dsa.DSAParameters): + def __init__(self, backend, dsa_cdata): + self._backend = backend + self._dsa_cdata = dsa_cdata + + def parameter_numbers(self) -> dsa.DSAParameterNumbers: + p = self._backend._ffi.new("BIGNUM **") + q = self._backend._ffi.new("BIGNUM **") + g = self._backend._ffi.new("BIGNUM **") + self._backend._lib.DSA_get0_pqg(self._dsa_cdata, p, q, g) + self._backend.openssl_assert(p[0] != self._backend._ffi.NULL) + self._backend.openssl_assert(q[0] != self._backend._ffi.NULL) + self._backend.openssl_assert(g[0] != self._backend._ffi.NULL) + return dsa.DSAParameterNumbers( + p=self._backend._bn_to_int(p[0]), + q=self._backend._bn_to_int(q[0]), + g=self._backend._bn_to_int(g[0]), + ) + + def generate_private_key(self) -> dsa.DSAPrivateKey: + return self._backend.generate_dsa_private_key(self) + + +class _DSAPrivateKey(dsa.DSAPrivateKey): + def __init__(self, backend, dsa_cdata, evp_pkey): + self._backend = backend + self._dsa_cdata = dsa_cdata + self._evp_pkey = evp_pkey + + p = self._backend._ffi.new("BIGNUM **") + self._backend._lib.DSA_get0_pqg( + dsa_cdata, p, self._backend._ffi.NULL, self._backend._ffi.NULL + ) + self._backend.openssl_assert(p[0] != backend._ffi.NULL) + self._key_size = self._backend._lib.BN_num_bits(p[0]) + + key_size = utils.read_only_property("_key_size") + + def signer( + self, signature_algorithm: hashes.HashAlgorithm + ) -> AsymmetricSignatureContext: + _warn_sign_verify_deprecated() + _check_not_prehashed(signature_algorithm) + return _DSASignatureContext(self._backend, self, signature_algorithm) + + def private_numbers(self) -> dsa.DSAPrivateNumbers: + p = self._backend._ffi.new("BIGNUM **") + q = self._backend._ffi.new("BIGNUM **") + g = self._backend._ffi.new("BIGNUM **") + pub_key = self._backend._ffi.new("BIGNUM **") + priv_key = self._backend._ffi.new("BIGNUM **") + self._backend._lib.DSA_get0_pqg(self._dsa_cdata, p, q, g) + self._backend.openssl_assert(p[0] != self._backend._ffi.NULL) + self._backend.openssl_assert(q[0] != self._backend._ffi.NULL) + self._backend.openssl_assert(g[0] != self._backend._ffi.NULL) + self._backend._lib.DSA_get0_key(self._dsa_cdata, pub_key, priv_key) + self._backend.openssl_assert(pub_key[0] != self._backend._ffi.NULL) + self._backend.openssl_assert(priv_key[0] != self._backend._ffi.NULL) + return dsa.DSAPrivateNumbers( + public_numbers=dsa.DSAPublicNumbers( + parameter_numbers=dsa.DSAParameterNumbers( + p=self._backend._bn_to_int(p[0]), + q=self._backend._bn_to_int(q[0]), + g=self._backend._bn_to_int(g[0]), + ), + y=self._backend._bn_to_int(pub_key[0]), + ), + x=self._backend._bn_to_int(priv_key[0]), + ) + + def public_key(self) -> dsa.DSAPublicKey: + dsa_cdata = self._backend._lib.DSAparams_dup(self._dsa_cdata) + self._backend.openssl_assert(dsa_cdata != self._backend._ffi.NULL) + dsa_cdata = self._backend._ffi.gc( + dsa_cdata, self._backend._lib.DSA_free + ) + pub_key = self._backend._ffi.new("BIGNUM **") + self._backend._lib.DSA_get0_key( + self._dsa_cdata, pub_key, self._backend._ffi.NULL + ) + self._backend.openssl_assert(pub_key[0] != self._backend._ffi.NULL) + pub_key_dup = self._backend._lib.BN_dup(pub_key[0]) + res = self._backend._lib.DSA_set0_key( + dsa_cdata, pub_key_dup, self._backend._ffi.NULL + ) + self._backend.openssl_assert(res == 1) + evp_pkey = self._backend._dsa_cdata_to_evp_pkey(dsa_cdata) + return _DSAPublicKey(self._backend, dsa_cdata, evp_pkey) + + def parameters(self) -> dsa.DSAParameters: + dsa_cdata = self._backend._lib.DSAparams_dup(self._dsa_cdata) + self._backend.openssl_assert(dsa_cdata != self._backend._ffi.NULL) + dsa_cdata = self._backend._ffi.gc( + dsa_cdata, self._backend._lib.DSA_free + ) + return _DSAParameters(self._backend, dsa_cdata) + + def private_bytes( + self, + encoding: serialization.Encoding, + format: serialization.PrivateFormat, + encryption_algorithm: serialization.KeySerializationEncryption, + ) -> bytes: + return self._backend._private_key_bytes( + encoding, + format, + encryption_algorithm, + self, + self._evp_pkey, + self._dsa_cdata, + ) + + def sign( + self, + data: bytes, + algorithm: typing.Union[asym_utils.Prehashed, hashes.HashAlgorithm], + ) -> bytes: + data, algorithm = _calculate_digest_and_algorithm( + self._backend, data, algorithm + ) + return _dsa_sig_sign(self._backend, self, data) + + +class _DSAPublicKey(dsa.DSAPublicKey): + def __init__(self, backend, dsa_cdata, evp_pkey): + self._backend = backend + self._dsa_cdata = dsa_cdata + self._evp_pkey = evp_pkey + p = self._backend._ffi.new("BIGNUM **") + self._backend._lib.DSA_get0_pqg( + dsa_cdata, p, self._backend._ffi.NULL, self._backend._ffi.NULL + ) + self._backend.openssl_assert(p[0] != backend._ffi.NULL) + self._key_size = self._backend._lib.BN_num_bits(p[0]) + + key_size = utils.read_only_property("_key_size") + + def verifier( + self, + signature: bytes, + signature_algorithm: hashes.HashAlgorithm, + ) -> AsymmetricVerificationContext: + _warn_sign_verify_deprecated() + utils._check_bytes("signature", signature) + + _check_not_prehashed(signature_algorithm) + return _DSAVerificationContext( + self._backend, self, signature, signature_algorithm + ) + + def public_numbers(self) -> dsa.DSAPublicNumbers: + p = self._backend._ffi.new("BIGNUM **") + q = self._backend._ffi.new("BIGNUM **") + g = self._backend._ffi.new("BIGNUM **") + pub_key = self._backend._ffi.new("BIGNUM **") + self._backend._lib.DSA_get0_pqg(self._dsa_cdata, p, q, g) + self._backend.openssl_assert(p[0] != self._backend._ffi.NULL) + self._backend.openssl_assert(q[0] != self._backend._ffi.NULL) + self._backend.openssl_assert(g[0] != self._backend._ffi.NULL) + self._backend._lib.DSA_get0_key( + self._dsa_cdata, pub_key, self._backend._ffi.NULL + ) + self._backend.openssl_assert(pub_key[0] != self._backend._ffi.NULL) + return dsa.DSAPublicNumbers( + parameter_numbers=dsa.DSAParameterNumbers( + p=self._backend._bn_to_int(p[0]), + q=self._backend._bn_to_int(q[0]), + g=self._backend._bn_to_int(g[0]), + ), + y=self._backend._bn_to_int(pub_key[0]), + ) + + def parameters(self) -> dsa.DSAParameters: + dsa_cdata = self._backend._lib.DSAparams_dup(self._dsa_cdata) + dsa_cdata = self._backend._ffi.gc( + dsa_cdata, self._backend._lib.DSA_free + ) + return _DSAParameters(self._backend, dsa_cdata) + + def public_bytes( + self, + encoding: serialization.Encoding, + format: serialization.PublicFormat, + ) -> bytes: + return self._backend._public_key_bytes( + encoding, format, self, self._evp_pkey, None + ) + + def verify( + self, + signature: bytes, + data: bytes, + algorithm: typing.Union[asym_utils.Prehashed, hashes.HashAlgorithm], + ) -> None: + data, algorithm = _calculate_digest_and_algorithm( + self._backend, data, algorithm + ) + return _dsa_sig_verify(self._backend, self, signature, data) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/backends/openssl/ec.py b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/backends/openssl/ec.py new file mode 100644 index 00000000..7c06d7a0 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/backends/openssl/ec.py @@ -0,0 +1,367 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + + +from cryptography import utils +from cryptography.exceptions import ( + InvalidSignature, + UnsupportedAlgorithm, + _Reasons, +) +from cryptography.hazmat.backends.openssl.utils import ( + _calculate_digest_and_algorithm, + _check_not_prehashed, + _evp_pkey_derive, + _warn_sign_verify_deprecated, +) +from cryptography.hazmat.primitives import hashes, serialization +from cryptography.hazmat.primitives.asymmetric import ( + AsymmetricSignatureContext, + AsymmetricVerificationContext, + ec, +) + + +def _check_signature_algorithm( + signature_algorithm: ec.EllipticCurveSignatureAlgorithm, +): + if not isinstance(signature_algorithm, ec.ECDSA): + raise UnsupportedAlgorithm( + "Unsupported elliptic curve signature algorithm.", + _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM, + ) + + +def _ec_key_curve_sn(backend, ec_key): + group = backend._lib.EC_KEY_get0_group(ec_key) + backend.openssl_assert(group != backend._ffi.NULL) + + nid = backend._lib.EC_GROUP_get_curve_name(group) + # The following check is to find EC keys with unnamed curves and raise + # an error for now. + if nid == backend._lib.NID_undef: + raise ValueError( + "ECDSA keys with explicit parameters are unsupported at this time" + ) + + # This is like the above check, but it also catches the case where you + # explicitly encoded a curve with the same parameters as a named curve. + # Don't do that. + if ( + not backend._lib.CRYPTOGRAPHY_IS_LIBRESSL + and backend._lib.EC_GROUP_get_asn1_flag(group) == 0 + ): + raise ValueError( + "ECDSA keys with explicit parameters are unsupported at this time" + ) + + curve_name = backend._lib.OBJ_nid2sn(nid) + backend.openssl_assert(curve_name != backend._ffi.NULL) + + sn = backend._ffi.string(curve_name).decode("ascii") + return sn + + +def _mark_asn1_named_ec_curve(backend, ec_cdata): + """ + Set the named curve flag on the EC_KEY. This causes OpenSSL to + serialize EC keys along with their curve OID which makes + deserialization easier. + """ + + backend._lib.EC_KEY_set_asn1_flag( + ec_cdata, backend._lib.OPENSSL_EC_NAMED_CURVE + ) + + +def _sn_to_elliptic_curve(backend, sn): + try: + return ec._CURVE_TYPES[sn]() + except KeyError: + raise UnsupportedAlgorithm( + "{} is not a supported elliptic curve".format(sn), + _Reasons.UNSUPPORTED_ELLIPTIC_CURVE, + ) + + +def _ecdsa_sig_sign(backend, private_key, data): + max_size = backend._lib.ECDSA_size(private_key._ec_key) + backend.openssl_assert(max_size > 0) + + sigbuf = backend._ffi.new("unsigned char[]", max_size) + siglen_ptr = backend._ffi.new("unsigned int[]", 1) + res = backend._lib.ECDSA_sign( + 0, data, len(data), sigbuf, siglen_ptr, private_key._ec_key + ) + backend.openssl_assert(res == 1) + return backend._ffi.buffer(sigbuf)[: siglen_ptr[0]] + + +def _ecdsa_sig_verify(backend, public_key, signature, data): + res = backend._lib.ECDSA_verify( + 0, data, len(data), signature, len(signature), public_key._ec_key + ) + if res != 1: + backend._consume_errors() + raise InvalidSignature + + +class _ECDSASignatureContext(AsymmetricSignatureContext): + def __init__( + self, + backend, + private_key: ec.EllipticCurvePrivateKey, + algorithm: hashes.HashAlgorithm, + ): + self._backend = backend + self._private_key = private_key + self._digest = hashes.Hash(algorithm, backend) + + def update(self, data: bytes) -> None: + self._digest.update(data) + + def finalize(self) -> bytes: + digest = self._digest.finalize() + + return _ecdsa_sig_sign(self._backend, self._private_key, digest) + + +class _ECDSAVerificationContext(AsymmetricVerificationContext): + def __init__( + self, + backend, + public_key: ec.EllipticCurvePublicKey, + signature: bytes, + algorithm: hashes.HashAlgorithm, + ): + self._backend = backend + self._public_key = public_key + self._signature = signature + self._digest = hashes.Hash(algorithm, backend) + + def update(self, data: bytes) -> None: + self._digest.update(data) + + def verify(self) -> None: + digest = self._digest.finalize() + _ecdsa_sig_verify( + self._backend, self._public_key, self._signature, digest + ) + + +class _EllipticCurvePrivateKey(ec.EllipticCurvePrivateKey): + def __init__(self, backend, ec_key_cdata, evp_pkey): + self._backend = backend + self._ec_key = ec_key_cdata + self._evp_pkey = evp_pkey + + sn = _ec_key_curve_sn(backend, ec_key_cdata) + self._curve = _sn_to_elliptic_curve(backend, sn) + _mark_asn1_named_ec_curve(backend, ec_key_cdata) + + curve = utils.read_only_property("_curve") + + @property + def key_size(self) -> int: + return self.curve.key_size + + def signer( + self, signature_algorithm: ec.EllipticCurveSignatureAlgorithm + ) -> AsymmetricSignatureContext: + _warn_sign_verify_deprecated() + _check_signature_algorithm(signature_algorithm) + _check_not_prehashed(signature_algorithm.algorithm) + # This assert is to help mypy realize what type this object holds + assert isinstance(signature_algorithm.algorithm, hashes.HashAlgorithm) + return _ECDSASignatureContext( + self._backend, self, signature_algorithm.algorithm + ) + + def exchange( + self, algorithm: ec.ECDH, peer_public_key: ec.EllipticCurvePublicKey + ) -> bytes: + if not ( + self._backend.elliptic_curve_exchange_algorithm_supported( + algorithm, self.curve + ) + ): + raise UnsupportedAlgorithm( + "This backend does not support the ECDH algorithm.", + _Reasons.UNSUPPORTED_EXCHANGE_ALGORITHM, + ) + + if peer_public_key.curve.name != self.curve.name: + raise ValueError( + "peer_public_key and self are not on the same curve" + ) + + return _evp_pkey_derive(self._backend, self._evp_pkey, peer_public_key) + + def public_key(self) -> ec.EllipticCurvePublicKey: + group = self._backend._lib.EC_KEY_get0_group(self._ec_key) + self._backend.openssl_assert(group != self._backend._ffi.NULL) + + curve_nid = self._backend._lib.EC_GROUP_get_curve_name(group) + public_ec_key = self._backend._ec_key_new_by_curve_nid(curve_nid) + + point = self._backend._lib.EC_KEY_get0_public_key(self._ec_key) + self._backend.openssl_assert(point != self._backend._ffi.NULL) + + res = self._backend._lib.EC_KEY_set_public_key(public_ec_key, point) + self._backend.openssl_assert(res == 1) + + evp_pkey = self._backend._ec_cdata_to_evp_pkey(public_ec_key) + + return _EllipticCurvePublicKey(self._backend, public_ec_key, evp_pkey) + + def private_numbers(self) -> ec.EllipticCurvePrivateNumbers: + bn = self._backend._lib.EC_KEY_get0_private_key(self._ec_key) + private_value = self._backend._bn_to_int(bn) + return ec.EllipticCurvePrivateNumbers( + private_value=private_value, + public_numbers=self.public_key().public_numbers(), + ) + + def private_bytes( + self, + encoding: serialization.Encoding, + format: serialization.PrivateFormat, + encryption_algorithm: serialization.KeySerializationEncryption, + ) -> bytes: + return self._backend._private_key_bytes( + encoding, + format, + encryption_algorithm, + self, + self._evp_pkey, + self._ec_key, + ) + + def sign( + self, + data: bytes, + signature_algorithm: ec.EllipticCurveSignatureAlgorithm, + ) -> bytes: + _check_signature_algorithm(signature_algorithm) + data, algorithm = _calculate_digest_and_algorithm( + self._backend, + data, + signature_algorithm._algorithm, # type: ignore[attr-defined] + ) + return _ecdsa_sig_sign(self._backend, self, data) + + +class _EllipticCurvePublicKey(ec.EllipticCurvePublicKey): + def __init__(self, backend, ec_key_cdata, evp_pkey): + self._backend = backend + self._ec_key = ec_key_cdata + self._evp_pkey = evp_pkey + + sn = _ec_key_curve_sn(backend, ec_key_cdata) + self._curve = _sn_to_elliptic_curve(backend, sn) + _mark_asn1_named_ec_curve(backend, ec_key_cdata) + + curve = utils.read_only_property("_curve") + + @property + def key_size(self) -> int: + return self.curve.key_size + + def verifier( + self, + signature: bytes, + signature_algorithm: ec.EllipticCurveSignatureAlgorithm, + ) -> AsymmetricVerificationContext: + _warn_sign_verify_deprecated() + utils._check_bytes("signature", signature) + + _check_signature_algorithm(signature_algorithm) + _check_not_prehashed(signature_algorithm.algorithm) + # This assert is to help mypy realize what type this object holds + assert isinstance(signature_algorithm.algorithm, hashes.HashAlgorithm) + return _ECDSAVerificationContext( + self._backend, self, signature, signature_algorithm.algorithm + ) + + def public_numbers(self) -> ec.EllipticCurvePublicNumbers: + get_func, group = self._backend._ec_key_determine_group_get_func( + self._ec_key + ) + point = self._backend._lib.EC_KEY_get0_public_key(self._ec_key) + self._backend.openssl_assert(point != self._backend._ffi.NULL) + + with self._backend._tmp_bn_ctx() as bn_ctx: + bn_x = self._backend._lib.BN_CTX_get(bn_ctx) + bn_y = self._backend._lib.BN_CTX_get(bn_ctx) + + res = get_func(group, point, bn_x, bn_y, bn_ctx) + self._backend.openssl_assert(res == 1) + + x = self._backend._bn_to_int(bn_x) + y = self._backend._bn_to_int(bn_y) + + return ec.EllipticCurvePublicNumbers(x=x, y=y, curve=self._curve) + + def _encode_point(self, format: serialization.PublicFormat) -> bytes: + if format is serialization.PublicFormat.CompressedPoint: + conversion = self._backend._lib.POINT_CONVERSION_COMPRESSED + else: + assert format is serialization.PublicFormat.UncompressedPoint + conversion = self._backend._lib.POINT_CONVERSION_UNCOMPRESSED + + group = self._backend._lib.EC_KEY_get0_group(self._ec_key) + self._backend.openssl_assert(group != self._backend._ffi.NULL) + point = self._backend._lib.EC_KEY_get0_public_key(self._ec_key) + self._backend.openssl_assert(point != self._backend._ffi.NULL) + with self._backend._tmp_bn_ctx() as bn_ctx: + buflen = self._backend._lib.EC_POINT_point2oct( + group, point, conversion, self._backend._ffi.NULL, 0, bn_ctx + ) + self._backend.openssl_assert(buflen > 0) + buf = self._backend._ffi.new("char[]", buflen) + res = self._backend._lib.EC_POINT_point2oct( + group, point, conversion, buf, buflen, bn_ctx + ) + self._backend.openssl_assert(buflen == res) + + return self._backend._ffi.buffer(buf)[:] + + def public_bytes( + self, + encoding: serialization.Encoding, + format: serialization.PublicFormat, + ) -> bytes: + if ( + encoding is serialization.Encoding.X962 + or format is serialization.PublicFormat.CompressedPoint + or format is serialization.PublicFormat.UncompressedPoint + ): + if encoding is not serialization.Encoding.X962 or format not in ( + serialization.PublicFormat.CompressedPoint, + serialization.PublicFormat.UncompressedPoint, + ): + raise ValueError( + "X962 encoding must be used with CompressedPoint or " + "UncompressedPoint format" + ) + + return self._encode_point(format) + else: + return self._backend._public_key_bytes( + encoding, format, self, self._evp_pkey, None + ) + + def verify( + self, + signature: bytes, + data: bytes, + signature_algorithm: ec.EllipticCurveSignatureAlgorithm, + ) -> None: + _check_signature_algorithm(signature_algorithm) + data, algorithm = _calculate_digest_and_algorithm( + self._backend, + data, + signature_algorithm._algorithm, # type: ignore[attr-defined] + ) + _ecdsa_sig_verify(self._backend, self, signature, data) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/backends/openssl/ed25519.py b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/backends/openssl/ed25519.py new file mode 100644 index 00000000..ff6c20d7 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/backends/openssl/ed25519.py @@ -0,0 +1,151 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + + +from cryptography import exceptions +from cryptography.hazmat.primitives import serialization +from cryptography.hazmat.primitives.asymmetric.ed25519 import ( + Ed25519PrivateKey, + Ed25519PublicKey, + _ED25519_KEY_SIZE, + _ED25519_SIG_SIZE, +) + + +class _Ed25519PublicKey(Ed25519PublicKey): + def __init__(self, backend, evp_pkey): + self._backend = backend + self._evp_pkey = evp_pkey + + def public_bytes( + self, + encoding: serialization.Encoding, + format: serialization.PublicFormat, + ) -> bytes: + if ( + encoding is serialization.Encoding.Raw + or format is serialization.PublicFormat.Raw + ): + if ( + encoding is not serialization.Encoding.Raw + or format is not serialization.PublicFormat.Raw + ): + raise ValueError( + "When using Raw both encoding and format must be Raw" + ) + + return self._raw_public_bytes() + + return self._backend._public_key_bytes( + encoding, format, self, self._evp_pkey, None + ) + + def _raw_public_bytes(self) -> bytes: + buf = self._backend._ffi.new("unsigned char []", _ED25519_KEY_SIZE) + buflen = self._backend._ffi.new("size_t *", _ED25519_KEY_SIZE) + res = self._backend._lib.EVP_PKEY_get_raw_public_key( + self._evp_pkey, buf, buflen + ) + self._backend.openssl_assert(res == 1) + self._backend.openssl_assert(buflen[0] == _ED25519_KEY_SIZE) + return self._backend._ffi.buffer(buf, _ED25519_KEY_SIZE)[:] + + def verify(self, signature: bytes, data: bytes) -> None: + evp_md_ctx = self._backend._lib.EVP_MD_CTX_new() + self._backend.openssl_assert(evp_md_ctx != self._backend._ffi.NULL) + evp_md_ctx = self._backend._ffi.gc( + evp_md_ctx, self._backend._lib.EVP_MD_CTX_free + ) + res = self._backend._lib.EVP_DigestVerifyInit( + evp_md_ctx, + self._backend._ffi.NULL, + self._backend._ffi.NULL, + self._backend._ffi.NULL, + self._evp_pkey, + ) + self._backend.openssl_assert(res == 1) + res = self._backend._lib.EVP_DigestVerify( + evp_md_ctx, signature, len(signature), data, len(data) + ) + if res != 1: + self._backend._consume_errors() + raise exceptions.InvalidSignature + + +class _Ed25519PrivateKey(Ed25519PrivateKey): + def __init__(self, backend, evp_pkey): + self._backend = backend + self._evp_pkey = evp_pkey + + def public_key(self) -> Ed25519PublicKey: + buf = self._backend._ffi.new("unsigned char []", _ED25519_KEY_SIZE) + buflen = self._backend._ffi.new("size_t *", _ED25519_KEY_SIZE) + res = self._backend._lib.EVP_PKEY_get_raw_public_key( + self._evp_pkey, buf, buflen + ) + self._backend.openssl_assert(res == 1) + self._backend.openssl_assert(buflen[0] == _ED25519_KEY_SIZE) + public_bytes = self._backend._ffi.buffer(buf)[:] + return self._backend.ed25519_load_public_bytes(public_bytes) + + def sign(self, data: bytes) -> bytes: + evp_md_ctx = self._backend._lib.EVP_MD_CTX_new() + self._backend.openssl_assert(evp_md_ctx != self._backend._ffi.NULL) + evp_md_ctx = self._backend._ffi.gc( + evp_md_ctx, self._backend._lib.EVP_MD_CTX_free + ) + res = self._backend._lib.EVP_DigestSignInit( + evp_md_ctx, + self._backend._ffi.NULL, + self._backend._ffi.NULL, + self._backend._ffi.NULL, + self._evp_pkey, + ) + self._backend.openssl_assert(res == 1) + buf = self._backend._ffi.new("unsigned char[]", _ED25519_SIG_SIZE) + buflen = self._backend._ffi.new("size_t *", len(buf)) + res = self._backend._lib.EVP_DigestSign( + evp_md_ctx, buf, buflen, data, len(data) + ) + self._backend.openssl_assert(res == 1) + self._backend.openssl_assert(buflen[0] == _ED25519_SIG_SIZE) + return self._backend._ffi.buffer(buf, buflen[0])[:] + + def private_bytes( + self, + encoding: serialization.Encoding, + format: serialization.PrivateFormat, + encryption_algorithm: serialization.KeySerializationEncryption, + ) -> bytes: + if ( + encoding is serialization.Encoding.Raw + or format is serialization.PublicFormat.Raw + ): + if ( + format is not serialization.PrivateFormat.Raw + or encoding is not serialization.Encoding.Raw + or not isinstance( + encryption_algorithm, serialization.NoEncryption + ) + ): + raise ValueError( + "When using Raw both encoding and format must be Raw " + "and encryption_algorithm must be NoEncryption()" + ) + + return self._raw_private_bytes() + + return self._backend._private_key_bytes( + encoding, format, encryption_algorithm, self, self._evp_pkey, None + ) + + def _raw_private_bytes(self) -> bytes: + buf = self._backend._ffi.new("unsigned char []", _ED25519_KEY_SIZE) + buflen = self._backend._ffi.new("size_t *", _ED25519_KEY_SIZE) + res = self._backend._lib.EVP_PKEY_get_raw_private_key( + self._evp_pkey, buf, buflen + ) + self._backend.openssl_assert(res == 1) + self._backend.openssl_assert(buflen[0] == _ED25519_KEY_SIZE) + return self._backend._ffi.buffer(buf, _ED25519_KEY_SIZE)[:] diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/backends/openssl/ed448.py b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/backends/openssl/ed448.py new file mode 100644 index 00000000..c787efdc --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/backends/openssl/ed448.py @@ -0,0 +1,152 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + + +from cryptography import exceptions +from cryptography.hazmat.primitives import serialization +from cryptography.hazmat.primitives.asymmetric.ed448 import ( + Ed448PrivateKey, + Ed448PublicKey, +) + +_ED448_KEY_SIZE = 57 +_ED448_SIG_SIZE = 114 + + +class _Ed448PublicKey(Ed448PublicKey): + def __init__(self, backend, evp_pkey): + self._backend = backend + self._evp_pkey = evp_pkey + + def public_bytes( + self, + encoding: serialization.Encoding, + format: serialization.PublicFormat, + ) -> bytes: + if ( + encoding is serialization.Encoding.Raw + or format is serialization.PublicFormat.Raw + ): + if ( + encoding is not serialization.Encoding.Raw + or format is not serialization.PublicFormat.Raw + ): + raise ValueError( + "When using Raw both encoding and format must be Raw" + ) + + return self._raw_public_bytes() + + return self._backend._public_key_bytes( + encoding, format, self, self._evp_pkey, None + ) + + def _raw_public_bytes(self) -> bytes: + buf = self._backend._ffi.new("unsigned char []", _ED448_KEY_SIZE) + buflen = self._backend._ffi.new("size_t *", _ED448_KEY_SIZE) + res = self._backend._lib.EVP_PKEY_get_raw_public_key( + self._evp_pkey, buf, buflen + ) + self._backend.openssl_assert(res == 1) + self._backend.openssl_assert(buflen[0] == _ED448_KEY_SIZE) + return self._backend._ffi.buffer(buf, _ED448_KEY_SIZE)[:] + + def verify(self, signature: bytes, data: bytes) -> None: + evp_md_ctx = self._backend._lib.EVP_MD_CTX_new() + self._backend.openssl_assert(evp_md_ctx != self._backend._ffi.NULL) + evp_md_ctx = self._backend._ffi.gc( + evp_md_ctx, self._backend._lib.EVP_MD_CTX_free + ) + res = self._backend._lib.EVP_DigestVerifyInit( + evp_md_ctx, + self._backend._ffi.NULL, + self._backend._ffi.NULL, + self._backend._ffi.NULL, + self._evp_pkey, + ) + self._backend.openssl_assert(res == 1) + res = self._backend._lib.EVP_DigestVerify( + evp_md_ctx, signature, len(signature), data, len(data) + ) + if res != 1: + self._backend._consume_errors() + raise exceptions.InvalidSignature + + +class _Ed448PrivateKey(Ed448PrivateKey): + def __init__(self, backend, evp_pkey): + self._backend = backend + self._evp_pkey = evp_pkey + + def public_key(self) -> Ed448PublicKey: + buf = self._backend._ffi.new("unsigned char []", _ED448_KEY_SIZE) + buflen = self._backend._ffi.new("size_t *", _ED448_KEY_SIZE) + res = self._backend._lib.EVP_PKEY_get_raw_public_key( + self._evp_pkey, buf, buflen + ) + self._backend.openssl_assert(res == 1) + self._backend.openssl_assert(buflen[0] == _ED448_KEY_SIZE) + public_bytes = self._backend._ffi.buffer(buf)[:] + return self._backend.ed448_load_public_bytes(public_bytes) + + def sign(self, data: bytes) -> bytes: + evp_md_ctx = self._backend._lib.EVP_MD_CTX_new() + self._backend.openssl_assert(evp_md_ctx != self._backend._ffi.NULL) + evp_md_ctx = self._backend._ffi.gc( + evp_md_ctx, self._backend._lib.EVP_MD_CTX_free + ) + res = self._backend._lib.EVP_DigestSignInit( + evp_md_ctx, + self._backend._ffi.NULL, + self._backend._ffi.NULL, + self._backend._ffi.NULL, + self._evp_pkey, + ) + self._backend.openssl_assert(res == 1) + buf = self._backend._ffi.new("unsigned char[]", _ED448_SIG_SIZE) + buflen = self._backend._ffi.new("size_t *", len(buf)) + res = self._backend._lib.EVP_DigestSign( + evp_md_ctx, buf, buflen, data, len(data) + ) + self._backend.openssl_assert(res == 1) + self._backend.openssl_assert(buflen[0] == _ED448_SIG_SIZE) + return self._backend._ffi.buffer(buf, buflen[0])[:] + + def private_bytes( + self, + encoding: serialization.Encoding, + format: serialization.PrivateFormat, + encryption_algorithm: serialization.KeySerializationEncryption, + ) -> bytes: + if ( + encoding is serialization.Encoding.Raw + or format is serialization.PublicFormat.Raw + ): + if ( + format is not serialization.PrivateFormat.Raw + or encoding is not serialization.Encoding.Raw + or not isinstance( + encryption_algorithm, serialization.NoEncryption + ) + ): + raise ValueError( + "When using Raw both encoding and format must be Raw " + "and encryption_algorithm must be NoEncryption()" + ) + + return self._raw_private_bytes() + + return self._backend._private_key_bytes( + encoding, format, encryption_algorithm, self, self._evp_pkey, None + ) + + def _raw_private_bytes(self) -> bytes: + buf = self._backend._ffi.new("unsigned char []", _ED448_KEY_SIZE) + buflen = self._backend._ffi.new("size_t *", _ED448_KEY_SIZE) + res = self._backend._lib.EVP_PKEY_get_raw_private_key( + self._evp_pkey, buf, buflen + ) + self._backend.openssl_assert(res == 1) + self._backend.openssl_assert(buflen[0] == _ED448_KEY_SIZE) + return self._backend._ffi.buffer(buf, _ED448_KEY_SIZE)[:] diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/backends/openssl/encode_asn1.py b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/backends/openssl/encode_asn1.py new file mode 100644 index 00000000..2f29d71c --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/backends/openssl/encode_asn1.py @@ -0,0 +1,18 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + + +from cryptography import x509 + + +_CRLREASONFLAGS = { + x509.ReasonFlags.key_compromise: 1, + x509.ReasonFlags.ca_compromise: 2, + x509.ReasonFlags.affiliation_changed: 3, + x509.ReasonFlags.superseded: 4, + x509.ReasonFlags.cessation_of_operation: 5, + x509.ReasonFlags.certificate_hold: 6, + x509.ReasonFlags.privilege_withdrawn: 7, + x509.ReasonFlags.aa_compromise: 8, +} diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/backends/openssl/hashes.py b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/backends/openssl/hashes.py new file mode 100644 index 00000000..aa816c12 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/backends/openssl/hashes.py @@ -0,0 +1,80 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + + +from cryptography.exceptions import UnsupportedAlgorithm, _Reasons +from cryptography.hazmat.primitives import hashes + + +class _HashContext(hashes.HashContext): + def __init__(self, backend, algorithm: hashes.HashAlgorithm, ctx=None): + self._algorithm = algorithm + + self._backend = backend + + if ctx is None: + ctx = self._backend._lib.EVP_MD_CTX_new() + ctx = self._backend._ffi.gc( + ctx, self._backend._lib.EVP_MD_CTX_free + ) + evp_md = self._backend._evp_md_from_algorithm(algorithm) + if evp_md == self._backend._ffi.NULL: + raise UnsupportedAlgorithm( + "{} is not a supported hash on this backend.".format( + algorithm.name + ), + _Reasons.UNSUPPORTED_HASH, + ) + res = self._backend._lib.EVP_DigestInit_ex( + ctx, evp_md, self._backend._ffi.NULL + ) + self._backend.openssl_assert(res != 0) + + self._ctx = ctx + + @property + def algorithm(self) -> hashes.HashAlgorithm: + return self._algorithm + + def copy(self) -> "_HashContext": + copied_ctx = self._backend._lib.EVP_MD_CTX_new() + copied_ctx = self._backend._ffi.gc( + copied_ctx, self._backend._lib.EVP_MD_CTX_free + ) + res = self._backend._lib.EVP_MD_CTX_copy_ex(copied_ctx, self._ctx) + self._backend.openssl_assert(res != 0) + return _HashContext(self._backend, self.algorithm, ctx=copied_ctx) + + def update(self, data: bytes) -> None: + data_ptr = self._backend._ffi.from_buffer(data) + res = self._backend._lib.EVP_DigestUpdate( + self._ctx, data_ptr, len(data) + ) + self._backend.openssl_assert(res != 0) + + def finalize(self) -> bytes: + if isinstance(self.algorithm, hashes.ExtendableOutputFunction): + # extendable output functions use a different finalize + return self._finalize_xof() + else: + buf = self._backend._ffi.new( + "unsigned char[]", self._backend._lib.EVP_MAX_MD_SIZE + ) + outlen = self._backend._ffi.new("unsigned int *") + res = self._backend._lib.EVP_DigestFinal_ex(self._ctx, buf, outlen) + self._backend.openssl_assert(res != 0) + self._backend.openssl_assert( + outlen[0] == self.algorithm.digest_size + ) + return self._backend._ffi.buffer(buf)[: outlen[0]] + + def _finalize_xof(self) -> bytes: + buf = self._backend._ffi.new( + "unsigned char[]", self.algorithm.digest_size + ) + res = self._backend._lib.EVP_DigestFinalXOF( + self._ctx, buf, self.algorithm.digest_size + ) + self._backend.openssl_assert(res != 0) + return self._backend._ffi.buffer(buf)[: self.algorithm.digest_size] diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/backends/openssl/hmac.py b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/backends/openssl/hmac.py new file mode 100644 index 00000000..c9c28f59 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/backends/openssl/hmac.py @@ -0,0 +1,76 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + + +from cryptography.exceptions import ( + InvalidSignature, + UnsupportedAlgorithm, + _Reasons, +) +from cryptography.hazmat.primitives import constant_time, hashes + + +class _HMACContext(hashes.HashContext): + def __init__( + self, backend, key: bytes, algorithm: hashes.HashAlgorithm, ctx=None + ): + self._algorithm = algorithm + self._backend = backend + + if ctx is None: + ctx = self._backend._lib.HMAC_CTX_new() + self._backend.openssl_assert(ctx != self._backend._ffi.NULL) + ctx = self._backend._ffi.gc(ctx, self._backend._lib.HMAC_CTX_free) + evp_md = self._backend._evp_md_from_algorithm(algorithm) + if evp_md == self._backend._ffi.NULL: + raise UnsupportedAlgorithm( + "{} is not a supported hash on this backend".format( + algorithm.name + ), + _Reasons.UNSUPPORTED_HASH, + ) + key_ptr = self._backend._ffi.from_buffer(key) + res = self._backend._lib.HMAC_Init_ex( + ctx, key_ptr, len(key), evp_md, self._backend._ffi.NULL + ) + self._backend.openssl_assert(res != 0) + + self._ctx = ctx + self._key = key + + @property + def algorithm(self) -> hashes.HashAlgorithm: + return self._algorithm + + def copy(self) -> "_HMACContext": + copied_ctx = self._backend._lib.HMAC_CTX_new() + self._backend.openssl_assert(copied_ctx != self._backend._ffi.NULL) + copied_ctx = self._backend._ffi.gc( + copied_ctx, self._backend._lib.HMAC_CTX_free + ) + res = self._backend._lib.HMAC_CTX_copy(copied_ctx, self._ctx) + self._backend.openssl_assert(res != 0) + return _HMACContext( + self._backend, self._key, self.algorithm, ctx=copied_ctx + ) + + def update(self, data: bytes) -> None: + data_ptr = self._backend._ffi.from_buffer(data) + res = self._backend._lib.HMAC_Update(self._ctx, data_ptr, len(data)) + self._backend.openssl_assert(res != 0) + + def finalize(self) -> bytes: + buf = self._backend._ffi.new( + "unsigned char[]", self._backend._lib.EVP_MAX_MD_SIZE + ) + outlen = self._backend._ffi.new("unsigned int *") + res = self._backend._lib.HMAC_Final(self._ctx, buf, outlen) + self._backend.openssl_assert(res != 0) + self._backend.openssl_assert(outlen[0] == self.algorithm.digest_size) + return self._backend._ffi.buffer(buf)[: outlen[0]] + + def verify(self, signature: bytes) -> None: + digest = self.finalize() + if not constant_time.bytes_eq(digest, signature): + raise InvalidSignature("Signature did not match digest.") diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/backends/openssl/poly1305.py b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/backends/openssl/poly1305.py new file mode 100644 index 00000000..2ddae984 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/backends/openssl/poly1305.py @@ -0,0 +1,63 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + + +from cryptography.exceptions import InvalidSignature +from cryptography.hazmat.primitives import constant_time + + +_POLY1305_TAG_SIZE = 16 +_POLY1305_KEY_SIZE = 32 + + +class _Poly1305Context(object): + def __init__(self, backend, key): + self._backend = backend + + key_ptr = self._backend._ffi.from_buffer(key) + # This function copies the key into OpenSSL-owned memory so we don't + # need to retain it ourselves + evp_pkey = self._backend._lib.EVP_PKEY_new_raw_private_key( + self._backend._lib.NID_poly1305, + self._backend._ffi.NULL, + key_ptr, + len(key), + ) + self._backend.openssl_assert(evp_pkey != self._backend._ffi.NULL) + self._evp_pkey = self._backend._ffi.gc( + evp_pkey, self._backend._lib.EVP_PKEY_free + ) + ctx = self._backend._lib.EVP_MD_CTX_new() + self._backend.openssl_assert(ctx != self._backend._ffi.NULL) + self._ctx = self._backend._ffi.gc( + ctx, self._backend._lib.EVP_MD_CTX_free + ) + res = self._backend._lib.EVP_DigestSignInit( + self._ctx, + self._backend._ffi.NULL, + self._backend._ffi.NULL, + self._backend._ffi.NULL, + self._evp_pkey, + ) + self._backend.openssl_assert(res == 1) + + def update(self, data): + data_ptr = self._backend._ffi.from_buffer(data) + res = self._backend._lib.EVP_DigestSignUpdate( + self._ctx, data_ptr, len(data) + ) + self._backend.openssl_assert(res != 0) + + def finalize(self): + buf = self._backend._ffi.new("unsigned char[]", _POLY1305_TAG_SIZE) + outlen = self._backend._ffi.new("size_t *", _POLY1305_TAG_SIZE) + res = self._backend._lib.EVP_DigestSignFinal(self._ctx, buf, outlen) + self._backend.openssl_assert(res != 0) + self._backend.openssl_assert(outlen[0] == _POLY1305_TAG_SIZE) + return self._backend._ffi.buffer(buf)[: outlen[0]] + + def verify(self, tag): + mac = self.finalize() + if not constant_time.bytes_eq(mac, tag): + raise InvalidSignature("Value did not match computed tag.") diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/backends/openssl/rsa.py b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/backends/openssl/rsa.py new file mode 100644 index 00000000..9bef49d2 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/backends/openssl/rsa.py @@ -0,0 +1,584 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + + +import typing + +from cryptography import utils +from cryptography.exceptions import ( + InvalidSignature, + UnsupportedAlgorithm, + _Reasons, +) +from cryptography.hazmat.backends.openssl.utils import ( + _calculate_digest_and_algorithm, + _check_not_prehashed, + _warn_sign_verify_deprecated, +) +from cryptography.hazmat.primitives import hashes, serialization +from cryptography.hazmat.primitives.asymmetric import ( + AsymmetricSignatureContext, + AsymmetricVerificationContext, + utils as asym_utils, +) +from cryptography.hazmat.primitives.asymmetric.padding import ( + AsymmetricPadding, + MGF1, + OAEP, + PKCS1v15, + PSS, + calculate_max_pss_salt_length, +) +from cryptography.hazmat.primitives.asymmetric.rsa import ( + RSAPrivateKey, + RSAPrivateNumbers, + RSAPublicKey, + RSAPublicNumbers, +) + + +def _get_rsa_pss_salt_length( + pss: PSS, + key: typing.Union[RSAPrivateKey, RSAPublicKey], + hash_algorithm: hashes.HashAlgorithm, +) -> int: + salt = pss._salt_length + + if salt is MGF1.MAX_LENGTH or salt is PSS.MAX_LENGTH: + return calculate_max_pss_salt_length(key, hash_algorithm) + else: + return salt + + +def _enc_dec_rsa( + backend, + key: typing.Union["_RSAPrivateKey", "_RSAPublicKey"], + data: bytes, + padding: AsymmetricPadding, +) -> bytes: + if not isinstance(padding, AsymmetricPadding): + raise TypeError("Padding must be an instance of AsymmetricPadding.") + + if isinstance(padding, PKCS1v15): + padding_enum = backend._lib.RSA_PKCS1_PADDING + elif isinstance(padding, OAEP): + padding_enum = backend._lib.RSA_PKCS1_OAEP_PADDING + + if not isinstance(padding._mgf, MGF1): + raise UnsupportedAlgorithm( + "Only MGF1 is supported by this backend.", + _Reasons.UNSUPPORTED_MGF, + ) + + if not backend.rsa_padding_supported(padding): + raise UnsupportedAlgorithm( + "This combination of padding and hash algorithm is not " + "supported by this backend.", + _Reasons.UNSUPPORTED_PADDING, + ) + + else: + raise UnsupportedAlgorithm( + "{} is not supported by this backend.".format(padding.name), + _Reasons.UNSUPPORTED_PADDING, + ) + + return _enc_dec_rsa_pkey_ctx(backend, key, data, padding_enum, padding) + + +def _enc_dec_rsa_pkey_ctx( + backend, + key: typing.Union["_RSAPrivateKey", "_RSAPublicKey"], + data: bytes, + padding_enum: int, + padding: AsymmetricPadding, +) -> bytes: + if isinstance(key, _RSAPublicKey): + init = backend._lib.EVP_PKEY_encrypt_init + crypt = backend._lib.EVP_PKEY_encrypt + else: + init = backend._lib.EVP_PKEY_decrypt_init + crypt = backend._lib.EVP_PKEY_decrypt + + pkey_ctx = backend._lib.EVP_PKEY_CTX_new(key._evp_pkey, backend._ffi.NULL) + backend.openssl_assert(pkey_ctx != backend._ffi.NULL) + pkey_ctx = backend._ffi.gc(pkey_ctx, backend._lib.EVP_PKEY_CTX_free) + res = init(pkey_ctx) + backend.openssl_assert(res == 1) + res = backend._lib.EVP_PKEY_CTX_set_rsa_padding(pkey_ctx, padding_enum) + backend.openssl_assert(res > 0) + buf_size = backend._lib.EVP_PKEY_size(key._evp_pkey) + backend.openssl_assert(buf_size > 0) + if isinstance(padding, OAEP) and backend._lib.Cryptography_HAS_RSA_OAEP_MD: + mgf1_md = backend._evp_md_non_null_from_algorithm( + padding._mgf._algorithm + ) + res = backend._lib.EVP_PKEY_CTX_set_rsa_mgf1_md(pkey_ctx, mgf1_md) + backend.openssl_assert(res > 0) + oaep_md = backend._evp_md_non_null_from_algorithm(padding._algorithm) + res = backend._lib.EVP_PKEY_CTX_set_rsa_oaep_md(pkey_ctx, oaep_md) + backend.openssl_assert(res > 0) + + if ( + isinstance(padding, OAEP) + and padding._label is not None + and len(padding._label) > 0 + ): + # set0_rsa_oaep_label takes ownership of the char * so we need to + # copy it into some new memory + labelptr = backend._lib.OPENSSL_malloc(len(padding._label)) + backend.openssl_assert(labelptr != backend._ffi.NULL) + backend._ffi.memmove(labelptr, padding._label, len(padding._label)) + res = backend._lib.EVP_PKEY_CTX_set0_rsa_oaep_label( + pkey_ctx, labelptr, len(padding._label) + ) + backend.openssl_assert(res == 1) + + outlen = backend._ffi.new("size_t *", buf_size) + buf = backend._ffi.new("unsigned char[]", buf_size) + # Everything from this line onwards is written with the goal of being as + # constant-time as is practical given the constraints of Python and our + # API. See Bleichenbacher's '98 attack on RSA, and its many many variants. + # As such, you should not attempt to change this (particularly to "clean it + # up") without understanding why it was written this way (see + # Chesterton's Fence), and without measuring to verify you have not + # introduced observable time differences. + res = crypt(pkey_ctx, buf, outlen, data, len(data)) + resbuf = backend._ffi.buffer(buf)[: outlen[0]] + backend._lib.ERR_clear_error() + if res <= 0: + raise ValueError("Encryption/decryption failed.") + return resbuf + + +def _rsa_sig_determine_padding(backend, key, padding, algorithm): + if not isinstance(padding, AsymmetricPadding): + raise TypeError("Expected provider of AsymmetricPadding.") + + pkey_size = backend._lib.EVP_PKEY_size(key._evp_pkey) + backend.openssl_assert(pkey_size > 0) + + if isinstance(padding, PKCS1v15): + # Hash algorithm is ignored for PKCS1v15-padding, may be None. + padding_enum = backend._lib.RSA_PKCS1_PADDING + elif isinstance(padding, PSS): + if not isinstance(padding._mgf, MGF1): + raise UnsupportedAlgorithm( + "Only MGF1 is supported by this backend.", + _Reasons.UNSUPPORTED_MGF, + ) + + # PSS padding requires a hash algorithm + if not isinstance(algorithm, hashes.HashAlgorithm): + raise TypeError("Expected instance of hashes.HashAlgorithm.") + + # Size of key in bytes - 2 is the maximum + # PSS signature length (salt length is checked later) + if pkey_size - algorithm.digest_size - 2 < 0: + raise ValueError( + "Digest too large for key size. Use a larger " + "key or different digest." + ) + + padding_enum = backend._lib.RSA_PKCS1_PSS_PADDING + else: + raise UnsupportedAlgorithm( + "{} is not supported by this backend.".format(padding.name), + _Reasons.UNSUPPORTED_PADDING, + ) + + return padding_enum + + +# Hash algorithm can be absent (None) to initialize the context without setting +# any message digest algorithm. This is currently only valid for the PKCS1v15 +# padding type, where it means that the signature data is encoded/decoded +# as provided, without being wrapped in a DigestInfo structure. +def _rsa_sig_setup(backend, padding, algorithm, key, init_func): + padding_enum = _rsa_sig_determine_padding(backend, key, padding, algorithm) + pkey_ctx = backend._lib.EVP_PKEY_CTX_new(key._evp_pkey, backend._ffi.NULL) + backend.openssl_assert(pkey_ctx != backend._ffi.NULL) + pkey_ctx = backend._ffi.gc(pkey_ctx, backend._lib.EVP_PKEY_CTX_free) + res = init_func(pkey_ctx) + if res != 1: + errors = backend._consume_errors() + raise ValueError("Unable to sign/verify with this key", errors) + + if algorithm is not None: + evp_md = backend._evp_md_non_null_from_algorithm(algorithm) + res = backend._lib.EVP_PKEY_CTX_set_signature_md(pkey_ctx, evp_md) + if res == 0: + backend._consume_errors() + raise UnsupportedAlgorithm( + "{} is not supported by this backend for RSA signing.".format( + algorithm.name + ), + _Reasons.UNSUPPORTED_HASH, + ) + res = backend._lib.EVP_PKEY_CTX_set_rsa_padding(pkey_ctx, padding_enum) + if res <= 0: + backend._consume_errors() + raise UnsupportedAlgorithm( + "{} is not supported for the RSA signature operation.".format( + padding.name + ), + _Reasons.UNSUPPORTED_PADDING, + ) + if isinstance(padding, PSS): + res = backend._lib.EVP_PKEY_CTX_set_rsa_pss_saltlen( + pkey_ctx, _get_rsa_pss_salt_length(padding, key, algorithm) + ) + backend.openssl_assert(res > 0) + + mgf1_md = backend._evp_md_non_null_from_algorithm( + padding._mgf._algorithm + ) + res = backend._lib.EVP_PKEY_CTX_set_rsa_mgf1_md(pkey_ctx, mgf1_md) + backend.openssl_assert(res > 0) + + return pkey_ctx + + +def _rsa_sig_sign(backend, padding, algorithm, private_key, data): + pkey_ctx = _rsa_sig_setup( + backend, + padding, + algorithm, + private_key, + backend._lib.EVP_PKEY_sign_init, + ) + buflen = backend._ffi.new("size_t *") + res = backend._lib.EVP_PKEY_sign( + pkey_ctx, backend._ffi.NULL, buflen, data, len(data) + ) + backend.openssl_assert(res == 1) + buf = backend._ffi.new("unsigned char[]", buflen[0]) + res = backend._lib.EVP_PKEY_sign(pkey_ctx, buf, buflen, data, len(data)) + if res != 1: + errors = backend._consume_errors_with_text() + raise ValueError( + "Digest or salt length too long for key size. Use a larger key " + "or shorter salt length if you are specifying a PSS salt", + errors, + ) + + return backend._ffi.buffer(buf)[:] + + +def _rsa_sig_verify(backend, padding, algorithm, public_key, signature, data): + pkey_ctx = _rsa_sig_setup( + backend, + padding, + algorithm, + public_key, + backend._lib.EVP_PKEY_verify_init, + ) + res = backend._lib.EVP_PKEY_verify( + pkey_ctx, signature, len(signature), data, len(data) + ) + # The previous call can return negative numbers in the event of an + # error. This is not a signature failure but we need to fail if it + # occurs. + backend.openssl_assert(res >= 0) + if res == 0: + backend._consume_errors() + raise InvalidSignature + + +def _rsa_sig_recover(backend, padding, algorithm, public_key, signature): + pkey_ctx = _rsa_sig_setup( + backend, + padding, + algorithm, + public_key, + backend._lib.EVP_PKEY_verify_recover_init, + ) + + # Attempt to keep the rest of the code in this function as constant/time + # as possible. See the comment in _enc_dec_rsa_pkey_ctx. Note that the + # buflen parameter is used even though its value may be undefined in the + # error case. Due to the tolerant nature of Python slicing this does not + # trigger any exceptions. + maxlen = backend._lib.EVP_PKEY_size(public_key._evp_pkey) + backend.openssl_assert(maxlen > 0) + buf = backend._ffi.new("unsigned char[]", maxlen) + buflen = backend._ffi.new("size_t *", maxlen) + res = backend._lib.EVP_PKEY_verify_recover( + pkey_ctx, buf, buflen, signature, len(signature) + ) + resbuf = backend._ffi.buffer(buf)[: buflen[0]] + backend._lib.ERR_clear_error() + # Assume that all parameter errors are handled during the setup phase and + # any error here is due to invalid signature. + if res != 1: + raise InvalidSignature + return resbuf + + +class _RSASignatureContext(AsymmetricSignatureContext): + def __init__( + self, + backend, + private_key: RSAPrivateKey, + padding: AsymmetricPadding, + algorithm: hashes.HashAlgorithm, + ): + self._backend = backend + self._private_key = private_key + + # We now call _rsa_sig_determine_padding in _rsa_sig_setup. However + # we need to make a pointless call to it here so we maintain the + # API of erroring on init with this context if the values are invalid. + _rsa_sig_determine_padding(backend, private_key, padding, algorithm) + self._padding = padding + self._algorithm = algorithm + self._hash_ctx = hashes.Hash(self._algorithm, self._backend) + + def update(self, data: bytes) -> None: + self._hash_ctx.update(data) + + def finalize(self) -> bytes: + return _rsa_sig_sign( + self._backend, + self._padding, + self._algorithm, + self._private_key, + self._hash_ctx.finalize(), + ) + + +class _RSAVerificationContext(AsymmetricVerificationContext): + def __init__( + self, + backend, + public_key: RSAPublicKey, + signature: bytes, + padding: AsymmetricPadding, + algorithm: hashes.HashAlgorithm, + ): + self._backend = backend + self._public_key = public_key + self._signature = signature + self._padding = padding + # We now call _rsa_sig_determine_padding in _rsa_sig_setup. However + # we need to make a pointless call to it here so we maintain the + # API of erroring on init with this context if the values are invalid. + _rsa_sig_determine_padding(backend, public_key, padding, algorithm) + + padding = padding + self._algorithm = algorithm + self._hash_ctx = hashes.Hash(self._algorithm, self._backend) + + def update(self, data: bytes) -> None: + self._hash_ctx.update(data) + + def verify(self) -> None: + return _rsa_sig_verify( + self._backend, + self._padding, + self._algorithm, + self._public_key, + self._signature, + self._hash_ctx.finalize(), + ) + + +class _RSAPrivateKey(RSAPrivateKey): + def __init__(self, backend, rsa_cdata, evp_pkey, _skip_check_key): + # RSA_check_key is slower in OpenSSL 3.0.0 due to improved + # primality checking. In normal use this is unlikely to be a problem + # since users don't load new keys constantly, but for TESTING we've + # added an init arg that allows skipping the checks. You should not + # use this in production code unless you understand the consequences. + if not _skip_check_key: + res = backend._lib.RSA_check_key(rsa_cdata) + if res != 1: + errors = backend._consume_errors_with_text() + raise ValueError("Invalid private key", errors) + + # Blinding is on by default in many versions of OpenSSL, but let's + # just be conservative here. + res = backend._lib.RSA_blinding_on(rsa_cdata, backend._ffi.NULL) + backend.openssl_assert(res == 1) + + self._backend = backend + self._rsa_cdata = rsa_cdata + self._evp_pkey = evp_pkey + + n = self._backend._ffi.new("BIGNUM **") + self._backend._lib.RSA_get0_key( + self._rsa_cdata, + n, + self._backend._ffi.NULL, + self._backend._ffi.NULL, + ) + self._backend.openssl_assert(n[0] != self._backend._ffi.NULL) + self._key_size = self._backend._lib.BN_num_bits(n[0]) + + key_size = utils.read_only_property("_key_size") + + def signer( + self, padding: AsymmetricPadding, algorithm: hashes.HashAlgorithm + ) -> AsymmetricSignatureContext: + _warn_sign_verify_deprecated() + _check_not_prehashed(algorithm) + return _RSASignatureContext(self._backend, self, padding, algorithm) + + def decrypt(self, ciphertext: bytes, padding: AsymmetricPadding) -> bytes: + key_size_bytes = (self.key_size + 7) // 8 + if key_size_bytes != len(ciphertext): + raise ValueError("Ciphertext length must be equal to key size.") + + return _enc_dec_rsa(self._backend, self, ciphertext, padding) + + def public_key(self) -> RSAPublicKey: + ctx = self._backend._lib.RSAPublicKey_dup(self._rsa_cdata) + self._backend.openssl_assert(ctx != self._backend._ffi.NULL) + ctx = self._backend._ffi.gc(ctx, self._backend._lib.RSA_free) + evp_pkey = self._backend._rsa_cdata_to_evp_pkey(ctx) + return _RSAPublicKey(self._backend, ctx, evp_pkey) + + def private_numbers(self) -> RSAPrivateNumbers: + n = self._backend._ffi.new("BIGNUM **") + e = self._backend._ffi.new("BIGNUM **") + d = self._backend._ffi.new("BIGNUM **") + p = self._backend._ffi.new("BIGNUM **") + q = self._backend._ffi.new("BIGNUM **") + dmp1 = self._backend._ffi.new("BIGNUM **") + dmq1 = self._backend._ffi.new("BIGNUM **") + iqmp = self._backend._ffi.new("BIGNUM **") + self._backend._lib.RSA_get0_key(self._rsa_cdata, n, e, d) + self._backend.openssl_assert(n[0] != self._backend._ffi.NULL) + self._backend.openssl_assert(e[0] != self._backend._ffi.NULL) + self._backend.openssl_assert(d[0] != self._backend._ffi.NULL) + self._backend._lib.RSA_get0_factors(self._rsa_cdata, p, q) + self._backend.openssl_assert(p[0] != self._backend._ffi.NULL) + self._backend.openssl_assert(q[0] != self._backend._ffi.NULL) + self._backend._lib.RSA_get0_crt_params( + self._rsa_cdata, dmp1, dmq1, iqmp + ) + self._backend.openssl_assert(dmp1[0] != self._backend._ffi.NULL) + self._backend.openssl_assert(dmq1[0] != self._backend._ffi.NULL) + self._backend.openssl_assert(iqmp[0] != self._backend._ffi.NULL) + return RSAPrivateNumbers( + p=self._backend._bn_to_int(p[0]), + q=self._backend._bn_to_int(q[0]), + d=self._backend._bn_to_int(d[0]), + dmp1=self._backend._bn_to_int(dmp1[0]), + dmq1=self._backend._bn_to_int(dmq1[0]), + iqmp=self._backend._bn_to_int(iqmp[0]), + public_numbers=RSAPublicNumbers( + e=self._backend._bn_to_int(e[0]), + n=self._backend._bn_to_int(n[0]), + ), + ) + + def private_bytes( + self, + encoding: serialization.Encoding, + format: serialization.PrivateFormat, + encryption_algorithm: serialization.KeySerializationEncryption, + ) -> bytes: + return self._backend._private_key_bytes( + encoding, + format, + encryption_algorithm, + self, + self._evp_pkey, + self._rsa_cdata, + ) + + def sign( + self, + data: bytes, + padding: AsymmetricPadding, + algorithm: typing.Union[asym_utils.Prehashed, hashes.HashAlgorithm], + ) -> bytes: + data, algorithm = _calculate_digest_and_algorithm( + self._backend, data, algorithm + ) + return _rsa_sig_sign(self._backend, padding, algorithm, self, data) + + +class _RSAPublicKey(RSAPublicKey): + def __init__(self, backend, rsa_cdata, evp_pkey): + self._backend = backend + self._rsa_cdata = rsa_cdata + self._evp_pkey = evp_pkey + + n = self._backend._ffi.new("BIGNUM **") + self._backend._lib.RSA_get0_key( + self._rsa_cdata, + n, + self._backend._ffi.NULL, + self._backend._ffi.NULL, + ) + self._backend.openssl_assert(n[0] != self._backend._ffi.NULL) + self._key_size = self._backend._lib.BN_num_bits(n[0]) + + key_size = utils.read_only_property("_key_size") + + def verifier( + self, + signature: bytes, + padding: AsymmetricPadding, + algorithm: hashes.HashAlgorithm, + ) -> AsymmetricVerificationContext: + _warn_sign_verify_deprecated() + utils._check_bytes("signature", signature) + + _check_not_prehashed(algorithm) + return _RSAVerificationContext( + self._backend, self, signature, padding, algorithm + ) + + def encrypt(self, plaintext: bytes, padding: AsymmetricPadding) -> bytes: + return _enc_dec_rsa(self._backend, self, plaintext, padding) + + def public_numbers(self) -> RSAPublicNumbers: + n = self._backend._ffi.new("BIGNUM **") + e = self._backend._ffi.new("BIGNUM **") + self._backend._lib.RSA_get0_key( + self._rsa_cdata, n, e, self._backend._ffi.NULL + ) + self._backend.openssl_assert(n[0] != self._backend._ffi.NULL) + self._backend.openssl_assert(e[0] != self._backend._ffi.NULL) + return RSAPublicNumbers( + e=self._backend._bn_to_int(e[0]), + n=self._backend._bn_to_int(n[0]), + ) + + def public_bytes( + self, + encoding: serialization.Encoding, + format: serialization.PublicFormat, + ) -> bytes: + return self._backend._public_key_bytes( + encoding, format, self, self._evp_pkey, self._rsa_cdata + ) + + def verify( + self, + signature: bytes, + data: bytes, + padding: AsymmetricPadding, + algorithm: typing.Union[asym_utils.Prehashed, hashes.HashAlgorithm], + ) -> None: + data, algorithm = _calculate_digest_and_algorithm( + self._backend, data, algorithm + ) + return _rsa_sig_verify( + self._backend, padding, algorithm, self, signature, data + ) + + def recover_data_from_signature( + self, + signature: bytes, + padding: AsymmetricPadding, + algorithm: typing.Optional[hashes.HashAlgorithm], + ) -> bytes: + _check_not_prehashed(algorithm) + return _rsa_sig_recover( + self._backend, padding, algorithm, self, signature + ) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/backends/openssl/utils.py b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/backends/openssl/utils.py new file mode 100644 index 00000000..e03ad899 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/backends/openssl/utils.py @@ -0,0 +1,67 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + + +import warnings + +from cryptography import utils +from cryptography.hazmat.primitives import hashes +from cryptography.hazmat.primitives.asymmetric.utils import Prehashed + + +def _evp_pkey_derive(backend, evp_pkey, peer_public_key): + ctx = backend._lib.EVP_PKEY_CTX_new(evp_pkey, backend._ffi.NULL) + backend.openssl_assert(ctx != backend._ffi.NULL) + ctx = backend._ffi.gc(ctx, backend._lib.EVP_PKEY_CTX_free) + res = backend._lib.EVP_PKEY_derive_init(ctx) + backend.openssl_assert(res == 1) + res = backend._lib.EVP_PKEY_derive_set_peer(ctx, peer_public_key._evp_pkey) + backend.openssl_assert(res == 1) + keylen = backend._ffi.new("size_t *") + res = backend._lib.EVP_PKEY_derive(ctx, backend._ffi.NULL, keylen) + backend.openssl_assert(res == 1) + backend.openssl_assert(keylen[0] > 0) + buf = backend._ffi.new("unsigned char[]", keylen[0]) + res = backend._lib.EVP_PKEY_derive(ctx, buf, keylen) + if res != 1: + errors_with_text = backend._consume_errors_with_text() + raise ValueError("Error computing shared key.", errors_with_text) + + return backend._ffi.buffer(buf, keylen[0])[:] + + +def _calculate_digest_and_algorithm(backend, data, algorithm): + if not isinstance(algorithm, Prehashed): + hash_ctx = hashes.Hash(algorithm, backend) + hash_ctx.update(data) + data = hash_ctx.finalize() + else: + algorithm = algorithm._algorithm + + if len(data) != algorithm.digest_size: + raise ValueError( + "The provided data must be the same length as the hash " + "algorithm's digest size." + ) + + return (data, algorithm) + + +def _check_not_prehashed(signature_algorithm): + if isinstance(signature_algorithm, Prehashed): + raise TypeError( + "Prehashed is only supported in the sign and verify methods. " + "It cannot be used with signer, verifier or " + "recover_data_from_signature." + ) + + +def _warn_sign_verify_deprecated(): + warnings.warn( + "signer and verifier have been deprecated since 2.1. Please use sign " + "and verify instead. Support for these functions will be dropped" + " in the next release of cryptography (37.0).", + utils.PersistentlyDeprecated2017, + stacklevel=3, + ) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/backends/openssl/x25519.py b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/backends/openssl/x25519.py new file mode 100644 index 00000000..c2eb87ad --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/backends/openssl/x25519.py @@ -0,0 +1,128 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + + +from cryptography.hazmat.backends.openssl.utils import _evp_pkey_derive +from cryptography.hazmat.primitives import serialization +from cryptography.hazmat.primitives.asymmetric.x25519 import ( + X25519PrivateKey, + X25519PublicKey, +) + + +_X25519_KEY_SIZE = 32 + + +class _X25519PublicKey(X25519PublicKey): + def __init__(self, backend, evp_pkey): + self._backend = backend + self._evp_pkey = evp_pkey + + def public_bytes( + self, + encoding: serialization.Encoding, + format: serialization.PublicFormat, + ) -> bytes: + if ( + encoding is serialization.Encoding.Raw + or format is serialization.PublicFormat.Raw + ): + if ( + encoding is not serialization.Encoding.Raw + or format is not serialization.PublicFormat.Raw + ): + raise ValueError( + "When using Raw both encoding and format must be Raw" + ) + + return self._raw_public_bytes() + + return self._backend._public_key_bytes( + encoding, format, self, self._evp_pkey, None + ) + + def _raw_public_bytes(self) -> bytes: + ucharpp = self._backend._ffi.new("unsigned char **") + res = self._backend._lib.EVP_PKEY_get1_tls_encodedpoint( + self._evp_pkey, ucharpp + ) + self._backend.openssl_assert(res == 32) + self._backend.openssl_assert(ucharpp[0] != self._backend._ffi.NULL) + data = self._backend._ffi.gc( + ucharpp[0], self._backend._lib.OPENSSL_free + ) + return self._backend._ffi.buffer(data, res)[:] + + +class _X25519PrivateKey(X25519PrivateKey): + def __init__(self, backend, evp_pkey): + self._backend = backend + self._evp_pkey = evp_pkey + + def public_key(self) -> X25519PublicKey: + bio = self._backend._create_mem_bio_gc() + res = self._backend._lib.i2d_PUBKEY_bio(bio, self._evp_pkey) + self._backend.openssl_assert(res == 1) + evp_pkey = self._backend._lib.d2i_PUBKEY_bio( + bio, self._backend._ffi.NULL + ) + self._backend.openssl_assert(evp_pkey != self._backend._ffi.NULL) + evp_pkey = self._backend._ffi.gc( + evp_pkey, self._backend._lib.EVP_PKEY_free + ) + return _X25519PublicKey(self._backend, evp_pkey) + + def exchange(self, peer_public_key: X25519PublicKey) -> bytes: + if not isinstance(peer_public_key, X25519PublicKey): + raise TypeError("peer_public_key must be X25519PublicKey.") + + return _evp_pkey_derive(self._backend, self._evp_pkey, peer_public_key) + + def private_bytes( + self, + encoding: serialization.Encoding, + format: serialization.PrivateFormat, + encryption_algorithm: serialization.KeySerializationEncryption, + ) -> bytes: + if ( + encoding is serialization.Encoding.Raw + or format is serialization.PublicFormat.Raw + ): + if ( + format is not serialization.PrivateFormat.Raw + or encoding is not serialization.Encoding.Raw + or not isinstance( + encryption_algorithm, serialization.NoEncryption + ) + ): + raise ValueError( + "When using Raw both encoding and format must be Raw " + "and encryption_algorithm must be NoEncryption()" + ) + + return self._raw_private_bytes() + + return self._backend._private_key_bytes( + encoding, format, encryption_algorithm, self, self._evp_pkey, None + ) + + def _raw_private_bytes(self) -> bytes: + # When we drop support for CRYPTOGRAPHY_OPENSSL_LESS_THAN_111 we can + # switch this to EVP_PKEY_new_raw_private_key + # The trick we use here is serializing to a PKCS8 key and just + # using the last 32 bytes, which is the key itself. + bio = self._backend._create_mem_bio_gc() + res = self._backend._lib.i2d_PKCS8PrivateKey_bio( + bio, + self._evp_pkey, + self._backend._ffi.NULL, + self._backend._ffi.NULL, + 0, + self._backend._ffi.NULL, + self._backend._ffi.NULL, + ) + self._backend.openssl_assert(res == 1) + pkcs8 = self._backend._read_mem_bio(bio) + self._backend.openssl_assert(len(pkcs8) == 48) + return pkcs8[-_X25519_KEY_SIZE:] diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/backends/openssl/x448.py b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/backends/openssl/x448.py new file mode 100644 index 00000000..8d3ceb11 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/backends/openssl/x448.py @@ -0,0 +1,112 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + + +from cryptography.hazmat.backends.openssl.utils import _evp_pkey_derive +from cryptography.hazmat.primitives import serialization +from cryptography.hazmat.primitives.asymmetric.x448 import ( + X448PrivateKey, + X448PublicKey, +) + +_X448_KEY_SIZE = 56 + + +class _X448PublicKey(X448PublicKey): + def __init__(self, backend, evp_pkey): + self._backend = backend + self._evp_pkey = evp_pkey + + def public_bytes( + self, + encoding: serialization.Encoding, + format: serialization.PublicFormat, + ) -> bytes: + if ( + encoding is serialization.Encoding.Raw + or format is serialization.PublicFormat.Raw + ): + if ( + encoding is not serialization.Encoding.Raw + or format is not serialization.PublicFormat.Raw + ): + raise ValueError( + "When using Raw both encoding and format must be Raw" + ) + + return self._raw_public_bytes() + + return self._backend._public_key_bytes( + encoding, format, self, self._evp_pkey, None + ) + + def _raw_public_bytes(self) -> bytes: + buf = self._backend._ffi.new("unsigned char []", _X448_KEY_SIZE) + buflen = self._backend._ffi.new("size_t *", _X448_KEY_SIZE) + res = self._backend._lib.EVP_PKEY_get_raw_public_key( + self._evp_pkey, buf, buflen + ) + self._backend.openssl_assert(res == 1) + self._backend.openssl_assert(buflen[0] == _X448_KEY_SIZE) + return self._backend._ffi.buffer(buf, _X448_KEY_SIZE)[:] + + +class _X448PrivateKey(X448PrivateKey): + def __init__(self, backend, evp_pkey): + self._backend = backend + self._evp_pkey = evp_pkey + + def public_key(self) -> X448PublicKey: + buf = self._backend._ffi.new("unsigned char []", _X448_KEY_SIZE) + buflen = self._backend._ffi.new("size_t *", _X448_KEY_SIZE) + res = self._backend._lib.EVP_PKEY_get_raw_public_key( + self._evp_pkey, buf, buflen + ) + self._backend.openssl_assert(res == 1) + self._backend.openssl_assert(buflen[0] == _X448_KEY_SIZE) + return self._backend.x448_load_public_bytes(buf) + + def exchange(self, peer_public_key: X448PublicKey) -> bytes: + if not isinstance(peer_public_key, X448PublicKey): + raise TypeError("peer_public_key must be X448PublicKey.") + + return _evp_pkey_derive(self._backend, self._evp_pkey, peer_public_key) + + def private_bytes( + self, + encoding: serialization.Encoding, + format: serialization.PrivateFormat, + encryption_algorithm: serialization.KeySerializationEncryption, + ) -> bytes: + if ( + encoding is serialization.Encoding.Raw + or format is serialization.PublicFormat.Raw + ): + if ( + format is not serialization.PrivateFormat.Raw + or encoding is not serialization.Encoding.Raw + or not isinstance( + encryption_algorithm, serialization.NoEncryption + ) + ): + raise ValueError( + "When using Raw both encoding and format must be Raw " + "and encryption_algorithm must be NoEncryption()" + ) + + return self._raw_private_bytes() + + return self._backend._private_key_bytes( + encoding, format, encryption_algorithm, self, self._evp_pkey, None + ) + + def _raw_private_bytes(self) -> bytes: + buf = self._backend._ffi.new("unsigned char []", _X448_KEY_SIZE) + buflen = self._backend._ffi.new("size_t *", _X448_KEY_SIZE) + res = self._backend._lib.EVP_PKEY_get_raw_private_key( + self._evp_pkey, buf, buflen + ) + self._backend.openssl_assert(res == 1) + self._backend.openssl_assert(buflen[0] == _X448_KEY_SIZE) + return self._backend._ffi.buffer(buf, _X448_KEY_SIZE)[:] diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/backends/openssl/x509.py b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/backends/openssl/x509.py new file mode 100644 index 00000000..aa4ed106 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/backends/openssl/x509.py @@ -0,0 +1,45 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + + +import warnings + +from cryptography import utils, x509 + + +# This exists for pyOpenSSL compatibility and SHOULD NOT BE USED +# WE WILL REMOVE THIS VERY SOON. +def _Certificate(backend, x509) -> x509.Certificate: # noqa: N802 + warnings.warn( + "This version of cryptography contains a temporary pyOpenSSL " + "fallback path. Upgrade pyOpenSSL now.", + utils.DeprecatedIn35, + ) + return backend._ossl2cert(x509) + + +# This exists for pyOpenSSL compatibility and SHOULD NOT BE USED +# WE WILL REMOVE THIS VERY SOON. +def _CertificateSigningRequest( # noqa: N802 + backend, x509_req +) -> x509.CertificateSigningRequest: + warnings.warn( + "This version of cryptography contains a temporary pyOpenSSL " + "fallback path. Upgrade pyOpenSSL now.", + utils.DeprecatedIn35, + ) + return backend._ossl2csr(x509_req) + + +# This exists for pyOpenSSL compatibility and SHOULD NOT BE USED +# WE WILL REMOVE THIS VERY SOON. +def _CertificateRevocationList( # noqa: N802 + backend, x509_crl +) -> x509.CertificateRevocationList: + warnings.warn( + "This version of cryptography contains a temporary pyOpenSSL " + "fallback path. Upgrade pyOpenSSL now.", + utils.DeprecatedIn35, + ) + return backend._ossl2crl(x509_crl) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/bindings/__init__.py b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/bindings/__init__.py new file mode 100644 index 00000000..b5093362 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/bindings/__init__.py @@ -0,0 +1,3 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/bindings/_rust/__init__.pyi b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/bindings/_rust/__init__.pyi new file mode 100644 index 00000000..393ee7ab --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/bindings/_rust/__init__.pyi @@ -0,0 +1,2 @@ +def check_pkcs7_padding(data: bytes) -> bool: ... +def check_ansix923_padding(data: bytes) -> bool: ... diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/bindings/_rust/asn1.pyi b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/bindings/_rust/asn1.pyi new file mode 100644 index 00000000..5579c4f3 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/bindings/_rust/asn1.pyi @@ -0,0 +1,12 @@ +import typing + +class TestCertificate: + not_after_tag: int + not_before_tag: int + issuer_value_tags: typing.List[int] + subject_value_tags: typing.List[int] + +def decode_dss_signature(signature: bytes) -> typing.Tuple[int, int]: ... +def encode_dss_signature(r: int, s: int) -> bytes: ... +def parse_spki_for_data(data: bytes) -> bytes: ... +def test_parse_certificate(data: bytes) -> TestCertificate: ... diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/bindings/_rust/ocsp.pyi b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/bindings/_rust/ocsp.pyi new file mode 100644 index 00000000..91b84955 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/bindings/_rust/ocsp.pyi @@ -0,0 +1,22 @@ +import typing + +from cryptography.hazmat.primitives.asymmetric.types import PRIVATE_KEY_TYPES +from cryptography.hazmat.primitives import hashes +from cryptography.x509 import Extension +from cryptography.x509.ocsp import ( + OCSPRequest, + OCSPRequestBuilder, + OCSPResponse, + OCSPResponseStatus, + OCSPResponseBuilder, +) + +def load_der_ocsp_request(data: bytes) -> OCSPRequest: ... +def load_der_ocsp_response(data: bytes) -> OCSPResponse: ... +def create_ocsp_request(builder: OCSPRequestBuilder) -> OCSPRequest: ... +def create_ocsp_response( + status: OCSPResponseStatus, + builder: typing.Optional[OCSPResponseBuilder], + private_key: typing.Optional[PRIVATE_KEY_TYPES], + hash_algorithm: typing.Optional[hashes.HashAlgorithm], +) -> OCSPResponse: ... diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/bindings/_rust/x509.pyi b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/bindings/_rust/x509.pyi new file mode 100644 index 00000000..79aeb63c --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/bindings/_rust/x509.pyi @@ -0,0 +1,36 @@ +import datetime +import typing + +from cryptography import x509 +from cryptography.hazmat.primitives import hashes +from cryptography.hazmat.primitives.asymmetric.types import PRIVATE_KEY_TYPES + +def load_pem_x509_certificate(data: bytes) -> x509.Certificate: ... +def load_der_x509_certificate(data: bytes) -> x509.Certificate: ... +def load_pem_x509_crl(data: bytes) -> x509.CertificateRevocationList: ... +def load_der_x509_crl(data: bytes) -> x509.CertificateRevocationList: ... +def load_pem_x509_csr(data: bytes) -> x509.CertificateSigningRequest: ... +def load_der_x509_csr(data: bytes) -> x509.CertificateSigningRequest: ... +def encode_name_bytes(name: x509.Name) -> bytes: ... +def encode_extension_value(extension: x509.ExtensionType) -> bytes: ... +def create_x509_certificate( + builder: x509.CertificateBuilder, + private_key: PRIVATE_KEY_TYPES, + hash_algorithm: typing.Optional[hashes.HashAlgorithm], +) -> x509.Certificate: ... +def create_x509_csr( + builder: x509.CertificateSigningRequestBuilder, + private_key: PRIVATE_KEY_TYPES, + hash_algorithm: typing.Optional[hashes.HashAlgorithm], +) -> x509.CertificateSigningRequest: ... +def create_x509_crl( + builder: x509.CertificateRevocationListBuilder, + private_key: PRIVATE_KEY_TYPES, + hash_algorithm: typing.Optional[hashes.HashAlgorithm], +) -> x509.CertificateRevocationList: ... + +class Sct: ... +class Certificate: ... +class RevokedCertificate: ... +class CertificateRevocationList: ... +class CertificateSigningRequest: ... diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/bindings/openssl/__init__.py b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/bindings/openssl/__init__.py new file mode 100644 index 00000000..b5093362 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/bindings/openssl/__init__.py @@ -0,0 +1,3 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/bindings/openssl/_conditional.py b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/bindings/openssl/_conditional.py new file mode 100644 index 00000000..8864069c --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/bindings/openssl/_conditional.py @@ -0,0 +1,354 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + + +def cryptography_has_ec2m(): + return [ + "EC_POINT_get_affine_coordinates_GF2m", + ] + + +def cryptography_has_rsa_oaep_md(): + return [ + "EVP_PKEY_CTX_set_rsa_oaep_md", + ] + + +def cryptography_has_rsa_oaep_label(): + return [ + "EVP_PKEY_CTX_set0_rsa_oaep_label", + ] + + +def cryptography_has_ssl3_method(): + return [ + "SSLv3_method", + "SSLv3_client_method", + "SSLv3_server_method", + ] + + +def cryptography_has_110_verification_params(): + return ["X509_CHECK_FLAG_NEVER_CHECK_SUBJECT"] + + +def cryptography_has_set_cert_cb(): + return [ + "SSL_CTX_set_cert_cb", + "SSL_set_cert_cb", + ] + + +def cryptography_has_ssl_st(): + return [ + "SSL_ST_BEFORE", + "SSL_ST_OK", + "SSL_ST_INIT", + "SSL_ST_RENEGOTIATE", + ] + + +def cryptography_has_tls_st(): + return [ + "TLS_ST_BEFORE", + "TLS_ST_OK", + ] + + +def cryptography_has_scrypt(): + return [ + "EVP_PBE_scrypt", + ] + + +def cryptography_has_evp_pkey_dhx(): + return [ + "EVP_PKEY_DHX", + ] + + +def cryptography_has_mem_functions(): + return [ + "Cryptography_CRYPTO_set_mem_functions", + ] + + +def cryptography_has_x509_store_ctx_get_issuer(): + return [ + "X509_STORE_get_get_issuer", + "X509_STORE_set_get_issuer", + ] + + +def cryptography_has_ed448(): + return [ + "EVP_PKEY_ED448", + "NID_ED448", + ] + + +def cryptography_has_ed25519(): + return [ + "NID_ED25519", + "EVP_PKEY_ED25519", + ] + + +def cryptography_has_poly1305(): + return [ + "NID_poly1305", + "EVP_PKEY_POLY1305", + ] + + +def cryptography_has_oneshot_evp_digest_sign_verify(): + return [ + "EVP_DigestSign", + "EVP_DigestVerify", + ] + + +def cryptography_has_evp_digestfinal_xof(): + return [ + "EVP_DigestFinalXOF", + ] + + +def cryptography_has_evp_pkey_get_set_tls_encodedpoint(): + return [ + "EVP_PKEY_get1_tls_encodedpoint", + "EVP_PKEY_set1_tls_encodedpoint", + ] + + +def cryptography_has_fips(): + return [ + "FIPS_mode_set", + "FIPS_mode", + ] + + +def cryptography_has_psk(): + return [ + "SSL_CTX_use_psk_identity_hint", + "SSL_CTX_set_psk_server_callback", + "SSL_CTX_set_psk_client_callback", + ] + + +def cryptography_has_custom_ext(): + return [ + "SSL_CTX_add_client_custom_ext", + "SSL_CTX_add_server_custom_ext", + "SSL_extension_supported", + ] + + +def cryptography_has_openssl_cleanup(): + return [ + "OPENSSL_cleanup", + ] + + +def cryptography_has_tlsv13(): + return [ + "TLS1_3_VERSION", + "SSL_OP_NO_TLSv1_3", + ] + + +def cryptography_has_tlsv13_functions(): + return [ + "SSL_VERIFY_POST_HANDSHAKE", + "SSL_CTX_set_ciphersuites", + "SSL_verify_client_post_handshake", + "SSL_CTX_set_post_handshake_auth", + "SSL_set_post_handshake_auth", + "SSL_SESSION_get_max_early_data", + "SSL_write_early_data", + "SSL_read_early_data", + "SSL_CTX_set_max_early_data", + ] + + +def cryptography_has_keylog(): + return [ + "SSL_CTX_set_keylog_callback", + "SSL_CTX_get_keylog_callback", + ] + + +def cryptography_has_raw_key(): + return [ + "EVP_PKEY_new_raw_private_key", + "EVP_PKEY_new_raw_public_key", + "EVP_PKEY_get_raw_private_key", + "EVP_PKEY_get_raw_public_key", + ] + + +def cryptography_has_engine(): + return [ + "ENGINE_by_id", + "ENGINE_init", + "ENGINE_finish", + "ENGINE_get_default_RAND", + "ENGINE_set_default_RAND", + "ENGINE_unregister_RAND", + "ENGINE_ctrl_cmd", + "ENGINE_free", + "ENGINE_get_name", + "Cryptography_add_osrandom_engine", + "ENGINE_ctrl_cmd_string", + "ENGINE_load_builtin_engines", + "ENGINE_load_private_key", + "ENGINE_load_public_key", + "SSL_CTX_set_client_cert_engine", + ] + + +def cryptography_has_verified_chain(): + return [ + "SSL_get0_verified_chain", + ] + + +def cryptography_has_srtp(): + return [ + "SSL_CTX_set_tlsext_use_srtp", + "SSL_set_tlsext_use_srtp", + "SSL_get_selected_srtp_profile", + ] + + +def cryptography_has_get_proto_version(): + return [ + "SSL_CTX_get_min_proto_version", + "SSL_CTX_get_max_proto_version", + "SSL_get_min_proto_version", + "SSL_get_max_proto_version", + ] + + +def cryptography_has_providers(): + return [ + "OSSL_PROVIDER_load", + "OSSL_PROVIDER_unload", + "ERR_LIB_PROV", + "PROV_R_WRONG_FINAL_BLOCK_LENGTH", + "PROV_R_BAD_DECRYPT", + ] + + +def cryptography_has_op_no_renegotiation(): + return [ + "SSL_OP_NO_RENEGOTIATION", + ] + + +def cryptography_has_dtls_get_data_mtu(): + return [ + "DTLS_get_data_mtu", + ] + + +def cryptography_has_300_fips(): + return [ + "EVP_default_properties_is_fips_enabled", + "EVP_default_properties_enable_fips", + ] + + +def cryptography_has_ssl_cookie(): + return [ + "SSL_OP_COOKIE_EXCHANGE", + "DTLSv1_listen", + "SSL_CTX_set_cookie_generate_cb", + "SSL_CTX_set_cookie_verify_cb", + ] + + +def cryptography_has_pkcs7_funcs(): + return [ + "SMIME_write_PKCS7", + "PEM_write_bio_PKCS7_stream", + "PKCS7_sign_add_signer", + "PKCS7_final", + "PKCS7_verify", + "SMIME_read_PKCS7", + "PKCS7_get0_signers", + ] + + +def cryptography_has_bn_flags(): + return [ + "BN_FLG_CONSTTIME", + "BN_set_flags", + "BN_prime_checks_for_size", + ] + + +def cryptography_has_evp_pkey_dh(): + return [ + "EVP_PKEY_set1_DH", + ] + + +# This is a mapping of +# {condition: function-returning-names-dependent-on-that-condition} so we can +# loop over them and delete unsupported names at runtime. It will be removed +# when cffi supports #if in cdef. We use functions instead of just a dict of +# lists so we can use coverage to measure which are used. +CONDITIONAL_NAMES = { + "Cryptography_HAS_EC2M": cryptography_has_ec2m, + "Cryptography_HAS_RSA_OAEP_MD": cryptography_has_rsa_oaep_md, + "Cryptography_HAS_RSA_OAEP_LABEL": cryptography_has_rsa_oaep_label, + "Cryptography_HAS_SSL3_METHOD": cryptography_has_ssl3_method, + "Cryptography_HAS_110_VERIFICATION_PARAMS": ( + cryptography_has_110_verification_params + ), + "Cryptography_HAS_SET_CERT_CB": cryptography_has_set_cert_cb, + "Cryptography_HAS_SSL_ST": cryptography_has_ssl_st, + "Cryptography_HAS_TLS_ST": cryptography_has_tls_st, + "Cryptography_HAS_SCRYPT": cryptography_has_scrypt, + "Cryptography_HAS_EVP_PKEY_DHX": cryptography_has_evp_pkey_dhx, + "Cryptography_HAS_MEM_FUNCTIONS": cryptography_has_mem_functions, + "Cryptography_HAS_X509_STORE_CTX_GET_ISSUER": ( + cryptography_has_x509_store_ctx_get_issuer + ), + "Cryptography_HAS_ED448": cryptography_has_ed448, + "Cryptography_HAS_ED25519": cryptography_has_ed25519, + "Cryptography_HAS_POLY1305": cryptography_has_poly1305, + "Cryptography_HAS_ONESHOT_EVP_DIGEST_SIGN_VERIFY": ( + cryptography_has_oneshot_evp_digest_sign_verify + ), + "Cryptography_HAS_EVP_PKEY_get_set_tls_encodedpoint": ( + cryptography_has_evp_pkey_get_set_tls_encodedpoint + ), + "Cryptography_HAS_FIPS": cryptography_has_fips, + "Cryptography_HAS_PSK": cryptography_has_psk, + "Cryptography_HAS_CUSTOM_EXT": cryptography_has_custom_ext, + "Cryptography_HAS_OPENSSL_CLEANUP": cryptography_has_openssl_cleanup, + "Cryptography_HAS_TLSv1_3": cryptography_has_tlsv13, + "Cryptography_HAS_TLSv1_3_FUNCTIONS": cryptography_has_tlsv13_functions, + "Cryptography_HAS_KEYLOG": cryptography_has_keylog, + "Cryptography_HAS_RAW_KEY": cryptography_has_raw_key, + "Cryptography_HAS_EVP_DIGESTFINAL_XOF": ( + cryptography_has_evp_digestfinal_xof + ), + "Cryptography_HAS_ENGINE": cryptography_has_engine, + "Cryptography_HAS_VERIFIED_CHAIN": cryptography_has_verified_chain, + "Cryptography_HAS_SRTP": cryptography_has_srtp, + "Cryptography_HAS_GET_PROTO_VERSION": cryptography_has_get_proto_version, + "Cryptography_HAS_PROVIDERS": cryptography_has_providers, + "Cryptography_HAS_OP_NO_RENEGOTIATION": ( + cryptography_has_op_no_renegotiation + ), + "Cryptography_HAS_DTLS_GET_DATA_MTU": cryptography_has_dtls_get_data_mtu, + "Cryptography_HAS_300_FIPS": cryptography_has_300_fips, + "Cryptography_HAS_SSL_COOKIE": cryptography_has_ssl_cookie, + "Cryptography_HAS_PKCS7_FUNCS": cryptography_has_pkcs7_funcs, + "Cryptography_HAS_BN_FLAGS": cryptography_has_bn_flags, + "Cryptography_HAS_EVP_PKEY_DH": cryptography_has_evp_pkey_dh, +} diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/bindings/openssl/binding.py b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/bindings/openssl/binding.py new file mode 100644 index 00000000..92d5b244 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/bindings/openssl/binding.py @@ -0,0 +1,205 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + + +import collections +import threading +import types +import typing + +import cryptography +from cryptography import utils +from cryptography.exceptions import InternalError +from cryptography.hazmat.bindings._openssl import ffi, lib +from cryptography.hazmat.bindings.openssl._conditional import CONDITIONAL_NAMES + +_OpenSSLErrorWithText = collections.namedtuple( + "_OpenSSLErrorWithText", ["code", "lib", "reason", "reason_text"] +) + + +class _OpenSSLError(object): + def __init__(self, code, lib, reason): + self._code = code + self._lib = lib + self._reason = reason + + def _lib_reason_match(self, lib, reason): + return lib == self.lib and reason == self.reason + + code = utils.read_only_property("_code") + lib = utils.read_only_property("_lib") + reason = utils.read_only_property("_reason") + + +def _consume_errors(lib): + errors = [] + while True: + code = lib.ERR_get_error() + if code == 0: + break + + err_lib = lib.ERR_GET_LIB(code) + err_reason = lib.ERR_GET_REASON(code) + + errors.append(_OpenSSLError(code, err_lib, err_reason)) + + return errors + + +def _errors_with_text(errors): + errors_with_text = [] + for err in errors: + buf = ffi.new("char[]", 256) + lib.ERR_error_string_n(err.code, buf, len(buf)) + err_text_reason = ffi.string(buf) + + errors_with_text.append( + _OpenSSLErrorWithText( + err.code, err.lib, err.reason, err_text_reason + ) + ) + + return errors_with_text + + +def _consume_errors_with_text(lib): + return _errors_with_text(_consume_errors(lib)) + + +def _openssl_assert(lib, ok, errors=None): + if not ok: + if errors is None: + errors = _consume_errors(lib) + errors_with_text = _errors_with_text(errors) + + raise InternalError( + "Unknown OpenSSL error. This error is commonly encountered when " + "another library is not cleaning up the OpenSSL error stack. If " + "you are using cryptography with another library that uses " + "OpenSSL try disabling it before reporting a bug. Otherwise " + "please file an issue at https://github.com/pyca/cryptography/" + "issues with information on how to reproduce " + "this. ({0!r})".format(errors_with_text), + errors_with_text, + ) + + +def build_conditional_library(lib, conditional_names): + conditional_lib = types.ModuleType("lib") + conditional_lib._original_lib = lib # type: ignore[attr-defined] + excluded_names = set() + for condition, names_cb in conditional_names.items(): + if not getattr(lib, condition): + excluded_names.update(names_cb()) + + for attr in dir(lib): + if attr not in excluded_names: + setattr(conditional_lib, attr, getattr(lib, attr)) + + return conditional_lib + + +class Binding(object): + """ + OpenSSL API wrapper. + """ + + lib: typing.ClassVar = None + ffi = ffi + _lib_loaded = False + _init_lock = threading.Lock() + _legacy_provider: typing.Any = None + _default_provider: typing.Any = None + + def __init__(self): + self._ensure_ffi_initialized() + + def _enable_fips(self): + # This function enables FIPS mode for OpenSSL 3.0.0 on installs that + # have the FIPS provider installed properly. + _openssl_assert(self.lib, self.lib.CRYPTOGRAPHY_OPENSSL_300_OR_GREATER) + self._base_provider = self.lib.OSSL_PROVIDER_load( + self.ffi.NULL, b"base" + ) + _openssl_assert(self.lib, self._base_provider != self.ffi.NULL) + self.lib._fips_provider = self.lib.OSSL_PROVIDER_load( + self.ffi.NULL, b"fips" + ) + _openssl_assert(self.lib, self.lib._fips_provider != self.ffi.NULL) + + res = self.lib.EVP_default_properties_enable_fips(self.ffi.NULL, 1) + _openssl_assert(self.lib, res == 1) + + @classmethod + def _register_osrandom_engine(cls): + # Clear any errors extant in the queue before we start. In many + # scenarios other things may be interacting with OpenSSL in the same + # process space and it has proven untenable to assume that they will + # reliably clear the error queue. Once we clear it here we will + # error on any subsequent unexpected item in the stack. + cls.lib.ERR_clear_error() + if cls.lib.CRYPTOGRAPHY_NEEDS_OSRANDOM_ENGINE: + result = cls.lib.Cryptography_add_osrandom_engine() + _openssl_assert(cls.lib, result in (1, 2)) + + @classmethod + def _ensure_ffi_initialized(cls): + with cls._init_lock: + if not cls._lib_loaded: + cls.lib = build_conditional_library(lib, CONDITIONAL_NAMES) + cls._lib_loaded = True + # initialize the SSL library + cls.lib.SSL_library_init() + # adds all ciphers/digests for EVP + cls.lib.OpenSSL_add_all_algorithms() + cls._register_osrandom_engine() + # As of OpenSSL 3.0.0 we must register a legacy cipher provider + # to get RC2 (needed for junk asymmetric private key + # serialization), RC4, Blowfish, IDEA, SEED, etc. These things + # are ugly legacy, but we aren't going to get rid of them + # any time soon. + if cls.lib.CRYPTOGRAPHY_OPENSSL_300_OR_GREATER: + cls._legacy_provider = cls.lib.OSSL_PROVIDER_load( + cls.ffi.NULL, b"legacy" + ) + _openssl_assert( + cls.lib, cls._legacy_provider != cls.ffi.NULL + ) + cls._default_provider = cls.lib.OSSL_PROVIDER_load( + cls.ffi.NULL, b"default" + ) + _openssl_assert( + cls.lib, cls._default_provider != cls.ffi.NULL + ) + + @classmethod + def init_static_locks(cls): + cls._ensure_ffi_initialized() + + +def _verify_package_version(version): + # Occasionally we run into situations where the version of the Python + # package does not match the version of the shared object that is loaded. + # This may occur in environments where multiple versions of cryptography + # are installed and available in the python path. To avoid errors cropping + # up later this code checks that the currently imported package and the + # shared object that were loaded have the same version and raise an + # ImportError if they do not + so_package_version = ffi.string(lib.CRYPTOGRAPHY_PACKAGE_VERSION) + if version.encode("ascii") != so_package_version: + raise ImportError( + "The version of cryptography does not match the loaded " + "shared object. This can happen if you have multiple copies of " + "cryptography installed in your Python path. Please try creating " + "a new virtual environment to resolve this issue. " + "Loaded python version: {}, shared object version: {}".format( + version, so_package_version + ) + ) + + +_verify_package_version(cryptography.__version__) + +Binding.init_static_locks() diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/__init__.py b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/__init__.py new file mode 100644 index 00000000..b5093362 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/__init__.py @@ -0,0 +1,3 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/_asymmetric.py b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/_asymmetric.py new file mode 100644 index 00000000..cdadbdef --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/_asymmetric.py @@ -0,0 +1,17 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +import abc + + +# This exists to break an import cycle. It is normally accessible from the +# asymmetric padding module. + + +class AsymmetricPadding(metaclass=abc.ABCMeta): + @abc.abstractproperty + def name(self) -> str: + """ + A string naming this padding (e.g. "PSS", "PKCS1"). + """ diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/_cipheralgorithm.py b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/_cipheralgorithm.py new file mode 100644 index 00000000..04ca5a98 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/_cipheralgorithm.py @@ -0,0 +1,38 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +import abc +import typing + + +# This exists to break an import cycle. It is normally accessible from the +# ciphers module. + + +class CipherAlgorithm(metaclass=abc.ABCMeta): + @abc.abstractproperty + def name(self) -> str: + """ + A string naming this mode (e.g. "AES", "Camellia"). + """ + + @abc.abstractproperty + def key_sizes(self) -> typing.FrozenSet[int]: + """ + Valid key sizes for this algorithm in bits + """ + + @abc.abstractproperty + def key_size(self) -> int: + """ + The size of the key being used as an integer in bits (e.g. 128, 256). + """ + + +class BlockCipherAlgorithm(metaclass=abc.ABCMeta): + @abc.abstractproperty + def block_size(self) -> int: + """ + The size of a block as an integer in bits (e.g. 64, 128). + """ diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/_serialization.py b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/_serialization.py new file mode 100644 index 00000000..160a6b89 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/_serialization.py @@ -0,0 +1,55 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +import abc + +from cryptography import utils + +# This exists to break an import cycle. These classes are normally accessible +# from the serialization module. + + +class Encoding(utils.Enum): + PEM = "PEM" + DER = "DER" + OpenSSH = "OpenSSH" + Raw = "Raw" + X962 = "ANSI X9.62" + SMIME = "S/MIME" + + +class PrivateFormat(utils.Enum): + PKCS8 = "PKCS8" + TraditionalOpenSSL = "TraditionalOpenSSL" + Raw = "Raw" + OpenSSH = "OpenSSH" + + +class PublicFormat(utils.Enum): + SubjectPublicKeyInfo = "X.509 subjectPublicKeyInfo with PKCS#1" + PKCS1 = "Raw PKCS#1" + OpenSSH = "OpenSSH" + Raw = "Raw" + CompressedPoint = "X9.62 Compressed Point" + UncompressedPoint = "X9.62 Uncompressed Point" + + +class ParameterFormat(utils.Enum): + PKCS3 = "PKCS3" + + +class KeySerializationEncryption(metaclass=abc.ABCMeta): + pass + + +class BestAvailableEncryption(KeySerializationEncryption): + def __init__(self, password: bytes): + if not isinstance(password, bytes) or len(password) == 0: + raise ValueError("Password must be 1 or more bytes.") + + self.password = password + + +class NoEncryption(KeySerializationEncryption): + pass diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/asymmetric/__init__.py b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/asymmetric/__init__.py new file mode 100644 index 00000000..f4953efc --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/asymmetric/__init__.py @@ -0,0 +1,35 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + + +import abc + + +class AsymmetricSignatureContext(metaclass=abc.ABCMeta): + @abc.abstractmethod + def update(self, data: bytes) -> None: + """ + Processes the provided bytes and returns nothing. + """ + + @abc.abstractmethod + def finalize(self) -> bytes: + """ + Returns the signature as bytes. + """ + + +class AsymmetricVerificationContext(metaclass=abc.ABCMeta): + @abc.abstractmethod + def update(self, data: bytes) -> None: + """ + Processes the provided bytes and returns nothing. + """ + + @abc.abstractmethod + def verify(self) -> None: + """ + Raises an exception if the bytes provided to update do not match the + signature or the signature does not match the public key. + """ diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/asymmetric/dh.py b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/asymmetric/dh.py new file mode 100644 index 00000000..009c761b --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/asymmetric/dh.py @@ -0,0 +1,241 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + + +import abc +import typing + +from cryptography.hazmat.primitives import serialization + + +_MIN_MODULUS_SIZE = 512 + + +def generate_parameters( + generator: int, key_size: int, backend: typing.Any = None +) -> "DHParameters": + from cryptography.hazmat.backends.openssl.backend import backend as ossl + + return ossl.generate_dh_parameters(generator, key_size) + + +class DHParameterNumbers(object): + def __init__(self, p: int, g: int, q: typing.Optional[int] = None) -> None: + if not isinstance(p, int) or not isinstance(g, int): + raise TypeError("p and g must be integers") + if q is not None and not isinstance(q, int): + raise TypeError("q must be integer or None") + + if g < 2: + raise ValueError("DH generator must be 2 or greater") + + if p.bit_length() < _MIN_MODULUS_SIZE: + raise ValueError( + "p (modulus) must be at least {}-bit".format(_MIN_MODULUS_SIZE) + ) + + self._p = p + self._g = g + self._q = q + + def __eq__(self, other): + if not isinstance(other, DHParameterNumbers): + return NotImplemented + + return ( + self._p == other._p and self._g == other._g and self._q == other._q + ) + + def __ne__(self, other): + return not self == other + + def parameters(self, backend: typing.Any = None) -> "DHParameters": + from cryptography.hazmat.backends.openssl.backend import ( + backend as ossl, + ) + + return ossl.load_dh_parameter_numbers(self) + + p = property(lambda self: self._p) + g = property(lambda self: self._g) + q = property(lambda self: self._q) + + +class DHPublicNumbers(object): + def __init__(self, y: int, parameter_numbers: DHParameterNumbers) -> None: + if not isinstance(y, int): + raise TypeError("y must be an integer.") + + if not isinstance(parameter_numbers, DHParameterNumbers): + raise TypeError( + "parameters must be an instance of DHParameterNumbers." + ) + + self._y = y + self._parameter_numbers = parameter_numbers + + def __eq__(self, other): + if not isinstance(other, DHPublicNumbers): + return NotImplemented + + return ( + self._y == other._y + and self._parameter_numbers == other._parameter_numbers + ) + + def __ne__(self, other): + return not self == other + + def public_key(self, backend: typing.Any = None) -> "DHPublicKey": + from cryptography.hazmat.backends.openssl.backend import ( + backend as ossl, + ) + + return ossl.load_dh_public_numbers(self) + + y = property(lambda self: self._y) + parameter_numbers = property(lambda self: self._parameter_numbers) + + +class DHPrivateNumbers(object): + def __init__(self, x: int, public_numbers: DHPublicNumbers) -> None: + if not isinstance(x, int): + raise TypeError("x must be an integer.") + + if not isinstance(public_numbers, DHPublicNumbers): + raise TypeError( + "public_numbers must be an instance of " "DHPublicNumbers." + ) + + self._x = x + self._public_numbers = public_numbers + + def __eq__(self, other): + if not isinstance(other, DHPrivateNumbers): + return NotImplemented + + return ( + self._x == other._x + and self._public_numbers == other._public_numbers + ) + + def __ne__(self, other): + return not self == other + + def private_key(self, backend: typing.Any = None) -> "DHPrivateKey": + from cryptography.hazmat.backends.openssl.backend import ( + backend as ossl, + ) + + return ossl.load_dh_private_numbers(self) + + public_numbers = property(lambda self: self._public_numbers) + x = property(lambda self: self._x) + + +class DHParameters(metaclass=abc.ABCMeta): + @abc.abstractmethod + def generate_private_key(self) -> "DHPrivateKey": + """ + Generates and returns a DHPrivateKey. + """ + + @abc.abstractmethod + def parameter_bytes( + self, + encoding: "serialization.Encoding", + format: "serialization.ParameterFormat", + ) -> bytes: + """ + Returns the parameters serialized as bytes. + """ + + @abc.abstractmethod + def parameter_numbers(self) -> DHParameterNumbers: + """ + Returns a DHParameterNumbers. + """ + + +DHParametersWithSerialization = DHParameters + + +class DHPublicKey(metaclass=abc.ABCMeta): + @abc.abstractproperty + def key_size(self) -> int: + """ + The bit length of the prime modulus. + """ + + @abc.abstractmethod + def parameters(self) -> DHParameters: + """ + The DHParameters object associated with this public key. + """ + + @abc.abstractmethod + def public_numbers(self) -> DHPublicNumbers: + """ + Returns a DHPublicNumbers. + """ + + @abc.abstractmethod + def public_bytes( + self, + encoding: "serialization.Encoding", + format: "serialization.PublicFormat", + ) -> bytes: + """ + Returns the key serialized as bytes. + """ + + +DHPublicKeyWithSerialization = DHPublicKey + + +class DHPrivateKey(metaclass=abc.ABCMeta): + @abc.abstractproperty + def key_size(self) -> int: + """ + The bit length of the prime modulus. + """ + + @abc.abstractmethod + def public_key(self) -> DHPublicKey: + """ + The DHPublicKey associated with this private key. + """ + + @abc.abstractmethod + def parameters(self) -> DHParameters: + """ + The DHParameters object associated with this private key. + """ + + @abc.abstractmethod + def exchange(self, peer_public_key: DHPublicKey) -> bytes: + """ + Given peer's DHPublicKey, carry out the key exchange and + return shared key as bytes. + """ + + @abc.abstractmethod + def private_numbers(self) -> DHPrivateNumbers: + """ + Returns a DHPrivateNumbers. + """ + + @abc.abstractmethod + def private_bytes( + self, + encoding: "serialization.Encoding", + format: "serialization.PrivateFormat", + encryption_algorithm: "serialization.KeySerializationEncryption", + ) -> bytes: + """ + Returns the key serialized as bytes. + """ + + +DHPrivateKeyWithSerialization = DHPrivateKey diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/asymmetric/dsa.py b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/asymmetric/dsa.py new file mode 100644 index 00000000..26f8e758 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/asymmetric/dsa.py @@ -0,0 +1,300 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + + +import abc +import typing + +from cryptography.hazmat.primitives import _serialization, hashes +from cryptography.hazmat.primitives.asymmetric import ( + AsymmetricSignatureContext, + AsymmetricVerificationContext, + utils as asym_utils, +) + + +class DSAParameters(metaclass=abc.ABCMeta): + @abc.abstractmethod + def generate_private_key(self) -> "DSAPrivateKey": + """ + Generates and returns a DSAPrivateKey. + """ + + @abc.abstractmethod + def parameter_numbers(self) -> "DSAParameterNumbers": + """ + Returns a DSAParameterNumbers. + """ + + +DSAParametersWithNumbers = DSAParameters + + +class DSAPrivateKey(metaclass=abc.ABCMeta): + @abc.abstractproperty + def key_size(self) -> int: + """ + The bit length of the prime modulus. + """ + + @abc.abstractmethod + def public_key(self) -> "DSAPublicKey": + """ + The DSAPublicKey associated with this private key. + """ + + @abc.abstractmethod + def parameters(self) -> DSAParameters: + """ + The DSAParameters object associated with this private key. + """ + + @abc.abstractmethod + def signer( + self, + signature_algorithm: hashes.HashAlgorithm, + ) -> AsymmetricSignatureContext: + """ + Returns an AsymmetricSignatureContext used for signing data. + """ + + @abc.abstractmethod + def sign( + self, + data: bytes, + algorithm: typing.Union[asym_utils.Prehashed, hashes.HashAlgorithm], + ) -> bytes: + """ + Signs the data + """ + + @abc.abstractmethod + def private_numbers(self) -> "DSAPrivateNumbers": + """ + Returns a DSAPrivateNumbers. + """ + + @abc.abstractmethod + def private_bytes( + self, + encoding: _serialization.Encoding, + format: _serialization.PrivateFormat, + encryption_algorithm: _serialization.KeySerializationEncryption, + ) -> bytes: + """ + Returns the key serialized as bytes. + """ + + +DSAPrivateKeyWithSerialization = DSAPrivateKey + + +class DSAPublicKey(metaclass=abc.ABCMeta): + @abc.abstractproperty + def key_size(self) -> int: + """ + The bit length of the prime modulus. + """ + + @abc.abstractmethod + def parameters(self) -> DSAParameters: + """ + The DSAParameters object associated with this public key. + """ + + @abc.abstractmethod + def verifier( + self, + signature: bytes, + signature_algorithm: hashes.HashAlgorithm, + ) -> AsymmetricVerificationContext: + """ + Returns an AsymmetricVerificationContext used for signing data. + """ + + @abc.abstractmethod + def public_numbers(self) -> "DSAPublicNumbers": + """ + Returns a DSAPublicNumbers. + """ + + @abc.abstractmethod + def public_bytes( + self, + encoding: _serialization.Encoding, + format: _serialization.PublicFormat, + ) -> bytes: + """ + Returns the key serialized as bytes. + """ + + @abc.abstractmethod + def verify( + self, + signature: bytes, + data: bytes, + algorithm: typing.Union[asym_utils.Prehashed, hashes.HashAlgorithm], + ) -> None: + """ + Verifies the signature of the data. + """ + + +DSAPublicKeyWithSerialization = DSAPublicKey + + +class DSAParameterNumbers(object): + def __init__(self, p: int, q: int, g: int): + if ( + not isinstance(p, int) + or not isinstance(q, int) + or not isinstance(g, int) + ): + raise TypeError( + "DSAParameterNumbers p, q, and g arguments must be integers." + ) + + self._p = p + self._q = q + self._g = g + + p = property(lambda self: self._p) + q = property(lambda self: self._q) + g = property(lambda self: self._g) + + def parameters(self, backend: typing.Any = None) -> DSAParameters: + from cryptography.hazmat.backends.openssl.backend import ( + backend as ossl, + ) + + return ossl.load_dsa_parameter_numbers(self) + + def __eq__(self, other): + if not isinstance(other, DSAParameterNumbers): + return NotImplemented + + return self.p == other.p and self.q == other.q and self.g == other.g + + def __ne__(self, other): + return not self == other + + def __repr__(self): + return ( + "<DSAParameterNumbers(p={self.p}, q={self.q}, " + "g={self.g})>".format(self=self) + ) + + +class DSAPublicNumbers(object): + def __init__(self, y: int, parameter_numbers: DSAParameterNumbers): + if not isinstance(y, int): + raise TypeError("DSAPublicNumbers y argument must be an integer.") + + if not isinstance(parameter_numbers, DSAParameterNumbers): + raise TypeError( + "parameter_numbers must be a DSAParameterNumbers instance." + ) + + self._y = y + self._parameter_numbers = parameter_numbers + + y = property(lambda self: self._y) + parameter_numbers = property(lambda self: self._parameter_numbers) + + def public_key(self, backend: typing.Any = None) -> DSAPublicKey: + from cryptography.hazmat.backends.openssl.backend import ( + backend as ossl, + ) + + return ossl.load_dsa_public_numbers(self) + + def __eq__(self, other): + if not isinstance(other, DSAPublicNumbers): + return NotImplemented + + return ( + self.y == other.y + and self.parameter_numbers == other.parameter_numbers + ) + + def __ne__(self, other): + return not self == other + + def __repr__(self): + return ( + "<DSAPublicNumbers(y={self.y}, " + "parameter_numbers={self.parameter_numbers})>".format(self=self) + ) + + +class DSAPrivateNumbers(object): + def __init__(self, x: int, public_numbers: DSAPublicNumbers): + if not isinstance(x, int): + raise TypeError("DSAPrivateNumbers x argument must be an integer.") + + if not isinstance(public_numbers, DSAPublicNumbers): + raise TypeError( + "public_numbers must be a DSAPublicNumbers instance." + ) + self._public_numbers = public_numbers + self._x = x + + x = property(lambda self: self._x) + public_numbers = property(lambda self: self._public_numbers) + + def private_key(self, backend: typing.Any = None) -> DSAPrivateKey: + from cryptography.hazmat.backends.openssl.backend import ( + backend as ossl, + ) + + return ossl.load_dsa_private_numbers(self) + + def __eq__(self, other): + if not isinstance(other, DSAPrivateNumbers): + return NotImplemented + + return ( + self.x == other.x and self.public_numbers == other.public_numbers + ) + + def __ne__(self, other): + return not self == other + + +def generate_parameters( + key_size: int, backend: typing.Any = None +) -> DSAParameters: + from cryptography.hazmat.backends.openssl.backend import backend as ossl + + return ossl.generate_dsa_parameters(key_size) + + +def generate_private_key( + key_size: int, backend: typing.Any = None +) -> DSAPrivateKey: + from cryptography.hazmat.backends.openssl.backend import backend as ossl + + return ossl.generate_dsa_private_key_and_parameters(key_size) + + +def _check_dsa_parameters(parameters: DSAParameterNumbers) -> None: + if parameters.p.bit_length() not in [1024, 2048, 3072, 4096]: + raise ValueError( + "p must be exactly 1024, 2048, 3072, or 4096 bits long" + ) + if parameters.q.bit_length() not in [160, 224, 256]: + raise ValueError("q must be exactly 160, 224, or 256 bits long") + + if not (1 < parameters.g < parameters.p): + raise ValueError("g, p don't satisfy 1 < g < p.") + + +def _check_dsa_private_numbers(numbers: DSAPrivateNumbers) -> None: + parameters = numbers.public_numbers.parameter_numbers + _check_dsa_parameters(parameters) + if numbers.x <= 0 or numbers.x >= parameters.q: + raise ValueError("x must be > 0 and < q.") + + if numbers.public_numbers.y != pow(parameters.g, numbers.x, parameters.p): + raise ValueError("y must be equal to (g ** x % p).") diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/asymmetric/ec.py b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/asymmetric/ec.py new file mode 100644 index 00000000..e4f29728 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/asymmetric/ec.py @@ -0,0 +1,537 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + + +import abc +import typing +import warnings + +from cryptography import utils +from cryptography.hazmat._oid import ObjectIdentifier +from cryptography.hazmat.primitives import _serialization, hashes +from cryptography.hazmat.primitives.asymmetric import ( + AsymmetricSignatureContext, + AsymmetricVerificationContext, + utils as asym_utils, +) + + +class EllipticCurveOID(object): + SECP192R1 = ObjectIdentifier("1.2.840.10045.3.1.1") + SECP224R1 = ObjectIdentifier("1.3.132.0.33") + SECP256K1 = ObjectIdentifier("1.3.132.0.10") + SECP256R1 = ObjectIdentifier("1.2.840.10045.3.1.7") + SECP384R1 = ObjectIdentifier("1.3.132.0.34") + SECP521R1 = ObjectIdentifier("1.3.132.0.35") + BRAINPOOLP256R1 = ObjectIdentifier("1.3.36.3.3.2.8.1.1.7") + BRAINPOOLP384R1 = ObjectIdentifier("1.3.36.3.3.2.8.1.1.11") + BRAINPOOLP512R1 = ObjectIdentifier("1.3.36.3.3.2.8.1.1.13") + SECT163K1 = ObjectIdentifier("1.3.132.0.1") + SECT163R2 = ObjectIdentifier("1.3.132.0.15") + SECT233K1 = ObjectIdentifier("1.3.132.0.26") + SECT233R1 = ObjectIdentifier("1.3.132.0.27") + SECT283K1 = ObjectIdentifier("1.3.132.0.16") + SECT283R1 = ObjectIdentifier("1.3.132.0.17") + SECT409K1 = ObjectIdentifier("1.3.132.0.36") + SECT409R1 = ObjectIdentifier("1.3.132.0.37") + SECT571K1 = ObjectIdentifier("1.3.132.0.38") + SECT571R1 = ObjectIdentifier("1.3.132.0.39") + + +class EllipticCurve(metaclass=abc.ABCMeta): + @abc.abstractproperty + def name(self) -> str: + """ + The name of the curve. e.g. secp256r1. + """ + + @abc.abstractproperty + def key_size(self) -> int: + """ + Bit size of a secret scalar for the curve. + """ + + +class EllipticCurveSignatureAlgorithm(metaclass=abc.ABCMeta): + @abc.abstractproperty + def algorithm( + self, + ) -> typing.Union[asym_utils.Prehashed, hashes.HashAlgorithm]: + """ + The digest algorithm used with this signature. + """ + + +class EllipticCurvePrivateKey(metaclass=abc.ABCMeta): + @abc.abstractmethod + def signer( + self, + signature_algorithm: EllipticCurveSignatureAlgorithm, + ) -> AsymmetricSignatureContext: + """ + Returns an AsymmetricSignatureContext used for signing data. + """ + + @abc.abstractmethod + def exchange( + self, algorithm: "ECDH", peer_public_key: "EllipticCurvePublicKey" + ) -> bytes: + """ + Performs a key exchange operation using the provided algorithm with the + provided peer's public key. + """ + + @abc.abstractmethod + def public_key(self) -> "EllipticCurvePublicKey": + """ + The EllipticCurvePublicKey for this private key. + """ + + @abc.abstractproperty + def curve(self) -> EllipticCurve: + """ + The EllipticCurve that this key is on. + """ + + @abc.abstractproperty + def key_size(self) -> int: + """ + Bit size of a secret scalar for the curve. + """ + + @abc.abstractmethod + def sign( + self, + data: bytes, + signature_algorithm: EllipticCurveSignatureAlgorithm, + ) -> bytes: + """ + Signs the data + """ + + @abc.abstractmethod + def private_numbers(self) -> "EllipticCurvePrivateNumbers": + """ + Returns an EllipticCurvePrivateNumbers. + """ + + @abc.abstractmethod + def private_bytes( + self, + encoding: _serialization.Encoding, + format: _serialization.PrivateFormat, + encryption_algorithm: _serialization.KeySerializationEncryption, + ) -> bytes: + """ + Returns the key serialized as bytes. + """ + + +EllipticCurvePrivateKeyWithSerialization = EllipticCurvePrivateKey + + +class EllipticCurvePublicKey(metaclass=abc.ABCMeta): + @abc.abstractmethod + def verifier( + self, + signature: bytes, + signature_algorithm: EllipticCurveSignatureAlgorithm, + ) -> AsymmetricVerificationContext: + """ + Returns an AsymmetricVerificationContext used for signing data. + """ + + @abc.abstractproperty + def curve(self) -> EllipticCurve: + """ + The EllipticCurve that this key is on. + """ + + @abc.abstractproperty + def key_size(self) -> int: + """ + Bit size of a secret scalar for the curve. + """ + + @abc.abstractmethod + def public_numbers(self) -> "EllipticCurvePublicNumbers": + """ + Returns an EllipticCurvePublicNumbers. + """ + + @abc.abstractmethod + def public_bytes( + self, + encoding: _serialization.Encoding, + format: _serialization.PublicFormat, + ) -> bytes: + """ + Returns the key serialized as bytes. + """ + + @abc.abstractmethod + def verify( + self, + signature: bytes, + data: bytes, + signature_algorithm: EllipticCurveSignatureAlgorithm, + ) -> None: + """ + Verifies the signature of the data. + """ + + @classmethod + def from_encoded_point( + cls, curve: EllipticCurve, data: bytes + ) -> "EllipticCurvePublicKey": + utils._check_bytes("data", data) + + if not isinstance(curve, EllipticCurve): + raise TypeError("curve must be an EllipticCurve instance") + + if len(data) == 0: + raise ValueError("data must not be an empty byte string") + + if data[0] not in [0x02, 0x03, 0x04]: + raise ValueError("Unsupported elliptic curve point type") + + from cryptography.hazmat.backends.openssl.backend import backend + + return backend.load_elliptic_curve_public_bytes(curve, data) + + +EllipticCurvePublicKeyWithSerialization = EllipticCurvePublicKey + + +class SECT571R1(EllipticCurve): + name = "sect571r1" + key_size = 570 + + +class SECT409R1(EllipticCurve): + name = "sect409r1" + key_size = 409 + + +class SECT283R1(EllipticCurve): + name = "sect283r1" + key_size = 283 + + +class SECT233R1(EllipticCurve): + name = "sect233r1" + key_size = 233 + + +class SECT163R2(EllipticCurve): + name = "sect163r2" + key_size = 163 + + +class SECT571K1(EllipticCurve): + name = "sect571k1" + key_size = 571 + + +class SECT409K1(EllipticCurve): + name = "sect409k1" + key_size = 409 + + +class SECT283K1(EllipticCurve): + name = "sect283k1" + key_size = 283 + + +class SECT233K1(EllipticCurve): + name = "sect233k1" + key_size = 233 + + +class SECT163K1(EllipticCurve): + name = "sect163k1" + key_size = 163 + + +class SECP521R1(EllipticCurve): + name = "secp521r1" + key_size = 521 + + +class SECP384R1(EllipticCurve): + name = "secp384r1" + key_size = 384 + + +class SECP256R1(EllipticCurve): + name = "secp256r1" + key_size = 256 + + +class SECP256K1(EllipticCurve): + name = "secp256k1" + key_size = 256 + + +class SECP224R1(EllipticCurve): + name = "secp224r1" + key_size = 224 + + +class SECP192R1(EllipticCurve): + name = "secp192r1" + key_size = 192 + + +class BrainpoolP256R1(EllipticCurve): + name = "brainpoolP256r1" + key_size = 256 + + +class BrainpoolP384R1(EllipticCurve): + name = "brainpoolP384r1" + key_size = 384 + + +class BrainpoolP512R1(EllipticCurve): + name = "brainpoolP512r1" + key_size = 512 + + +_CURVE_TYPES: typing.Dict[str, typing.Type[EllipticCurve]] = { + "prime192v1": SECP192R1, + "prime256v1": SECP256R1, + "secp192r1": SECP192R1, + "secp224r1": SECP224R1, + "secp256r1": SECP256R1, + "secp384r1": SECP384R1, + "secp521r1": SECP521R1, + "secp256k1": SECP256K1, + "sect163k1": SECT163K1, + "sect233k1": SECT233K1, + "sect283k1": SECT283K1, + "sect409k1": SECT409K1, + "sect571k1": SECT571K1, + "sect163r2": SECT163R2, + "sect233r1": SECT233R1, + "sect283r1": SECT283R1, + "sect409r1": SECT409R1, + "sect571r1": SECT571R1, + "brainpoolP256r1": BrainpoolP256R1, + "brainpoolP384r1": BrainpoolP384R1, + "brainpoolP512r1": BrainpoolP512R1, +} + + +class ECDSA(EllipticCurveSignatureAlgorithm): + def __init__( + self, + algorithm: typing.Union[asym_utils.Prehashed, hashes.HashAlgorithm], + ): + self._algorithm = algorithm + + @property + def algorithm( + self, + ) -> typing.Union[asym_utils.Prehashed, hashes.HashAlgorithm]: + return self._algorithm + + +def generate_private_key( + curve: EllipticCurve, backend: typing.Any = None +) -> EllipticCurvePrivateKey: + from cryptography.hazmat.backends.openssl.backend import backend as ossl + + return ossl.generate_elliptic_curve_private_key(curve) + + +def derive_private_key( + private_value: int, + curve: EllipticCurve, + backend: typing.Any = None, +) -> EllipticCurvePrivateKey: + from cryptography.hazmat.backends.openssl.backend import backend as ossl + + if not isinstance(private_value, int): + raise TypeError("private_value must be an integer type.") + + if private_value <= 0: + raise ValueError("private_value must be a positive integer.") + + if not isinstance(curve, EllipticCurve): + raise TypeError("curve must provide the EllipticCurve interface.") + + return ossl.derive_elliptic_curve_private_key(private_value, curve) + + +class EllipticCurvePublicNumbers(object): + def __init__(self, x: int, y: int, curve: EllipticCurve): + if not isinstance(x, int) or not isinstance(y, int): + raise TypeError("x and y must be integers.") + + if not isinstance(curve, EllipticCurve): + raise TypeError("curve must provide the EllipticCurve interface.") + + self._y = y + self._x = x + self._curve = curve + + def public_key(self, backend: typing.Any = None) -> EllipticCurvePublicKey: + from cryptography.hazmat.backends.openssl.backend import ( + backend as ossl, + ) + + return ossl.load_elliptic_curve_public_numbers(self) + + def encode_point(self) -> bytes: + warnings.warn( + "encode_point has been deprecated on EllipticCurvePublicNumbers" + " and will be removed in a future version. Please use " + "EllipticCurvePublicKey.public_bytes to obtain both " + "compressed and uncompressed point encoding.", + utils.PersistentlyDeprecated2019, + stacklevel=2, + ) + # key_size is in bits. Convert to bytes and round up + byte_length = (self.curve.key_size + 7) // 8 + return ( + b"\x04" + + utils.int_to_bytes(self.x, byte_length) + + utils.int_to_bytes(self.y, byte_length) + ) + + @classmethod + def from_encoded_point( + cls, curve: EllipticCurve, data: bytes + ) -> "EllipticCurvePublicNumbers": + if not isinstance(curve, EllipticCurve): + raise TypeError("curve must be an EllipticCurve instance") + + warnings.warn( + "Support for unsafe construction of public numbers from " + "encoded data will be removed in a future version. " + "Please use EllipticCurvePublicKey.from_encoded_point", + utils.PersistentlyDeprecated2019, + stacklevel=2, + ) + + if data.startswith(b"\x04"): + # key_size is in bits. Convert to bytes and round up + byte_length = (curve.key_size + 7) // 8 + if len(data) == 2 * byte_length + 1: + x = int.from_bytes(data[1 : byte_length + 1], "big") + y = int.from_bytes(data[byte_length + 1 :], "big") + return cls(x, y, curve) + else: + raise ValueError("Invalid elliptic curve point data length") + else: + raise ValueError("Unsupported elliptic curve point type") + + curve = property(lambda self: self._curve) + x = property(lambda self: self._x) + y = property(lambda self: self._y) + + def __eq__(self, other): + if not isinstance(other, EllipticCurvePublicNumbers): + return NotImplemented + + return ( + self.x == other.x + and self.y == other.y + and self.curve.name == other.curve.name + and self.curve.key_size == other.curve.key_size + ) + + def __ne__(self, other): + return not self == other + + def __hash__(self): + return hash((self.x, self.y, self.curve.name, self.curve.key_size)) + + def __repr__(self): + return ( + "<EllipticCurvePublicNumbers(curve={0.curve.name}, x={0.x}, " + "y={0.y}>".format(self) + ) + + +class EllipticCurvePrivateNumbers(object): + def __init__( + self, private_value: int, public_numbers: EllipticCurvePublicNumbers + ): + if not isinstance(private_value, int): + raise TypeError("private_value must be an integer.") + + if not isinstance(public_numbers, EllipticCurvePublicNumbers): + raise TypeError( + "public_numbers must be an EllipticCurvePublicNumbers " + "instance." + ) + + self._private_value = private_value + self._public_numbers = public_numbers + + def private_key( + self, backend: typing.Any = None + ) -> EllipticCurvePrivateKey: + from cryptography.hazmat.backends.openssl.backend import ( + backend as ossl, + ) + + return ossl.load_elliptic_curve_private_numbers(self) + + private_value = property(lambda self: self._private_value) + public_numbers = property(lambda self: self._public_numbers) + + def __eq__(self, other): + if not isinstance(other, EllipticCurvePrivateNumbers): + return NotImplemented + + return ( + self.private_value == other.private_value + and self.public_numbers == other.public_numbers + ) + + def __ne__(self, other): + return not self == other + + def __hash__(self): + return hash((self.private_value, self.public_numbers)) + + +class ECDH(object): + pass + + +_OID_TO_CURVE = { + EllipticCurveOID.SECP192R1: SECP192R1, + EllipticCurveOID.SECP224R1: SECP224R1, + EllipticCurveOID.SECP256K1: SECP256K1, + EllipticCurveOID.SECP256R1: SECP256R1, + EllipticCurveOID.SECP384R1: SECP384R1, + EllipticCurveOID.SECP521R1: SECP521R1, + EllipticCurveOID.BRAINPOOLP256R1: BrainpoolP256R1, + EllipticCurveOID.BRAINPOOLP384R1: BrainpoolP384R1, + EllipticCurveOID.BRAINPOOLP512R1: BrainpoolP512R1, + EllipticCurveOID.SECT163K1: SECT163K1, + EllipticCurveOID.SECT163R2: SECT163R2, + EllipticCurveOID.SECT233K1: SECT233K1, + EllipticCurveOID.SECT233R1: SECT233R1, + EllipticCurveOID.SECT283K1: SECT283K1, + EllipticCurveOID.SECT283R1: SECT283R1, + EllipticCurveOID.SECT409K1: SECT409K1, + EllipticCurveOID.SECT409R1: SECT409R1, + EllipticCurveOID.SECT571K1: SECT571K1, + EllipticCurveOID.SECT571R1: SECT571R1, +} + + +def get_curve_for_oid(oid: ObjectIdentifier) -> typing.Type[EllipticCurve]: + try: + return _OID_TO_CURVE[oid] + except KeyError: + raise LookupError( + "The provided object identifier has no matching elliptic " + "curve class" + ) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/asymmetric/ed25519.py b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/asymmetric/ed25519.py new file mode 100644 index 00000000..43277028 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/asymmetric/ed25519.py @@ -0,0 +1,92 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + + +import abc + +from cryptography.exceptions import UnsupportedAlgorithm, _Reasons +from cryptography.hazmat.primitives import _serialization + + +_ED25519_KEY_SIZE = 32 +_ED25519_SIG_SIZE = 64 + + +class Ed25519PublicKey(metaclass=abc.ABCMeta): + @classmethod + def from_public_bytes(cls, data: bytes) -> "Ed25519PublicKey": + from cryptography.hazmat.backends.openssl.backend import backend + + if not backend.ed25519_supported(): + raise UnsupportedAlgorithm( + "ed25519 is not supported by this version of OpenSSL.", + _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM, + ) + + return backend.ed25519_load_public_bytes(data) + + @abc.abstractmethod + def public_bytes( + self, + encoding: _serialization.Encoding, + format: _serialization.PublicFormat, + ) -> bytes: + """ + The serialized bytes of the public key. + """ + + @abc.abstractmethod + def verify(self, signature: bytes, data: bytes) -> None: + """ + Verify the signature. + """ + + +class Ed25519PrivateKey(metaclass=abc.ABCMeta): + @classmethod + def generate(cls) -> "Ed25519PrivateKey": + from cryptography.hazmat.backends.openssl.backend import backend + + if not backend.ed25519_supported(): + raise UnsupportedAlgorithm( + "ed25519 is not supported by this version of OpenSSL.", + _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM, + ) + + return backend.ed25519_generate_key() + + @classmethod + def from_private_bytes(cls, data: bytes) -> "Ed25519PrivateKey": + from cryptography.hazmat.backends.openssl.backend import backend + + if not backend.ed25519_supported(): + raise UnsupportedAlgorithm( + "ed25519 is not supported by this version of OpenSSL.", + _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM, + ) + + return backend.ed25519_load_private_bytes(data) + + @abc.abstractmethod + def public_key(self) -> Ed25519PublicKey: + """ + The Ed25519PublicKey derived from the private key. + """ + + @abc.abstractmethod + def private_bytes( + self, + encoding: _serialization.Encoding, + format: _serialization.PrivateFormat, + encryption_algorithm: _serialization.KeySerializationEncryption, + ) -> bytes: + """ + The serialized bytes of the private key. + """ + + @abc.abstractmethod + def sign(self, data: bytes) -> bytes: + """ + Signs the data. + """ diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/asymmetric/ed448.py b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/asymmetric/ed448.py new file mode 100644 index 00000000..27bc27c6 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/asymmetric/ed448.py @@ -0,0 +1,87 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + + +import abc + +from cryptography.exceptions import UnsupportedAlgorithm, _Reasons +from cryptography.hazmat.primitives import _serialization + + +class Ed448PublicKey(metaclass=abc.ABCMeta): + @classmethod + def from_public_bytes(cls, data: bytes) -> "Ed448PublicKey": + from cryptography.hazmat.backends.openssl.backend import backend + + if not backend.ed448_supported(): + raise UnsupportedAlgorithm( + "ed448 is not supported by this version of OpenSSL.", + _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM, + ) + + return backend.ed448_load_public_bytes(data) + + @abc.abstractmethod + def public_bytes( + self, + encoding: _serialization.Encoding, + format: _serialization.PublicFormat, + ) -> bytes: + """ + The serialized bytes of the public key. + """ + + @abc.abstractmethod + def verify(self, signature: bytes, data: bytes) -> None: + """ + Verify the signature. + """ + + +class Ed448PrivateKey(metaclass=abc.ABCMeta): + @classmethod + def generate(cls) -> "Ed448PrivateKey": + from cryptography.hazmat.backends.openssl.backend import backend + + if not backend.ed448_supported(): + raise UnsupportedAlgorithm( + "ed448 is not supported by this version of OpenSSL.", + _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM, + ) + return backend.ed448_generate_key() + + @classmethod + def from_private_bytes(cls, data: bytes) -> "Ed448PrivateKey": + from cryptography.hazmat.backends.openssl.backend import backend + + if not backend.ed448_supported(): + raise UnsupportedAlgorithm( + "ed448 is not supported by this version of OpenSSL.", + _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM, + ) + + return backend.ed448_load_private_bytes(data) + + @abc.abstractmethod + def public_key(self) -> Ed448PublicKey: + """ + The Ed448PublicKey derived from the private key. + """ + + @abc.abstractmethod + def sign(self, data: bytes) -> bytes: + """ + Signs the data. + """ + + @abc.abstractmethod + def private_bytes( + self, + encoding: _serialization.Encoding, + format: _serialization.PrivateFormat, + encryption_algorithm: _serialization.KeySerializationEncryption, + ) -> bytes: + """ + The serialized bytes of the private key. + """ diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/asymmetric/padding.py b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/asymmetric/padding.py new file mode 100644 index 00000000..a97c5db0 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/asymmetric/padding.py @@ -0,0 +1,75 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + + +import typing + +from cryptography.hazmat.primitives import hashes +from cryptography.hazmat.primitives._asymmetric import ( + AsymmetricPadding as AsymmetricPadding, +) +from cryptography.hazmat.primitives.asymmetric import rsa + + +class PKCS1v15(AsymmetricPadding): + name = "EMSA-PKCS1-v1_5" + + +class PSS(AsymmetricPadding): + MAX_LENGTH = object() + name = "EMSA-PSS" + + def __init__(self, mgf, salt_length): + self._mgf = mgf + + if ( + not isinstance(salt_length, int) + and salt_length is not self.MAX_LENGTH + ): + raise TypeError("salt_length must be an integer.") + + if salt_length is not self.MAX_LENGTH and salt_length < 0: + raise ValueError("salt_length must be zero or greater.") + + self._salt_length = salt_length + + +class OAEP(AsymmetricPadding): + name = "EME-OAEP" + + def __init__( + self, + mgf: "MGF1", + algorithm: hashes.HashAlgorithm, + label: typing.Optional[bytes], + ): + if not isinstance(algorithm, hashes.HashAlgorithm): + raise TypeError("Expected instance of hashes.HashAlgorithm.") + + self._mgf = mgf + self._algorithm = algorithm + self._label = label + + +class MGF1(object): + MAX_LENGTH = object() + + def __init__(self, algorithm: hashes.HashAlgorithm): + if not isinstance(algorithm, hashes.HashAlgorithm): + raise TypeError("Expected instance of hashes.HashAlgorithm.") + + self._algorithm = algorithm + + +def calculate_max_pss_salt_length( + key: typing.Union["rsa.RSAPrivateKey", "rsa.RSAPublicKey"], + hash_algorithm: hashes.HashAlgorithm, +) -> int: + if not isinstance(key, (rsa.RSAPrivateKey, rsa.RSAPublicKey)): + raise TypeError("key must be an RSA public or private key") + # bit length - 1 per RFC 3447 + emlen = (key.key_size + 6) // 8 + salt_length = emlen - hash_algorithm.digest_size - 2 + assert salt_length >= 0 + return salt_length diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/asymmetric/rsa.py b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/asymmetric/rsa.py new file mode 100644 index 00000000..20cf4e01 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/asymmetric/rsa.py @@ -0,0 +1,427 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + + +import abc +import typing +from math import gcd + +from cryptography.hazmat.primitives import _serialization, hashes +from cryptography.hazmat.primitives._asymmetric import AsymmetricPadding +from cryptography.hazmat.primitives.asymmetric import ( + AsymmetricSignatureContext, + AsymmetricVerificationContext, + utils as asym_utils, +) + + +class RSAPrivateKey(metaclass=abc.ABCMeta): + @abc.abstractmethod + def signer( + self, padding: AsymmetricPadding, algorithm: hashes.HashAlgorithm + ) -> AsymmetricSignatureContext: + """ + Returns an AsymmetricSignatureContext used for signing data. + """ + + @abc.abstractmethod + def decrypt(self, ciphertext: bytes, padding: AsymmetricPadding) -> bytes: + """ + Decrypts the provided ciphertext. + """ + + @abc.abstractproperty + def key_size(self) -> int: + """ + The bit length of the public modulus. + """ + + @abc.abstractmethod + def public_key(self) -> "RSAPublicKey": + """ + The RSAPublicKey associated with this private key. + """ + + @abc.abstractmethod + def sign( + self, + data: bytes, + padding: AsymmetricPadding, + algorithm: typing.Union[asym_utils.Prehashed, hashes.HashAlgorithm], + ) -> bytes: + """ + Signs the data. + """ + + @abc.abstractmethod + def private_numbers(self) -> "RSAPrivateNumbers": + """ + Returns an RSAPrivateNumbers. + """ + + @abc.abstractmethod + def private_bytes( + self, + encoding: _serialization.Encoding, + format: _serialization.PrivateFormat, + encryption_algorithm: _serialization.KeySerializationEncryption, + ) -> bytes: + """ + Returns the key serialized as bytes. + """ + + +RSAPrivateKeyWithSerialization = RSAPrivateKey + + +class RSAPublicKey(metaclass=abc.ABCMeta): + @abc.abstractmethod + def verifier( + self, + signature: bytes, + padding: AsymmetricPadding, + algorithm: hashes.HashAlgorithm, + ) -> AsymmetricVerificationContext: + """ + Returns an AsymmetricVerificationContext used for verifying signatures. + """ + + @abc.abstractmethod + def encrypt(self, plaintext: bytes, padding: AsymmetricPadding) -> bytes: + """ + Encrypts the given plaintext. + """ + + @abc.abstractproperty + def key_size(self) -> int: + """ + The bit length of the public modulus. + """ + + @abc.abstractmethod + def public_numbers(self) -> "RSAPublicNumbers": + """ + Returns an RSAPublicNumbers + """ + + @abc.abstractmethod + def public_bytes( + self, + encoding: _serialization.Encoding, + format: _serialization.PublicFormat, + ) -> bytes: + """ + Returns the key serialized as bytes. + """ + + @abc.abstractmethod + def verify( + self, + signature: bytes, + data: bytes, + padding: AsymmetricPadding, + algorithm: typing.Union[asym_utils.Prehashed, hashes.HashAlgorithm], + ) -> None: + """ + Verifies the signature of the data. + """ + + @abc.abstractmethod + def recover_data_from_signature( + self, + signature: bytes, + padding: AsymmetricPadding, + algorithm: typing.Optional[hashes.HashAlgorithm], + ) -> bytes: + """ + Recovers the original data from the signature. + """ + + +RSAPublicKeyWithSerialization = RSAPublicKey + + +def generate_private_key( + public_exponent: int, + key_size: int, + backend: typing.Any = None, +) -> RSAPrivateKey: + from cryptography.hazmat.backends.openssl.backend import backend as ossl + + _verify_rsa_parameters(public_exponent, key_size) + return ossl.generate_rsa_private_key(public_exponent, key_size) + + +def _verify_rsa_parameters(public_exponent: int, key_size: int) -> None: + if public_exponent not in (3, 65537): + raise ValueError( + "public_exponent must be either 3 (for legacy compatibility) or " + "65537. Almost everyone should choose 65537 here!" + ) + + if key_size < 512: + raise ValueError("key_size must be at least 512-bits.") + + +def _check_private_key_components( + p: int, + q: int, + private_exponent: int, + dmp1: int, + dmq1: int, + iqmp: int, + public_exponent: int, + modulus: int, +) -> None: + if modulus < 3: + raise ValueError("modulus must be >= 3.") + + if p >= modulus: + raise ValueError("p must be < modulus.") + + if q >= modulus: + raise ValueError("q must be < modulus.") + + if dmp1 >= modulus: + raise ValueError("dmp1 must be < modulus.") + + if dmq1 >= modulus: + raise ValueError("dmq1 must be < modulus.") + + if iqmp >= modulus: + raise ValueError("iqmp must be < modulus.") + + if private_exponent >= modulus: + raise ValueError("private_exponent must be < modulus.") + + if public_exponent < 3 or public_exponent >= modulus: + raise ValueError("public_exponent must be >= 3 and < modulus.") + + if public_exponent & 1 == 0: + raise ValueError("public_exponent must be odd.") + + if dmp1 & 1 == 0: + raise ValueError("dmp1 must be odd.") + + if dmq1 & 1 == 0: + raise ValueError("dmq1 must be odd.") + + if p * q != modulus: + raise ValueError("p*q must equal modulus.") + + +def _check_public_key_components(e: int, n: int) -> None: + if n < 3: + raise ValueError("n must be >= 3.") + + if e < 3 or e >= n: + raise ValueError("e must be >= 3 and < n.") + + if e & 1 == 0: + raise ValueError("e must be odd.") + + +def _modinv(e: int, m: int) -> int: + """ + Modular Multiplicative Inverse. Returns x such that: (x*e) mod m == 1 + """ + x1, x2 = 1, 0 + a, b = e, m + while b > 0: + q, r = divmod(a, b) + xn = x1 - q * x2 + a, b, x1, x2 = b, r, x2, xn + return x1 % m + + +def rsa_crt_iqmp(p: int, q: int) -> int: + """ + Compute the CRT (q ** -1) % p value from RSA primes p and q. + """ + return _modinv(q, p) + + +def rsa_crt_dmp1(private_exponent: int, p: int) -> int: + """ + Compute the CRT private_exponent % (p - 1) value from the RSA + private_exponent (d) and p. + """ + return private_exponent % (p - 1) + + +def rsa_crt_dmq1(private_exponent: int, q: int) -> int: + """ + Compute the CRT private_exponent % (q - 1) value from the RSA + private_exponent (d) and q. + """ + return private_exponent % (q - 1) + + +# Controls the number of iterations rsa_recover_prime_factors will perform +# to obtain the prime factors. Each iteration increments by 2 so the actual +# maximum attempts is half this number. +_MAX_RECOVERY_ATTEMPTS = 1000 + + +def rsa_recover_prime_factors( + n: int, e: int, d: int +) -> typing.Tuple[int, int]: + """ + Compute factors p and q from the private exponent d. We assume that n has + no more than two factors. This function is adapted from code in PyCrypto. + """ + # See 8.2.2(i) in Handbook of Applied Cryptography. + ktot = d * e - 1 + # The quantity d*e-1 is a multiple of phi(n), even, + # and can be represented as t*2^s. + t = ktot + while t % 2 == 0: + t = t // 2 + # Cycle through all multiplicative inverses in Zn. + # The algorithm is non-deterministic, but there is a 50% chance + # any candidate a leads to successful factoring. + # See "Digitalized Signatures and Public Key Functions as Intractable + # as Factorization", M. Rabin, 1979 + spotted = False + a = 2 + while not spotted and a < _MAX_RECOVERY_ATTEMPTS: + k = t + # Cycle through all values a^{t*2^i}=a^k + while k < ktot: + cand = pow(a, k, n) + # Check if a^k is a non-trivial root of unity (mod n) + if cand != 1 and cand != (n - 1) and pow(cand, 2, n) == 1: + # We have found a number such that (cand-1)(cand+1)=0 (mod n). + # Either of the terms divides n. + p = gcd(cand + 1, n) + spotted = True + break + k *= 2 + # This value was not any good... let's try another! + a += 2 + if not spotted: + raise ValueError("Unable to compute factors p and q from exponent d.") + # Found ! + q, r = divmod(n, p) + assert r == 0 + p, q = sorted((p, q), reverse=True) + return (p, q) + + +class RSAPrivateNumbers(object): + def __init__( + self, + p: int, + q: int, + d: int, + dmp1: int, + dmq1: int, + iqmp: int, + public_numbers: "RSAPublicNumbers", + ): + if ( + not isinstance(p, int) + or not isinstance(q, int) + or not isinstance(d, int) + or not isinstance(dmp1, int) + or not isinstance(dmq1, int) + or not isinstance(iqmp, int) + ): + raise TypeError( + "RSAPrivateNumbers p, q, d, dmp1, dmq1, iqmp arguments must" + " all be an integers." + ) + + if not isinstance(public_numbers, RSAPublicNumbers): + raise TypeError( + "RSAPrivateNumbers public_numbers must be an RSAPublicNumbers" + " instance." + ) + + self._p = p + self._q = q + self._d = d + self._dmp1 = dmp1 + self._dmq1 = dmq1 + self._iqmp = iqmp + self._public_numbers = public_numbers + + p = property(lambda self: self._p) + q = property(lambda self: self._q) + d = property(lambda self: self._d) + dmp1 = property(lambda self: self._dmp1) + dmq1 = property(lambda self: self._dmq1) + iqmp = property(lambda self: self._iqmp) + public_numbers = property(lambda self: self._public_numbers) + + def private_key(self, backend: typing.Any = None) -> RSAPrivateKey: + from cryptography.hazmat.backends.openssl.backend import ( + backend as ossl, + ) + + return ossl.load_rsa_private_numbers(self) + + def __eq__(self, other): + if not isinstance(other, RSAPrivateNumbers): + return NotImplemented + + return ( + self.p == other.p + and self.q == other.q + and self.d == other.d + and self.dmp1 == other.dmp1 + and self.dmq1 == other.dmq1 + and self.iqmp == other.iqmp + and self.public_numbers == other.public_numbers + ) + + def __ne__(self, other): + return not self == other + + def __hash__(self): + return hash( + ( + self.p, + self.q, + self.d, + self.dmp1, + self.dmq1, + self.iqmp, + self.public_numbers, + ) + ) + + +class RSAPublicNumbers(object): + def __init__(self, e: int, n: int): + if not isinstance(e, int) or not isinstance(n, int): + raise TypeError("RSAPublicNumbers arguments must be integers.") + + self._e = e + self._n = n + + e = property(lambda self: self._e) + n = property(lambda self: self._n) + + def public_key(self, backend: typing.Any = None) -> RSAPublicKey: + from cryptography.hazmat.backends.openssl.backend import ( + backend as ossl, + ) + + return ossl.load_rsa_public_numbers(self) + + def __repr__(self): + return "<RSAPublicNumbers(e={0.e}, n={0.n})>".format(self) + + def __eq__(self, other): + if not isinstance(other, RSAPublicNumbers): + return NotImplemented + + return self.e == other.e and self.n == other.n + + def __ne__(self, other): + return not self == other + + def __hash__(self): + return hash((self.e, self.n)) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/asymmetric/types.py b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/asymmetric/types.py new file mode 100644 index 00000000..ccf339f3 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/asymmetric/types.py @@ -0,0 +1,40 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +import typing + +from cryptography.hazmat.primitives.asymmetric import ( + dsa, + ec, + ed25519, + ed448, + rsa, + x25519, + x448, +) + + +PUBLIC_KEY_TYPES = typing.Union[ + dsa.DSAPublicKey, + rsa.RSAPublicKey, + ec.EllipticCurvePublicKey, + ed25519.Ed25519PublicKey, + ed448.Ed448PublicKey, +] +PRIVATE_KEY_TYPES = typing.Union[ + ed25519.Ed25519PrivateKey, + ed448.Ed448PrivateKey, + rsa.RSAPrivateKey, + dsa.DSAPrivateKey, + ec.EllipticCurvePrivateKey, +] +CERTIFICATE_PUBLIC_KEY_TYPES = typing.Union[ + dsa.DSAPublicKey, + rsa.RSAPublicKey, + ec.EllipticCurvePublicKey, + ed25519.Ed25519PublicKey, + ed448.Ed448PublicKey, + x25519.X25519PublicKey, + x448.X448PublicKey, +] diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/asymmetric/utils.py b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/asymmetric/utils.py new file mode 100644 index 00000000..b01a0dbc --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/asymmetric/utils.py @@ -0,0 +1,22 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + + +from cryptography.hazmat.bindings._rust import asn1 +from cryptography.hazmat.primitives import hashes + + +decode_dss_signature = asn1.decode_dss_signature +encode_dss_signature = asn1.encode_dss_signature + + +class Prehashed(object): + def __init__(self, algorithm: hashes.HashAlgorithm): + if not isinstance(algorithm, hashes.HashAlgorithm): + raise TypeError("Expected instance of HashAlgorithm.") + + self._algorithm = algorithm + self._digest_size = algorithm.digest_size + + digest_size = property(lambda self: self._digest_size) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/asymmetric/x25519.py b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/asymmetric/x25519.py new file mode 100644 index 00000000..690af78c --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/asymmetric/x25519.py @@ -0,0 +1,81 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + + +import abc + +from cryptography.exceptions import UnsupportedAlgorithm, _Reasons +from cryptography.hazmat.primitives import _serialization + + +class X25519PublicKey(metaclass=abc.ABCMeta): + @classmethod + def from_public_bytes(cls, data: bytes) -> "X25519PublicKey": + from cryptography.hazmat.backends.openssl.backend import backend + + if not backend.x25519_supported(): + raise UnsupportedAlgorithm( + "X25519 is not supported by this version of OpenSSL.", + _Reasons.UNSUPPORTED_EXCHANGE_ALGORITHM, + ) + + return backend.x25519_load_public_bytes(data) + + @abc.abstractmethod + def public_bytes( + self, + encoding: _serialization.Encoding, + format: _serialization.PublicFormat, + ) -> bytes: + """ + The serialized bytes of the public key. + """ + + +class X25519PrivateKey(metaclass=abc.ABCMeta): + @classmethod + def generate(cls) -> "X25519PrivateKey": + from cryptography.hazmat.backends.openssl.backend import backend + + if not backend.x25519_supported(): + raise UnsupportedAlgorithm( + "X25519 is not supported by this version of OpenSSL.", + _Reasons.UNSUPPORTED_EXCHANGE_ALGORITHM, + ) + return backend.x25519_generate_key() + + @classmethod + def from_private_bytes(cls, data: bytes) -> "X25519PrivateKey": + from cryptography.hazmat.backends.openssl.backend import backend + + if not backend.x25519_supported(): + raise UnsupportedAlgorithm( + "X25519 is not supported by this version of OpenSSL.", + _Reasons.UNSUPPORTED_EXCHANGE_ALGORITHM, + ) + + return backend.x25519_load_private_bytes(data) + + @abc.abstractmethod + def public_key(self) -> X25519PublicKey: + """ + The serialized bytes of the public key. + """ + + @abc.abstractmethod + def private_bytes( + self, + encoding: _serialization.Encoding, + format: _serialization.PrivateFormat, + encryption_algorithm: _serialization.KeySerializationEncryption, + ) -> bytes: + """ + The serialized bytes of the private key. + """ + + @abc.abstractmethod + def exchange(self, peer_public_key: X25519PublicKey) -> bytes: + """ + Performs a key exchange operation using the provided peer's public key. + """ diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/asymmetric/x448.py b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/asymmetric/x448.py new file mode 100644 index 00000000..7f71c272 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/asymmetric/x448.py @@ -0,0 +1,81 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + + +import abc + +from cryptography.exceptions import UnsupportedAlgorithm, _Reasons +from cryptography.hazmat.primitives import _serialization + + +class X448PublicKey(metaclass=abc.ABCMeta): + @classmethod + def from_public_bytes(cls, data: bytes) -> "X448PublicKey": + from cryptography.hazmat.backends.openssl.backend import backend + + if not backend.x448_supported(): + raise UnsupportedAlgorithm( + "X448 is not supported by this version of OpenSSL.", + _Reasons.UNSUPPORTED_EXCHANGE_ALGORITHM, + ) + + return backend.x448_load_public_bytes(data) + + @abc.abstractmethod + def public_bytes( + self, + encoding: _serialization.Encoding, + format: _serialization.PublicFormat, + ) -> bytes: + """ + The serialized bytes of the public key. + """ + + +class X448PrivateKey(metaclass=abc.ABCMeta): + @classmethod + def generate(cls) -> "X448PrivateKey": + from cryptography.hazmat.backends.openssl.backend import backend + + if not backend.x448_supported(): + raise UnsupportedAlgorithm( + "X448 is not supported by this version of OpenSSL.", + _Reasons.UNSUPPORTED_EXCHANGE_ALGORITHM, + ) + return backend.x448_generate_key() + + @classmethod + def from_private_bytes(cls, data: bytes) -> "X448PrivateKey": + from cryptography.hazmat.backends.openssl.backend import backend + + if not backend.x448_supported(): + raise UnsupportedAlgorithm( + "X448 is not supported by this version of OpenSSL.", + _Reasons.UNSUPPORTED_EXCHANGE_ALGORITHM, + ) + + return backend.x448_load_private_bytes(data) + + @abc.abstractmethod + def public_key(self) -> X448PublicKey: + """ + The serialized bytes of the public key. + """ + + @abc.abstractmethod + def private_bytes( + self, + encoding: _serialization.Encoding, + format: _serialization.PrivateFormat, + encryption_algorithm: _serialization.KeySerializationEncryption, + ) -> bytes: + """ + The serialized bytes of the private key. + """ + + @abc.abstractmethod + def exchange(self, peer_public_key: X448PublicKey) -> bytes: + """ + Performs a key exchange operation using the provided peer's public key. + """ diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/ciphers/__init__.py b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/ciphers/__init__.py new file mode 100644 index 00000000..874dbd45 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/ciphers/__init__.py @@ -0,0 +1,27 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + + +from cryptography.hazmat.primitives._cipheralgorithm import ( + BlockCipherAlgorithm, + CipherAlgorithm, +) +from cryptography.hazmat.primitives.ciphers.base import ( + AEADCipherContext, + AEADDecryptionContext, + AEADEncryptionContext, + Cipher, + CipherContext, +) + + +__all__ = [ + "Cipher", + "CipherAlgorithm", + "BlockCipherAlgorithm", + "CipherContext", + "AEADCipherContext", + "AEADDecryptionContext", + "AEADEncryptionContext", +] diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/ciphers/aead.py b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/ciphers/aead.py new file mode 100644 index 00000000..aa386207 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/ciphers/aead.py @@ -0,0 +1,291 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + + +import os +import typing + +from cryptography import exceptions, utils +from cryptography.hazmat.backends.openssl import aead +from cryptography.hazmat.backends.openssl.backend import backend + + +class ChaCha20Poly1305(object): + _MAX_SIZE = 2 ** 32 + + def __init__(self, key: bytes): + if not backend.aead_cipher_supported(self): + raise exceptions.UnsupportedAlgorithm( + "ChaCha20Poly1305 is not supported by this version of OpenSSL", + exceptions._Reasons.UNSUPPORTED_CIPHER, + ) + utils._check_byteslike("key", key) + + if len(key) != 32: + raise ValueError("ChaCha20Poly1305 key must be 32 bytes.") + + self._key = key + + @classmethod + def generate_key(cls) -> bytes: + return os.urandom(32) + + def encrypt( + self, + nonce: bytes, + data: bytes, + associated_data: typing.Optional[bytes], + ) -> bytes: + if associated_data is None: + associated_data = b"" + + if len(data) > self._MAX_SIZE or len(associated_data) > self._MAX_SIZE: + # This is OverflowError to match what cffi would raise + raise OverflowError( + "Data or associated data too long. Max 2**32 bytes" + ) + + self._check_params(nonce, data, associated_data) + return aead._encrypt(backend, self, nonce, data, associated_data, 16) + + def decrypt( + self, + nonce: bytes, + data: bytes, + associated_data: typing.Optional[bytes], + ) -> bytes: + if associated_data is None: + associated_data = b"" + + self._check_params(nonce, data, associated_data) + return aead._decrypt(backend, self, nonce, data, associated_data, 16) + + def _check_params( + self, + nonce: bytes, + data: bytes, + associated_data: bytes, + ) -> None: + utils._check_byteslike("nonce", nonce) + utils._check_bytes("data", data) + utils._check_bytes("associated_data", associated_data) + if len(nonce) != 12: + raise ValueError("Nonce must be 12 bytes") + + +class AESCCM(object): + _MAX_SIZE = 2 ** 32 + + def __init__(self, key: bytes, tag_length: int = 16): + utils._check_byteslike("key", key) + if len(key) not in (16, 24, 32): + raise ValueError("AESCCM key must be 128, 192, or 256 bits.") + + self._key = key + if not isinstance(tag_length, int): + raise TypeError("tag_length must be an integer") + + if tag_length not in (4, 6, 8, 10, 12, 14, 16): + raise ValueError("Invalid tag_length") + + self._tag_length = tag_length + + if not backend.aead_cipher_supported(self): + raise exceptions.UnsupportedAlgorithm( + "AESCCM is not supported by this version of OpenSSL", + exceptions._Reasons.UNSUPPORTED_CIPHER, + ) + + @classmethod + def generate_key(cls, bit_length: int) -> bytes: + if not isinstance(bit_length, int): + raise TypeError("bit_length must be an integer") + + if bit_length not in (128, 192, 256): + raise ValueError("bit_length must be 128, 192, or 256") + + return os.urandom(bit_length // 8) + + def encrypt( + self, + nonce: bytes, + data: bytes, + associated_data: typing.Optional[bytes], + ) -> bytes: + if associated_data is None: + associated_data = b"" + + if len(data) > self._MAX_SIZE or len(associated_data) > self._MAX_SIZE: + # This is OverflowError to match what cffi would raise + raise OverflowError( + "Data or associated data too long. Max 2**32 bytes" + ) + + self._check_params(nonce, data, associated_data) + self._validate_lengths(nonce, len(data)) + return aead._encrypt( + backend, self, nonce, data, associated_data, self._tag_length + ) + + def decrypt( + self, + nonce: bytes, + data: bytes, + associated_data: typing.Optional[bytes], + ) -> bytes: + if associated_data is None: + associated_data = b"" + + self._check_params(nonce, data, associated_data) + return aead._decrypt( + backend, self, nonce, data, associated_data, self._tag_length + ) + + def _validate_lengths(self, nonce: bytes, data_len: int) -> None: + # For information about computing this, see + # https://tools.ietf.org/html/rfc3610#section-2.1 + l_val = 15 - len(nonce) + if 2 ** (8 * l_val) < data_len: + raise ValueError("Data too long for nonce") + + def _check_params( + self, nonce: bytes, data: bytes, associated_data: bytes + ) -> None: + utils._check_byteslike("nonce", nonce) + utils._check_bytes("data", data) + utils._check_bytes("associated_data", associated_data) + if not 7 <= len(nonce) <= 13: + raise ValueError("Nonce must be between 7 and 13 bytes") + + +class AESGCM(object): + _MAX_SIZE = 2 ** 32 + + def __init__(self, key: bytes): + utils._check_byteslike("key", key) + if len(key) not in (16, 24, 32): + raise ValueError("AESGCM key must be 128, 192, or 256 bits.") + + self._key = key + + @classmethod + def generate_key(cls, bit_length: int) -> bytes: + if not isinstance(bit_length, int): + raise TypeError("bit_length must be an integer") + + if bit_length not in (128, 192, 256): + raise ValueError("bit_length must be 128, 192, or 256") + + return os.urandom(bit_length // 8) + + def encrypt( + self, + nonce: bytes, + data: bytes, + associated_data: typing.Optional[bytes], + ) -> bytes: + if associated_data is None: + associated_data = b"" + + if len(data) > self._MAX_SIZE or len(associated_data) > self._MAX_SIZE: + # This is OverflowError to match what cffi would raise + raise OverflowError( + "Data or associated data too long. Max 2**32 bytes" + ) + + self._check_params(nonce, data, associated_data) + return aead._encrypt(backend, self, nonce, data, associated_data, 16) + + def decrypt( + self, + nonce: bytes, + data: bytes, + associated_data: typing.Optional[bytes], + ) -> bytes: + if associated_data is None: + associated_data = b"" + + self._check_params(nonce, data, associated_data) + return aead._decrypt(backend, self, nonce, data, associated_data, 16) + + def _check_params( + self, + nonce: bytes, + data: bytes, + associated_data: bytes, + ) -> None: + utils._check_byteslike("nonce", nonce) + utils._check_bytes("data", data) + utils._check_bytes("associated_data", associated_data) + if len(nonce) < 8 or len(nonce) > 128: + raise ValueError("Nonce must be between 8 and 128 bytes") + + +class AESOCB3(object): + _MAX_SIZE = 2 ** 32 + + def __init__(self, key: bytes): + utils._check_byteslike("key", key) + if len(key) not in (16, 24, 32): + raise ValueError("AESOCB3 key must be 128, 192, or 256 bits.") + + self._key = key + + if not backend.aead_cipher_supported(self): + raise exceptions.UnsupportedAlgorithm( + "OCB3 is not supported by this version of OpenSSL", + exceptions._Reasons.UNSUPPORTED_CIPHER, + ) + + @classmethod + def generate_key(cls, bit_length: int) -> bytes: + if not isinstance(bit_length, int): + raise TypeError("bit_length must be an integer") + + if bit_length not in (128, 192, 256): + raise ValueError("bit_length must be 128, 192, or 256") + + return os.urandom(bit_length // 8) + + def encrypt( + self, + nonce: bytes, + data: bytes, + associated_data: typing.Optional[bytes], + ) -> bytes: + if associated_data is None: + associated_data = b"" + + if len(data) > self._MAX_SIZE or len(associated_data) > self._MAX_SIZE: + # This is OverflowError to match what cffi would raise + raise OverflowError( + "Data or associated data too long. Max 2**32 bytes" + ) + + self._check_params(nonce, data, associated_data) + return aead._encrypt(backend, self, nonce, data, associated_data, 16) + + def decrypt( + self, + nonce: bytes, + data: bytes, + associated_data: typing.Optional[bytes], + ) -> bytes: + if associated_data is None: + associated_data = b"" + + self._check_params(nonce, data, associated_data) + return aead._decrypt(backend, self, nonce, data, associated_data, 16) + + def _check_params( + self, + nonce: bytes, + data: bytes, + associated_data: bytes, + ) -> None: + utils._check_byteslike("nonce", nonce) + utils._check_bytes("data", data) + utils._check_bytes("associated_data", associated_data) + if len(nonce) != 12: + raise ValueError("Nonce must be 96-bits (12 bytes)") diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/ciphers/algorithms.py b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/ciphers/algorithms.py new file mode 100644 index 00000000..ba3c968e --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/ciphers/algorithms.py @@ -0,0 +1,168 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + + +from cryptography import utils +from cryptography.hazmat.primitives.ciphers import ( + BlockCipherAlgorithm, + CipherAlgorithm, +) +from cryptography.hazmat.primitives.ciphers.modes import ModeWithNonce + + +def _verify_key_size(algorithm: CipherAlgorithm, key: bytes) -> bytes: + # Verify that the key is instance of bytes + utils._check_byteslike("key", key) + + # Verify that the key size matches the expected key size + if len(key) * 8 not in algorithm.key_sizes: + raise ValueError( + "Invalid key size ({}) for {}.".format( + len(key) * 8, algorithm.name + ) + ) + return key + + +class AES(CipherAlgorithm, BlockCipherAlgorithm): + name = "AES" + block_size = 128 + # 512 added to support AES-256-XTS, which uses 512-bit keys + key_sizes = frozenset([128, 192, 256, 512]) + + def __init__(self, key: bytes): + self.key = _verify_key_size(self, key) + + @property + def key_size(self) -> int: + return len(self.key) * 8 + + +class Camellia(CipherAlgorithm, BlockCipherAlgorithm): + name = "camellia" + block_size = 128 + key_sizes = frozenset([128, 192, 256]) + + def __init__(self, key: bytes): + self.key = _verify_key_size(self, key) + + @property + def key_size(self) -> int: + return len(self.key) * 8 + + +class TripleDES(CipherAlgorithm, BlockCipherAlgorithm): + name = "3DES" + block_size = 64 + key_sizes = frozenset([64, 128, 192]) + + def __init__(self, key: bytes): + if len(key) == 8: + key += key + key + elif len(key) == 16: + key += key[:8] + self.key = _verify_key_size(self, key) + + @property + def key_size(self) -> int: + return len(self.key) * 8 + + +class Blowfish(CipherAlgorithm, BlockCipherAlgorithm): + name = "Blowfish" + block_size = 64 + key_sizes = frozenset(range(32, 449, 8)) + + def __init__(self, key: bytes): + self.key = _verify_key_size(self, key) + + @property + def key_size(self) -> int: + return len(self.key) * 8 + + +class CAST5(CipherAlgorithm, BlockCipherAlgorithm): + name = "CAST5" + block_size = 64 + key_sizes = frozenset(range(40, 129, 8)) + + def __init__(self, key: bytes): + self.key = _verify_key_size(self, key) + + @property + def key_size(self) -> int: + return len(self.key) * 8 + + +class ARC4(CipherAlgorithm): + name = "RC4" + key_sizes = frozenset([40, 56, 64, 80, 128, 160, 192, 256]) + + def __init__(self, key: bytes): + self.key = _verify_key_size(self, key) + + @property + def key_size(self) -> int: + return len(self.key) * 8 + + +class IDEA(CipherAlgorithm): + name = "IDEA" + block_size = 64 + key_sizes = frozenset([128]) + + def __init__(self, key: bytes): + self.key = _verify_key_size(self, key) + + @property + def key_size(self) -> int: + return len(self.key) * 8 + + +class SEED(CipherAlgorithm, BlockCipherAlgorithm): + name = "SEED" + block_size = 128 + key_sizes = frozenset([128]) + + def __init__(self, key: bytes): + self.key = _verify_key_size(self, key) + + @property + def key_size(self) -> int: + return len(self.key) * 8 + + +class ChaCha20(CipherAlgorithm, ModeWithNonce): + name = "ChaCha20" + key_sizes = frozenset([256]) + + def __init__(self, key: bytes, nonce: bytes): + self.key = _verify_key_size(self, key) + utils._check_byteslike("nonce", nonce) + + if len(nonce) != 16: + raise ValueError("nonce must be 128-bits (16 bytes)") + + self._nonce = nonce + + @property + def nonce(self) -> bytes: + return self._nonce + + @property + def key_size(self) -> int: + return len(self.key) * 8 + + +class SM4(CipherAlgorithm, BlockCipherAlgorithm): + name = "SM4" + block_size = 128 + key_sizes = frozenset([128]) + + def __init__(self, key: bytes): + self.key = _verify_key_size(self, key) + + @property + def key_size(self) -> int: + return len(self.key) * 8 diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/ciphers/base.py b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/ciphers/base.py new file mode 100644 index 00000000..9b80421c --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/ciphers/base.py @@ -0,0 +1,211 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + + +import abc +import typing + +from cryptography import utils +from cryptography.exceptions import ( + AlreadyFinalized, + AlreadyUpdated, + NotYetFinalized, +) +from cryptography.hazmat.primitives._cipheralgorithm import CipherAlgorithm +from cryptography.hazmat.primitives.ciphers import modes + + +class CipherContext(metaclass=abc.ABCMeta): + @abc.abstractmethod + def update(self, data: bytes) -> bytes: + """ + Processes the provided bytes through the cipher and returns the results + as bytes. + """ + + @abc.abstractmethod + def update_into(self, data: bytes, buf) -> int: + """ + Processes the provided bytes and writes the resulting data into the + provided buffer. Returns the number of bytes written. + """ + + @abc.abstractmethod + def finalize(self) -> bytes: + """ + Returns the results of processing the final block as bytes. + """ + + +class AEADCipherContext(metaclass=abc.ABCMeta): + @abc.abstractmethod + def authenticate_additional_data(self, data: bytes) -> None: + """ + Authenticates the provided bytes. + """ + + +class AEADDecryptionContext(metaclass=abc.ABCMeta): + @abc.abstractmethod + def finalize_with_tag(self, tag: bytes) -> bytes: + """ + Returns the results of processing the final block as bytes and allows + delayed passing of the authentication tag. + """ + + +class AEADEncryptionContext(metaclass=abc.ABCMeta): + @abc.abstractproperty + def tag(self) -> bytes: + """ + Returns tag bytes. This is only available after encryption is + finalized. + """ + + +class Cipher(object): + def __init__( + self, + algorithm: CipherAlgorithm, + mode: typing.Optional[modes.Mode], + backend: typing.Any = None, + ): + + if not isinstance(algorithm, CipherAlgorithm): + raise TypeError("Expected interface of CipherAlgorithm.") + + if mode is not None: + mode.validate_for_algorithm(algorithm) + + self.algorithm = algorithm + self.mode = mode + + def encryptor(self): + if isinstance(self.mode, modes.ModeWithAuthenticationTag): + if self.mode.tag is not None: + raise ValueError( + "Authentication tag must be None when encrypting." + ) + from cryptography.hazmat.backends.openssl.backend import backend + + ctx = backend.create_symmetric_encryption_ctx( + self.algorithm, self.mode + ) + return self._wrap_ctx(ctx, encrypt=True) + + def decryptor(self): + from cryptography.hazmat.backends.openssl.backend import backend + + ctx = backend.create_symmetric_decryption_ctx( + self.algorithm, self.mode + ) + return self._wrap_ctx(ctx, encrypt=False) + + def _wrap_ctx(self, ctx, encrypt): + if isinstance(self.mode, modes.ModeWithAuthenticationTag): + if encrypt: + return _AEADEncryptionContext(ctx) + else: + return _AEADCipherContext(ctx) + else: + return _CipherContext(ctx) + + +@utils.register_interface(CipherContext) +class _CipherContext(object): + def __init__(self, ctx): + self._ctx = ctx + + def update(self, data: bytes) -> bytes: + if self._ctx is None: + raise AlreadyFinalized("Context was already finalized.") + return self._ctx.update(data) + + def update_into(self, data: bytes, buf) -> int: + if self._ctx is None: + raise AlreadyFinalized("Context was already finalized.") + return self._ctx.update_into(data, buf) + + def finalize(self) -> bytes: + if self._ctx is None: + raise AlreadyFinalized("Context was already finalized.") + data = self._ctx.finalize() + self._ctx = None + return data + + +@utils.register_interface(AEADCipherContext) +@utils.register_interface(CipherContext) +@utils.register_interface(AEADDecryptionContext) +class _AEADCipherContext(object): + def __init__(self, ctx): + self._ctx = ctx + self._bytes_processed = 0 + self._aad_bytes_processed = 0 + self._tag = None + self._updated = False + + def _check_limit(self, data_size: int) -> None: + if self._ctx is None: + raise AlreadyFinalized("Context was already finalized.") + self._updated = True + self._bytes_processed += data_size + if self._bytes_processed > self._ctx._mode._MAX_ENCRYPTED_BYTES: + raise ValueError( + "{} has a maximum encrypted byte limit of {}".format( + self._ctx._mode.name, self._ctx._mode._MAX_ENCRYPTED_BYTES + ) + ) + + def update(self, data: bytes) -> bytes: + self._check_limit(len(data)) + return self._ctx.update(data) + + def update_into(self, data: bytes, buf) -> int: + self._check_limit(len(data)) + return self._ctx.update_into(data, buf) + + def finalize(self) -> bytes: + if self._ctx is None: + raise AlreadyFinalized("Context was already finalized.") + data = self._ctx.finalize() + self._tag = self._ctx.tag + self._ctx = None + return data + + def finalize_with_tag(self, tag: bytes) -> bytes: + if self._ctx is None: + raise AlreadyFinalized("Context was already finalized.") + data = self._ctx.finalize_with_tag(tag) + self._tag = self._ctx.tag + self._ctx = None + return data + + def authenticate_additional_data(self, data: bytes) -> None: + if self._ctx is None: + raise AlreadyFinalized("Context was already finalized.") + if self._updated: + raise AlreadyUpdated("Update has been called on this context.") + + self._aad_bytes_processed += len(data) + if self._aad_bytes_processed > self._ctx._mode._MAX_AAD_BYTES: + raise ValueError( + "{} has a maximum AAD byte limit of {}".format( + self._ctx._mode.name, self._ctx._mode._MAX_AAD_BYTES + ) + ) + + self._ctx.authenticate_additional_data(data) + + +@utils.register_interface(AEADEncryptionContext) +class _AEADEncryptionContext(_AEADCipherContext): + @property + def tag(self) -> bytes: + if self._ctx is not None: + raise NotYetFinalized( + "You must finalize encryption before " "getting the tag." + ) + assert self._tag is not None + return self._tag diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/ciphers/modes.py b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/ciphers/modes.py new file mode 100644 index 00000000..3491dc20 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/ciphers/modes.py @@ -0,0 +1,247 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + + +import abc +import typing + +from cryptography import utils +from cryptography.exceptions import UnsupportedAlgorithm, _Reasons +from cryptography.hazmat.primitives._cipheralgorithm import ( + BlockCipherAlgorithm, + CipherAlgorithm, +) + + +class Mode(metaclass=abc.ABCMeta): + @abc.abstractproperty + def name(self) -> str: + """ + A string naming this mode (e.g. "ECB", "CBC"). + """ + + @abc.abstractmethod + def validate_for_algorithm(self, algorithm: CipherAlgorithm) -> None: + """ + Checks that all the necessary invariants of this (mode, algorithm) + combination are met. + """ + + +class ModeWithInitializationVector(metaclass=abc.ABCMeta): + @abc.abstractproperty + def initialization_vector(self) -> bytes: + """ + The value of the initialization vector for this mode as bytes. + """ + + +class ModeWithTweak(metaclass=abc.ABCMeta): + @abc.abstractproperty + def tweak(self) -> bytes: + """ + The value of the tweak for this mode as bytes. + """ + + +class ModeWithNonce(metaclass=abc.ABCMeta): + @abc.abstractproperty + def nonce(self) -> bytes: + """ + The value of the nonce for this mode as bytes. + """ + + +class ModeWithAuthenticationTag(metaclass=abc.ABCMeta): + @abc.abstractproperty + def tag(self) -> typing.Optional[bytes]: + """ + The value of the tag supplied to the constructor of this mode. + """ + + +def _check_aes_key_length(self, algorithm): + if algorithm.key_size > 256 and algorithm.name == "AES": + raise ValueError( + "Only 128, 192, and 256 bit keys are allowed for this AES mode" + ) + + +def _check_iv_length(self, algorithm): + if len(self.initialization_vector) * 8 != algorithm.block_size: + raise ValueError( + "Invalid IV size ({}) for {}.".format( + len(self.initialization_vector), self.name + ) + ) + + +def _check_nonce_length(nonce: bytes, name: str, algorithm) -> None: + if len(nonce) * 8 != algorithm.block_size: + raise ValueError( + "Invalid nonce size ({}) for {}.".format(len(nonce), name) + ) + + +def _check_iv_and_key_length(self, algorithm): + _check_aes_key_length(self, algorithm) + _check_iv_length(self, algorithm) + + +class CBC(Mode, ModeWithInitializationVector): + name = "CBC" + + def __init__(self, initialization_vector: bytes): + utils._check_byteslike("initialization_vector", initialization_vector) + self._initialization_vector = initialization_vector + + @property + def initialization_vector(self) -> bytes: + return self._initialization_vector + + validate_for_algorithm = _check_iv_and_key_length + + +class XTS(Mode, ModeWithTweak): + name = "XTS" + + def __init__(self, tweak: bytes): + utils._check_byteslike("tweak", tweak) + + if len(tweak) != 16: + raise ValueError("tweak must be 128-bits (16 bytes)") + + self._tweak = tweak + + @property + def tweak(self) -> bytes: + return self._tweak + + def validate_for_algorithm(self, algorithm: CipherAlgorithm) -> None: + if algorithm.key_size not in (256, 512): + raise ValueError( + "The XTS specification requires a 256-bit key for AES-128-XTS" + " and 512-bit key for AES-256-XTS" + ) + + +class ECB(Mode): + name = "ECB" + + validate_for_algorithm = _check_aes_key_length + + +class OFB(Mode, ModeWithInitializationVector): + name = "OFB" + + def __init__(self, initialization_vector: bytes): + utils._check_byteslike("initialization_vector", initialization_vector) + self._initialization_vector = initialization_vector + + @property + def initialization_vector(self) -> bytes: + return self._initialization_vector + + validate_for_algorithm = _check_iv_and_key_length + + +class CFB(Mode, ModeWithInitializationVector): + name = "CFB" + + def __init__(self, initialization_vector: bytes): + utils._check_byteslike("initialization_vector", initialization_vector) + self._initialization_vector = initialization_vector + + @property + def initialization_vector(self) -> bytes: + return self._initialization_vector + + validate_for_algorithm = _check_iv_and_key_length + + +class CFB8(Mode, ModeWithInitializationVector): + name = "CFB8" + + def __init__(self, initialization_vector: bytes): + utils._check_byteslike("initialization_vector", initialization_vector) + self._initialization_vector = initialization_vector + + @property + def initialization_vector(self) -> bytes: + return self._initialization_vector + + validate_for_algorithm = _check_iv_and_key_length + + +class CTR(Mode, ModeWithNonce): + name = "CTR" + + def __init__(self, nonce: bytes): + utils._check_byteslike("nonce", nonce) + self._nonce = nonce + + @property + def nonce(self) -> bytes: + return self._nonce + + def validate_for_algorithm(self, algorithm: CipherAlgorithm) -> None: + _check_aes_key_length(self, algorithm) + _check_nonce_length(self.nonce, self.name, algorithm) + + +class GCM(Mode, ModeWithInitializationVector, ModeWithAuthenticationTag): + name = "GCM" + _MAX_ENCRYPTED_BYTES = (2 ** 39 - 256) // 8 + _MAX_AAD_BYTES = (2 ** 64) // 8 + + def __init__( + self, + initialization_vector: bytes, + tag: typing.Optional[bytes] = None, + min_tag_length: int = 16, + ): + # OpenSSL 3.0.0 constrains GCM IVs to [64, 1024] bits inclusive + # This is a sane limit anyway so we'll enforce it here. + utils._check_byteslike("initialization_vector", initialization_vector) + if len(initialization_vector) < 8 or len(initialization_vector) > 128: + raise ValueError( + "initialization_vector must be between 8 and 128 bytes (64 " + "and 1024 bits)." + ) + self._initialization_vector = initialization_vector + if tag is not None: + utils._check_bytes("tag", tag) + if min_tag_length < 4: + raise ValueError("min_tag_length must be >= 4") + if len(tag) < min_tag_length: + raise ValueError( + "Authentication tag must be {} bytes or longer.".format( + min_tag_length + ) + ) + self._tag = tag + self._min_tag_length = min_tag_length + + @property + def tag(self) -> typing.Optional[bytes]: + return self._tag + + @property + def initialization_vector(self) -> bytes: + return self._initialization_vector + + def validate_for_algorithm(self, algorithm: CipherAlgorithm) -> None: + _check_aes_key_length(self, algorithm) + if not isinstance(algorithm, BlockCipherAlgorithm): + raise UnsupportedAlgorithm( + "GCM requires a block cipher algorithm", + _Reasons.UNSUPPORTED_CIPHER, + ) + block_size_bytes = algorithm.block_size // 8 + if self._tag is not None and len(self._tag) > block_size_bytes: + raise ValueError( + "Authentication tag cannot be more than {} bytes.".format( + block_size_bytes + ) + ) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/cmac.py b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/cmac.py new file mode 100644 index 00000000..4a148ece --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/cmac.py @@ -0,0 +1,60 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + + +import typing + +from cryptography import utils +from cryptography.exceptions import ( + AlreadyFinalized, +) +from cryptography.hazmat.primitives import ciphers + + +class CMAC(object): + def __init__( + self, + algorithm: ciphers.BlockCipherAlgorithm, + backend: typing.Any = None, + ctx=None, + ): + if not isinstance(algorithm, ciphers.BlockCipherAlgorithm): + raise TypeError("Expected instance of BlockCipherAlgorithm.") + self._algorithm = algorithm + + if ctx is None: + from cryptography.hazmat.backends.openssl.backend import ( + backend as ossl, + ) + + self._ctx = ossl.create_cmac_ctx(self._algorithm) + else: + self._ctx = ctx + + def update(self, data: bytes) -> None: + if self._ctx is None: + raise AlreadyFinalized("Context was already finalized.") + + utils._check_bytes("data", data) + self._ctx.update(data) + + def finalize(self) -> bytes: + if self._ctx is None: + raise AlreadyFinalized("Context was already finalized.") + digest = self._ctx.finalize() + self._ctx = None + return digest + + def verify(self, signature: bytes) -> None: + utils._check_bytes("signature", signature) + if self._ctx is None: + raise AlreadyFinalized("Context was already finalized.") + + ctx, self._ctx = self._ctx, None + ctx.verify(signature) + + def copy(self) -> "CMAC": + if self._ctx is None: + raise AlreadyFinalized("Context was already finalized.") + return CMAC(self._algorithm, ctx=self._ctx.copy()) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/constant_time.py b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/constant_time.py new file mode 100644 index 00000000..a02fa9c4 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/constant_time.py @@ -0,0 +1,13 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + + +import hmac + + +def bytes_eq(a: bytes, b: bytes) -> bool: + if not isinstance(a, bytes) or not isinstance(b, bytes): + raise TypeError("a and b must be bytes.") + + return hmac.compare_digest(a, b) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/hashes.py b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/hashes.py new file mode 100644 index 00000000..3362c2ab --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/hashes.py @@ -0,0 +1,257 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +import abc +import typing + +from cryptography import utils +from cryptography.exceptions import ( + AlreadyFinalized, +) + + +class HashAlgorithm(metaclass=abc.ABCMeta): + @abc.abstractproperty + def name(self) -> str: + """ + A string naming this algorithm (e.g. "sha256", "md5"). + """ + + @abc.abstractproperty + def digest_size(self) -> int: + """ + The size of the resulting digest in bytes. + """ + + @abc.abstractproperty + def block_size(self) -> typing.Optional[int]: + """ + The internal block size of the hash function, or None if the hash + function does not use blocks internally (e.g. SHA3). + """ + + +class HashContext(metaclass=abc.ABCMeta): + @abc.abstractproperty + def algorithm(self) -> HashAlgorithm: + """ + A HashAlgorithm that will be used by this context. + """ + + @abc.abstractmethod + def update(self, data: bytes) -> None: + """ + Processes the provided bytes through the hash. + """ + + @abc.abstractmethod + def finalize(self) -> bytes: + """ + Finalizes the hash context and returns the hash digest as bytes. + """ + + @abc.abstractmethod + def copy(self) -> "HashContext": + """ + Return a HashContext that is a copy of the current context. + """ + + +class ExtendableOutputFunction(metaclass=abc.ABCMeta): + """ + An interface for extendable output functions. + """ + + +class Hash(HashContext): + def __init__( + self, + algorithm: HashAlgorithm, + backend: typing.Any = None, + ctx: typing.Optional["HashContext"] = None, + ): + if not isinstance(algorithm, HashAlgorithm): + raise TypeError("Expected instance of hashes.HashAlgorithm.") + self._algorithm = algorithm + + if ctx is None: + from cryptography.hazmat.backends.openssl.backend import ( + backend as ossl, + ) + + self._ctx = ossl.create_hash_ctx(self.algorithm) + else: + self._ctx = ctx + + @property + def algorithm(self) -> HashAlgorithm: + return self._algorithm + + def update(self, data: bytes) -> None: + if self._ctx is None: + raise AlreadyFinalized("Context was already finalized.") + utils._check_byteslike("data", data) + self._ctx.update(data) + + def copy(self) -> "Hash": + if self._ctx is None: + raise AlreadyFinalized("Context was already finalized.") + return Hash(self.algorithm, ctx=self._ctx.copy()) + + def finalize(self) -> bytes: + if self._ctx is None: + raise AlreadyFinalized("Context was already finalized.") + digest = self._ctx.finalize() + self._ctx = None + return digest + + +class SHA1(HashAlgorithm): + name = "sha1" + digest_size = 20 + block_size = 64 + + +class SHA512_224(HashAlgorithm): # noqa: N801 + name = "sha512-224" + digest_size = 28 + block_size = 128 + + +class SHA512_256(HashAlgorithm): # noqa: N801 + name = "sha512-256" + digest_size = 32 + block_size = 128 + + +class SHA224(HashAlgorithm): + name = "sha224" + digest_size = 28 + block_size = 64 + + +class SHA256(HashAlgorithm): + name = "sha256" + digest_size = 32 + block_size = 64 + + +class SHA384(HashAlgorithm): + name = "sha384" + digest_size = 48 + block_size = 128 + + +class SHA512(HashAlgorithm): + name = "sha512" + digest_size = 64 + block_size = 128 + + +class SHA3_224(HashAlgorithm): # noqa: N801 + name = "sha3-224" + digest_size = 28 + block_size = None + + +class SHA3_256(HashAlgorithm): # noqa: N801 + name = "sha3-256" + digest_size = 32 + block_size = None + + +class SHA3_384(HashAlgorithm): # noqa: N801 + name = "sha3-384" + digest_size = 48 + block_size = None + + +class SHA3_512(HashAlgorithm): # noqa: N801 + name = "sha3-512" + digest_size = 64 + block_size = None + + +class SHAKE128(HashAlgorithm, ExtendableOutputFunction): + name = "shake128" + block_size = None + + def __init__(self, digest_size: int): + if not isinstance(digest_size, int): + raise TypeError("digest_size must be an integer") + + if digest_size < 1: + raise ValueError("digest_size must be a positive integer") + + self._digest_size = digest_size + + @property + def digest_size(self) -> int: + return self._digest_size + + +class SHAKE256(HashAlgorithm, ExtendableOutputFunction): + name = "shake256" + block_size = None + + def __init__(self, digest_size: int): + if not isinstance(digest_size, int): + raise TypeError("digest_size must be an integer") + + if digest_size < 1: + raise ValueError("digest_size must be a positive integer") + + self._digest_size = digest_size + + @property + def digest_size(self) -> int: + return self._digest_size + + +class MD5(HashAlgorithm): + name = "md5" + digest_size = 16 + block_size = 64 + + +class BLAKE2b(HashAlgorithm): + name = "blake2b" + _max_digest_size = 64 + _min_digest_size = 1 + block_size = 128 + + def __init__(self, digest_size: int): + + if digest_size != 64: + raise ValueError("Digest size must be 64") + + self._digest_size = digest_size + + @property + def digest_size(self) -> int: + return self._digest_size + + +class BLAKE2s(HashAlgorithm): + name = "blake2s" + block_size = 64 + _max_digest_size = 32 + _min_digest_size = 1 + + def __init__(self, digest_size: int): + + if digest_size != 32: + raise ValueError("Digest size must be 32") + + self._digest_size = digest_size + + @property + def digest_size(self) -> int: + return self._digest_size + + +class SM3(HashAlgorithm): + name = "sm3" + digest_size = 32 + block_size = 64 diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/hmac.py b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/hmac.py new file mode 100644 index 00000000..a2436f83 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/hmac.py @@ -0,0 +1,69 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + + +import typing + +from cryptography import utils +from cryptography.exceptions import ( + AlreadyFinalized, +) +from cryptography.hazmat.primitives import hashes + + +class HMAC(hashes.HashContext): + def __init__( + self, + key: bytes, + algorithm: hashes.HashAlgorithm, + backend: typing.Any = None, + ctx=None, + ): + if not isinstance(algorithm, hashes.HashAlgorithm): + raise TypeError("Expected instance of hashes.HashAlgorithm.") + self._algorithm = algorithm + + self._key = key + if ctx is None: + from cryptography.hazmat.backends.openssl.backend import ( + backend as ossl, + ) + + self._ctx = ossl.create_hmac_ctx(key, self.algorithm) + else: + self._ctx = ctx + + @property + def algorithm(self) -> hashes.HashAlgorithm: + return self._algorithm + + def update(self, data: bytes) -> None: + if self._ctx is None: + raise AlreadyFinalized("Context was already finalized.") + utils._check_byteslike("data", data) + self._ctx.update(data) + + def copy(self) -> "HMAC": + if self._ctx is None: + raise AlreadyFinalized("Context was already finalized.") + return HMAC( + self._key, + self.algorithm, + ctx=self._ctx.copy(), + ) + + def finalize(self) -> bytes: + if self._ctx is None: + raise AlreadyFinalized("Context was already finalized.") + digest = self._ctx.finalize() + self._ctx = None + return digest + + def verify(self, signature: bytes) -> None: + utils._check_bytes("signature", signature) + if self._ctx is None: + raise AlreadyFinalized("Context was already finalized.") + + ctx, self._ctx = self._ctx, None + ctx.verify(signature) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/kdf/__init__.py b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/kdf/__init__.py new file mode 100644 index 00000000..38e2f8bc --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/kdf/__init__.py @@ -0,0 +1,22 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + + +import abc + + +class KeyDerivationFunction(metaclass=abc.ABCMeta): + @abc.abstractmethod + def derive(self, key_material: bytes) -> bytes: + """ + Deterministically generates and returns a new key based on the existing + key material. + """ + + @abc.abstractmethod + def verify(self, key_material: bytes, expected_key: bytes) -> None: + """ + Checks whether the key generated by the key material matches the + expected derived key. Raises an exception if they do not match. + """ diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/kdf/concatkdf.py b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/kdf/concatkdf.py new file mode 100644 index 00000000..5ef5f420 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/kdf/concatkdf.py @@ -0,0 +1,131 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + + +import struct +import typing + +from cryptography import utils +from cryptography.exceptions import ( + AlreadyFinalized, + InvalidKey, +) +from cryptography.hazmat.primitives import constant_time, hashes, hmac +from cryptography.hazmat.primitives.kdf import KeyDerivationFunction + + +def _int_to_u32be(n: int) -> bytes: + return struct.pack(">I", n) + + +def _common_args_checks( + algorithm: hashes.HashAlgorithm, + length: int, + otherinfo: typing.Optional[bytes], +) -> None: + max_length = algorithm.digest_size * (2 ** 32 - 1) + if length > max_length: + raise ValueError( + "Cannot derive keys larger than {} bits.".format(max_length) + ) + if otherinfo is not None: + utils._check_bytes("otherinfo", otherinfo) + + +def _concatkdf_derive( + key_material: bytes, + length: int, + auxfn: typing.Callable[[], hashes.HashContext], + otherinfo: bytes, +) -> bytes: + utils._check_byteslike("key_material", key_material) + output = [b""] + outlen = 0 + counter = 1 + + while length > outlen: + h = auxfn() + h.update(_int_to_u32be(counter)) + h.update(key_material) + h.update(otherinfo) + output.append(h.finalize()) + outlen += len(output[-1]) + counter += 1 + + return b"".join(output)[:length] + + +class ConcatKDFHash(KeyDerivationFunction): + def __init__( + self, + algorithm: hashes.HashAlgorithm, + length: int, + otherinfo: typing.Optional[bytes], + backend: typing.Any = None, + ): + _common_args_checks(algorithm, length, otherinfo) + self._algorithm = algorithm + self._length = length + self._otherinfo: bytes = otherinfo if otherinfo is not None else b"" + + self._used = False + + def _hash(self) -> hashes.Hash: + return hashes.Hash(self._algorithm) + + def derive(self, key_material: bytes) -> bytes: + if self._used: + raise AlreadyFinalized + self._used = True + return _concatkdf_derive( + key_material, self._length, self._hash, self._otherinfo + ) + + def verify(self, key_material: bytes, expected_key: bytes) -> None: + if not constant_time.bytes_eq(self.derive(key_material), expected_key): + raise InvalidKey + + +class ConcatKDFHMAC(KeyDerivationFunction): + def __init__( + self, + algorithm: hashes.HashAlgorithm, + length: int, + salt: typing.Optional[bytes], + otherinfo: typing.Optional[bytes], + backend: typing.Any = None, + ): + _common_args_checks(algorithm, length, otherinfo) + self._algorithm = algorithm + self._length = length + self._otherinfo: bytes = otherinfo if otherinfo is not None else b"" + + if algorithm.block_size is None: + raise TypeError( + "{} is unsupported for ConcatKDF".format(algorithm.name) + ) + + if salt is None: + salt = b"\x00" * algorithm.block_size + else: + utils._check_bytes("salt", salt) + + self._salt = salt + + self._used = False + + def _hmac(self) -> hmac.HMAC: + return hmac.HMAC(self._salt, self._algorithm) + + def derive(self, key_material: bytes) -> bytes: + if self._used: + raise AlreadyFinalized + self._used = True + return _concatkdf_derive( + key_material, self._length, self._hmac, self._otherinfo + ) + + def verify(self, key_material: bytes, expected_key: bytes) -> None: + if not constant_time.bytes_eq(self.derive(key_material), expected_key): + raise InvalidKey diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/kdf/hkdf.py b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/kdf/hkdf.py new file mode 100644 index 00000000..44889b67 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/kdf/hkdf.py @@ -0,0 +1,103 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + + +import typing + +from cryptography import utils +from cryptography.exceptions import ( + AlreadyFinalized, + InvalidKey, +) +from cryptography.hazmat.primitives import constant_time, hashes, hmac +from cryptography.hazmat.primitives.kdf import KeyDerivationFunction + + +class HKDF(KeyDerivationFunction): + def __init__( + self, + algorithm: hashes.HashAlgorithm, + length: int, + salt: typing.Optional[bytes], + info: typing.Optional[bytes], + backend: typing.Any = None, + ): + self._algorithm = algorithm + + if salt is None: + salt = b"\x00" * self._algorithm.digest_size + else: + utils._check_bytes("salt", salt) + + self._salt = salt + + self._hkdf_expand = HKDFExpand(self._algorithm, length, info) + + def _extract(self, key_material: bytes) -> bytes: + h = hmac.HMAC(self._salt, self._algorithm) + h.update(key_material) + return h.finalize() + + def derive(self, key_material: bytes) -> bytes: + utils._check_byteslike("key_material", key_material) + return self._hkdf_expand.derive(self._extract(key_material)) + + def verify(self, key_material: bytes, expected_key: bytes) -> None: + if not constant_time.bytes_eq(self.derive(key_material), expected_key): + raise InvalidKey + + +class HKDFExpand(KeyDerivationFunction): + def __init__( + self, + algorithm: hashes.HashAlgorithm, + length: int, + info: typing.Optional[bytes], + backend: typing.Any = None, + ): + self._algorithm = algorithm + + max_length = 255 * algorithm.digest_size + + if length > max_length: + raise ValueError( + "Cannot derive keys larger than {} octets.".format(max_length) + ) + + self._length = length + + if info is None: + info = b"" + else: + utils._check_bytes("info", info) + + self._info = info + + self._used = False + + def _expand(self, key_material: bytes) -> bytes: + output = [b""] + counter = 1 + + while self._algorithm.digest_size * (len(output) - 1) < self._length: + h = hmac.HMAC(key_material, self._algorithm) + h.update(output[-1]) + h.update(self._info) + h.update(bytes([counter])) + output.append(h.finalize()) + counter += 1 + + return b"".join(output)[: self._length] + + def derive(self, key_material: bytes) -> bytes: + utils._check_byteslike("key_material", key_material) + if self._used: + raise AlreadyFinalized + + self._used = True + return self._expand(key_material) + + def verify(self, key_material: bytes, expected_key: bytes) -> None: + if not constant_time.bytes_eq(self.derive(key_material), expected_key): + raise InvalidKey diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/kdf/kbkdf.py b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/kdf/kbkdf.py new file mode 100644 index 00000000..778784ef --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/kdf/kbkdf.py @@ -0,0 +1,258 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +import typing + +from cryptography import utils +from cryptography.exceptions import ( + AlreadyFinalized, + InvalidKey, + UnsupportedAlgorithm, + _Reasons, +) +from cryptography.hazmat.primitives import ( + ciphers, + cmac, + constant_time, + hashes, + hmac, +) +from cryptography.hazmat.primitives.kdf import KeyDerivationFunction + + +class Mode(utils.Enum): + CounterMode = "ctr" + + +class CounterLocation(utils.Enum): + BeforeFixed = "before_fixed" + AfterFixed = "after_fixed" + + +class _KBKDFDeriver: + def __init__( + self, + prf: typing.Callable, + mode: Mode, + length: int, + rlen: int, + llen: typing.Optional[int], + location: CounterLocation, + label: typing.Optional[bytes], + context: typing.Optional[bytes], + fixed: typing.Optional[bytes], + ): + assert callable(prf) + + if not isinstance(mode, Mode): + raise TypeError("mode must be of type Mode") + + if not isinstance(location, CounterLocation): + raise TypeError("location must be of type CounterLocation") + + if (label or context) and fixed: + raise ValueError( + "When supplying fixed data, " "label and context are ignored." + ) + + if rlen is None or not self._valid_byte_length(rlen): + raise ValueError("rlen must be between 1 and 4") + + if llen is None and fixed is None: + raise ValueError("Please specify an llen") + + if llen is not None and not isinstance(llen, int): + raise TypeError("llen must be an integer") + + if label is None: + label = b"" + + if context is None: + context = b"" + + utils._check_bytes("label", label) + utils._check_bytes("context", context) + self._prf = prf + self._mode = mode + self._length = length + self._rlen = rlen + self._llen = llen + self._location = location + self._label = label + self._context = context + self._used = False + self._fixed_data = fixed + + @staticmethod + def _valid_byte_length(value: int) -> bool: + if not isinstance(value, int): + raise TypeError("value must be of type int") + + value_bin = utils.int_to_bytes(1, value) + if not 1 <= len(value_bin) <= 4: + return False + return True + + def derive(self, key_material: bytes, prf_output_size: int) -> bytes: + if self._used: + raise AlreadyFinalized + + utils._check_byteslike("key_material", key_material) + self._used = True + + # inverse floor division (equivalent to ceiling) + rounds = -(-self._length // prf_output_size) + + output = [b""] + + # For counter mode, the number of iterations shall not be + # larger than 2^r-1, where r <= 32 is the binary length of the counter + # This ensures that the counter values used as an input to the + # PRF will not repeat during a particular call to the KDF function. + r_bin = utils.int_to_bytes(1, self._rlen) + if rounds > pow(2, len(r_bin) * 8) - 1: + raise ValueError("There are too many iterations.") + + for i in range(1, rounds + 1): + h = self._prf(key_material) + + counter = utils.int_to_bytes(i, self._rlen) + if self._location == CounterLocation.BeforeFixed: + h.update(counter) + + h.update(self._generate_fixed_input()) + + if self._location == CounterLocation.AfterFixed: + h.update(counter) + + output.append(h.finalize()) + + return b"".join(output)[: self._length] + + def _generate_fixed_input(self) -> bytes: + if self._fixed_data and isinstance(self._fixed_data, bytes): + return self._fixed_data + + l_val = utils.int_to_bytes(self._length * 8, self._llen) + + return b"".join([self._label, b"\x00", self._context, l_val]) + + +class KBKDFHMAC(KeyDerivationFunction): + def __init__( + self, + algorithm: hashes.HashAlgorithm, + mode: Mode, + length: int, + rlen: int, + llen: typing.Optional[int], + location: CounterLocation, + label: typing.Optional[bytes], + context: typing.Optional[bytes], + fixed: typing.Optional[bytes], + backend: typing.Any = None, + ): + if not isinstance(algorithm, hashes.HashAlgorithm): + raise UnsupportedAlgorithm( + "Algorithm supplied is not a supported hash algorithm.", + _Reasons.UNSUPPORTED_HASH, + ) + + from cryptography.hazmat.backends.openssl.backend import ( + backend as ossl, + ) + + if not ossl.hmac_supported(algorithm): + raise UnsupportedAlgorithm( + "Algorithm supplied is not a supported hmac algorithm.", + _Reasons.UNSUPPORTED_HASH, + ) + + self._algorithm = algorithm + + self._deriver = _KBKDFDeriver( + self._prf, + mode, + length, + rlen, + llen, + location, + label, + context, + fixed, + ) + + def _prf(self, key_material: bytes): + return hmac.HMAC(key_material, self._algorithm) + + def derive(self, key_material) -> bytes: + return self._deriver.derive(key_material, self._algorithm.digest_size) + + def verify(self, key_material: bytes, expected_key: bytes) -> None: + if not constant_time.bytes_eq(self.derive(key_material), expected_key): + raise InvalidKey + + +class KBKDFCMAC(KeyDerivationFunction): + def __init__( + self, + algorithm, + mode: Mode, + length: int, + rlen: int, + llen: typing.Optional[int], + location: CounterLocation, + label: typing.Optional[bytes], + context: typing.Optional[bytes], + fixed: typing.Optional[bytes], + backend: typing.Any = None, + ): + if not issubclass( + algorithm, ciphers.BlockCipherAlgorithm + ) or not issubclass(algorithm, ciphers.CipherAlgorithm): + raise UnsupportedAlgorithm( + "Algorithm supplied is not a supported cipher algorithm.", + _Reasons.UNSUPPORTED_CIPHER, + ) + + self._algorithm = algorithm + self._cipher: typing.Optional[ciphers.BlockCipherAlgorithm] = None + + self._deriver = _KBKDFDeriver( + self._prf, + mode, + length, + rlen, + llen, + location, + label, + context, + fixed, + ) + + def _prf(self, _: bytes): + assert self._cipher is not None + + return cmac.CMAC(self._cipher) + + def derive(self, key_material: bytes) -> bytes: + self._cipher = self._algorithm(key_material) + + assert self._cipher is not None + + from cryptography.hazmat.backends.openssl.backend import ( + backend as ossl, + ) + + if not ossl.cmac_algorithm_supported(self._cipher): + raise UnsupportedAlgorithm( + "Algorithm supplied is not a supported cipher algorithm.", + _Reasons.UNSUPPORTED_CIPHER, + ) + + return self._deriver.derive(key_material, self._cipher.block_size // 8) + + def verify(self, key_material: bytes, expected_key: bytes) -> None: + if not constant_time.bytes_eq(self.derive(key_material), expected_key): + raise InvalidKey diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/kdf/pbkdf2.py b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/kdf/pbkdf2.py new file mode 100644 index 00000000..8d23f8c2 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/kdf/pbkdf2.py @@ -0,0 +1,65 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + + +import typing + +from cryptography import utils +from cryptography.exceptions import ( + AlreadyFinalized, + InvalidKey, + UnsupportedAlgorithm, + _Reasons, +) +from cryptography.hazmat.primitives import constant_time, hashes +from cryptography.hazmat.primitives.kdf import KeyDerivationFunction + + +class PBKDF2HMAC(KeyDerivationFunction): + def __init__( + self, + algorithm: hashes.HashAlgorithm, + length: int, + salt: bytes, + iterations: int, + backend: typing.Any = None, + ): + from cryptography.hazmat.backends.openssl.backend import ( + backend as ossl, + ) + + if not ossl.pbkdf2_hmac_supported(algorithm): + raise UnsupportedAlgorithm( + "{} is not supported for PBKDF2 by this backend.".format( + algorithm.name + ), + _Reasons.UNSUPPORTED_HASH, + ) + self._used = False + self._algorithm = algorithm + self._length = length + utils._check_bytes("salt", salt) + self._salt = salt + self._iterations = iterations + + def derive(self, key_material: bytes) -> bytes: + if self._used: + raise AlreadyFinalized("PBKDF2 instances can only be used once.") + self._used = True + + utils._check_byteslike("key_material", key_material) + from cryptography.hazmat.backends.openssl.backend import backend + + return backend.derive_pbkdf2_hmac( + self._algorithm, + self._length, + self._salt, + self._iterations, + key_material, + ) + + def verify(self, key_material: bytes, expected_key: bytes) -> None: + derived_key = self.derive(key_material) + if not constant_time.bytes_eq(derived_key, expected_key): + raise InvalidKey("Keys do not match.") diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/kdf/scrypt.py b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/kdf/scrypt.py new file mode 100644 index 00000000..ff81bbb1 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/kdf/scrypt.py @@ -0,0 +1,74 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + + +import sys +import typing + +from cryptography import utils +from cryptography.exceptions import ( + AlreadyFinalized, + InvalidKey, + UnsupportedAlgorithm, +) +from cryptography.hazmat.primitives import constant_time +from cryptography.hazmat.primitives.kdf import KeyDerivationFunction + + +# This is used by the scrypt tests to skip tests that require more memory +# than the MEM_LIMIT +_MEM_LIMIT = sys.maxsize // 2 + + +class Scrypt(KeyDerivationFunction): + def __init__( + self, + salt: bytes, + length: int, + n: int, + r: int, + p: int, + backend: typing.Any = None, + ): + from cryptography.hazmat.backends.openssl.backend import ( + backend as ossl, + ) + + if not ossl.scrypt_supported(): + raise UnsupportedAlgorithm( + "This version of OpenSSL does not support scrypt" + ) + self._length = length + utils._check_bytes("salt", salt) + if n < 2 or (n & (n - 1)) != 0: + raise ValueError("n must be greater than 1 and be a power of 2.") + + if r < 1: + raise ValueError("r must be greater than or equal to 1.") + + if p < 1: + raise ValueError("p must be greater than or equal to 1.") + + self._used = False + self._salt = salt + self._n = n + self._r = r + self._p = p + + def derive(self, key_material: bytes) -> bytes: + if self._used: + raise AlreadyFinalized("Scrypt instances can only be used once.") + self._used = True + + utils._check_byteslike("key_material", key_material) + from cryptography.hazmat.backends.openssl.backend import backend + + return backend.derive_scrypt( + key_material, self._salt, self._length, self._n, self._r, self._p + ) + + def verify(self, key_material: bytes, expected_key: bytes) -> None: + derived_key = self.derive(key_material) + if not constant_time.bytes_eq(derived_key, expected_key): + raise InvalidKey("Keys do not match.") diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/kdf/x963kdf.py b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/kdf/x963kdf.py new file mode 100644 index 00000000..caf3545b --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/kdf/x963kdf.py @@ -0,0 +1,66 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + + +import struct +import typing + +from cryptography import utils +from cryptography.exceptions import ( + AlreadyFinalized, + InvalidKey, +) +from cryptography.hazmat.primitives import constant_time, hashes +from cryptography.hazmat.primitives.kdf import KeyDerivationFunction + + +def _int_to_u32be(n): + return struct.pack(">I", n) + + +class X963KDF(KeyDerivationFunction): + def __init__( + self, + algorithm: hashes.HashAlgorithm, + length: int, + sharedinfo: typing.Optional[bytes], + backend: typing.Any = None, + ): + max_len = algorithm.digest_size * (2 ** 32 - 1) + if length > max_len: + raise ValueError( + "Cannot derive keys larger than {} bits.".format(max_len) + ) + if sharedinfo is not None: + utils._check_bytes("sharedinfo", sharedinfo) + + self._algorithm = algorithm + self._length = length + self._sharedinfo = sharedinfo + self._used = False + + def derive(self, key_material: bytes) -> bytes: + if self._used: + raise AlreadyFinalized + self._used = True + utils._check_byteslike("key_material", key_material) + output = [b""] + outlen = 0 + counter = 1 + + while self._length > outlen: + h = hashes.Hash(self._algorithm) + h.update(key_material) + h.update(_int_to_u32be(counter)) + if self._sharedinfo is not None: + h.update(self._sharedinfo) + output.append(h.finalize()) + outlen += len(output[-1]) + counter += 1 + + return b"".join(output)[: self._length] + + def verify(self, key_material: bytes, expected_key: bytes) -> None: + if not constant_time.bytes_eq(self.derive(key_material), expected_key): + raise InvalidKey diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/keywrap.py b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/keywrap.py new file mode 100644 index 00000000..123db376 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/keywrap.py @@ -0,0 +1,180 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + + +import struct +import typing + +from cryptography.hazmat.primitives.ciphers import Cipher +from cryptography.hazmat.primitives.ciphers.algorithms import AES +from cryptography.hazmat.primitives.ciphers.modes import ECB +from cryptography.hazmat.primitives.constant_time import bytes_eq + + +def _wrap_core( + wrapping_key: bytes, + a: bytes, + r: typing.List[bytes], +) -> bytes: + # RFC 3394 Key Wrap - 2.2.1 (index method) + encryptor = Cipher(AES(wrapping_key), ECB()).encryptor() + n = len(r) + for j in range(6): + for i in range(n): + # every encryption operation is a discrete 16 byte chunk (because + # AES has a 128-bit block size) and since we're using ECB it is + # safe to reuse the encryptor for the entire operation + b = encryptor.update(a + r[i]) + # pack/unpack are safe as these are always 64-bit chunks + a = struct.pack( + ">Q", struct.unpack(">Q", b[:8])[0] ^ ((n * j) + i + 1) + ) + r[i] = b[-8:] + + assert encryptor.finalize() == b"" + + return a + b"".join(r) + + +def aes_key_wrap( + wrapping_key: bytes, + key_to_wrap: bytes, + backend: typing.Any = None, +) -> bytes: + if len(wrapping_key) not in [16, 24, 32]: + raise ValueError("The wrapping key must be a valid AES key length") + + if len(key_to_wrap) < 16: + raise ValueError("The key to wrap must be at least 16 bytes") + + if len(key_to_wrap) % 8 != 0: + raise ValueError("The key to wrap must be a multiple of 8 bytes") + + a = b"\xa6\xa6\xa6\xa6\xa6\xa6\xa6\xa6" + r = [key_to_wrap[i : i + 8] for i in range(0, len(key_to_wrap), 8)] + return _wrap_core(wrapping_key, a, r) + + +def _unwrap_core( + wrapping_key: bytes, + a: bytes, + r: typing.List[bytes], +) -> typing.Tuple[bytes, typing.List[bytes]]: + # Implement RFC 3394 Key Unwrap - 2.2.2 (index method) + decryptor = Cipher(AES(wrapping_key), ECB()).decryptor() + n = len(r) + for j in reversed(range(6)): + for i in reversed(range(n)): + # pack/unpack are safe as these are always 64-bit chunks + atr = ( + struct.pack( + ">Q", struct.unpack(">Q", a)[0] ^ ((n * j) + i + 1) + ) + + r[i] + ) + # every decryption operation is a discrete 16 byte chunk so + # it is safe to reuse the decryptor for the entire operation + b = decryptor.update(atr) + a = b[:8] + r[i] = b[-8:] + + assert decryptor.finalize() == b"" + return a, r + + +def aes_key_wrap_with_padding( + wrapping_key: bytes, + key_to_wrap: bytes, + backend: typing.Any = None, +) -> bytes: + if len(wrapping_key) not in [16, 24, 32]: + raise ValueError("The wrapping key must be a valid AES key length") + + aiv = b"\xA6\x59\x59\xA6" + struct.pack(">i", len(key_to_wrap)) + # pad the key to wrap if necessary + pad = (8 - (len(key_to_wrap) % 8)) % 8 + key_to_wrap = key_to_wrap + b"\x00" * pad + if len(key_to_wrap) == 8: + # RFC 5649 - 4.1 - exactly 8 octets after padding + encryptor = Cipher(AES(wrapping_key), ECB()).encryptor() + b = encryptor.update(aiv + key_to_wrap) + assert encryptor.finalize() == b"" + return b + else: + r = [key_to_wrap[i : i + 8] for i in range(0, len(key_to_wrap), 8)] + return _wrap_core(wrapping_key, aiv, r) + + +def aes_key_unwrap_with_padding( + wrapping_key: bytes, + wrapped_key: bytes, + backend: typing.Any = None, +) -> bytes: + if len(wrapped_key) < 16: + raise InvalidUnwrap("Must be at least 16 bytes") + + if len(wrapping_key) not in [16, 24, 32]: + raise ValueError("The wrapping key must be a valid AES key length") + + if len(wrapped_key) == 16: + # RFC 5649 - 4.2 - exactly two 64-bit blocks + decryptor = Cipher(AES(wrapping_key), ECB()).decryptor() + b = decryptor.update(wrapped_key) + assert decryptor.finalize() == b"" + a = b[:8] + data = b[8:] + n = 1 + else: + r = [wrapped_key[i : i + 8] for i in range(0, len(wrapped_key), 8)] + encrypted_aiv = r.pop(0) + n = len(r) + a, r = _unwrap_core(wrapping_key, encrypted_aiv, r) + data = b"".join(r) + + # 1) Check that MSB(32,A) = A65959A6. + # 2) Check that 8*(n-1) < LSB(32,A) <= 8*n. If so, let + # MLI = LSB(32,A). + # 3) Let b = (8*n)-MLI, and then check that the rightmost b octets of + # the output data are zero. + (mli,) = struct.unpack(">I", a[4:]) + b = (8 * n) - mli + if ( + not bytes_eq(a[:4], b"\xa6\x59\x59\xa6") + or not 8 * (n - 1) < mli <= 8 * n + or (b != 0 and not bytes_eq(data[-b:], b"\x00" * b)) + ): + raise InvalidUnwrap() + + if b == 0: + return data + else: + return data[:-b] + + +def aes_key_unwrap( + wrapping_key: bytes, + wrapped_key: bytes, + backend: typing.Any = None, +) -> bytes: + if len(wrapped_key) < 24: + raise InvalidUnwrap("Must be at least 24 bytes") + + if len(wrapped_key) % 8 != 0: + raise InvalidUnwrap("The wrapped key must be a multiple of 8 bytes") + + if len(wrapping_key) not in [16, 24, 32]: + raise ValueError("The wrapping key must be a valid AES key length") + + aiv = b"\xa6\xa6\xa6\xa6\xa6\xa6\xa6\xa6" + r = [wrapped_key[i : i + 8] for i in range(0, len(wrapped_key), 8)] + a = r.pop(0) + a, r = _unwrap_core(wrapping_key, a, r) + if not bytes_eq(a, aiv): + raise InvalidUnwrap() + + return b"".join(r) + + +class InvalidUnwrap(Exception): + pass diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/padding.py b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/padding.py new file mode 100644 index 00000000..ccfde740 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/padding.py @@ -0,0 +1,224 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + + +import abc +import typing + +from cryptography import utils +from cryptography.exceptions import AlreadyFinalized +from cryptography.hazmat.bindings._rust import ( + check_ansix923_padding, + check_pkcs7_padding, +) + + +class PaddingContext(metaclass=abc.ABCMeta): + @abc.abstractmethod + def update(self, data: bytes) -> bytes: + """ + Pads the provided bytes and returns any available data as bytes. + """ + + @abc.abstractmethod + def finalize(self) -> bytes: + """ + Finalize the padding, returns bytes. + """ + + +def _byte_padding_check(block_size: int) -> None: + if not (0 <= block_size <= 2040): + raise ValueError("block_size must be in range(0, 2041).") + + if block_size % 8 != 0: + raise ValueError("block_size must be a multiple of 8.") + + +def _byte_padding_update( + buffer_: typing.Optional[bytes], data: bytes, block_size: int +) -> typing.Tuple[bytes, bytes]: + if buffer_ is None: + raise AlreadyFinalized("Context was already finalized.") + + utils._check_byteslike("data", data) + + buffer_ += bytes(data) + + finished_blocks = len(buffer_) // (block_size // 8) + + result = buffer_[: finished_blocks * (block_size // 8)] + buffer_ = buffer_[finished_blocks * (block_size // 8) :] + + return buffer_, result + + +def _byte_padding_pad( + buffer_: typing.Optional[bytes], + block_size: int, + paddingfn: typing.Callable[[int], bytes], +) -> bytes: + if buffer_ is None: + raise AlreadyFinalized("Context was already finalized.") + + pad_size = block_size // 8 - len(buffer_) + return buffer_ + paddingfn(pad_size) + + +def _byte_unpadding_update( + buffer_: typing.Optional[bytes], data: bytes, block_size: int +) -> typing.Tuple[bytes, bytes]: + if buffer_ is None: + raise AlreadyFinalized("Context was already finalized.") + + utils._check_byteslike("data", data) + + buffer_ += bytes(data) + + finished_blocks = max(len(buffer_) // (block_size // 8) - 1, 0) + + result = buffer_[: finished_blocks * (block_size // 8)] + buffer_ = buffer_[finished_blocks * (block_size // 8) :] + + return buffer_, result + + +def _byte_unpadding_check( + buffer_: typing.Optional[bytes], + block_size: int, + checkfn: typing.Callable[[bytes], int], +) -> bytes: + if buffer_ is None: + raise AlreadyFinalized("Context was already finalized.") + + if len(buffer_) != block_size // 8: + raise ValueError("Invalid padding bytes.") + + valid = checkfn(buffer_) + + if not valid: + raise ValueError("Invalid padding bytes.") + + pad_size = buffer_[-1] + return buffer_[:-pad_size] + + +class PKCS7(object): + def __init__(self, block_size: int): + _byte_padding_check(block_size) + self.block_size = block_size + + def padder(self): + return _PKCS7PaddingContext(self.block_size) + + def unpadder(self): + return _PKCS7UnpaddingContext(self.block_size) + + +class _PKCS7PaddingContext(PaddingContext): + _buffer: typing.Optional[bytes] + + def __init__(self, block_size: int): + self.block_size = block_size + # TODO: more copies than necessary, we should use zero-buffer (#193) + self._buffer = b"" + + def update(self, data: bytes) -> bytes: + self._buffer, result = _byte_padding_update( + self._buffer, data, self.block_size + ) + return result + + def _padding(self, size: int) -> bytes: + return bytes([size]) * size + + def finalize(self) -> bytes: + result = _byte_padding_pad( + self._buffer, self.block_size, self._padding + ) + self._buffer = None + return result + + +class _PKCS7UnpaddingContext(PaddingContext): + _buffer: typing.Optional[bytes] + + def __init__(self, block_size: int): + self.block_size = block_size + # TODO: more copies than necessary, we should use zero-buffer (#193) + self._buffer = b"" + + def update(self, data: bytes) -> bytes: + self._buffer, result = _byte_unpadding_update( + self._buffer, data, self.block_size + ) + return result + + def finalize(self) -> bytes: + result = _byte_unpadding_check( + self._buffer, self.block_size, check_pkcs7_padding + ) + self._buffer = None + return result + + +class ANSIX923(object): + def __init__(self, block_size: int): + _byte_padding_check(block_size) + self.block_size = block_size + + def padder(self) -> PaddingContext: + return _ANSIX923PaddingContext(self.block_size) + + def unpadder(self) -> PaddingContext: + return _ANSIX923UnpaddingContext(self.block_size) + + +class _ANSIX923PaddingContext(PaddingContext): + _buffer: typing.Optional[bytes] + + def __init__(self, block_size: int): + self.block_size = block_size + # TODO: more copies than necessary, we should use zero-buffer (#193) + self._buffer = b"" + + def update(self, data: bytes) -> bytes: + self._buffer, result = _byte_padding_update( + self._buffer, data, self.block_size + ) + return result + + def _padding(self, size: int) -> bytes: + return bytes([0]) * (size - 1) + bytes([size]) + + def finalize(self) -> bytes: + result = _byte_padding_pad( + self._buffer, self.block_size, self._padding + ) + self._buffer = None + return result + + +class _ANSIX923UnpaddingContext(PaddingContext): + _buffer: typing.Optional[bytes] + + def __init__(self, block_size: int): + self.block_size = block_size + # TODO: more copies than necessary, we should use zero-buffer (#193) + self._buffer = b"" + + def update(self, data: bytes) -> bytes: + self._buffer, result = _byte_unpadding_update( + self._buffer, data, self.block_size + ) + return result + + def finalize(self) -> bytes: + result = _byte_unpadding_check( + self._buffer, + self.block_size, + check_ansix923_padding, + ) + self._buffer = None + return result diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/poly1305.py b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/poly1305.py new file mode 100644 index 00000000..f7819eaf --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/poly1305.py @@ -0,0 +1,56 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + + +from cryptography import utils +from cryptography.exceptions import ( + AlreadyFinalized, + UnsupportedAlgorithm, + _Reasons, +) + + +class Poly1305(object): + def __init__(self, key: bytes): + from cryptography.hazmat.backends.openssl.backend import backend + + if not backend.poly1305_supported(): + raise UnsupportedAlgorithm( + "poly1305 is not supported by this version of OpenSSL.", + _Reasons.UNSUPPORTED_MAC, + ) + self._ctx = backend.create_poly1305_ctx(key) + + def update(self, data: bytes) -> None: + if self._ctx is None: + raise AlreadyFinalized("Context was already finalized.") + utils._check_byteslike("data", data) + self._ctx.update(data) + + def finalize(self) -> bytes: + if self._ctx is None: + raise AlreadyFinalized("Context was already finalized.") + mac = self._ctx.finalize() + self._ctx = None + return mac + + def verify(self, tag: bytes) -> None: + utils._check_bytes("tag", tag) + if self._ctx is None: + raise AlreadyFinalized("Context was already finalized.") + + ctx, self._ctx = self._ctx, None + ctx.verify(tag) + + @classmethod + def generate_tag(cls, key: bytes, data: bytes) -> bytes: + p = Poly1305(key) + p.update(data) + return p.finalize() + + @classmethod + def verify_tag(cls, key: bytes, data: bytes, tag: bytes) -> None: + p = Poly1305(key) + p.update(data) + p.verify(tag) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/serialization/__init__.py b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/serialization/__init__.py new file mode 100644 index 00000000..1e0174b0 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/serialization/__init__.py @@ -0,0 +1,45 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + + +from cryptography.hazmat.primitives._serialization import ( + BestAvailableEncryption, + Encoding, + KeySerializationEncryption, + NoEncryption, + ParameterFormat, + PrivateFormat, + PublicFormat, +) +from cryptography.hazmat.primitives.serialization.base import ( + load_der_parameters, + load_der_private_key, + load_der_public_key, + load_pem_parameters, + load_pem_private_key, + load_pem_public_key, +) +from cryptography.hazmat.primitives.serialization.ssh import ( + load_ssh_private_key, + load_ssh_public_key, +) + + +__all__ = [ + "load_der_parameters", + "load_der_private_key", + "load_der_public_key", + "load_pem_parameters", + "load_pem_private_key", + "load_pem_public_key", + "load_ssh_private_key", + "load_ssh_public_key", + "Encoding", + "PrivateFormat", + "PublicFormat", + "ParameterFormat", + "KeySerializationEncryption", + "BestAvailableEncryption", + "NoEncryption", +] diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/serialization/base.py b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/serialization/base.py new file mode 100644 index 00000000..059b6e40 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/serialization/base.py @@ -0,0 +1,64 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + + +import typing + +from cryptography.hazmat.primitives.asymmetric import dh +from cryptography.hazmat.primitives.asymmetric.types import ( + PRIVATE_KEY_TYPES, + PUBLIC_KEY_TYPES, +) + + +def load_pem_private_key( + data: bytes, + password: typing.Optional[bytes], + backend: typing.Any = None, +) -> PRIVATE_KEY_TYPES: + from cryptography.hazmat.backends.openssl.backend import backend as ossl + + return ossl.load_pem_private_key(data, password) + + +def load_pem_public_key( + data: bytes, backend: typing.Any = None +) -> PUBLIC_KEY_TYPES: + from cryptography.hazmat.backends.openssl.backend import backend as ossl + + return ossl.load_pem_public_key(data) + + +def load_pem_parameters( + data: bytes, backend: typing.Any = None +) -> "dh.DHParameters": + from cryptography.hazmat.backends.openssl.backend import backend as ossl + + return ossl.load_pem_parameters(data) + + +def load_der_private_key( + data: bytes, + password: typing.Optional[bytes], + backend: typing.Any = None, +) -> PRIVATE_KEY_TYPES: + from cryptography.hazmat.backends.openssl.backend import backend as ossl + + return ossl.load_der_private_key(data, password) + + +def load_der_public_key( + data: bytes, backend: typing.Any = None +) -> PUBLIC_KEY_TYPES: + from cryptography.hazmat.backends.openssl.backend import backend as ossl + + return ossl.load_der_public_key(data) + + +def load_der_parameters( + data: bytes, backend: typing.Any = None +) -> "dh.DHParameters": + from cryptography.hazmat.backends.openssl.backend import backend as ossl + + return ossl.load_der_parameters(data) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/serialization/pkcs12.py b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/serialization/pkcs12.py new file mode 100644 index 00000000..5b7e5485 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/serialization/pkcs12.py @@ -0,0 +1,205 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +import typing + +from cryptography import x509 +from cryptography.hazmat.primitives import serialization +from cryptography.hazmat.primitives.asymmetric import ( + dsa, + ec, + ed25519, + ed448, + rsa, +) +from cryptography.hazmat.primitives.asymmetric.types import ( + PRIVATE_KEY_TYPES, +) + + +_ALLOWED_PKCS12_TYPES = typing.Union[ + rsa.RSAPrivateKey, + dsa.DSAPrivateKey, + ec.EllipticCurvePrivateKey, +] + + +class PKCS12Certificate: + def __init__( + self, + cert: x509.Certificate, + friendly_name: typing.Optional[bytes], + ): + if not isinstance(cert, x509.Certificate): + raise TypeError("Expecting x509.Certificate object") + if friendly_name is not None and not isinstance(friendly_name, bytes): + raise TypeError("friendly_name must be bytes or None") + self._cert = cert + self._friendly_name = friendly_name + + @property + def friendly_name(self) -> typing.Optional[bytes]: + return self._friendly_name + + @property + def certificate(self) -> x509.Certificate: + return self._cert + + def __eq__(self, other: typing.Any) -> bool: + if not isinstance(other, PKCS12Certificate): + return NotImplemented + + return ( + self.certificate == other.certificate + and self.friendly_name == other.friendly_name + ) + + def __ne__(self, other: typing.Any) -> bool: + return not self == other + + def __hash__(self) -> int: + return hash((self.certificate, self.friendly_name)) + + def __repr__(self) -> str: + return "<PKCS12Certificate({}, friendly_name={!r})>".format( + self.certificate, self.friendly_name + ) + + +class PKCS12KeyAndCertificates: + def __init__( + self, + key: typing.Optional[PRIVATE_KEY_TYPES], + cert: typing.Optional[PKCS12Certificate], + additional_certs: typing.List[PKCS12Certificate], + ): + if key is not None and not isinstance( + key, + ( + rsa.RSAPrivateKey, + dsa.DSAPrivateKey, + ec.EllipticCurvePrivateKey, + ed25519.Ed25519PrivateKey, + ed448.Ed448PrivateKey, + ), + ): + raise TypeError( + "Key must be RSA, DSA, EllipticCurve, ED25519, or ED448" + " private key, or None." + ) + if cert is not None and not isinstance(cert, PKCS12Certificate): + raise TypeError("cert must be a PKCS12Certificate object or None") + if not all( + isinstance(add_cert, PKCS12Certificate) + for add_cert in additional_certs + ): + raise TypeError( + "all values in additional_certs must be PKCS12Certificate" + " objects" + ) + self._key = key + self._cert = cert + self._additional_certs = additional_certs + + @property + def key(self) -> typing.Optional[PRIVATE_KEY_TYPES]: + return self._key + + @property + def cert(self) -> typing.Optional[PKCS12Certificate]: + return self._cert + + @property + def additional_certs(self) -> typing.List[PKCS12Certificate]: + return self._additional_certs + + def __eq__(self, other: typing.Any) -> bool: + if not isinstance(other, PKCS12KeyAndCertificates): + return NotImplemented + + return ( + self.key == other.key + and self.cert == other.cert + and self.additional_certs == other.additional_certs + ) + + def __ne__(self, other: typing.Any) -> bool: + return not self == other + + def __hash__(self) -> int: + return hash((self.key, self.cert, tuple(self.additional_certs))) + + def __repr__(self) -> str: + fmt = ( + "<PKCS12KeyAndCertificates(key={}, cert={}, additional_certs={})>" + ) + return fmt.format(self.key, self.cert, self.additional_certs) + + +def load_key_and_certificates( + data: bytes, + password: typing.Optional[bytes], + backend: typing.Any = None, +) -> typing.Tuple[ + typing.Optional[_ALLOWED_PKCS12_TYPES], + typing.Optional[x509.Certificate], + typing.List[x509.Certificate], +]: + from cryptography.hazmat.backends.openssl.backend import backend as ossl + + return ossl.load_key_and_certificates_from_pkcs12(data, password) + + +def load_pkcs12( + data: bytes, + password: typing.Optional[bytes], + backend: typing.Any = None, +) -> PKCS12KeyAndCertificates: + from cryptography.hazmat.backends.openssl.backend import backend as ossl + + return ossl.load_pkcs12(data, password) + + +def serialize_key_and_certificates( + name: typing.Optional[bytes], + key: typing.Optional[_ALLOWED_PKCS12_TYPES], + cert: typing.Optional[x509.Certificate], + cas: typing.Optional[typing.Iterable[x509.Certificate]], + encryption_algorithm: serialization.KeySerializationEncryption, +) -> bytes: + if key is not None and not isinstance( + key, + ( + rsa.RSAPrivateKey, + dsa.DSAPrivateKey, + ec.EllipticCurvePrivateKey, + ), + ): + raise TypeError( + "Key must be RSA, DSA, or EllipticCurve private key or None." + ) + if cert is not None and not isinstance(cert, x509.Certificate): + raise TypeError("cert must be a certificate or None") + + if cas is not None: + cas = list(cas) + if not all(isinstance(val, x509.Certificate) for val in cas): + raise TypeError("all values in cas must be certificates") + + if not isinstance( + encryption_algorithm, serialization.KeySerializationEncryption + ): + raise TypeError( + "Key encryption algorithm must be a " + "KeySerializationEncryption instance" + ) + + if key is None and cert is None and not cas: + raise ValueError("You must supply at least one of key, cert, or cas") + + from cryptography.hazmat.backends.openssl.backend import backend + + return backend.serialize_key_and_certificates_to_pkcs12( + name, key, cert, cas, encryption_algorithm + ) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/serialization/pkcs7.py b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/serialization/pkcs7.py new file mode 100644 index 00000000..2e052e3b --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/serialization/pkcs7.py @@ -0,0 +1,160 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +import typing + +from cryptography import utils +from cryptography import x509 +from cryptography.hazmat.primitives import hashes, serialization +from cryptography.hazmat.primitives.asymmetric import ec, rsa +from cryptography.utils import _check_byteslike + + +def load_pem_pkcs7_certificates(data: bytes) -> typing.List[x509.Certificate]: + from cryptography.hazmat.backends.openssl.backend import backend + + return backend.load_pem_pkcs7_certificates(data) + + +def load_der_pkcs7_certificates(data: bytes) -> typing.List[x509.Certificate]: + from cryptography.hazmat.backends.openssl.backend import backend + + return backend.load_der_pkcs7_certificates(data) + + +_ALLOWED_PKCS7_HASH_TYPES = typing.Union[ + hashes.SHA1, + hashes.SHA224, + hashes.SHA256, + hashes.SHA384, + hashes.SHA512, +] + +_ALLOWED_PRIVATE_KEY_TYPES = typing.Union[ + rsa.RSAPrivateKey, ec.EllipticCurvePrivateKey +] + + +class PKCS7Options(utils.Enum): + Text = "Add text/plain MIME type" + Binary = "Don't translate input data into canonical MIME format" + DetachedSignature = "Don't embed data in the PKCS7 structure" + NoCapabilities = "Don't embed SMIME capabilities" + NoAttributes = "Don't embed authenticatedAttributes" + NoCerts = "Don't embed signer certificate" + + +class PKCS7SignatureBuilder(object): + def __init__(self, data=None, signers=[], additional_certs=[]): + self._data = data + self._signers = signers + self._additional_certs = additional_certs + + def set_data(self, data: bytes) -> "PKCS7SignatureBuilder": + _check_byteslike("data", data) + if self._data is not None: + raise ValueError("data may only be set once") + + return PKCS7SignatureBuilder(data, self._signers) + + def add_signer( + self, + certificate: x509.Certificate, + private_key: _ALLOWED_PRIVATE_KEY_TYPES, + hash_algorithm: _ALLOWED_PKCS7_HASH_TYPES, + ) -> "PKCS7SignatureBuilder": + if not isinstance( + hash_algorithm, + ( + hashes.SHA1, + hashes.SHA224, + hashes.SHA256, + hashes.SHA384, + hashes.SHA512, + ), + ): + raise TypeError( + "hash_algorithm must be one of hashes.SHA1, SHA224, " + "SHA256, SHA384, or SHA512" + ) + if not isinstance(certificate, x509.Certificate): + raise TypeError("certificate must be a x509.Certificate") + + if not isinstance( + private_key, (rsa.RSAPrivateKey, ec.EllipticCurvePrivateKey) + ): + raise TypeError("Only RSA & EC keys are supported at this time.") + + return PKCS7SignatureBuilder( + self._data, + self._signers + [(certificate, private_key, hash_algorithm)], + ) + + def add_certificate( + self, certificate: x509.Certificate + ) -> "PKCS7SignatureBuilder": + if not isinstance(certificate, x509.Certificate): + raise TypeError("certificate must be a x509.Certificate") + + return PKCS7SignatureBuilder( + self._data, self._signers, self._additional_certs + [certificate] + ) + + def sign( + self, + encoding: serialization.Encoding, + options: typing.Iterable[PKCS7Options], + backend: typing.Any = None, + ) -> bytes: + if len(self._signers) == 0: + raise ValueError("Must have at least one signer") + if self._data is None: + raise ValueError("You must add data to sign") + options = list(options) + if not all(isinstance(x, PKCS7Options) for x in options): + raise ValueError("options must be from the PKCS7Options enum") + if encoding not in ( + serialization.Encoding.PEM, + serialization.Encoding.DER, + serialization.Encoding.SMIME, + ): + raise ValueError( + "Must be PEM, DER, or SMIME from the Encoding enum" + ) + + # Text is a meaningless option unless it is accompanied by + # DetachedSignature + if ( + PKCS7Options.Text in options + and PKCS7Options.DetachedSignature not in options + ): + raise ValueError( + "When passing the Text option you must also pass " + "DetachedSignature" + ) + + if PKCS7Options.Text in options and encoding in ( + serialization.Encoding.DER, + serialization.Encoding.PEM, + ): + raise ValueError( + "The Text option is only available for SMIME serialization" + ) + + # No attributes implies no capabilities so we'll error if you try to + # pass both. + if ( + PKCS7Options.NoAttributes in options + and PKCS7Options.NoCapabilities in options + ): + raise ValueError( + "NoAttributes is a superset of NoCapabilities. Do not pass " + "both values." + ) + + from cryptography.hazmat.backends.openssl.backend import ( + backend as ossl, + ) + + return ossl.pkcs7_sign(self, encoding, options) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/serialization/ssh.py b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/serialization/ssh.py new file mode 100644 index 00000000..1897fec4 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/serialization/ssh.py @@ -0,0 +1,705 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + + +import binascii +import os +import re +import struct +import typing +from base64 import encodebytes as _base64_encode + +from cryptography import utils +from cryptography.exceptions import UnsupportedAlgorithm +from cryptography.hazmat.primitives.asymmetric import dsa, ec, ed25519, rsa +from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes +from cryptography.hazmat.primitives.serialization import ( + Encoding, + NoEncryption, + PrivateFormat, + PublicFormat, +) + +try: + from bcrypt import kdf as _bcrypt_kdf + + _bcrypt_supported = True +except ImportError: + _bcrypt_supported = False + + def _bcrypt_kdf( + password: bytes, + salt: bytes, + desired_key_bytes: int, + rounds: int, + ignore_few_rounds: bool = False, + ) -> bytes: + raise UnsupportedAlgorithm("Need bcrypt module") + + +_SSH_ED25519 = b"ssh-ed25519" +_SSH_RSA = b"ssh-rsa" +_SSH_DSA = b"ssh-dss" +_ECDSA_NISTP256 = b"ecdsa-sha2-nistp256" +_ECDSA_NISTP384 = b"ecdsa-sha2-nistp384" +_ECDSA_NISTP521 = b"ecdsa-sha2-nistp521" +_CERT_SUFFIX = b"-cert-v01@openssh.com" + +_SSH_PUBKEY_RC = re.compile(br"\A(\S+)[ \t]+(\S+)") +_SK_MAGIC = b"openssh-key-v1\0" +_SK_START = b"-----BEGIN OPENSSH PRIVATE KEY-----" +_SK_END = b"-----END OPENSSH PRIVATE KEY-----" +_BCRYPT = b"bcrypt" +_NONE = b"none" +_DEFAULT_CIPHER = b"aes256-ctr" +_DEFAULT_ROUNDS = 16 +_MAX_PASSWORD = 72 + +# re is only way to work on bytes-like data +_PEM_RC = re.compile(_SK_START + b"(.*?)" + _SK_END, re.DOTALL) + +# padding for max blocksize +_PADDING = memoryview(bytearray(range(1, 1 + 16))) + +# ciphers that are actually used in key wrapping +_SSH_CIPHERS = { + b"aes256-ctr": (algorithms.AES, 32, modes.CTR, 16), + b"aes256-cbc": (algorithms.AES, 32, modes.CBC, 16), +} + +# map local curve name to key type +_ECDSA_KEY_TYPE = { + "secp256r1": _ECDSA_NISTP256, + "secp384r1": _ECDSA_NISTP384, + "secp521r1": _ECDSA_NISTP521, +} + +_U32 = struct.Struct(b">I") +_U64 = struct.Struct(b">Q") + + +def _ecdsa_key_type(public_key): + """Return SSH key_type and curve_name for private key.""" + curve = public_key.curve + if curve.name not in _ECDSA_KEY_TYPE: + raise ValueError( + "Unsupported curve for ssh private key: %r" % curve.name + ) + return _ECDSA_KEY_TYPE[curve.name] + + +def _ssh_pem_encode(data, prefix=_SK_START + b"\n", suffix=_SK_END + b"\n"): + return b"".join([prefix, _base64_encode(data), suffix]) + + +def _check_block_size(data, block_len): + """Require data to be full blocks""" + if not data or len(data) % block_len != 0: + raise ValueError("Corrupt data: missing padding") + + +def _check_empty(data): + """All data should have been parsed.""" + if data: + raise ValueError("Corrupt data: unparsed data") + + +def _init_cipher(ciphername, password, salt, rounds): + """Generate key + iv and return cipher.""" + if not password: + raise ValueError("Key is password-protected.") + + algo, key_len, mode, iv_len = _SSH_CIPHERS[ciphername] + seed = _bcrypt_kdf(password, salt, key_len + iv_len, rounds, True) + return Cipher(algo(seed[:key_len]), mode(seed[key_len:])) + + +def _get_u32(data): + """Uint32""" + if len(data) < 4: + raise ValueError("Invalid data") + return _U32.unpack(data[:4])[0], data[4:] + + +def _get_u64(data): + """Uint64""" + if len(data) < 8: + raise ValueError("Invalid data") + return _U64.unpack(data[:8])[0], data[8:] + + +def _get_sshstr(data): + """Bytes with u32 length prefix""" + n, data = _get_u32(data) + if n > len(data): + raise ValueError("Invalid data") + return data[:n], data[n:] + + +def _get_mpint(data): + """Big integer.""" + val, data = _get_sshstr(data) + if val and val[0] > 0x7F: + raise ValueError("Invalid data") + return int.from_bytes(val, "big"), data + + +def _to_mpint(val): + """Storage format for signed bigint.""" + if val < 0: + raise ValueError("negative mpint not allowed") + if not val: + return b"" + nbytes = (val.bit_length() + 8) // 8 + return utils.int_to_bytes(val, nbytes) + + +class _FragList(object): + """Build recursive structure without data copy.""" + + def __init__(self, init=None): + self.flist = [] + if init: + self.flist.extend(init) + + def put_raw(self, val): + """Add plain bytes""" + self.flist.append(val) + + def put_u32(self, val): + """Big-endian uint32""" + self.flist.append(_U32.pack(val)) + + def put_sshstr(self, val): + """Bytes prefixed with u32 length""" + if isinstance(val, (bytes, memoryview, bytearray)): + self.put_u32(len(val)) + self.flist.append(val) + else: + self.put_u32(val.size()) + self.flist.extend(val.flist) + + def put_mpint(self, val): + """Big-endian bigint prefixed with u32 length""" + self.put_sshstr(_to_mpint(val)) + + def size(self): + """Current number of bytes""" + return sum(map(len, self.flist)) + + def render(self, dstbuf, pos=0): + """Write into bytearray""" + for frag in self.flist: + flen = len(frag) + start, pos = pos, pos + flen + dstbuf[start:pos] = frag + return pos + + def tobytes(self): + """Return as bytes""" + buf = memoryview(bytearray(self.size())) + self.render(buf) + return buf.tobytes() + + +class _SSHFormatRSA(object): + """Format for RSA keys. + + Public: + mpint e, n + Private: + mpint n, e, d, iqmp, p, q + """ + + def get_public(self, data): + """RSA public fields""" + e, data = _get_mpint(data) + n, data = _get_mpint(data) + return (e, n), data + + def load_public(self, key_type, data): + """Make RSA public key from data.""" + (e, n), data = self.get_public(data) + public_numbers = rsa.RSAPublicNumbers(e, n) + public_key = public_numbers.public_key() + return public_key, data + + def load_private(self, data, pubfields): + """Make RSA private key from data.""" + n, data = _get_mpint(data) + e, data = _get_mpint(data) + d, data = _get_mpint(data) + iqmp, data = _get_mpint(data) + p, data = _get_mpint(data) + q, data = _get_mpint(data) + + if (e, n) != pubfields: + raise ValueError("Corrupt data: rsa field mismatch") + dmp1 = rsa.rsa_crt_dmp1(d, p) + dmq1 = rsa.rsa_crt_dmq1(d, q) + public_numbers = rsa.RSAPublicNumbers(e, n) + private_numbers = rsa.RSAPrivateNumbers( + p, q, d, dmp1, dmq1, iqmp, public_numbers + ) + private_key = private_numbers.private_key() + return private_key, data + + def encode_public(self, public_key, f_pub): + """Write RSA public key""" + pubn = public_key.public_numbers() + f_pub.put_mpint(pubn.e) + f_pub.put_mpint(pubn.n) + + def encode_private(self, private_key, f_priv): + """Write RSA private key""" + private_numbers = private_key.private_numbers() + public_numbers = private_numbers.public_numbers + + f_priv.put_mpint(public_numbers.n) + f_priv.put_mpint(public_numbers.e) + + f_priv.put_mpint(private_numbers.d) + f_priv.put_mpint(private_numbers.iqmp) + f_priv.put_mpint(private_numbers.p) + f_priv.put_mpint(private_numbers.q) + + +class _SSHFormatDSA(object): + """Format for DSA keys. + + Public: + mpint p, q, g, y + Private: + mpint p, q, g, y, x + """ + + def get_public(self, data): + """DSA public fields""" + p, data = _get_mpint(data) + q, data = _get_mpint(data) + g, data = _get_mpint(data) + y, data = _get_mpint(data) + return (p, q, g, y), data + + def load_public(self, key_type, data): + """Make DSA public key from data.""" + (p, q, g, y), data = self.get_public(data) + parameter_numbers = dsa.DSAParameterNumbers(p, q, g) + public_numbers = dsa.DSAPublicNumbers(y, parameter_numbers) + self._validate(public_numbers) + public_key = public_numbers.public_key() + return public_key, data + + def load_private(self, data, pubfields): + """Make DSA private key from data.""" + (p, q, g, y), data = self.get_public(data) + x, data = _get_mpint(data) + + if (p, q, g, y) != pubfields: + raise ValueError("Corrupt data: dsa field mismatch") + parameter_numbers = dsa.DSAParameterNumbers(p, q, g) + public_numbers = dsa.DSAPublicNumbers(y, parameter_numbers) + self._validate(public_numbers) + private_numbers = dsa.DSAPrivateNumbers(x, public_numbers) + private_key = private_numbers.private_key() + return private_key, data + + def encode_public(self, public_key, f_pub): + """Write DSA public key""" + public_numbers = public_key.public_numbers() + parameter_numbers = public_numbers.parameter_numbers + self._validate(public_numbers) + + f_pub.put_mpint(parameter_numbers.p) + f_pub.put_mpint(parameter_numbers.q) + f_pub.put_mpint(parameter_numbers.g) + f_pub.put_mpint(public_numbers.y) + + def encode_private(self, private_key, f_priv): + """Write DSA private key""" + self.encode_public(private_key.public_key(), f_priv) + f_priv.put_mpint(private_key.private_numbers().x) + + def _validate(self, public_numbers): + parameter_numbers = public_numbers.parameter_numbers + if parameter_numbers.p.bit_length() != 1024: + raise ValueError("SSH supports only 1024 bit DSA keys") + + +class _SSHFormatECDSA(object): + """Format for ECDSA keys. + + Public: + str curve + bytes point + Private: + str curve + bytes point + mpint secret + """ + + def __init__(self, ssh_curve_name, curve): + self.ssh_curve_name = ssh_curve_name + self.curve = curve + + def get_public(self, data): + """ECDSA public fields""" + curve, data = _get_sshstr(data) + point, data = _get_sshstr(data) + if curve != self.ssh_curve_name: + raise ValueError("Curve name mismatch") + if point[0] != 4: + raise NotImplementedError("Need uncompressed point") + return (curve, point), data + + def load_public(self, key_type, data): + """Make ECDSA public key from data.""" + (curve_name, point), data = self.get_public(data) + public_key = ec.EllipticCurvePublicKey.from_encoded_point( + self.curve, point.tobytes() + ) + return public_key, data + + def load_private(self, data, pubfields): + """Make ECDSA private key from data.""" + (curve_name, point), data = self.get_public(data) + secret, data = _get_mpint(data) + + if (curve_name, point) != pubfields: + raise ValueError("Corrupt data: ecdsa field mismatch") + private_key = ec.derive_private_key(secret, self.curve) + return private_key, data + + def encode_public(self, public_key, f_pub): + """Write ECDSA public key""" + point = public_key.public_bytes( + Encoding.X962, PublicFormat.UncompressedPoint + ) + f_pub.put_sshstr(self.ssh_curve_name) + f_pub.put_sshstr(point) + + def encode_private(self, private_key, f_priv): + """Write ECDSA private key""" + public_key = private_key.public_key() + private_numbers = private_key.private_numbers() + + self.encode_public(public_key, f_priv) + f_priv.put_mpint(private_numbers.private_value) + + +class _SSHFormatEd25519(object): + """Format for Ed25519 keys. + + Public: + bytes point + Private: + bytes point + bytes secret_and_point + """ + + def get_public(self, data): + """Ed25519 public fields""" + point, data = _get_sshstr(data) + return (point,), data + + def load_public(self, key_type, data): + """Make Ed25519 public key from data.""" + (point,), data = self.get_public(data) + public_key = ed25519.Ed25519PublicKey.from_public_bytes( + point.tobytes() + ) + return public_key, data + + def load_private(self, data, pubfields): + """Make Ed25519 private key from data.""" + (point,), data = self.get_public(data) + keypair, data = _get_sshstr(data) + + secret = keypair[:32] + point2 = keypair[32:] + if point != point2 or (point,) != pubfields: + raise ValueError("Corrupt data: ed25519 field mismatch") + private_key = ed25519.Ed25519PrivateKey.from_private_bytes(secret) + return private_key, data + + def encode_public(self, public_key, f_pub): + """Write Ed25519 public key""" + raw_public_key = public_key.public_bytes( + Encoding.Raw, PublicFormat.Raw + ) + f_pub.put_sshstr(raw_public_key) + + def encode_private(self, private_key, f_priv): + """Write Ed25519 private key""" + public_key = private_key.public_key() + raw_private_key = private_key.private_bytes( + Encoding.Raw, PrivateFormat.Raw, NoEncryption() + ) + raw_public_key = public_key.public_bytes( + Encoding.Raw, PublicFormat.Raw + ) + f_keypair = _FragList([raw_private_key, raw_public_key]) + + self.encode_public(public_key, f_priv) + f_priv.put_sshstr(f_keypair) + + +_KEY_FORMATS = { + _SSH_RSA: _SSHFormatRSA(), + _SSH_DSA: _SSHFormatDSA(), + _SSH_ED25519: _SSHFormatEd25519(), + _ECDSA_NISTP256: _SSHFormatECDSA(b"nistp256", ec.SECP256R1()), + _ECDSA_NISTP384: _SSHFormatECDSA(b"nistp384", ec.SECP384R1()), + _ECDSA_NISTP521: _SSHFormatECDSA(b"nistp521", ec.SECP521R1()), +} + + +def _lookup_kformat(key_type): + """Return valid format or throw error""" + if not isinstance(key_type, bytes): + key_type = memoryview(key_type).tobytes() + if key_type in _KEY_FORMATS: + return _KEY_FORMATS[key_type] + raise UnsupportedAlgorithm("Unsupported key type: %r" % key_type) + + +_SSH_PRIVATE_KEY_TYPES = typing.Union[ + ec.EllipticCurvePrivateKey, + rsa.RSAPrivateKey, + dsa.DSAPrivateKey, + ed25519.Ed25519PrivateKey, +] + + +def load_ssh_private_key( + data: bytes, + password: typing.Optional[bytes], + backend: typing.Any = None, +) -> _SSH_PRIVATE_KEY_TYPES: + """Load private key from OpenSSH custom encoding.""" + utils._check_byteslike("data", data) + if password is not None: + utils._check_bytes("password", password) + + m = _PEM_RC.search(data) + if not m: + raise ValueError("Not OpenSSH private key format") + p1 = m.start(1) + p2 = m.end(1) + data = binascii.a2b_base64(memoryview(data)[p1:p2]) + if not data.startswith(_SK_MAGIC): + raise ValueError("Not OpenSSH private key format") + data = memoryview(data)[len(_SK_MAGIC) :] + + # parse header + ciphername, data = _get_sshstr(data) + kdfname, data = _get_sshstr(data) + kdfoptions, data = _get_sshstr(data) + nkeys, data = _get_u32(data) + if nkeys != 1: + raise ValueError("Only one key supported") + + # load public key data + pubdata, data = _get_sshstr(data) + pub_key_type, pubdata = _get_sshstr(pubdata) + kformat = _lookup_kformat(pub_key_type) + pubfields, pubdata = kformat.get_public(pubdata) + _check_empty(pubdata) + + # load secret data + edata, data = _get_sshstr(data) + _check_empty(data) + + if (ciphername, kdfname) != (_NONE, _NONE): + ciphername = ciphername.tobytes() + if ciphername not in _SSH_CIPHERS: + raise UnsupportedAlgorithm("Unsupported cipher: %r" % ciphername) + if kdfname != _BCRYPT: + raise UnsupportedAlgorithm("Unsupported KDF: %r" % kdfname) + blklen = _SSH_CIPHERS[ciphername][3] + _check_block_size(edata, blklen) + salt, kbuf = _get_sshstr(kdfoptions) + rounds, kbuf = _get_u32(kbuf) + _check_empty(kbuf) + ciph = _init_cipher(ciphername, password, salt.tobytes(), rounds) + edata = memoryview(ciph.decryptor().update(edata)) + else: + blklen = 8 + _check_block_size(edata, blklen) + ck1, edata = _get_u32(edata) + ck2, edata = _get_u32(edata) + if ck1 != ck2: + raise ValueError("Corrupt data: broken checksum") + + # load per-key struct + key_type, edata = _get_sshstr(edata) + if key_type != pub_key_type: + raise ValueError("Corrupt data: key type mismatch") + private_key, edata = kformat.load_private(edata, pubfields) + comment, edata = _get_sshstr(edata) + + # yes, SSH does padding check *after* all other parsing is done. + # need to follow as it writes zero-byte padding too. + if edata != _PADDING[: len(edata)]: + raise ValueError("Corrupt data: invalid padding") + + return private_key + + +def serialize_ssh_private_key( + private_key: _SSH_PRIVATE_KEY_TYPES, + password: typing.Optional[bytes] = None, +) -> bytes: + """Serialize private key with OpenSSH custom encoding.""" + if password is not None: + utils._check_bytes("password", password) + if password and len(password) > _MAX_PASSWORD: + raise ValueError( + "Passwords longer than 72 bytes are not supported by " + "OpenSSH private key format" + ) + + if isinstance(private_key, ec.EllipticCurvePrivateKey): + key_type = _ecdsa_key_type(private_key.public_key()) + elif isinstance(private_key, rsa.RSAPrivateKey): + key_type = _SSH_RSA + elif isinstance(private_key, dsa.DSAPrivateKey): + key_type = _SSH_DSA + elif isinstance(private_key, ed25519.Ed25519PrivateKey): + key_type = _SSH_ED25519 + else: + raise ValueError("Unsupported key type") + kformat = _lookup_kformat(key_type) + + # setup parameters + f_kdfoptions = _FragList() + if password: + ciphername = _DEFAULT_CIPHER + blklen = _SSH_CIPHERS[ciphername][3] + kdfname = _BCRYPT + rounds = _DEFAULT_ROUNDS + salt = os.urandom(16) + f_kdfoptions.put_sshstr(salt) + f_kdfoptions.put_u32(rounds) + ciph = _init_cipher(ciphername, password, salt, rounds) + else: + ciphername = kdfname = _NONE + blklen = 8 + ciph = None + nkeys = 1 + checkval = os.urandom(4) + comment = b"" + + # encode public and private parts together + f_public_key = _FragList() + f_public_key.put_sshstr(key_type) + kformat.encode_public(private_key.public_key(), f_public_key) + + f_secrets = _FragList([checkval, checkval]) + f_secrets.put_sshstr(key_type) + kformat.encode_private(private_key, f_secrets) + f_secrets.put_sshstr(comment) + f_secrets.put_raw(_PADDING[: blklen - (f_secrets.size() % blklen)]) + + # top-level structure + f_main = _FragList() + f_main.put_raw(_SK_MAGIC) + f_main.put_sshstr(ciphername) + f_main.put_sshstr(kdfname) + f_main.put_sshstr(f_kdfoptions) + f_main.put_u32(nkeys) + f_main.put_sshstr(f_public_key) + f_main.put_sshstr(f_secrets) + + # copy result info bytearray + slen = f_secrets.size() + mlen = f_main.size() + buf = memoryview(bytearray(mlen + blklen)) + f_main.render(buf) + ofs = mlen - slen + + # encrypt in-place + if ciph is not None: + ciph.encryptor().update_into(buf[ofs:mlen], buf[ofs:]) + + txt = _ssh_pem_encode(buf[:mlen]) + # Ignore the following type because mypy wants + # Sequence[bytes] but what we're passing is fine. + # https://github.com/python/mypy/issues/9999 + buf[ofs:mlen] = bytearray(slen) # type: ignore + return txt + + +_SSH_PUBLIC_KEY_TYPES = typing.Union[ + ec.EllipticCurvePublicKey, + rsa.RSAPublicKey, + dsa.DSAPublicKey, + ed25519.Ed25519PublicKey, +] + + +def load_ssh_public_key( + data: bytes, backend: typing.Any = None +) -> _SSH_PUBLIC_KEY_TYPES: + """Load public key from OpenSSH one-line format.""" + utils._check_byteslike("data", data) + + m = _SSH_PUBKEY_RC.match(data) + if not m: + raise ValueError("Invalid line format") + key_type = orig_key_type = m.group(1) + key_body = m.group(2) + with_cert = False + if _CERT_SUFFIX == key_type[-len(_CERT_SUFFIX) :]: + with_cert = True + key_type = key_type[: -len(_CERT_SUFFIX)] + kformat = _lookup_kformat(key_type) + + try: + data = memoryview(binascii.a2b_base64(key_body)) + except (TypeError, binascii.Error): + raise ValueError("Invalid key format") + + inner_key_type, data = _get_sshstr(data) + if inner_key_type != orig_key_type: + raise ValueError("Invalid key format") + if with_cert: + nonce, data = _get_sshstr(data) + public_key, data = kformat.load_public(key_type, data) + if with_cert: + serial, data = _get_u64(data) + cctype, data = _get_u32(data) + key_id, data = _get_sshstr(data) + principals, data = _get_sshstr(data) + valid_after, data = _get_u64(data) + valid_before, data = _get_u64(data) + crit_options, data = _get_sshstr(data) + extensions, data = _get_sshstr(data) + reserved, data = _get_sshstr(data) + sig_key, data = _get_sshstr(data) + signature, data = _get_sshstr(data) + _check_empty(data) + return public_key + + +def serialize_ssh_public_key(public_key: _SSH_PUBLIC_KEY_TYPES) -> bytes: + """One-line public key format for OpenSSH""" + if isinstance(public_key, ec.EllipticCurvePublicKey): + key_type = _ecdsa_key_type(public_key) + elif isinstance(public_key, rsa.RSAPublicKey): + key_type = _SSH_RSA + elif isinstance(public_key, dsa.DSAPublicKey): + key_type = _SSH_DSA + elif isinstance(public_key, ed25519.Ed25519PublicKey): + key_type = _SSH_ED25519 + else: + raise ValueError("Unsupported key type") + kformat = _lookup_kformat(key_type) + + f_pub = _FragList() + f_pub.put_sshstr(key_type) + kformat.encode_public(public_key, f_pub) + + pub = binascii.b2a_base64(f_pub.tobytes()).strip() + return b"".join([key_type, b" ", pub]) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/twofactor/__init__.py b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/twofactor/__init__.py new file mode 100644 index 00000000..8a8b30f2 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/twofactor/__init__.py @@ -0,0 +1,7 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + + +class InvalidToken(Exception): + pass diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/twofactor/hotp.py b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/twofactor/hotp.py new file mode 100644 index 00000000..4dd9bac3 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/twofactor/hotp.py @@ -0,0 +1,97 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + + +import base64 +import struct +import typing +from urllib.parse import quote, urlencode + +from cryptography.hazmat.primitives import constant_time, hmac +from cryptography.hazmat.primitives.hashes import SHA1, SHA256, SHA512 +from cryptography.hazmat.primitives.twofactor import InvalidToken + + +_ALLOWED_HASH_TYPES = typing.Union[SHA1, SHA256, SHA512] + + +def _generate_uri( + hotp: "HOTP", + type_name: str, + account_name: str, + issuer: typing.Optional[str], + extra_parameters: typing.List[typing.Tuple[str, int]], +) -> str: + parameters = [ + ("digits", hotp._length), + ("secret", base64.b32encode(hotp._key)), + ("algorithm", hotp._algorithm.name.upper()), + ] + + if issuer is not None: + parameters.append(("issuer", issuer)) + + parameters.extend(extra_parameters) + + uriparts = { + "type": type_name, + "label": ( + "%s:%s" % (quote(issuer), quote(account_name)) + if issuer + else quote(account_name) + ), + "parameters": urlencode(parameters), + } + return "otpauth://{type}/{label}?{parameters}".format(**uriparts) + + +class HOTP(object): + def __init__( + self, + key: bytes, + length: int, + algorithm: _ALLOWED_HASH_TYPES, + backend: typing.Any = None, + enforce_key_length: bool = True, + ) -> None: + if len(key) < 16 and enforce_key_length is True: + raise ValueError("Key length has to be at least 128 bits.") + + if not isinstance(length, int): + raise TypeError("Length parameter must be an integer type.") + + if length < 6 or length > 8: + raise ValueError("Length of HOTP has to be between 6 to 8.") + + if not isinstance(algorithm, (SHA1, SHA256, SHA512)): + raise TypeError("Algorithm must be SHA1, SHA256 or SHA512.") + + self._key = key + self._length = length + self._algorithm = algorithm + + def generate(self, counter: int) -> bytes: + truncated_value = self._dynamic_truncate(counter) + hotp = truncated_value % (10 ** self._length) + return "{0:0{1}}".format(hotp, self._length).encode() + + def verify(self, hotp: bytes, counter: int) -> None: + if not constant_time.bytes_eq(self.generate(counter), hotp): + raise InvalidToken("Supplied HOTP value does not match.") + + def _dynamic_truncate(self, counter: int) -> int: + ctx = hmac.HMAC(self._key, self._algorithm) + ctx.update(struct.pack(">Q", counter)) + hmac_value = ctx.finalize() + + offset = hmac_value[len(hmac_value) - 1] & 0b1111 + p = hmac_value[offset : offset + 4] + return struct.unpack(">I", p)[0] & 0x7FFFFFFF + + def get_provisioning_uri( + self, account_name: str, counter: int, issuer: typing.Optional[str] + ) -> str: + return _generate_uri( + self, "hotp", account_name, issuer, [("counter", int(counter))] + ) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/twofactor/totp.py b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/twofactor/totp.py new file mode 100644 index 00000000..b59fb17b --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/hazmat/primitives/twofactor/totp.py @@ -0,0 +1,48 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +import typing + +from cryptography.hazmat.primitives import constant_time +from cryptography.hazmat.primitives.twofactor import InvalidToken +from cryptography.hazmat.primitives.twofactor.hotp import ( + HOTP, + _ALLOWED_HASH_TYPES, + _generate_uri, +) + + +class TOTP(object): + def __init__( + self, + key: bytes, + length: int, + algorithm: _ALLOWED_HASH_TYPES, + time_step: int, + backend: typing.Any = None, + enforce_key_length: bool = True, + ): + self._time_step = time_step + self._hotp = HOTP( + key, length, algorithm, enforce_key_length=enforce_key_length + ) + + def generate(self, time: typing.Union[int, float]) -> bytes: + counter = int(time / self._time_step) + return self._hotp.generate(counter) + + def verify(self, totp: bytes, time: int) -> None: + if not constant_time.bytes_eq(self.generate(time), totp): + raise InvalidToken("Supplied TOTP value does not match.") + + def get_provisioning_uri( + self, account_name: str, issuer: typing.Optional[str] + ) -> str: + return _generate_uri( + self._hotp, + "totp", + account_name, + issuer, + [("period", int(self._time_step))], + ) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/py.typed b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/py.typed new file mode 100644 index 00000000..e69de29b diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/utils.py b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/utils.py new file mode 100644 index 00000000..eb652bb9 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/utils.py @@ -0,0 +1,183 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + + +import abc +import enum +import inspect +import sys +import types +import typing +import warnings + + +# We use a UserWarning subclass, instead of DeprecationWarning, because CPython +# decided deprecation warnings should be invisble by default. +class CryptographyDeprecationWarning(UserWarning): + pass + + +# Several APIs were deprecated with no specific end-of-life date because of the +# ubiquity of their use. They should not be removed until we agree on when that +# cycle ends. +PersistentlyDeprecated2017 = CryptographyDeprecationWarning +PersistentlyDeprecated2019 = CryptographyDeprecationWarning +DeprecatedIn34 = CryptographyDeprecationWarning +DeprecatedIn35 = CryptographyDeprecationWarning +DeprecatedIn36 = CryptographyDeprecationWarning + + +def _check_bytes(name: str, value: bytes) -> None: + if not isinstance(value, bytes): + raise TypeError("{} must be bytes".format(name)) + + +def _check_byteslike(name: str, value: bytes) -> None: + try: + memoryview(value) + except TypeError: + raise TypeError("{} must be bytes-like".format(name)) + + +def read_only_property(name: str): + return property(lambda self: getattr(self, name)) + + +if typing.TYPE_CHECKING: + from typing_extensions import Protocol + + _T_class = typing.TypeVar("_T_class", bound=type) + + class _RegisterDecoratorType(Protocol): + def __call__( + self, klass: _T_class, *, check_annotations: bool = False + ) -> _T_class: + ... + + +def register_interface(iface: abc.ABCMeta) -> "_RegisterDecoratorType": + def register_decorator( + klass: "_T_class", *, check_annotations: bool = False + ) -> "_T_class": + verify_interface(iface, klass, check_annotations=check_annotations) + iface.register(klass) + return klass + + return register_decorator + + +def int_to_bytes(integer: int, length: typing.Optional[int] = None) -> bytes: + return integer.to_bytes( + length or (integer.bit_length() + 7) // 8 or 1, "big" + ) + + +class InterfaceNotImplemented(Exception): + pass + + +def strip_annotation(signature): + return inspect.Signature( + [ + param.replace(annotation=inspect.Parameter.empty) + for param in signature.parameters.values() + ] + ) + + +def verify_interface(iface, klass, *, check_annotations=False): + for method in iface.__abstractmethods__: + if not hasattr(klass, method): + raise InterfaceNotImplemented( + "{} is missing a {!r} method".format(klass, method) + ) + if isinstance(getattr(iface, method), abc.abstractproperty): + # Can't properly verify these yet. + continue + sig = inspect.signature(getattr(iface, method)) + actual = inspect.signature(getattr(klass, method)) + if check_annotations: + ok = sig == actual + else: + ok = strip_annotation(sig) == strip_annotation(actual) + if not ok: + raise InterfaceNotImplemented( + "{}.{}'s signature differs from the expected. Expected: " + "{!r}. Received: {!r}".format(klass, method, sig, actual) + ) + + +class _DeprecatedValue(object): + def __init__(self, value, message, warning_class): + self.value = value + self.message = message + self.warning_class = warning_class + + +class _ModuleWithDeprecations(types.ModuleType): + def __init__(self, module): + super().__init__(module.__name__) + self.__dict__["_module"] = module + + def __getattr__(self, attr): + obj = getattr(self._module, attr) + if isinstance(obj, _DeprecatedValue): + warnings.warn(obj.message, obj.warning_class, stacklevel=2) + obj = obj.value + return obj + + def __setattr__(self, attr, value): + setattr(self._module, attr, value) + + def __delattr__(self, attr): + obj = getattr(self._module, attr) + if isinstance(obj, _DeprecatedValue): + warnings.warn(obj.message, obj.warning_class, stacklevel=2) + + delattr(self._module, attr) + + def __dir__(self): + return ["_module"] + dir(self._module) + + +def deprecated(value, module_name, message, warning_class): + module = sys.modules[module_name] + if not isinstance(module, _ModuleWithDeprecations): + sys.modules[module_name] = _ModuleWithDeprecations( + module + ) # type: ignore[assignment] + return _DeprecatedValue(value, message, warning_class) + + +def cached_property(func): + cached_name = "_cached_{}".format(func) + sentinel = object() + + def inner(instance): + cache = getattr(instance, cached_name, sentinel) + if cache is not sentinel: + return cache + result = func(instance) + setattr(instance, cached_name, result) + return result + + return property(inner) + + +int_from_bytes = deprecated( + int.from_bytes, + __name__, + "int_from_bytes is deprecated, use int.from_bytes instead", + DeprecatedIn34, +) + + +# Python 3.10 changed representation of enums. We use well-defined object +# representation and string representation from Python 3.9. +class Enum(enum.Enum): + def __repr__(self): + return f"<{self.__class__.__name__}.{self._name_}: {self._value_!r}>" + + def __str__(self): + return f"{self.__class__.__name__}.{self._name_}" diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/x509/__init__.py b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/x509/__init__.py new file mode 100644 index 00000000..906075d1 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/x509/__init__.py @@ -0,0 +1,249 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + + +from cryptography.x509 import certificate_transparency +from cryptography.x509.base import ( + Attribute, + AttributeNotFound, + Attributes, + Certificate, + CertificateBuilder, + CertificateRevocationList, + CertificateRevocationListBuilder, + CertificateSigningRequest, + CertificateSigningRequestBuilder, + InvalidVersion, + RevokedCertificate, + RevokedCertificateBuilder, + Version, + load_der_x509_certificate, + load_der_x509_crl, + load_der_x509_csr, + load_pem_x509_certificate, + load_pem_x509_crl, + load_pem_x509_csr, + random_serial_number, +) +from cryptography.x509.extensions import ( + AccessDescription, + AuthorityInformationAccess, + AuthorityKeyIdentifier, + BasicConstraints, + CRLDistributionPoints, + CRLNumber, + CRLReason, + CertificateIssuer, + CertificatePolicies, + DeltaCRLIndicator, + DistributionPoint, + DuplicateExtension, + ExtendedKeyUsage, + Extension, + ExtensionNotFound, + ExtensionType, + Extensions, + FreshestCRL, + GeneralNames, + InhibitAnyPolicy, + InvalidityDate, + IssuerAlternativeName, + IssuingDistributionPoint, + KeyUsage, + NameConstraints, + NoticeReference, + OCSPNoCheck, + OCSPNonce, + PolicyConstraints, + PolicyInformation, + PrecertPoison, + PrecertificateSignedCertificateTimestamps, + ReasonFlags, + SignedCertificateTimestamps, + SubjectAlternativeName, + SubjectInformationAccess, + SubjectKeyIdentifier, + TLSFeature, + TLSFeatureType, + UnrecognizedExtension, + UserNotice, +) +from cryptography.x509.general_name import ( + DNSName, + DirectoryName, + GeneralName, + IPAddress, + OtherName, + RFC822Name, + RegisteredID, + UniformResourceIdentifier, + UnsupportedGeneralNameType, +) +from cryptography.x509.name import ( + Name, + NameAttribute, + RelativeDistinguishedName, +) +from cryptography.x509.oid import ( + AuthorityInformationAccessOID, + CRLEntryExtensionOID, + CertificatePoliciesOID, + ExtendedKeyUsageOID, + ExtensionOID, + NameOID, + ObjectIdentifier, + SignatureAlgorithmOID, +) + + +OID_AUTHORITY_INFORMATION_ACCESS = ExtensionOID.AUTHORITY_INFORMATION_ACCESS +OID_AUTHORITY_KEY_IDENTIFIER = ExtensionOID.AUTHORITY_KEY_IDENTIFIER +OID_BASIC_CONSTRAINTS = ExtensionOID.BASIC_CONSTRAINTS +OID_CERTIFICATE_POLICIES = ExtensionOID.CERTIFICATE_POLICIES +OID_CRL_DISTRIBUTION_POINTS = ExtensionOID.CRL_DISTRIBUTION_POINTS +OID_EXTENDED_KEY_USAGE = ExtensionOID.EXTENDED_KEY_USAGE +OID_FRESHEST_CRL = ExtensionOID.FRESHEST_CRL +OID_INHIBIT_ANY_POLICY = ExtensionOID.INHIBIT_ANY_POLICY +OID_ISSUER_ALTERNATIVE_NAME = ExtensionOID.ISSUER_ALTERNATIVE_NAME +OID_KEY_USAGE = ExtensionOID.KEY_USAGE +OID_NAME_CONSTRAINTS = ExtensionOID.NAME_CONSTRAINTS +OID_OCSP_NO_CHECK = ExtensionOID.OCSP_NO_CHECK +OID_POLICY_CONSTRAINTS = ExtensionOID.POLICY_CONSTRAINTS +OID_POLICY_MAPPINGS = ExtensionOID.POLICY_MAPPINGS +OID_SUBJECT_ALTERNATIVE_NAME = ExtensionOID.SUBJECT_ALTERNATIVE_NAME +OID_SUBJECT_DIRECTORY_ATTRIBUTES = ExtensionOID.SUBJECT_DIRECTORY_ATTRIBUTES +OID_SUBJECT_INFORMATION_ACCESS = ExtensionOID.SUBJECT_INFORMATION_ACCESS +OID_SUBJECT_KEY_IDENTIFIER = ExtensionOID.SUBJECT_KEY_IDENTIFIER + +OID_DSA_WITH_SHA1 = SignatureAlgorithmOID.DSA_WITH_SHA1 +OID_DSA_WITH_SHA224 = SignatureAlgorithmOID.DSA_WITH_SHA224 +OID_DSA_WITH_SHA256 = SignatureAlgorithmOID.DSA_WITH_SHA256 +OID_ECDSA_WITH_SHA1 = SignatureAlgorithmOID.ECDSA_WITH_SHA1 +OID_ECDSA_WITH_SHA224 = SignatureAlgorithmOID.ECDSA_WITH_SHA224 +OID_ECDSA_WITH_SHA256 = SignatureAlgorithmOID.ECDSA_WITH_SHA256 +OID_ECDSA_WITH_SHA384 = SignatureAlgorithmOID.ECDSA_WITH_SHA384 +OID_ECDSA_WITH_SHA512 = SignatureAlgorithmOID.ECDSA_WITH_SHA512 +OID_RSA_WITH_MD5 = SignatureAlgorithmOID.RSA_WITH_MD5 +OID_RSA_WITH_SHA1 = SignatureAlgorithmOID.RSA_WITH_SHA1 +OID_RSA_WITH_SHA224 = SignatureAlgorithmOID.RSA_WITH_SHA224 +OID_RSA_WITH_SHA256 = SignatureAlgorithmOID.RSA_WITH_SHA256 +OID_RSA_WITH_SHA384 = SignatureAlgorithmOID.RSA_WITH_SHA384 +OID_RSA_WITH_SHA512 = SignatureAlgorithmOID.RSA_WITH_SHA512 +OID_RSASSA_PSS = SignatureAlgorithmOID.RSASSA_PSS + +OID_COMMON_NAME = NameOID.COMMON_NAME +OID_COUNTRY_NAME = NameOID.COUNTRY_NAME +OID_DOMAIN_COMPONENT = NameOID.DOMAIN_COMPONENT +OID_DN_QUALIFIER = NameOID.DN_QUALIFIER +OID_EMAIL_ADDRESS = NameOID.EMAIL_ADDRESS +OID_GENERATION_QUALIFIER = NameOID.GENERATION_QUALIFIER +OID_GIVEN_NAME = NameOID.GIVEN_NAME +OID_LOCALITY_NAME = NameOID.LOCALITY_NAME +OID_ORGANIZATIONAL_UNIT_NAME = NameOID.ORGANIZATIONAL_UNIT_NAME +OID_ORGANIZATION_NAME = NameOID.ORGANIZATION_NAME +OID_PSEUDONYM = NameOID.PSEUDONYM +OID_SERIAL_NUMBER = NameOID.SERIAL_NUMBER +OID_STATE_OR_PROVINCE_NAME = NameOID.STATE_OR_PROVINCE_NAME +OID_SURNAME = NameOID.SURNAME +OID_TITLE = NameOID.TITLE + +OID_CLIENT_AUTH = ExtendedKeyUsageOID.CLIENT_AUTH +OID_CODE_SIGNING = ExtendedKeyUsageOID.CODE_SIGNING +OID_EMAIL_PROTECTION = ExtendedKeyUsageOID.EMAIL_PROTECTION +OID_OCSP_SIGNING = ExtendedKeyUsageOID.OCSP_SIGNING +OID_SERVER_AUTH = ExtendedKeyUsageOID.SERVER_AUTH +OID_TIME_STAMPING = ExtendedKeyUsageOID.TIME_STAMPING + +OID_ANY_POLICY = CertificatePoliciesOID.ANY_POLICY +OID_CPS_QUALIFIER = CertificatePoliciesOID.CPS_QUALIFIER +OID_CPS_USER_NOTICE = CertificatePoliciesOID.CPS_USER_NOTICE + +OID_CERTIFICATE_ISSUER = CRLEntryExtensionOID.CERTIFICATE_ISSUER +OID_CRL_REASON = CRLEntryExtensionOID.CRL_REASON +OID_INVALIDITY_DATE = CRLEntryExtensionOID.INVALIDITY_DATE + +OID_CA_ISSUERS = AuthorityInformationAccessOID.CA_ISSUERS +OID_OCSP = AuthorityInformationAccessOID.OCSP + +__all__ = [ + "certificate_transparency", + "load_pem_x509_certificate", + "load_der_x509_certificate", + "load_pem_x509_csr", + "load_der_x509_csr", + "load_pem_x509_crl", + "load_der_x509_crl", + "random_serial_number", + "Attribute", + "AttributeNotFound", + "Attributes", + "InvalidVersion", + "DeltaCRLIndicator", + "DuplicateExtension", + "ExtensionNotFound", + "UnsupportedGeneralNameType", + "NameAttribute", + "Name", + "RelativeDistinguishedName", + "ObjectIdentifier", + "ExtensionType", + "Extensions", + "Extension", + "ExtendedKeyUsage", + "FreshestCRL", + "IssuingDistributionPoint", + "TLSFeature", + "TLSFeatureType", + "OCSPNoCheck", + "BasicConstraints", + "CRLNumber", + "KeyUsage", + "AuthorityInformationAccess", + "SubjectInformationAccess", + "AccessDescription", + "CertificatePolicies", + "PolicyInformation", + "UserNotice", + "NoticeReference", + "SubjectKeyIdentifier", + "NameConstraints", + "CRLDistributionPoints", + "DistributionPoint", + "ReasonFlags", + "InhibitAnyPolicy", + "SubjectAlternativeName", + "IssuerAlternativeName", + "AuthorityKeyIdentifier", + "GeneralNames", + "GeneralName", + "RFC822Name", + "DNSName", + "UniformResourceIdentifier", + "RegisteredID", + "DirectoryName", + "IPAddress", + "OtherName", + "Certificate", + "CertificateRevocationList", + "CertificateRevocationListBuilder", + "CertificateSigningRequest", + "RevokedCertificate", + "RevokedCertificateBuilder", + "CertificateSigningRequestBuilder", + "CertificateBuilder", + "Version", + "OID_CA_ISSUERS", + "OID_OCSP", + "CertificateIssuer", + "CRLReason", + "InvalidityDate", + "UnrecognizedExtension", + "PolicyConstraints", + "PrecertificateSignedCertificateTimestamps", + "PrecertPoison", + "OCSPNonce", + "SignedCertificateTimestamps", + "SignatureAlgorithmOID", + "NameOID", +] diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/x509/base.py b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/x509/base.py new file mode 100644 index 00000000..1df89839 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/x509/base.py @@ -0,0 +1,1093 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + + +import abc +import datetime +import os +import typing + +from cryptography import utils +from cryptography.hazmat.bindings._rust import x509 as rust_x509 +from cryptography.hazmat.primitives import hashes, serialization +from cryptography.hazmat.primitives.asymmetric import ( + dsa, + ec, + ed25519, + ed448, + rsa, + x25519, + x448, +) +from cryptography.hazmat.primitives.asymmetric.types import ( + CERTIFICATE_PUBLIC_KEY_TYPES, + PRIVATE_KEY_TYPES as PRIVATE_KEY_TYPES, + PUBLIC_KEY_TYPES as PUBLIC_KEY_TYPES, +) +from cryptography.x509.extensions import ( + Extension, + ExtensionType, + Extensions, + _make_sequence_methods, +) +from cryptography.x509.name import Name, _ASN1Type +from cryptography.x509.oid import ObjectIdentifier + + +_EARLIEST_UTC_TIME = datetime.datetime(1950, 1, 1) + + +class AttributeNotFound(Exception): + def __init__(self, msg: str, oid: ObjectIdentifier) -> None: + super(AttributeNotFound, self).__init__(msg) + self.oid = oid + + +def _reject_duplicate_extension( + extension: Extension[ExtensionType], + extensions: typing.List[Extension[ExtensionType]], +) -> None: + # This is quadratic in the number of extensions + for e in extensions: + if e.oid == extension.oid: + raise ValueError("This extension has already been set.") + + +def _reject_duplicate_attribute( + oid: ObjectIdentifier, + attributes: typing.List[typing.Tuple[ObjectIdentifier, bytes]], +) -> None: + # This is quadratic in the number of attributes + for attr_oid, _ in attributes: + if attr_oid == oid: + raise ValueError("This attribute has already been set.") + + +def _convert_to_naive_utc_time(time: datetime.datetime) -> datetime.datetime: + """Normalizes a datetime to a naive datetime in UTC. + + time -- datetime to normalize. Assumed to be in UTC if not timezone + aware. + """ + if time.tzinfo is not None: + offset = time.utcoffset() + offset = offset if offset else datetime.timedelta() + return time.replace(tzinfo=None) - offset + else: + return time + + +class Attribute: + def __init__( + self, + oid: ObjectIdentifier, + value: bytes, + _type: int = _ASN1Type.UTF8String.value, + ) -> None: + self._oid = oid + self._value = value + self._type = _type + + @property + def oid(self) -> ObjectIdentifier: + return self._oid + + @property + def value(self) -> bytes: + return self._value + + def __repr__(self): + return "<Attribute(oid={}, value={!r})>".format(self.oid, self.value) + + def __eq__(self, other: typing.Any) -> bool: + if not isinstance(other, Attribute): + return NotImplemented + + return ( + self.oid == other.oid + and self.value == other.value + and self._type == other._type + ) + + def __ne__(self, other: typing.Any) -> bool: + return not self == other + + def __hash__(self) -> int: + return hash((self.oid, self.value, self._type)) + + +class Attributes: + def __init__( + self, + attributes: typing.Iterable[Attribute], + ) -> None: + self._attributes = list(attributes) + + __len__, __iter__, __getitem__ = _make_sequence_methods("_attributes") + + def __repr__(self): + return "<Attributes({})>".format(self._attributes) + + def get_attribute_for_oid(self, oid: ObjectIdentifier) -> Attribute: + for attr in self: + if attr.oid == oid: + return attr + + raise AttributeNotFound("No {} attribute was found".format(oid), oid) + + +class Version(utils.Enum): + v1 = 0 + v3 = 2 + + +class InvalidVersion(Exception): + def __init__(self, msg: str, parsed_version: int) -> None: + super(InvalidVersion, self).__init__(msg) + self.parsed_version = parsed_version + + +class Certificate(metaclass=abc.ABCMeta): + @abc.abstractmethod + def fingerprint(self, algorithm: hashes.HashAlgorithm) -> bytes: + """ + Returns bytes using digest passed. + """ + + @abc.abstractproperty + def serial_number(self) -> int: + """ + Returns certificate serial number + """ + + @abc.abstractproperty + def version(self) -> Version: + """ + Returns the certificate version + """ + + @abc.abstractmethod + def public_key(self) -> CERTIFICATE_PUBLIC_KEY_TYPES: + """ + Returns the public key + """ + + @abc.abstractproperty + def not_valid_before(self) -> datetime.datetime: + """ + Not before time (represented as UTC datetime) + """ + + @abc.abstractproperty + def not_valid_after(self) -> datetime.datetime: + """ + Not after time (represented as UTC datetime) + """ + + @abc.abstractproperty + def issuer(self) -> Name: + """ + Returns the issuer name object. + """ + + @abc.abstractproperty + def subject(self) -> Name: + """ + Returns the subject name object. + """ + + @abc.abstractproperty + def signature_hash_algorithm( + self, + ) -> typing.Optional[hashes.HashAlgorithm]: + """ + Returns a HashAlgorithm corresponding to the type of the digest signed + in the certificate. + """ + + @abc.abstractproperty + def signature_algorithm_oid(self) -> ObjectIdentifier: + """ + Returns the ObjectIdentifier of the signature algorithm. + """ + + @abc.abstractproperty + def extensions(self) -> Extensions: + """ + Returns an Extensions object. + """ + + @abc.abstractproperty + def signature(self) -> bytes: + """ + Returns the signature bytes. + """ + + @abc.abstractproperty + def tbs_certificate_bytes(self) -> bytes: + """ + Returns the tbsCertificate payload bytes as defined in RFC 5280. + """ + + @abc.abstractmethod + def __eq__(self, other: object) -> bool: + """ + Checks equality. + """ + + @abc.abstractmethod + def __ne__(self, other: object) -> bool: + """ + Checks not equal. + """ + + @abc.abstractmethod + def __hash__(self) -> int: + """ + Computes a hash. + """ + + @abc.abstractmethod + def public_bytes(self, encoding: serialization.Encoding) -> bytes: + """ + Serializes the certificate to PEM or DER format. + """ + + +# Runtime isinstance checks need this since the rust class is not a subclass. +Certificate.register(rust_x509.Certificate) + + +class RevokedCertificate(metaclass=abc.ABCMeta): + @abc.abstractproperty + def serial_number(self) -> int: + """ + Returns the serial number of the revoked certificate. + """ + + @abc.abstractproperty + def revocation_date(self) -> datetime.datetime: + """ + Returns the date of when this certificate was revoked. + """ + + @abc.abstractproperty + def extensions(self) -> Extensions: + """ + Returns an Extensions object containing a list of Revoked extensions. + """ + + +# Runtime isinstance checks need this since the rust class is not a subclass. +RevokedCertificate.register(rust_x509.RevokedCertificate) + + +class _RawRevokedCertificate(RevokedCertificate): + def __init__( + self, + serial_number: int, + revocation_date: datetime.datetime, + extensions: Extensions, + ): + self._serial_number = serial_number + self._revocation_date = revocation_date + self._extensions = extensions + + @property + def serial_number(self) -> int: + return self._serial_number + + @property + def revocation_date(self) -> datetime.datetime: + return self._revocation_date + + @property + def extensions(self) -> Extensions: + return self._extensions + + +class CertificateRevocationList(metaclass=abc.ABCMeta): + @abc.abstractmethod + def public_bytes(self, encoding: serialization.Encoding) -> bytes: + """ + Serializes the CRL to PEM or DER format. + """ + + @abc.abstractmethod + def fingerprint(self, algorithm: hashes.HashAlgorithm) -> bytes: + """ + Returns bytes using digest passed. + """ + + @abc.abstractmethod + def get_revoked_certificate_by_serial_number( + self, serial_number: int + ) -> typing.Optional[RevokedCertificate]: + """ + Returns an instance of RevokedCertificate or None if the serial_number + is not in the CRL. + """ + + @abc.abstractproperty + def signature_hash_algorithm( + self, + ) -> typing.Optional[hashes.HashAlgorithm]: + """ + Returns a HashAlgorithm corresponding to the type of the digest signed + in the certificate. + """ + + @abc.abstractproperty + def signature_algorithm_oid(self) -> ObjectIdentifier: + """ + Returns the ObjectIdentifier of the signature algorithm. + """ + + @abc.abstractproperty + def issuer(self) -> Name: + """ + Returns the X509Name with the issuer of this CRL. + """ + + @abc.abstractproperty + def next_update(self) -> typing.Optional[datetime.datetime]: + """ + Returns the date of next update for this CRL. + """ + + @abc.abstractproperty + def last_update(self) -> datetime.datetime: + """ + Returns the date of last update for this CRL. + """ + + @abc.abstractproperty + def extensions(self) -> Extensions: + """ + Returns an Extensions object containing a list of CRL extensions. + """ + + @abc.abstractproperty + def signature(self) -> bytes: + """ + Returns the signature bytes. + """ + + @abc.abstractproperty + def tbs_certlist_bytes(self) -> bytes: + """ + Returns the tbsCertList payload bytes as defined in RFC 5280. + """ + + @abc.abstractmethod + def __eq__(self, other: object) -> bool: + """ + Checks equality. + """ + + @abc.abstractmethod + def __ne__(self, other: object) -> bool: + """ + Checks not equal. + """ + + @abc.abstractmethod + def __len__(self) -> int: + """ + Number of revoked certificates in the CRL. + """ + + @typing.overload + def __getitem__(self, idx: int) -> RevokedCertificate: + ... + + @typing.overload + def __getitem__(self, idx: slice) -> typing.List[RevokedCertificate]: + ... + + @abc.abstractmethod + def __getitem__( + self, idx: typing.Union[int, slice] + ) -> typing.Union[RevokedCertificate, typing.List[RevokedCertificate]]: + """ + Returns a revoked certificate (or slice of revoked certificates). + """ + + @abc.abstractmethod + def __iter__(self) -> typing.Iterator[RevokedCertificate]: + """ + Iterator over the revoked certificates + """ + + @abc.abstractmethod + def is_signature_valid(self, public_key: PUBLIC_KEY_TYPES) -> bool: + """ + Verifies signature of revocation list against given public key. + """ + + +CertificateRevocationList.register(rust_x509.CertificateRevocationList) + + +class CertificateSigningRequest(metaclass=abc.ABCMeta): + @abc.abstractmethod + def __eq__(self, other: object) -> bool: + """ + Checks equality. + """ + + @abc.abstractmethod + def __ne__(self, other: object) -> bool: + """ + Checks not equal. + """ + + @abc.abstractmethod + def __hash__(self) -> int: + """ + Computes a hash. + """ + + @abc.abstractmethod + def public_key(self) -> PUBLIC_KEY_TYPES: + """ + Returns the public key + """ + + @abc.abstractproperty + def subject(self) -> Name: + """ + Returns the subject name object. + """ + + @abc.abstractproperty + def signature_hash_algorithm( + self, + ) -> typing.Optional[hashes.HashAlgorithm]: + """ + Returns a HashAlgorithm corresponding to the type of the digest signed + in the certificate. + """ + + @abc.abstractproperty + def signature_algorithm_oid(self) -> ObjectIdentifier: + """ + Returns the ObjectIdentifier of the signature algorithm. + """ + + @abc.abstractproperty + def extensions(self) -> Extensions: + """ + Returns the extensions in the signing request. + """ + + @abc.abstractproperty + def attributes(self) -> Attributes: + """ + Returns an Attributes object. + """ + + @abc.abstractmethod + def public_bytes(self, encoding: serialization.Encoding) -> bytes: + """ + Encodes the request to PEM or DER format. + """ + + @abc.abstractproperty + def signature(self) -> bytes: + """ + Returns the signature bytes. + """ + + @abc.abstractproperty + def tbs_certrequest_bytes(self) -> bytes: + """ + Returns the PKCS#10 CertificationRequestInfo bytes as defined in RFC + 2986. + """ + + @abc.abstractproperty + def is_signature_valid(self) -> bool: + """ + Verifies signature of signing request. + """ + + @abc.abstractmethod + def get_attribute_for_oid(self, oid: ObjectIdentifier) -> bytes: + """ + Get the attribute value for a given OID. + """ + + +# Runtime isinstance checks need this since the rust class is not a subclass. +CertificateSigningRequest.register(rust_x509.CertificateSigningRequest) + + +# Backend argument preserved for API compatibility, but ignored. +def load_pem_x509_certificate( + data: bytes, backend: typing.Any = None +) -> Certificate: + return rust_x509.load_pem_x509_certificate(data) + + +# Backend argument preserved for API compatibility, but ignored. +def load_der_x509_certificate( + data: bytes, backend: typing.Any = None +) -> Certificate: + return rust_x509.load_der_x509_certificate(data) + + +# Backend argument preserved for API compatibility, but ignored. +def load_pem_x509_csr( + data: bytes, backend: typing.Any = None +) -> CertificateSigningRequest: + return rust_x509.load_pem_x509_csr(data) + + +# Backend argument preserved for API compatibility, but ignored. +def load_der_x509_csr( + data: bytes, backend: typing.Any = None +) -> CertificateSigningRequest: + return rust_x509.load_der_x509_csr(data) + + +# Backend argument preserved for API compatibility, but ignored. +def load_pem_x509_crl( + data: bytes, backend: typing.Any = None +) -> CertificateRevocationList: + return rust_x509.load_pem_x509_crl(data) + + +# Backend argument preserved for API compatibility, but ignored. +def load_der_x509_crl( + data: bytes, backend: typing.Any = None +) -> CertificateRevocationList: + return rust_x509.load_der_x509_crl(data) + + +class CertificateSigningRequestBuilder(object): + def __init__( + self, + subject_name: typing.Optional[Name] = None, + extensions: typing.List[Extension[ExtensionType]] = [], + attributes: typing.List[typing.Tuple[ObjectIdentifier, bytes]] = [], + ): + """ + Creates an empty X.509 certificate request (v1). + """ + self._subject_name = subject_name + self._extensions = extensions + self._attributes = attributes + + def subject_name(self, name: Name) -> "CertificateSigningRequestBuilder": + """ + Sets the certificate requestor's distinguished name. + """ + if not isinstance(name, Name): + raise TypeError("Expecting x509.Name object.") + if self._subject_name is not None: + raise ValueError("The subject name may only be set once.") + return CertificateSigningRequestBuilder( + name, self._extensions, self._attributes + ) + + def add_extension( + self, extval: ExtensionType, critical: bool + ) -> "CertificateSigningRequestBuilder": + """ + Adds an X.509 extension to the certificate request. + """ + if not isinstance(extval, ExtensionType): + raise TypeError("extension must be an ExtensionType") + + extension = Extension(extval.oid, critical, extval) + _reject_duplicate_extension(extension, self._extensions) + + return CertificateSigningRequestBuilder( + self._subject_name, + self._extensions + [extension], + self._attributes, + ) + + def add_attribute( + self, oid: ObjectIdentifier, value: bytes + ) -> "CertificateSigningRequestBuilder": + """ + Adds an X.509 attribute with an OID and associated value. + """ + if not isinstance(oid, ObjectIdentifier): + raise TypeError("oid must be an ObjectIdentifier") + + if not isinstance(value, bytes): + raise TypeError("value must be bytes") + + _reject_duplicate_attribute(oid, self._attributes) + + return CertificateSigningRequestBuilder( + self._subject_name, + self._extensions, + self._attributes + [(oid, value)], + ) + + def sign( + self, + private_key: PRIVATE_KEY_TYPES, + algorithm: typing.Optional[hashes.HashAlgorithm], + backend: typing.Any = None, + ) -> CertificateSigningRequest: + """ + Signs the request using the requestor's private key. + """ + if self._subject_name is None: + raise ValueError("A CertificateSigningRequest must have a subject") + return rust_x509.create_x509_csr(self, private_key, algorithm) + + +class CertificateBuilder(object): + _extensions: typing.List[Extension[ExtensionType]] + + def __init__( + self, + issuer_name: typing.Optional[Name] = None, + subject_name: typing.Optional[Name] = None, + public_key: typing.Optional[CERTIFICATE_PUBLIC_KEY_TYPES] = None, + serial_number: typing.Optional[int] = None, + not_valid_before: typing.Optional[datetime.datetime] = None, + not_valid_after: typing.Optional[datetime.datetime] = None, + extensions: typing.List[Extension[ExtensionType]] = [], + ) -> None: + self._version = Version.v3 + self._issuer_name = issuer_name + self._subject_name = subject_name + self._public_key = public_key + self._serial_number = serial_number + self._not_valid_before = not_valid_before + self._not_valid_after = not_valid_after + self._extensions = extensions + + def issuer_name(self, name: Name) -> "CertificateBuilder": + """ + Sets the CA's distinguished name. + """ + if not isinstance(name, Name): + raise TypeError("Expecting x509.Name object.") + if self._issuer_name is not None: + raise ValueError("The issuer name may only be set once.") + return CertificateBuilder( + name, + self._subject_name, + self._public_key, + self._serial_number, + self._not_valid_before, + self._not_valid_after, + self._extensions, + ) + + def subject_name(self, name: Name) -> "CertificateBuilder": + """ + Sets the requestor's distinguished name. + """ + if not isinstance(name, Name): + raise TypeError("Expecting x509.Name object.") + if self._subject_name is not None: + raise ValueError("The subject name may only be set once.") + return CertificateBuilder( + self._issuer_name, + name, + self._public_key, + self._serial_number, + self._not_valid_before, + self._not_valid_after, + self._extensions, + ) + + def public_key( + self, + key: CERTIFICATE_PUBLIC_KEY_TYPES, + ) -> "CertificateBuilder": + """ + Sets the requestor's public key (as found in the signing request). + """ + if not isinstance( + key, + ( + dsa.DSAPublicKey, + rsa.RSAPublicKey, + ec.EllipticCurvePublicKey, + ed25519.Ed25519PublicKey, + ed448.Ed448PublicKey, + x25519.X25519PublicKey, + x448.X448PublicKey, + ), + ): + raise TypeError( + "Expecting one of DSAPublicKey, RSAPublicKey," + " EllipticCurvePublicKey, Ed25519PublicKey," + " Ed448PublicKey, X25519PublicKey, or " + "X448PublicKey." + ) + if self._public_key is not None: + raise ValueError("The public key may only be set once.") + return CertificateBuilder( + self._issuer_name, + self._subject_name, + key, + self._serial_number, + self._not_valid_before, + self._not_valid_after, + self._extensions, + ) + + def serial_number(self, number: int) -> "CertificateBuilder": + """ + Sets the certificate serial number. + """ + if not isinstance(number, int): + raise TypeError("Serial number must be of integral type.") + if self._serial_number is not None: + raise ValueError("The serial number may only be set once.") + if number <= 0: + raise ValueError("The serial number should be positive.") + + # ASN.1 integers are always signed, so most significant bit must be + # zero. + if number.bit_length() >= 160: # As defined in RFC 5280 + raise ValueError( + "The serial number should not be more than 159 " "bits." + ) + return CertificateBuilder( + self._issuer_name, + self._subject_name, + self._public_key, + number, + self._not_valid_before, + self._not_valid_after, + self._extensions, + ) + + def not_valid_before( + self, time: datetime.datetime + ) -> "CertificateBuilder": + """ + Sets the certificate activation time. + """ + if not isinstance(time, datetime.datetime): + raise TypeError("Expecting datetime object.") + if self._not_valid_before is not None: + raise ValueError("The not valid before may only be set once.") + time = _convert_to_naive_utc_time(time) + if time < _EARLIEST_UTC_TIME: + raise ValueError( + "The not valid before date must be on or after" + " 1950 January 1)." + ) + if self._not_valid_after is not None and time > self._not_valid_after: + raise ValueError( + "The not valid before date must be before the not valid after " + "date." + ) + return CertificateBuilder( + self._issuer_name, + self._subject_name, + self._public_key, + self._serial_number, + time, + self._not_valid_after, + self._extensions, + ) + + def not_valid_after(self, time: datetime.datetime) -> "CertificateBuilder": + """ + Sets the certificate expiration time. + """ + if not isinstance(time, datetime.datetime): + raise TypeError("Expecting datetime object.") + if self._not_valid_after is not None: + raise ValueError("The not valid after may only be set once.") + time = _convert_to_naive_utc_time(time) + if time < _EARLIEST_UTC_TIME: + raise ValueError( + "The not valid after date must be on or after" + " 1950 January 1." + ) + if ( + self._not_valid_before is not None + and time < self._not_valid_before + ): + raise ValueError( + "The not valid after date must be after the not valid before " + "date." + ) + return CertificateBuilder( + self._issuer_name, + self._subject_name, + self._public_key, + self._serial_number, + self._not_valid_before, + time, + self._extensions, + ) + + def add_extension( + self, extval: ExtensionType, critical: bool + ) -> "CertificateBuilder": + """ + Adds an X.509 extension to the certificate. + """ + if not isinstance(extval, ExtensionType): + raise TypeError("extension must be an ExtensionType") + + extension = Extension(extval.oid, critical, extval) + _reject_duplicate_extension(extension, self._extensions) + + return CertificateBuilder( + self._issuer_name, + self._subject_name, + self._public_key, + self._serial_number, + self._not_valid_before, + self._not_valid_after, + self._extensions + [extension], + ) + + def sign( + self, + private_key: PRIVATE_KEY_TYPES, + algorithm: typing.Optional[hashes.HashAlgorithm], + backend: typing.Any = None, + ) -> Certificate: + """ + Signs the certificate using the CA's private key. + """ + if self._subject_name is None: + raise ValueError("A certificate must have a subject name") + + if self._issuer_name is None: + raise ValueError("A certificate must have an issuer name") + + if self._serial_number is None: + raise ValueError("A certificate must have a serial number") + + if self._not_valid_before is None: + raise ValueError("A certificate must have a not valid before time") + + if self._not_valid_after is None: + raise ValueError("A certificate must have a not valid after time") + + if self._public_key is None: + raise ValueError("A certificate must have a public key") + + return rust_x509.create_x509_certificate(self, private_key, algorithm) + + +class CertificateRevocationListBuilder(object): + _extensions: typing.List[Extension[ExtensionType]] + _revoked_certificates: typing.List[RevokedCertificate] + + def __init__( + self, + issuer_name: typing.Optional[Name] = None, + last_update: typing.Optional[datetime.datetime] = None, + next_update: typing.Optional[datetime.datetime] = None, + extensions: typing.List[Extension[ExtensionType]] = [], + revoked_certificates: typing.List[RevokedCertificate] = [], + ): + self._issuer_name = issuer_name + self._last_update = last_update + self._next_update = next_update + self._extensions = extensions + self._revoked_certificates = revoked_certificates + + def issuer_name( + self, issuer_name: Name + ) -> "CertificateRevocationListBuilder": + if not isinstance(issuer_name, Name): + raise TypeError("Expecting x509.Name object.") + if self._issuer_name is not None: + raise ValueError("The issuer name may only be set once.") + return CertificateRevocationListBuilder( + issuer_name, + self._last_update, + self._next_update, + self._extensions, + self._revoked_certificates, + ) + + def last_update( + self, last_update: datetime.datetime + ) -> "CertificateRevocationListBuilder": + if not isinstance(last_update, datetime.datetime): + raise TypeError("Expecting datetime object.") + if self._last_update is not None: + raise ValueError("Last update may only be set once.") + last_update = _convert_to_naive_utc_time(last_update) + if last_update < _EARLIEST_UTC_TIME: + raise ValueError( + "The last update date must be on or after" " 1950 January 1." + ) + if self._next_update is not None and last_update > self._next_update: + raise ValueError( + "The last update date must be before the next update date." + ) + return CertificateRevocationListBuilder( + self._issuer_name, + last_update, + self._next_update, + self._extensions, + self._revoked_certificates, + ) + + def next_update( + self, next_update: datetime.datetime + ) -> "CertificateRevocationListBuilder": + if not isinstance(next_update, datetime.datetime): + raise TypeError("Expecting datetime object.") + if self._next_update is not None: + raise ValueError("Last update may only be set once.") + next_update = _convert_to_naive_utc_time(next_update) + if next_update < _EARLIEST_UTC_TIME: + raise ValueError( + "The last update date must be on or after" " 1950 January 1." + ) + if self._last_update is not None and next_update < self._last_update: + raise ValueError( + "The next update date must be after the last update date." + ) + return CertificateRevocationListBuilder( + self._issuer_name, + self._last_update, + next_update, + self._extensions, + self._revoked_certificates, + ) + + def add_extension( + self, extval: ExtensionType, critical: bool + ) -> "CertificateRevocationListBuilder": + """ + Adds an X.509 extension to the certificate revocation list. + """ + if not isinstance(extval, ExtensionType): + raise TypeError("extension must be an ExtensionType") + + extension = Extension(extval.oid, critical, extval) + _reject_duplicate_extension(extension, self._extensions) + return CertificateRevocationListBuilder( + self._issuer_name, + self._last_update, + self._next_update, + self._extensions + [extension], + self._revoked_certificates, + ) + + def add_revoked_certificate( + self, revoked_certificate: RevokedCertificate + ) -> "CertificateRevocationListBuilder": + """ + Adds a revoked certificate to the CRL. + """ + if not isinstance(revoked_certificate, RevokedCertificate): + raise TypeError("Must be an instance of RevokedCertificate") + + return CertificateRevocationListBuilder( + self._issuer_name, + self._last_update, + self._next_update, + self._extensions, + self._revoked_certificates + [revoked_certificate], + ) + + def sign( + self, + private_key: PRIVATE_KEY_TYPES, + algorithm: typing.Optional[hashes.HashAlgorithm], + backend: typing.Any = None, + ) -> CertificateRevocationList: + if self._issuer_name is None: + raise ValueError("A CRL must have an issuer name") + + if self._last_update is None: + raise ValueError("A CRL must have a last update time") + + if self._next_update is None: + raise ValueError("A CRL must have a next update time") + + return rust_x509.create_x509_crl(self, private_key, algorithm) + + +class RevokedCertificateBuilder(object): + def __init__( + self, + serial_number: typing.Optional[int] = None, + revocation_date: typing.Optional[datetime.datetime] = None, + extensions: typing.List[Extension[ExtensionType]] = [], + ): + self._serial_number = serial_number + self._revocation_date = revocation_date + self._extensions = extensions + + def serial_number(self, number: int) -> "RevokedCertificateBuilder": + if not isinstance(number, int): + raise TypeError("Serial number must be of integral type.") + if self._serial_number is not None: + raise ValueError("The serial number may only be set once.") + if number <= 0: + raise ValueError("The serial number should be positive") + + # ASN.1 integers are always signed, so most significant bit must be + # zero. + if number.bit_length() >= 160: # As defined in RFC 5280 + raise ValueError( + "The serial number should not be more than 159 " "bits." + ) + return RevokedCertificateBuilder( + number, self._revocation_date, self._extensions + ) + + def revocation_date( + self, time: datetime.datetime + ) -> "RevokedCertificateBuilder": + if not isinstance(time, datetime.datetime): + raise TypeError("Expecting datetime object.") + if self._revocation_date is not None: + raise ValueError("The revocation date may only be set once.") + time = _convert_to_naive_utc_time(time) + if time < _EARLIEST_UTC_TIME: + raise ValueError( + "The revocation date must be on or after" " 1950 January 1." + ) + return RevokedCertificateBuilder( + self._serial_number, time, self._extensions + ) + + def add_extension( + self, extval: ExtensionType, critical: bool + ) -> "RevokedCertificateBuilder": + if not isinstance(extval, ExtensionType): + raise TypeError("extension must be an ExtensionType") + + extension = Extension(extval.oid, critical, extval) + _reject_duplicate_extension(extension, self._extensions) + return RevokedCertificateBuilder( + self._serial_number, + self._revocation_date, + self._extensions + [extension], + ) + + def build(self, backend: typing.Any = None) -> RevokedCertificate: + if self._serial_number is None: + raise ValueError("A revoked certificate must have a serial number") + if self._revocation_date is None: + raise ValueError( + "A revoked certificate must have a revocation date" + ) + return _RawRevokedCertificate( + self._serial_number, + self._revocation_date, + Extensions(self._extensions), + ) + + +def random_serial_number() -> int: + return int.from_bytes(os.urandom(20), "big") >> 1 diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/x509/certificate_transparency.py b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/x509/certificate_transparency.py new file mode 100644 index 00000000..8c198a1c --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/x509/certificate_transparency.py @@ -0,0 +1,48 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + + +import abc +import datetime + +from cryptography import utils +from cryptography.hazmat.bindings._rust import x509 as rust_x509 + + +class LogEntryType(utils.Enum): + X509_CERTIFICATE = 0 + PRE_CERTIFICATE = 1 + + +class Version(utils.Enum): + v1 = 0 + + +class SignedCertificateTimestamp(metaclass=abc.ABCMeta): + @abc.abstractproperty + def version(self) -> Version: + """ + Returns the SCT version. + """ + + @abc.abstractproperty + def log_id(self) -> bytes: + """ + Returns an identifier indicating which log this SCT is for. + """ + + @abc.abstractproperty + def timestamp(self) -> datetime.datetime: + """ + Returns the timestamp for this SCT. + """ + + @abc.abstractproperty + def entry_type(self) -> LogEntryType: + """ + Returns whether this is an SCT for a certificate or pre-certificate. + """ + + +SignedCertificateTimestamp.register(rust_x509.Sct) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/x509/extensions.py b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/x509/extensions.py new file mode 100644 index 00000000..aa21cffb --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/x509/extensions.py @@ -0,0 +1,2198 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + + +import abc +import datetime +import hashlib +import ipaddress +import typing + +from cryptography import utils +from cryptography.hazmat.bindings._rust import asn1 +from cryptography.hazmat.bindings._rust import x509 as rust_x509 +from cryptography.hazmat.primitives import constant_time, serialization +from cryptography.hazmat.primitives.asymmetric.ec import EllipticCurvePublicKey +from cryptography.hazmat.primitives.asymmetric.rsa import RSAPublicKey +from cryptography.hazmat.primitives.asymmetric.types import ( + CERTIFICATE_PUBLIC_KEY_TYPES, + PUBLIC_KEY_TYPES, +) +from cryptography.x509.certificate_transparency import ( + SignedCertificateTimestamp, +) +from cryptography.x509.general_name import ( + DNSName, + DirectoryName, + GeneralName, + IPAddress, + OtherName, + RFC822Name, + RegisteredID, + UniformResourceIdentifier, + _IPADDRESS_TYPES, +) +from cryptography.x509.name import Name, RelativeDistinguishedName +from cryptography.x509.oid import ( + CRLEntryExtensionOID, + ExtensionOID, + OCSPExtensionOID, + ObjectIdentifier, +) + +ExtensionTypeVar = typing.TypeVar("ExtensionTypeVar", bound="ExtensionType") + + +def _key_identifier_from_public_key( + public_key: CERTIFICATE_PUBLIC_KEY_TYPES, +) -> bytes: + if isinstance(public_key, RSAPublicKey): + data = public_key.public_bytes( + serialization.Encoding.DER, + serialization.PublicFormat.PKCS1, + ) + elif isinstance(public_key, EllipticCurvePublicKey): + data = public_key.public_bytes( + serialization.Encoding.X962, + serialization.PublicFormat.UncompressedPoint, + ) + else: + # This is a very slow way to do this. + serialized = public_key.public_bytes( + serialization.Encoding.DER, + serialization.PublicFormat.SubjectPublicKeyInfo, + ) + data = asn1.parse_spki_for_data(serialized) + + return hashlib.sha1(data).digest() + + +def _make_sequence_methods(field_name: str): + def len_method(self) -> int: + return len(getattr(self, field_name)) + + def iter_method(self): + return iter(getattr(self, field_name)) + + def getitem_method(self, idx): + return getattr(self, field_name)[idx] + + return len_method, iter_method, getitem_method + + +class DuplicateExtension(Exception): + def __init__(self, msg: str, oid: ObjectIdentifier) -> None: + super(DuplicateExtension, self).__init__(msg) + self.oid = oid + + +class ExtensionNotFound(Exception): + def __init__(self, msg: str, oid: ObjectIdentifier) -> None: + super(ExtensionNotFound, self).__init__(msg) + self.oid = oid + + +class ExtensionType(metaclass=abc.ABCMeta): + oid: typing.ClassVar[ObjectIdentifier] + + def public_bytes(self) -> bytes: + """ + Serializes the extension type to DER. + """ + raise NotImplementedError( + "public_bytes is not implemented for extension type {0!r}".format( + self + ) + ) + + +class Extensions(object): + def __init__( + self, extensions: typing.Iterable["Extension[ExtensionType]"] + ) -> None: + self._extensions = list(extensions) + + def get_extension_for_oid( + self, oid: ObjectIdentifier + ) -> "Extension[ExtensionType]": + for ext in self: + if ext.oid == oid: + return ext + + raise ExtensionNotFound("No {} extension was found".format(oid), oid) + + def get_extension_for_class( + self, extclass: typing.Type[ExtensionTypeVar] + ) -> "Extension[ExtensionTypeVar]": + if extclass is UnrecognizedExtension: + raise TypeError( + "UnrecognizedExtension can't be used with " + "get_extension_for_class because more than one instance of the" + " class may be present." + ) + + for ext in self: + if isinstance(ext.value, extclass): + return ext + + raise ExtensionNotFound( + "No {} extension was found".format(extclass), extclass.oid + ) + + __len__, __iter__, __getitem__ = _make_sequence_methods("_extensions") + + def __repr__(self) -> str: + return "<Extensions({})>".format(self._extensions) + + +class CRLNumber(ExtensionType): + oid = ExtensionOID.CRL_NUMBER + + def __init__(self, crl_number: int) -> None: + if not isinstance(crl_number, int): + raise TypeError("crl_number must be an integer") + + self._crl_number = crl_number + + def __eq__(self, other: typing.Any) -> bool: + if not isinstance(other, CRLNumber): + return NotImplemented + + return self.crl_number == other.crl_number + + def __ne__(self, other: typing.Any) -> bool: + return not self == other + + def __hash__(self) -> int: + return hash(self.crl_number) + + def __repr__(self) -> str: + return "<CRLNumber({})>".format(self.crl_number) + + @property + def crl_number(self) -> int: + return self._crl_number + + def public_bytes(self) -> bytes: + return rust_x509.encode_extension_value(self) + + +class AuthorityKeyIdentifier(ExtensionType): + oid = ExtensionOID.AUTHORITY_KEY_IDENTIFIER + + def __init__( + self, + key_identifier: typing.Optional[bytes], + authority_cert_issuer: typing.Optional[typing.Iterable[GeneralName]], + authority_cert_serial_number: typing.Optional[int], + ) -> None: + if (authority_cert_issuer is None) != ( + authority_cert_serial_number is None + ): + raise ValueError( + "authority_cert_issuer and authority_cert_serial_number " + "must both be present or both None" + ) + + if authority_cert_issuer is not None: + authority_cert_issuer = list(authority_cert_issuer) + if not all( + isinstance(x, GeneralName) for x in authority_cert_issuer + ): + raise TypeError( + "authority_cert_issuer must be a list of GeneralName " + "objects" + ) + + if authority_cert_serial_number is not None and not isinstance( + authority_cert_serial_number, int + ): + raise TypeError("authority_cert_serial_number must be an integer") + + self._key_identifier = key_identifier + self._authority_cert_issuer = authority_cert_issuer + self._authority_cert_serial_number = authority_cert_serial_number + + # This takes PUBLIC_KEY_TYPES and not CERTIFICATE_PUBLIC_KEY_TYPES + # because an issuer cannot have an X25519/X448 key. This introduces + # some unfortunate asymmetry that requires typing users to explicitly + # narrow their type, but we should make this accurate and not just + # convenient. + @classmethod + def from_issuer_public_key( + cls, public_key: PUBLIC_KEY_TYPES + ) -> "AuthorityKeyIdentifier": + digest = _key_identifier_from_public_key(public_key) + return cls( + key_identifier=digest, + authority_cert_issuer=None, + authority_cert_serial_number=None, + ) + + @classmethod + def from_issuer_subject_key_identifier( + cls, ski: "SubjectKeyIdentifier" + ) -> "AuthorityKeyIdentifier": + return cls( + key_identifier=ski.digest, + authority_cert_issuer=None, + authority_cert_serial_number=None, + ) + + def __repr__(self) -> str: + return ( + "<AuthorityKeyIdentifier(key_identifier={0.key_identifier!r}, " + "authority_cert_issuer={0.authority_cert_issuer}, " + "authority_cert_serial_number={0.authority_cert_serial_number}" + ")>".format(self) + ) + + def __eq__(self, other: typing.Any) -> bool: + if not isinstance(other, AuthorityKeyIdentifier): + return NotImplemented + + return ( + self.key_identifier == other.key_identifier + and self.authority_cert_issuer == other.authority_cert_issuer + and self.authority_cert_serial_number + == other.authority_cert_serial_number + ) + + def __ne__(self, other: typing.Any) -> bool: + return not self == other + + def __hash__(self) -> int: + if self.authority_cert_issuer is None: + aci = None + else: + aci = tuple(self.authority_cert_issuer) + return hash( + (self.key_identifier, aci, self.authority_cert_serial_number) + ) + + @property + def key_identifier(self) -> typing.Optional[bytes]: + return self._key_identifier + + @property + def authority_cert_issuer( + self, + ) -> typing.Optional[typing.List[GeneralName]]: + return self._authority_cert_issuer + + @property + def authority_cert_serial_number(self) -> typing.Optional[int]: + return self._authority_cert_serial_number + + def public_bytes(self) -> bytes: + return rust_x509.encode_extension_value(self) + + +class SubjectKeyIdentifier(ExtensionType): + oid = ExtensionOID.SUBJECT_KEY_IDENTIFIER + + def __init__(self, digest: bytes) -> None: + self._digest = digest + + @classmethod + def from_public_key( + cls, public_key: CERTIFICATE_PUBLIC_KEY_TYPES + ) -> "SubjectKeyIdentifier": + return cls(_key_identifier_from_public_key(public_key)) + + @property + def digest(self) -> bytes: + return self._digest + + @property + def key_identifier(self) -> bytes: + return self._digest + + def __repr__(self) -> str: + return "<SubjectKeyIdentifier(digest={0!r})>".format(self.digest) + + def __eq__(self, other: typing.Any) -> bool: + if not isinstance(other, SubjectKeyIdentifier): + return NotImplemented + + return constant_time.bytes_eq(self.digest, other.digest) + + def __ne__(self, other: typing.Any) -> bool: + return not self == other + + def __hash__(self) -> int: + return hash(self.digest) + + def public_bytes(self) -> bytes: + return rust_x509.encode_extension_value(self) + + +class AuthorityInformationAccess(ExtensionType): + oid = ExtensionOID.AUTHORITY_INFORMATION_ACCESS + + def __init__( + self, descriptions: typing.Iterable["AccessDescription"] + ) -> None: + descriptions = list(descriptions) + if not all(isinstance(x, AccessDescription) for x in descriptions): + raise TypeError( + "Every item in the descriptions list must be an " + "AccessDescription" + ) + + self._descriptions = descriptions + + __len__, __iter__, __getitem__ = _make_sequence_methods("_descriptions") + + def __repr__(self) -> str: + return "<AuthorityInformationAccess({})>".format(self._descriptions) + + def __eq__(self, other: typing.Any) -> bool: + if not isinstance(other, AuthorityInformationAccess): + return NotImplemented + + return self._descriptions == other._descriptions + + def __ne__(self, other: typing.Any) -> bool: + return not self == other + + def __hash__(self) -> int: + return hash(tuple(self._descriptions)) + + def public_bytes(self) -> bytes: + return rust_x509.encode_extension_value(self) + + +class SubjectInformationAccess(ExtensionType): + oid = ExtensionOID.SUBJECT_INFORMATION_ACCESS + + def __init__( + self, descriptions: typing.Iterable["AccessDescription"] + ) -> None: + descriptions = list(descriptions) + if not all(isinstance(x, AccessDescription) for x in descriptions): + raise TypeError( + "Every item in the descriptions list must be an " + "AccessDescription" + ) + + self._descriptions = descriptions + + __len__, __iter__, __getitem__ = _make_sequence_methods("_descriptions") + + def __repr__(self) -> str: + return "<SubjectInformationAccess({})>".format(self._descriptions) + + def __eq__(self, other: typing.Any) -> bool: + if not isinstance(other, SubjectInformationAccess): + return NotImplemented + + return self._descriptions == other._descriptions + + def __ne__(self, other: typing.Any) -> bool: + return not self == other + + def __hash__(self) -> int: + return hash(tuple(self._descriptions)) + + def public_bytes(self) -> bytes: + return rust_x509.encode_extension_value(self) + + +class AccessDescription(object): + def __init__( + self, access_method: ObjectIdentifier, access_location: GeneralName + ) -> None: + if not isinstance(access_method, ObjectIdentifier): + raise TypeError("access_method must be an ObjectIdentifier") + + if not isinstance(access_location, GeneralName): + raise TypeError("access_location must be a GeneralName") + + self._access_method = access_method + self._access_location = access_location + + def __repr__(self) -> str: + return ( + "<AccessDescription(access_method={0.access_method}, access_locati" + "on={0.access_location})>".format(self) + ) + + def __eq__(self, other: typing.Any) -> bool: + if not isinstance(other, AccessDescription): + return NotImplemented + + return ( + self.access_method == other.access_method + and self.access_location == other.access_location + ) + + def __ne__(self, other: typing.Any) -> bool: + return not self == other + + def __hash__(self) -> int: + return hash((self.access_method, self.access_location)) + + @property + def access_method(self) -> ObjectIdentifier: + return self._access_method + + @property + def access_location(self) -> GeneralName: + return self._access_location + + +class BasicConstraints(ExtensionType): + oid = ExtensionOID.BASIC_CONSTRAINTS + + def __init__(self, ca: bool, path_length: typing.Optional[int]) -> None: + if not isinstance(ca, bool): + raise TypeError("ca must be a boolean value") + + if path_length is not None and not ca: + raise ValueError("path_length must be None when ca is False") + + if path_length is not None and ( + not isinstance(path_length, int) or path_length < 0 + ): + raise TypeError( + "path_length must be a non-negative integer or None" + ) + + self._ca = ca + self._path_length = path_length + + @property + def ca(self) -> bool: + return self._ca + + @property + def path_length(self) -> typing.Optional[int]: + return self._path_length + + def __repr__(self) -> str: + return ( + "<BasicConstraints(ca={0.ca}, " "path_length={0.path_length})>" + ).format(self) + + def __eq__(self, other: typing.Any) -> bool: + if not isinstance(other, BasicConstraints): + return NotImplemented + + return self.ca == other.ca and self.path_length == other.path_length + + def __ne__(self, other: typing.Any) -> bool: + return not self == other + + def __hash__(self) -> int: + return hash((self.ca, self.path_length)) + + def public_bytes(self) -> bytes: + return rust_x509.encode_extension_value(self) + + +class DeltaCRLIndicator(ExtensionType): + oid = ExtensionOID.DELTA_CRL_INDICATOR + + def __init__(self, crl_number: int) -> None: + if not isinstance(crl_number, int): + raise TypeError("crl_number must be an integer") + + self._crl_number = crl_number + + @property + def crl_number(self) -> int: + return self._crl_number + + def __eq__(self, other: typing.Any) -> bool: + if not isinstance(other, DeltaCRLIndicator): + return NotImplemented + + return self.crl_number == other.crl_number + + def __ne__(self, other: typing.Any) -> bool: + return not self == other + + def __hash__(self) -> int: + return hash(self.crl_number) + + def __repr__(self) -> str: + return "<DeltaCRLIndicator(crl_number={0.crl_number})>".format(self) + + def public_bytes(self) -> bytes: + return rust_x509.encode_extension_value(self) + + +class CRLDistributionPoints(ExtensionType): + oid = ExtensionOID.CRL_DISTRIBUTION_POINTS + + def __init__( + self, distribution_points: typing.Iterable["DistributionPoint"] + ) -> None: + distribution_points = list(distribution_points) + if not all( + isinstance(x, DistributionPoint) for x in distribution_points + ): + raise TypeError( + "distribution_points must be a list of DistributionPoint " + "objects" + ) + + self._distribution_points = distribution_points + + __len__, __iter__, __getitem__ = _make_sequence_methods( + "_distribution_points" + ) + + def __repr__(self) -> str: + return "<CRLDistributionPoints({})>".format(self._distribution_points) + + def __eq__(self, other: typing.Any) -> bool: + if not isinstance(other, CRLDistributionPoints): + return NotImplemented + + return self._distribution_points == other._distribution_points + + def __ne__(self, other: typing.Any) -> bool: + return not self == other + + def __hash__(self) -> int: + return hash(tuple(self._distribution_points)) + + def public_bytes(self) -> bytes: + return rust_x509.encode_extension_value(self) + + +class FreshestCRL(ExtensionType): + oid = ExtensionOID.FRESHEST_CRL + + def __init__( + self, distribution_points: typing.Iterable["DistributionPoint"] + ) -> None: + distribution_points = list(distribution_points) + if not all( + isinstance(x, DistributionPoint) for x in distribution_points + ): + raise TypeError( + "distribution_points must be a list of DistributionPoint " + "objects" + ) + + self._distribution_points = distribution_points + + __len__, __iter__, __getitem__ = _make_sequence_methods( + "_distribution_points" + ) + + def __repr__(self) -> str: + return "<FreshestCRL({})>".format(self._distribution_points) + + def __eq__(self, other: typing.Any) -> bool: + if not isinstance(other, FreshestCRL): + return NotImplemented + + return self._distribution_points == other._distribution_points + + def __ne__(self, other: typing.Any) -> bool: + return not self == other + + def __hash__(self) -> int: + return hash(tuple(self._distribution_points)) + + def public_bytes(self) -> bytes: + return rust_x509.encode_extension_value(self) + + +class DistributionPoint(object): + def __init__( + self, + full_name: typing.Optional[typing.Iterable[GeneralName]], + relative_name: typing.Optional[RelativeDistinguishedName], + reasons: typing.Optional[typing.FrozenSet["ReasonFlags"]], + crl_issuer: typing.Optional[typing.Iterable[GeneralName]], + ) -> None: + if full_name and relative_name: + raise ValueError( + "You cannot provide both full_name and relative_name, at " + "least one must be None." + ) + + if full_name is not None: + full_name = list(full_name) + if not all(isinstance(x, GeneralName) for x in full_name): + raise TypeError( + "full_name must be a list of GeneralName objects" + ) + + if relative_name: + if not isinstance(relative_name, RelativeDistinguishedName): + raise TypeError( + "relative_name must be a RelativeDistinguishedName" + ) + + if crl_issuer is not None: + crl_issuer = list(crl_issuer) + if not all(isinstance(x, GeneralName) for x in crl_issuer): + raise TypeError( + "crl_issuer must be None or a list of general names" + ) + + if reasons and ( + not isinstance(reasons, frozenset) + or not all(isinstance(x, ReasonFlags) for x in reasons) + ): + raise TypeError("reasons must be None or frozenset of ReasonFlags") + + if reasons and ( + ReasonFlags.unspecified in reasons + or ReasonFlags.remove_from_crl in reasons + ): + raise ValueError( + "unspecified and remove_from_crl are not valid reasons in a " + "DistributionPoint" + ) + + if reasons and not crl_issuer and not (full_name or relative_name): + raise ValueError( + "You must supply crl_issuer, full_name, or relative_name when " + "reasons is not None" + ) + + self._full_name = full_name + self._relative_name = relative_name + self._reasons = reasons + self._crl_issuer = crl_issuer + + def __repr__(self) -> str: + return ( + "<DistributionPoint(full_name={0.full_name}, relative_name={0.rela" + "tive_name}, reasons={0.reasons}, " + "crl_issuer={0.crl_issuer})>".format(self) + ) + + def __eq__(self, other: typing.Any) -> bool: + if not isinstance(other, DistributionPoint): + return NotImplemented + + return ( + self.full_name == other.full_name + and self.relative_name == other.relative_name + and self.reasons == other.reasons + and self.crl_issuer == other.crl_issuer + ) + + def __ne__(self, other: typing.Any) -> bool: + return not self == other + + def __hash__(self) -> int: + if self.full_name is not None: + fn: typing.Optional[typing.Tuple[GeneralName, ...]] = tuple( + self.full_name + ) + else: + fn = None + + if self.crl_issuer is not None: + crl_issuer: typing.Optional[ + typing.Tuple[GeneralName, ...] + ] = tuple(self.crl_issuer) + else: + crl_issuer = None + + return hash((fn, self.relative_name, self.reasons, crl_issuer)) + + @property + def full_name(self) -> typing.Optional[typing.List[GeneralName]]: + return self._full_name + + @property + def relative_name(self) -> typing.Optional[RelativeDistinguishedName]: + return self._relative_name + + @property + def reasons(self) -> typing.Optional[typing.FrozenSet["ReasonFlags"]]: + return self._reasons + + @property + def crl_issuer(self) -> typing.Optional[typing.List[GeneralName]]: + return self._crl_issuer + + +class ReasonFlags(utils.Enum): + unspecified = "unspecified" + key_compromise = "keyCompromise" + ca_compromise = "cACompromise" + affiliation_changed = "affiliationChanged" + superseded = "superseded" + cessation_of_operation = "cessationOfOperation" + certificate_hold = "certificateHold" + privilege_withdrawn = "privilegeWithdrawn" + aa_compromise = "aACompromise" + remove_from_crl = "removeFromCRL" + + +# These are distribution point bit string mappings. Not to be confused with +# CRLReason reason flags bit string mappings. +# ReasonFlags ::= BIT STRING { +# unused (0), +# keyCompromise (1), +# cACompromise (2), +# affiliationChanged (3), +# superseded (4), +# cessationOfOperation (5), +# certificateHold (6), +# privilegeWithdrawn (7), +# aACompromise (8) } +_REASON_BIT_MAPPING = { + 1: ReasonFlags.key_compromise, + 2: ReasonFlags.ca_compromise, + 3: ReasonFlags.affiliation_changed, + 4: ReasonFlags.superseded, + 5: ReasonFlags.cessation_of_operation, + 6: ReasonFlags.certificate_hold, + 7: ReasonFlags.privilege_withdrawn, + 8: ReasonFlags.aa_compromise, +} + + +class PolicyConstraints(ExtensionType): + oid = ExtensionOID.POLICY_CONSTRAINTS + + def __init__( + self, + require_explicit_policy: typing.Optional[int], + inhibit_policy_mapping: typing.Optional[int], + ) -> None: + if require_explicit_policy is not None and not isinstance( + require_explicit_policy, int + ): + raise TypeError( + "require_explicit_policy must be a non-negative integer or " + "None" + ) + + if inhibit_policy_mapping is not None and not isinstance( + inhibit_policy_mapping, int + ): + raise TypeError( + "inhibit_policy_mapping must be a non-negative integer or None" + ) + + if inhibit_policy_mapping is None and require_explicit_policy is None: + raise ValueError( + "At least one of require_explicit_policy and " + "inhibit_policy_mapping must not be None" + ) + + self._require_explicit_policy = require_explicit_policy + self._inhibit_policy_mapping = inhibit_policy_mapping + + def __repr__(self) -> str: + return ( + "<PolicyConstraints(require_explicit_policy={0.require_explicit" + "_policy}, inhibit_policy_mapping={0.inhibit_policy_" + "mapping})>".format(self) + ) + + def __eq__(self, other: typing.Any) -> bool: + if not isinstance(other, PolicyConstraints): + return NotImplemented + + return ( + self.require_explicit_policy == other.require_explicit_policy + and self.inhibit_policy_mapping == other.inhibit_policy_mapping + ) + + def __ne__(self, other: typing.Any) -> bool: + return not self == other + + def __hash__(self) -> int: + return hash( + (self.require_explicit_policy, self.inhibit_policy_mapping) + ) + + @property + def require_explicit_policy(self) -> typing.Optional[int]: + return self._require_explicit_policy + + @property + def inhibit_policy_mapping(self) -> typing.Optional[int]: + return self._inhibit_policy_mapping + + def public_bytes(self) -> bytes: + return rust_x509.encode_extension_value(self) + + +class CertificatePolicies(ExtensionType): + oid = ExtensionOID.CERTIFICATE_POLICIES + + def __init__(self, policies: typing.Iterable["PolicyInformation"]) -> None: + policies = list(policies) + if not all(isinstance(x, PolicyInformation) for x in policies): + raise TypeError( + "Every item in the policies list must be a " + "PolicyInformation" + ) + + self._policies = policies + + __len__, __iter__, __getitem__ = _make_sequence_methods("_policies") + + def __repr__(self) -> str: + return "<CertificatePolicies({})>".format(self._policies) + + def __eq__(self, other: typing.Any) -> bool: + if not isinstance(other, CertificatePolicies): + return NotImplemented + + return self._policies == other._policies + + def __ne__(self, other: typing.Any) -> bool: + return not self == other + + def __hash__(self) -> int: + return hash(tuple(self._policies)) + + def public_bytes(self) -> bytes: + return rust_x509.encode_extension_value(self) + + +class PolicyInformation(object): + def __init__( + self, + policy_identifier: ObjectIdentifier, + policy_qualifiers: typing.Optional[ + typing.Iterable[typing.Union[str, "UserNotice"]] + ], + ) -> None: + if not isinstance(policy_identifier, ObjectIdentifier): + raise TypeError("policy_identifier must be an ObjectIdentifier") + + self._policy_identifier = policy_identifier + + if policy_qualifiers is not None: + policy_qualifiers = list(policy_qualifiers) + if not all( + isinstance(x, (str, UserNotice)) for x in policy_qualifiers + ): + raise TypeError( + "policy_qualifiers must be a list of strings and/or " + "UserNotice objects or None" + ) + + self._policy_qualifiers = policy_qualifiers + + def __repr__(self) -> str: + return ( + "<PolicyInformation(policy_identifier={0.policy_identifier}, polic" + "y_qualifiers={0.policy_qualifiers})>".format(self) + ) + + def __eq__(self, other: typing.Any) -> bool: + if not isinstance(other, PolicyInformation): + return NotImplemented + + return ( + self.policy_identifier == other.policy_identifier + and self.policy_qualifiers == other.policy_qualifiers + ) + + def __ne__(self, other: typing.Any) -> bool: + return not self == other + + def __hash__(self) -> int: + if self.policy_qualifiers is not None: + pq: typing.Optional[ + typing.Tuple[typing.Union[str, "UserNotice"], ...] + ] = tuple(self.policy_qualifiers) + else: + pq = None + + return hash((self.policy_identifier, pq)) + + @property + def policy_identifier(self) -> ObjectIdentifier: + return self._policy_identifier + + @property + def policy_qualifiers( + self, + ) -> typing.Optional[typing.List[typing.Union[str, "UserNotice"]]]: + return self._policy_qualifiers + + +class UserNotice(object): + def __init__( + self, + notice_reference: typing.Optional["NoticeReference"], + explicit_text: typing.Optional[str], + ) -> None: + if notice_reference and not isinstance( + notice_reference, NoticeReference + ): + raise TypeError( + "notice_reference must be None or a NoticeReference" + ) + + self._notice_reference = notice_reference + self._explicit_text = explicit_text + + def __repr__(self) -> str: + return ( + "<UserNotice(notice_reference={0.notice_reference}, explicit_text=" + "{0.explicit_text!r})>".format(self) + ) + + def __eq__(self, other: typing.Any) -> bool: + if not isinstance(other, UserNotice): + return NotImplemented + + return ( + self.notice_reference == other.notice_reference + and self.explicit_text == other.explicit_text + ) + + def __ne__(self, other: typing.Any) -> bool: + return not self == other + + def __hash__(self) -> int: + return hash((self.notice_reference, self.explicit_text)) + + @property + def notice_reference(self) -> typing.Optional["NoticeReference"]: + return self._notice_reference + + @property + def explicit_text(self) -> typing.Optional[str]: + return self._explicit_text + + +class NoticeReference(object): + def __init__( + self, + organization: typing.Optional[str], + notice_numbers: typing.Iterable[int], + ) -> None: + self._organization = organization + notice_numbers = list(notice_numbers) + if not all(isinstance(x, int) for x in notice_numbers): + raise TypeError("notice_numbers must be a list of integers") + + self._notice_numbers = notice_numbers + + def __repr__(self) -> str: + return ( + "<NoticeReference(organization={0.organization!r}, notice_numbers=" + "{0.notice_numbers})>".format(self) + ) + + def __eq__(self, other: typing.Any) -> bool: + if not isinstance(other, NoticeReference): + return NotImplemented + + return ( + self.organization == other.organization + and self.notice_numbers == other.notice_numbers + ) + + def __ne__(self, other: typing.Any) -> bool: + return not self == other + + def __hash__(self) -> int: + return hash((self.organization, tuple(self.notice_numbers))) + + @property + def organization(self) -> typing.Optional[str]: + return self._organization + + @property + def notice_numbers(self) -> typing.List[int]: + return self._notice_numbers + + +class ExtendedKeyUsage(ExtensionType): + oid = ExtensionOID.EXTENDED_KEY_USAGE + + def __init__(self, usages: typing.Iterable[ObjectIdentifier]) -> None: + usages = list(usages) + if not all(isinstance(x, ObjectIdentifier) for x in usages): + raise TypeError( + "Every item in the usages list must be an ObjectIdentifier" + ) + + self._usages = usages + + __len__, __iter__, __getitem__ = _make_sequence_methods("_usages") + + def __repr__(self) -> str: + return "<ExtendedKeyUsage({})>".format(self._usages) + + def __eq__(self, other: typing.Any) -> bool: + if not isinstance(other, ExtendedKeyUsage): + return NotImplemented + + return self._usages == other._usages + + def __ne__(self, other: typing.Any) -> bool: + return not self == other + + def __hash__(self) -> int: + return hash(tuple(self._usages)) + + def public_bytes(self) -> bytes: + return rust_x509.encode_extension_value(self) + + +class OCSPNoCheck(ExtensionType): + oid = ExtensionOID.OCSP_NO_CHECK + + def __eq__(self, other: typing.Any) -> bool: + if not isinstance(other, OCSPNoCheck): + return NotImplemented + + return True + + def __ne__(self, other: typing.Any) -> bool: + return not self == other + + def __hash__(self) -> int: + return hash(OCSPNoCheck) + + def __repr__(self) -> str: + return "<OCSPNoCheck()>" + + def public_bytes(self) -> bytes: + return rust_x509.encode_extension_value(self) + + +class PrecertPoison(ExtensionType): + oid = ExtensionOID.PRECERT_POISON + + def __eq__(self, other: typing.Any) -> bool: + if not isinstance(other, PrecertPoison): + return NotImplemented + + return True + + def __ne__(self, other: typing.Any) -> bool: + return not self == other + + def __hash__(self) -> int: + return hash(PrecertPoison) + + def __repr__(self) -> str: + return "<PrecertPoison()>" + + def public_bytes(self) -> bytes: + return rust_x509.encode_extension_value(self) + + +class TLSFeature(ExtensionType): + oid = ExtensionOID.TLS_FEATURE + + def __init__(self, features: typing.Iterable["TLSFeatureType"]) -> None: + features = list(features) + if ( + not all(isinstance(x, TLSFeatureType) for x in features) + or len(features) == 0 + ): + raise TypeError( + "features must be a list of elements from the TLSFeatureType " + "enum" + ) + + self._features = features + + __len__, __iter__, __getitem__ = _make_sequence_methods("_features") + + def __repr__(self) -> str: + return "<TLSFeature(features={0._features})>".format(self) + + def __eq__(self, other: typing.Any) -> bool: + if not isinstance(other, TLSFeature): + return NotImplemented + + return self._features == other._features + + def __ne__(self, other: typing.Any) -> bool: + return not self == other + + def __hash__(self) -> int: + return hash(tuple(self._features)) + + def public_bytes(self) -> bytes: + return rust_x509.encode_extension_value(self) + + +class TLSFeatureType(utils.Enum): + # status_request is defined in RFC 6066 and is used for what is commonly + # called OCSP Must-Staple when present in the TLS Feature extension in an + # X.509 certificate. + status_request = 5 + # status_request_v2 is defined in RFC 6961 and allows multiple OCSP + # responses to be provided. It is not currently in use by clients or + # servers. + status_request_v2 = 17 + + +_TLS_FEATURE_TYPE_TO_ENUM = {x.value: x for x in TLSFeatureType} + + +class InhibitAnyPolicy(ExtensionType): + oid = ExtensionOID.INHIBIT_ANY_POLICY + + def __init__(self, skip_certs: int) -> None: + if not isinstance(skip_certs, int): + raise TypeError("skip_certs must be an integer") + + if skip_certs < 0: + raise ValueError("skip_certs must be a non-negative integer") + + self._skip_certs = skip_certs + + def __repr__(self) -> str: + return "<InhibitAnyPolicy(skip_certs={0.skip_certs})>".format(self) + + def __eq__(self, other: typing.Any) -> bool: + if not isinstance(other, InhibitAnyPolicy): + return NotImplemented + + return self.skip_certs == other.skip_certs + + def __ne__(self, other: typing.Any) -> bool: + return not self == other + + def __hash__(self) -> int: + return hash(self.skip_certs) + + @property + def skip_certs(self) -> int: + return self._skip_certs + + def public_bytes(self) -> bytes: + return rust_x509.encode_extension_value(self) + + +class KeyUsage(ExtensionType): + oid = ExtensionOID.KEY_USAGE + + def __init__( + self, + digital_signature: bool, + content_commitment: bool, + key_encipherment: bool, + data_encipherment: bool, + key_agreement: bool, + key_cert_sign: bool, + crl_sign: bool, + encipher_only: bool, + decipher_only: bool, + ) -> None: + if not key_agreement and (encipher_only or decipher_only): + raise ValueError( + "encipher_only and decipher_only can only be true when " + "key_agreement is true" + ) + + self._digital_signature = digital_signature + self._content_commitment = content_commitment + self._key_encipherment = key_encipherment + self._data_encipherment = data_encipherment + self._key_agreement = key_agreement + self._key_cert_sign = key_cert_sign + self._crl_sign = crl_sign + self._encipher_only = encipher_only + self._decipher_only = decipher_only + + @property + def digital_signature(self) -> bool: + return self._digital_signature + + @property + def content_commitment(self) -> bool: + return self._content_commitment + + @property + def key_encipherment(self) -> bool: + return self._key_encipherment + + @property + def data_encipherment(self) -> bool: + return self._data_encipherment + + @property + def key_agreement(self) -> bool: + return self._key_agreement + + @property + def key_cert_sign(self) -> bool: + return self._key_cert_sign + + @property + def crl_sign(self) -> bool: + return self._crl_sign + + @property + def encipher_only(self) -> bool: + if not self.key_agreement: + raise ValueError( + "encipher_only is undefined unless key_agreement is true" + ) + else: + return self._encipher_only + + @property + def decipher_only(self) -> bool: + if not self.key_agreement: + raise ValueError( + "decipher_only is undefined unless key_agreement is true" + ) + else: + return self._decipher_only + + def __repr__(self) -> str: + try: + encipher_only = self.encipher_only + decipher_only = self.decipher_only + except ValueError: + # Users found None confusing because even though encipher/decipher + # have no meaning unless key_agreement is true, to construct an + # instance of the class you still need to pass False. + encipher_only = False + decipher_only = False + + return ( + "<KeyUsage(digital_signature={0.digital_signature}, " + "content_commitment={0.content_commitment}, " + "key_encipherment={0.key_encipherment}, " + "data_encipherment={0.data_encipherment}, " + "key_agreement={0.key_agreement}, " + "key_cert_sign={0.key_cert_sign}, crl_sign={0.crl_sign}, " + "encipher_only={1}, decipher_only={2})>" + ).format(self, encipher_only, decipher_only) + + def __eq__(self, other: typing.Any) -> bool: + if not isinstance(other, KeyUsage): + return NotImplemented + + return ( + self.digital_signature == other.digital_signature + and self.content_commitment == other.content_commitment + and self.key_encipherment == other.key_encipherment + and self.data_encipherment == other.data_encipherment + and self.key_agreement == other.key_agreement + and self.key_cert_sign == other.key_cert_sign + and self.crl_sign == other.crl_sign + and self._encipher_only == other._encipher_only + and self._decipher_only == other._decipher_only + ) + + def __ne__(self, other: typing.Any) -> bool: + return not self == other + + def __hash__(self) -> int: + return hash( + ( + self.digital_signature, + self.content_commitment, + self.key_encipherment, + self.data_encipherment, + self.key_agreement, + self.key_cert_sign, + self.crl_sign, + self._encipher_only, + self._decipher_only, + ) + ) + + def public_bytes(self) -> bytes: + return rust_x509.encode_extension_value(self) + + +class NameConstraints(ExtensionType): + oid = ExtensionOID.NAME_CONSTRAINTS + + def __init__( + self, + permitted_subtrees: typing.Optional[typing.Iterable[GeneralName]], + excluded_subtrees: typing.Optional[typing.Iterable[GeneralName]], + ) -> None: + if permitted_subtrees is not None: + permitted_subtrees = list(permitted_subtrees) + if not all(isinstance(x, GeneralName) for x in permitted_subtrees): + raise TypeError( + "permitted_subtrees must be a list of GeneralName objects " + "or None" + ) + + self._validate_ip_name(permitted_subtrees) + + if excluded_subtrees is not None: + excluded_subtrees = list(excluded_subtrees) + if not all(isinstance(x, GeneralName) for x in excluded_subtrees): + raise TypeError( + "excluded_subtrees must be a list of GeneralName objects " + "or None" + ) + + self._validate_ip_name(excluded_subtrees) + + if permitted_subtrees is None and excluded_subtrees is None: + raise ValueError( + "At least one of permitted_subtrees and excluded_subtrees " + "must not be None" + ) + + self._permitted_subtrees = permitted_subtrees + self._excluded_subtrees = excluded_subtrees + + def __eq__(self, other: typing.Any) -> bool: + if not isinstance(other, NameConstraints): + return NotImplemented + + return ( + self.excluded_subtrees == other.excluded_subtrees + and self.permitted_subtrees == other.permitted_subtrees + ) + + def __ne__(self, other: typing.Any) -> bool: + return not self == other + + def _validate_ip_name(self, tree: typing.Iterable[GeneralName]) -> None: + if any( + isinstance(name, IPAddress) + and not isinstance( + name.value, (ipaddress.IPv4Network, ipaddress.IPv6Network) + ) + for name in tree + ): + raise TypeError( + "IPAddress name constraints must be an IPv4Network or" + " IPv6Network object" + ) + + def __repr__(self) -> str: + return ( + "<NameConstraints(permitted_subtrees={0.permitted_subtrees}, " + "excluded_subtrees={0.excluded_subtrees})>".format(self) + ) + + def __hash__(self) -> int: + if self.permitted_subtrees is not None: + ps: typing.Optional[typing.Tuple[GeneralName, ...]] = tuple( + self.permitted_subtrees + ) + else: + ps = None + + if self.excluded_subtrees is not None: + es: typing.Optional[typing.Tuple[GeneralName, ...]] = tuple( + self.excluded_subtrees + ) + else: + es = None + + return hash((ps, es)) + + @property + def permitted_subtrees( + self, + ) -> typing.Optional[typing.List[GeneralName]]: + return self._permitted_subtrees + + @property + def excluded_subtrees( + self, + ) -> typing.Optional[typing.List[GeneralName]]: + return self._excluded_subtrees + + def public_bytes(self) -> bytes: + return rust_x509.encode_extension_value(self) + + +class Extension(typing.Generic[ExtensionTypeVar]): + def __init__( + self, oid: ObjectIdentifier, critical: bool, value: ExtensionTypeVar + ) -> None: + if not isinstance(oid, ObjectIdentifier): + raise TypeError( + "oid argument must be an ObjectIdentifier instance." + ) + + if not isinstance(critical, bool): + raise TypeError("critical must be a boolean value") + + self._oid = oid + self._critical = critical + self._value = value + + @property + def oid(self) -> ObjectIdentifier: + return self._oid + + @property + def critical(self) -> bool: + return self._critical + + @property + def value(self) -> ExtensionTypeVar: + return self._value + + def __repr__(self) -> str: + return ( + "<Extension(oid={0.oid}, critical={0.critical}, " + "value={0.value})>" + ).format(self) + + def __eq__(self, other: typing.Any) -> bool: + if not isinstance(other, Extension): + return NotImplemented + + return ( + self.oid == other.oid + and self.critical == other.critical + and self.value == other.value + ) + + def __ne__(self, other: typing.Any) -> bool: + return not self == other + + def __hash__(self) -> int: + return hash((self.oid, self.critical, self.value)) + + +class GeneralNames(object): + def __init__(self, general_names: typing.Iterable[GeneralName]) -> None: + general_names = list(general_names) + if not all(isinstance(x, GeneralName) for x in general_names): + raise TypeError( + "Every item in the general_names list must be an " + "object conforming to the GeneralName interface" + ) + + self._general_names = general_names + + __len__, __iter__, __getitem__ = _make_sequence_methods("_general_names") + + @typing.overload + def get_values_for_type( + self, + type: typing.Union[ + typing.Type[DNSName], + typing.Type[UniformResourceIdentifier], + typing.Type[RFC822Name], + ], + ) -> typing.List[str]: + ... + + @typing.overload + def get_values_for_type( + self, + type: typing.Type[DirectoryName], + ) -> typing.List[Name]: + ... + + @typing.overload + def get_values_for_type( + self, + type: typing.Type[RegisteredID], + ) -> typing.List[ObjectIdentifier]: + ... + + @typing.overload + def get_values_for_type( + self, type: typing.Type[IPAddress] + ) -> typing.List[_IPADDRESS_TYPES]: + ... + + @typing.overload + def get_values_for_type( + self, type: typing.Type[OtherName] + ) -> typing.List[OtherName]: + ... + + def get_values_for_type( + self, + type: typing.Union[ + typing.Type[DNSName], + typing.Type[DirectoryName], + typing.Type[IPAddress], + typing.Type[OtherName], + typing.Type[RFC822Name], + typing.Type[RegisteredID], + typing.Type[UniformResourceIdentifier], + ], + ) -> typing.Union[ + typing.List[_IPADDRESS_TYPES], + typing.List[str], + typing.List[OtherName], + typing.List[Name], + typing.List[ObjectIdentifier], + ]: + # Return the value of each GeneralName, except for OtherName instances + # which we return directly because it has two important properties not + # just one value. + objs = (i for i in self if isinstance(i, type)) + if type != OtherName: + return [i.value for i in objs] + return list(objs) + + def __repr__(self) -> str: + return "<GeneralNames({})>".format(self._general_names) + + def __eq__(self, other: typing.Any) -> bool: + if not isinstance(other, GeneralNames): + return NotImplemented + + return self._general_names == other._general_names + + def __ne__(self, other: typing.Any) -> bool: + return not self == other + + def __hash__(self) -> int: + return hash(tuple(self._general_names)) + + +class SubjectAlternativeName(ExtensionType): + oid = ExtensionOID.SUBJECT_ALTERNATIVE_NAME + + def __init__(self, general_names: typing.Iterable[GeneralName]) -> None: + self._general_names = GeneralNames(general_names) + + __len__, __iter__, __getitem__ = _make_sequence_methods("_general_names") + + @typing.overload + def get_values_for_type( + self, + type: typing.Union[ + typing.Type[DNSName], + typing.Type[UniformResourceIdentifier], + typing.Type[RFC822Name], + ], + ) -> typing.List[str]: + ... + + @typing.overload + def get_values_for_type( + self, + type: typing.Type[DirectoryName], + ) -> typing.List[Name]: + ... + + @typing.overload + def get_values_for_type( + self, + type: typing.Type[RegisteredID], + ) -> typing.List[ObjectIdentifier]: + ... + + @typing.overload + def get_values_for_type( + self, type: typing.Type[IPAddress] + ) -> typing.List[_IPADDRESS_TYPES]: + ... + + @typing.overload + def get_values_for_type( + self, type: typing.Type[OtherName] + ) -> typing.List[OtherName]: + ... + + def get_values_for_type( + self, + type: typing.Union[ + typing.Type[DNSName], + typing.Type[DirectoryName], + typing.Type[IPAddress], + typing.Type[OtherName], + typing.Type[RFC822Name], + typing.Type[RegisteredID], + typing.Type[UniformResourceIdentifier], + ], + ) -> typing.Union[ + typing.List[_IPADDRESS_TYPES], + typing.List[str], + typing.List[OtherName], + typing.List[Name], + typing.List[ObjectIdentifier], + ]: + return self._general_names.get_values_for_type(type) + + def __repr__(self) -> str: + return "<SubjectAlternativeName({})>".format(self._general_names) + + def __eq__(self, other: typing.Any) -> bool: + if not isinstance(other, SubjectAlternativeName): + return NotImplemented + + return self._general_names == other._general_names + + def __ne__(self, other: typing.Any) -> bool: + return not self == other + + def __hash__(self) -> int: + return hash(self._general_names) + + def public_bytes(self) -> bytes: + return rust_x509.encode_extension_value(self) + + +class IssuerAlternativeName(ExtensionType): + oid = ExtensionOID.ISSUER_ALTERNATIVE_NAME + + def __init__(self, general_names: typing.Iterable[GeneralName]) -> None: + self._general_names = GeneralNames(general_names) + + __len__, __iter__, __getitem__ = _make_sequence_methods("_general_names") + + @typing.overload + def get_values_for_type( + self, + type: typing.Union[ + typing.Type[DNSName], + typing.Type[UniformResourceIdentifier], + typing.Type[RFC822Name], + ], + ) -> typing.List[str]: + ... + + @typing.overload + def get_values_for_type( + self, + type: typing.Type[DirectoryName], + ) -> typing.List[Name]: + ... + + @typing.overload + def get_values_for_type( + self, + type: typing.Type[RegisteredID], + ) -> typing.List[ObjectIdentifier]: + ... + + @typing.overload + def get_values_for_type( + self, type: typing.Type[IPAddress] + ) -> typing.List[_IPADDRESS_TYPES]: + ... + + @typing.overload + def get_values_for_type( + self, type: typing.Type[OtherName] + ) -> typing.List[OtherName]: + ... + + def get_values_for_type( + self, + type: typing.Union[ + typing.Type[DNSName], + typing.Type[DirectoryName], + typing.Type[IPAddress], + typing.Type[OtherName], + typing.Type[RFC822Name], + typing.Type[RegisteredID], + typing.Type[UniformResourceIdentifier], + ], + ) -> typing.Union[ + typing.List[_IPADDRESS_TYPES], + typing.List[str], + typing.List[OtherName], + typing.List[Name], + typing.List[ObjectIdentifier], + ]: + return self._general_names.get_values_for_type(type) + + def __repr__(self) -> str: + return "<IssuerAlternativeName({})>".format(self._general_names) + + def __eq__(self, other: typing.Any) -> bool: + if not isinstance(other, IssuerAlternativeName): + return NotImplemented + + return self._general_names == other._general_names + + def __ne__(self, other: typing.Any) -> bool: + return not self == other + + def __hash__(self) -> int: + return hash(self._general_names) + + def public_bytes(self) -> bytes: + return rust_x509.encode_extension_value(self) + + +class CertificateIssuer(ExtensionType): + oid = CRLEntryExtensionOID.CERTIFICATE_ISSUER + + def __init__(self, general_names: typing.Iterable[GeneralName]) -> None: + self._general_names = GeneralNames(general_names) + + __len__, __iter__, __getitem__ = _make_sequence_methods("_general_names") + + @typing.overload + def get_values_for_type( + self, + type: typing.Union[ + typing.Type[DNSName], + typing.Type[UniformResourceIdentifier], + typing.Type[RFC822Name], + ], + ) -> typing.List[str]: + ... + + @typing.overload + def get_values_for_type( + self, + type: typing.Type[DirectoryName], + ) -> typing.List[Name]: + ... + + @typing.overload + def get_values_for_type( + self, + type: typing.Type[RegisteredID], + ) -> typing.List[ObjectIdentifier]: + ... + + @typing.overload + def get_values_for_type( + self, type: typing.Type[IPAddress] + ) -> typing.List[_IPADDRESS_TYPES]: + ... + + @typing.overload + def get_values_for_type( + self, type: typing.Type[OtherName] + ) -> typing.List[OtherName]: + ... + + def get_values_for_type( + self, + type: typing.Union[ + typing.Type[DNSName], + typing.Type[DirectoryName], + typing.Type[IPAddress], + typing.Type[OtherName], + typing.Type[RFC822Name], + typing.Type[RegisteredID], + typing.Type[UniformResourceIdentifier], + ], + ) -> typing.Union[ + typing.List[_IPADDRESS_TYPES], + typing.List[str], + typing.List[OtherName], + typing.List[Name], + typing.List[ObjectIdentifier], + ]: + return self._general_names.get_values_for_type(type) + + def __repr__(self) -> str: + return "<CertificateIssuer({})>".format(self._general_names) + + def __eq__(self, other: typing.Any) -> bool: + if not isinstance(other, CertificateIssuer): + return NotImplemented + + return self._general_names == other._general_names + + def __ne__(self, other: typing.Any) -> bool: + return not self == other + + def __hash__(self) -> int: + return hash(self._general_names) + + def public_bytes(self) -> bytes: + return rust_x509.encode_extension_value(self) + + +class CRLReason(ExtensionType): + oid = CRLEntryExtensionOID.CRL_REASON + + def __init__(self, reason: ReasonFlags) -> None: + if not isinstance(reason, ReasonFlags): + raise TypeError("reason must be an element from ReasonFlags") + + self._reason = reason + + def __repr__(self) -> str: + return "<CRLReason(reason={})>".format(self._reason) + + def __eq__(self, other: typing.Any) -> bool: + if not isinstance(other, CRLReason): + return NotImplemented + + return self.reason == other.reason + + def __ne__(self, other: typing.Any) -> bool: + return not self == other + + def __hash__(self) -> int: + return hash(self.reason) + + @property + def reason(self) -> ReasonFlags: + return self._reason + + def public_bytes(self) -> bytes: + return rust_x509.encode_extension_value(self) + + +class InvalidityDate(ExtensionType): + oid = CRLEntryExtensionOID.INVALIDITY_DATE + + def __init__(self, invalidity_date: datetime.datetime) -> None: + if not isinstance(invalidity_date, datetime.datetime): + raise TypeError("invalidity_date must be a datetime.datetime") + + self._invalidity_date = invalidity_date + + def __repr__(self) -> str: + return "<InvalidityDate(invalidity_date={})>".format( + self._invalidity_date + ) + + def __eq__(self, other: typing.Any) -> bool: + if not isinstance(other, InvalidityDate): + return NotImplemented + + return self.invalidity_date == other.invalidity_date + + def __ne__(self, other: typing.Any) -> bool: + return not self == other + + def __hash__(self) -> int: + return hash(self.invalidity_date) + + @property + def invalidity_date(self) -> datetime.datetime: + return self._invalidity_date + + def public_bytes(self) -> bytes: + return rust_x509.encode_extension_value(self) + + +class PrecertificateSignedCertificateTimestamps(ExtensionType): + oid = ExtensionOID.PRECERT_SIGNED_CERTIFICATE_TIMESTAMPS + + def __init__( + self, + signed_certificate_timestamps: typing.Iterable[ + SignedCertificateTimestamp + ], + ) -> None: + signed_certificate_timestamps = list(signed_certificate_timestamps) + if not all( + isinstance(sct, SignedCertificateTimestamp) + for sct in signed_certificate_timestamps + ): + raise TypeError( + "Every item in the signed_certificate_timestamps list must be " + "a SignedCertificateTimestamp" + ) + self._signed_certificate_timestamps = signed_certificate_timestamps + + __len__, __iter__, __getitem__ = _make_sequence_methods( + "_signed_certificate_timestamps" + ) + + def __repr__(self) -> str: + return "<PrecertificateSignedCertificateTimestamps({})>".format( + list(self) + ) + + def __hash__(self) -> int: + return hash(tuple(self._signed_certificate_timestamps)) + + def __eq__(self, other: typing.Any) -> bool: + if not isinstance(other, PrecertificateSignedCertificateTimestamps): + return NotImplemented + + return ( + self._signed_certificate_timestamps + == other._signed_certificate_timestamps + ) + + def __ne__(self, other: typing.Any) -> bool: + return not self == other + + def public_bytes(self) -> bytes: + return rust_x509.encode_extension_value(self) + + +class SignedCertificateTimestamps(ExtensionType): + oid = ExtensionOID.SIGNED_CERTIFICATE_TIMESTAMPS + + def __init__( + self, + signed_certificate_timestamps: typing.Iterable[ + SignedCertificateTimestamp + ], + ) -> None: + signed_certificate_timestamps = list(signed_certificate_timestamps) + if not all( + isinstance(sct, SignedCertificateTimestamp) + for sct in signed_certificate_timestamps + ): + raise TypeError( + "Every item in the signed_certificate_timestamps list must be " + "a SignedCertificateTimestamp" + ) + self._signed_certificate_timestamps = signed_certificate_timestamps + + __len__, __iter__, __getitem__ = _make_sequence_methods( + "_signed_certificate_timestamps" + ) + + def __repr__(self) -> str: + return "<SignedCertificateTimestamps({})>".format(list(self)) + + def __hash__(self) -> int: + return hash(tuple(self._signed_certificate_timestamps)) + + def __eq__(self, other: typing.Any) -> bool: + if not isinstance(other, SignedCertificateTimestamps): + return NotImplemented + + return ( + self._signed_certificate_timestamps + == other._signed_certificate_timestamps + ) + + def __ne__(self, other: typing.Any) -> bool: + return not self == other + + def public_bytes(self) -> bytes: + return rust_x509.encode_extension_value(self) + + +class OCSPNonce(ExtensionType): + oid = OCSPExtensionOID.NONCE + + def __init__(self, nonce: bytes) -> None: + if not isinstance(nonce, bytes): + raise TypeError("nonce must be bytes") + + self._nonce = nonce + + def __eq__(self, other: typing.Any) -> bool: + if not isinstance(other, OCSPNonce): + return NotImplemented + + return self.nonce == other.nonce + + def __ne__(self, other: typing.Any) -> bool: + return not self == other + + def __hash__(self) -> int: + return hash(self.nonce) + + def __repr__(self) -> str: + return "<OCSPNonce(nonce={0.nonce!r})>".format(self) + + @property + def nonce(self) -> bytes: + return self._nonce + + def public_bytes(self) -> bytes: + return rust_x509.encode_extension_value(self) + + +class IssuingDistributionPoint(ExtensionType): + oid = ExtensionOID.ISSUING_DISTRIBUTION_POINT + + def __init__( + self, + full_name: typing.Optional[typing.Iterable[GeneralName]], + relative_name: typing.Optional[RelativeDistinguishedName], + only_contains_user_certs: bool, + only_contains_ca_certs: bool, + only_some_reasons: typing.Optional[typing.FrozenSet[ReasonFlags]], + indirect_crl: bool, + only_contains_attribute_certs: bool, + ) -> None: + if full_name is not None: + full_name = list(full_name) + + if only_some_reasons and ( + not isinstance(only_some_reasons, frozenset) + or not all(isinstance(x, ReasonFlags) for x in only_some_reasons) + ): + raise TypeError( + "only_some_reasons must be None or frozenset of ReasonFlags" + ) + + if only_some_reasons and ( + ReasonFlags.unspecified in only_some_reasons + or ReasonFlags.remove_from_crl in only_some_reasons + ): + raise ValueError( + "unspecified and remove_from_crl are not valid reasons in an " + "IssuingDistributionPoint" + ) + + if not ( + isinstance(only_contains_user_certs, bool) + and isinstance(only_contains_ca_certs, bool) + and isinstance(indirect_crl, bool) + and isinstance(only_contains_attribute_certs, bool) + ): + raise TypeError( + "only_contains_user_certs, only_contains_ca_certs, " + "indirect_crl and only_contains_attribute_certs " + "must all be boolean." + ) + + crl_constraints = [ + only_contains_user_certs, + only_contains_ca_certs, + indirect_crl, + only_contains_attribute_certs, + ] + + if len([x for x in crl_constraints if x]) > 1: + raise ValueError( + "Only one of the following can be set to True: " + "only_contains_user_certs, only_contains_ca_certs, " + "indirect_crl, only_contains_attribute_certs" + ) + + if not any( + [ + only_contains_user_certs, + only_contains_ca_certs, + indirect_crl, + only_contains_attribute_certs, + full_name, + relative_name, + only_some_reasons, + ] + ): + raise ValueError( + "Cannot create empty extension: " + "if only_contains_user_certs, only_contains_ca_certs, " + "indirect_crl, and only_contains_attribute_certs are all False" + ", then either full_name, relative_name, or only_some_reasons " + "must have a value." + ) + + self._only_contains_user_certs = only_contains_user_certs + self._only_contains_ca_certs = only_contains_ca_certs + self._indirect_crl = indirect_crl + self._only_contains_attribute_certs = only_contains_attribute_certs + self._only_some_reasons = only_some_reasons + self._full_name = full_name + self._relative_name = relative_name + + def __repr__(self) -> str: + return ( + "<IssuingDistributionPoint(full_name={0.full_name}, " + "relative_name={0.relative_name}, " + "only_contains_user_certs={0.only_contains_user_certs}, " + "only_contains_ca_certs={0.only_contains_ca_certs}, " + "only_some_reasons={0.only_some_reasons}, " + "indirect_crl={0.indirect_crl}, " + "only_contains_attribute_certs=" + "{0.only_contains_attribute_certs})>".format(self) + ) + + def __eq__(self, other: typing.Any) -> bool: + if not isinstance(other, IssuingDistributionPoint): + return NotImplemented + + return ( + self.full_name == other.full_name + and self.relative_name == other.relative_name + and self.only_contains_user_certs == other.only_contains_user_certs + and self.only_contains_ca_certs == other.only_contains_ca_certs + and self.only_some_reasons == other.only_some_reasons + and self.indirect_crl == other.indirect_crl + and self.only_contains_attribute_certs + == other.only_contains_attribute_certs + ) + + def __ne__(self, other: typing.Any) -> bool: + return not self == other + + def __hash__(self) -> int: + return hash( + ( + self.full_name, + self.relative_name, + self.only_contains_user_certs, + self.only_contains_ca_certs, + self.only_some_reasons, + self.indirect_crl, + self.only_contains_attribute_certs, + ) + ) + + @property + def full_name(self) -> typing.Optional[typing.List[GeneralName]]: + return self._full_name + + @property + def relative_name(self) -> typing.Optional[RelativeDistinguishedName]: + return self._relative_name + + @property + def only_contains_user_certs(self) -> bool: + return self._only_contains_user_certs + + @property + def only_contains_ca_certs(self) -> bool: + return self._only_contains_ca_certs + + @property + def only_some_reasons( + self, + ) -> typing.Optional[typing.FrozenSet[ReasonFlags]]: + return self._only_some_reasons + + @property + def indirect_crl(self) -> bool: + return self._indirect_crl + + @property + def only_contains_attribute_certs(self) -> bool: + return self._only_contains_attribute_certs + + def public_bytes(self) -> bytes: + return rust_x509.encode_extension_value(self) + + +class UnrecognizedExtension(ExtensionType): + def __init__(self, oid: ObjectIdentifier, value: bytes) -> None: + if not isinstance(oid, ObjectIdentifier): + raise TypeError("oid must be an ObjectIdentifier") + self._oid = oid + self._value = value + + @property + def oid(self) -> ObjectIdentifier: # type: ignore[override] + return self._oid + + @property + def value(self) -> bytes: + return self._value + + def __repr__(self) -> str: + return ( + "<UnrecognizedExtension(oid={0.oid}, " + "value={0.value!r})>".format(self) + ) + + def __eq__(self, other: typing.Any) -> bool: + if not isinstance(other, UnrecognizedExtension): + return NotImplemented + + return self.oid == other.oid and self.value == other.value + + def __ne__(self, other: typing.Any) -> bool: + return not self == other + + def __hash__(self) -> int: + return hash((self.oid, self.value)) + + def public_bytes(self) -> bytes: + return self.value diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/x509/general_name.py b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/x509/general_name.py new file mode 100644 index 00000000..7ddf90b5 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/x509/general_name.py @@ -0,0 +1,305 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + + +import abc +import ipaddress +import typing +from email.utils import parseaddr + +from cryptography.x509.name import Name +from cryptography.x509.oid import ObjectIdentifier + + +_IPADDRESS_TYPES = typing.Union[ + ipaddress.IPv4Address, + ipaddress.IPv6Address, + ipaddress.IPv4Network, + ipaddress.IPv6Network, +] + + +class UnsupportedGeneralNameType(Exception): + pass + + +class GeneralName(metaclass=abc.ABCMeta): + @abc.abstractproperty + def value(self) -> typing.Any: + """ + Return the value of the object + """ + + +class RFC822Name(GeneralName): + def __init__(self, value: str) -> None: + if isinstance(value, str): + try: + value.encode("ascii") + except UnicodeEncodeError: + raise ValueError( + "RFC822Name values should be passed as an A-label string. " + "This means unicode characters should be encoded via " + "a library like idna." + ) + else: + raise TypeError("value must be string") + + name, address = parseaddr(value) + if name or not address: + # parseaddr has found a name (e.g. Name <email>) or the entire + # value is an empty string. + raise ValueError("Invalid rfc822name value") + + self._value = value + + @property + def value(self) -> str: + return self._value + + @classmethod + def _init_without_validation(cls, value: str) -> "RFC822Name": + instance = cls.__new__(cls) + instance._value = value + return instance + + def __repr__(self) -> str: + return "<RFC822Name(value={0!r})>".format(self.value) + + def __eq__(self, other: object) -> bool: + if not isinstance(other, RFC822Name): + return NotImplemented + + return self.value == other.value + + def __ne__(self, other: object) -> bool: + return not self == other + + def __hash__(self) -> int: + return hash(self.value) + + +class DNSName(GeneralName): + def __init__(self, value: str) -> None: + if isinstance(value, str): + try: + value.encode("ascii") + except UnicodeEncodeError: + raise ValueError( + "DNSName values should be passed as an A-label string. " + "This means unicode characters should be encoded via " + "a library like idna." + ) + else: + raise TypeError("value must be string") + + self._value = value + + @property + def value(self) -> str: + return self._value + + @classmethod + def _init_without_validation(cls, value: str) -> "DNSName": + instance = cls.__new__(cls) + instance._value = value + return instance + + def __repr__(self) -> str: + return "<DNSName(value={0!r})>".format(self.value) + + def __eq__(self, other: object) -> bool: + if not isinstance(other, DNSName): + return NotImplemented + + return self.value == other.value + + def __ne__(self, other: object) -> bool: + return not self == other + + def __hash__(self) -> int: + return hash(self.value) + + +class UniformResourceIdentifier(GeneralName): + def __init__(self, value: str) -> None: + if isinstance(value, str): + try: + value.encode("ascii") + except UnicodeEncodeError: + raise ValueError( + "URI values should be passed as an A-label string. " + "This means unicode characters should be encoded via " + "a library like idna." + ) + else: + raise TypeError("value must be string") + + self._value = value + + @property + def value(self) -> str: + return self._value + + @classmethod + def _init_without_validation( + cls, value: str + ) -> "UniformResourceIdentifier": + instance = cls.__new__(cls) + instance._value = value + return instance + + def __repr__(self) -> str: + return "<UniformResourceIdentifier(value={0!r})>".format(self.value) + + def __eq__(self, other: object) -> bool: + if not isinstance(other, UniformResourceIdentifier): + return NotImplemented + + return self.value == other.value + + def __ne__(self, other: object) -> bool: + return not self == other + + def __hash__(self) -> int: + return hash(self.value) + + +class DirectoryName(GeneralName): + def __init__(self, value: Name) -> None: + if not isinstance(value, Name): + raise TypeError("value must be a Name") + + self._value = value + + @property + def value(self) -> Name: + return self._value + + def __repr__(self) -> str: + return "<DirectoryName(value={})>".format(self.value) + + def __eq__(self, other: object) -> bool: + if not isinstance(other, DirectoryName): + return NotImplemented + + return self.value == other.value + + def __ne__(self, other: object) -> bool: + return not self == other + + def __hash__(self) -> int: + return hash(self.value) + + +class RegisteredID(GeneralName): + def __init__(self, value: ObjectIdentifier) -> None: + if not isinstance(value, ObjectIdentifier): + raise TypeError("value must be an ObjectIdentifier") + + self._value = value + + @property + def value(self) -> ObjectIdentifier: + return self._value + + def __repr__(self) -> str: + return "<RegisteredID(value={})>".format(self.value) + + def __eq__(self, other: object) -> bool: + if not isinstance(other, RegisteredID): + return NotImplemented + + return self.value == other.value + + def __ne__(self, other: object) -> bool: + return not self == other + + def __hash__(self) -> int: + return hash(self.value) + + +class IPAddress(GeneralName): + def __init__(self, value: _IPADDRESS_TYPES) -> None: + if not isinstance( + value, + ( + ipaddress.IPv4Address, + ipaddress.IPv6Address, + ipaddress.IPv4Network, + ipaddress.IPv6Network, + ), + ): + raise TypeError( + "value must be an instance of ipaddress.IPv4Address, " + "ipaddress.IPv6Address, ipaddress.IPv4Network, or " + "ipaddress.IPv6Network" + ) + + self._value = value + + @property + def value(self) -> _IPADDRESS_TYPES: + return self._value + + def _packed(self) -> bytes: + if isinstance( + self.value, (ipaddress.IPv4Address, ipaddress.IPv6Address) + ): + return self.value.packed + else: + return ( + self.value.network_address.packed + self.value.netmask.packed + ) + + def __repr__(self) -> str: + return "<IPAddress(value={})>".format(self.value) + + def __eq__(self, other: object) -> bool: + if not isinstance(other, IPAddress): + return NotImplemented + + return self.value == other.value + + def __ne__(self, other: object) -> bool: + return not self == other + + def __hash__(self) -> int: + return hash(self.value) + + +class OtherName(GeneralName): + def __init__(self, type_id: ObjectIdentifier, value: bytes) -> None: + if not isinstance(type_id, ObjectIdentifier): + raise TypeError("type_id must be an ObjectIdentifier") + if not isinstance(value, bytes): + raise TypeError("value must be a binary string") + + self._type_id = type_id + self._value = value + + @property + def type_id(self) -> ObjectIdentifier: + return self._type_id + + @property + def value(self) -> bytes: + return self._value + + def __repr__(self) -> str: + return "<OtherName(type_id={}, value={!r})>".format( + self.type_id, self.value + ) + + def __eq__(self, other: object) -> bool: + if not isinstance(other, OtherName): + return NotImplemented + + return self.type_id == other.type_id and self.value == other.value + + def __ne__(self, other: object) -> bool: + return not self == other + + def __hash__(self) -> int: + return hash((self.type_id, self.value)) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/x509/name.py b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/x509/name.py new file mode 100644 index 00000000..b02f08ba --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/x509/name.py @@ -0,0 +1,322 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +import typing +import warnings + +from cryptography import utils +from cryptography.hazmat.bindings._rust import ( + x509 as rust_x509, +) +from cryptography.x509.oid import NameOID, ObjectIdentifier + + +class _ASN1Type(utils.Enum): + UTF8String = 12 + NumericString = 18 + PrintableString = 19 + T61String = 20 + IA5String = 22 + UTCTime = 23 + GeneralizedTime = 24 + VisibleString = 26 + UniversalString = 28 + BMPString = 30 + + +_ASN1_TYPE_TO_ENUM = {i.value: i for i in _ASN1Type} +_SENTINEL = object() +_NAMEOID_DEFAULT_TYPE = { + NameOID.COUNTRY_NAME: _ASN1Type.PrintableString, + NameOID.JURISDICTION_COUNTRY_NAME: _ASN1Type.PrintableString, + NameOID.SERIAL_NUMBER: _ASN1Type.PrintableString, + NameOID.DN_QUALIFIER: _ASN1Type.PrintableString, + NameOID.EMAIL_ADDRESS: _ASN1Type.IA5String, + NameOID.DOMAIN_COMPONENT: _ASN1Type.IA5String, +} + +# Type alias +_OidNameMap = typing.Mapping[ObjectIdentifier, str] + +#: Short attribute names from RFC 4514: +#: https://tools.ietf.org/html/rfc4514#page-7 +_NAMEOID_TO_NAME: _OidNameMap = { + NameOID.COMMON_NAME: "CN", + NameOID.LOCALITY_NAME: "L", + NameOID.STATE_OR_PROVINCE_NAME: "ST", + NameOID.ORGANIZATION_NAME: "O", + NameOID.ORGANIZATIONAL_UNIT_NAME: "OU", + NameOID.COUNTRY_NAME: "C", + NameOID.STREET_ADDRESS: "STREET", + NameOID.DOMAIN_COMPONENT: "DC", + NameOID.USER_ID: "UID", +} + + +def _escape_dn_value(val: str) -> str: + """Escape special characters in RFC4514 Distinguished Name value.""" + + if not val: + return "" + + # See https://tools.ietf.org/html/rfc4514#section-2.4 + val = val.replace("\\", "\\\\") + val = val.replace('"', '\\"') + val = val.replace("+", "\\+") + val = val.replace(",", "\\,") + val = val.replace(";", "\\;") + val = val.replace("<", "\\<") + val = val.replace(">", "\\>") + val = val.replace("\0", "\\00") + + if val[0] in ("#", " "): + val = "\\" + val + if val[-1] == " ": + val = val[:-1] + "\\ " + + return val + + +class NameAttribute(object): + def __init__( + self, + oid: ObjectIdentifier, + value: str, + _type=_SENTINEL, + *, + _validate=True, + ) -> None: + if not isinstance(oid, ObjectIdentifier): + raise TypeError( + "oid argument must be an ObjectIdentifier instance." + ) + + if not isinstance(value, str): + raise TypeError("value argument must be a str.") + + if ( + oid == NameOID.COUNTRY_NAME + or oid == NameOID.JURISDICTION_COUNTRY_NAME + ): + c_len = len(value.encode("utf8")) + if c_len != 2 and _validate is True: + raise ValueError( + "Country name must be a 2 character country code" + ) + elif c_len != 2: + warnings.warn( + "Country names should be two characters, but the " + "attribute is {} characters in length.".format(c_len), + stacklevel=2, + ) + + # The appropriate ASN1 string type varies by OID and is defined across + # multiple RFCs including 2459, 3280, and 5280. In general UTF8String + # is preferred (2459), but 3280 and 5280 specify several OIDs with + # alternate types. This means when we see the sentinel value we need + # to look up whether the OID has a non-UTF8 type. If it does, set it + # to that. Otherwise, UTF8! + if _type == _SENTINEL: + _type = _NAMEOID_DEFAULT_TYPE.get(oid, _ASN1Type.UTF8String) + + if not isinstance(_type, _ASN1Type): + raise TypeError("_type must be from the _ASN1Type enum") + + self._oid = oid + self._value = value + self._type = _type + + @property + def oid(self) -> ObjectIdentifier: + return self._oid + + @property + def value(self) -> str: + return self._value + + @property + def rfc4514_attribute_name(self) -> str: + """ + The short attribute name (for example "CN") if available, + otherwise the OID dotted string. + """ + return _NAMEOID_TO_NAME.get(self.oid, self.oid.dotted_string) + + def rfc4514_string( + self, attr_name_overrides: typing.Optional[_OidNameMap] = None + ) -> str: + """ + Format as RFC4514 Distinguished Name string. + + Use short attribute name if available, otherwise fall back to OID + dotted string. + """ + attr_name = ( + attr_name_overrides.get(self.oid) if attr_name_overrides else None + ) + if attr_name is None: + attr_name = self.rfc4514_attribute_name + + return "%s=%s" % (attr_name, _escape_dn_value(self.value)) + + def __eq__(self, other: object) -> bool: + if not isinstance(other, NameAttribute): + return NotImplemented + + return self.oid == other.oid and self.value == other.value + + def __ne__(self, other: object) -> bool: + return not self == other + + def __hash__(self) -> int: + return hash((self.oid, self.value)) + + def __repr__(self) -> str: + return "<NameAttribute(oid={0.oid}, value={0.value!r})>".format(self) + + +class RelativeDistinguishedName(object): + def __init__(self, attributes: typing.Iterable[NameAttribute]): + attributes = list(attributes) + if not attributes: + raise ValueError("a relative distinguished name cannot be empty") + if not all(isinstance(x, NameAttribute) for x in attributes): + raise TypeError("attributes must be an iterable of NameAttribute") + + # Keep list and frozenset to preserve attribute order where it matters + self._attributes = attributes + self._attribute_set = frozenset(attributes) + + if len(self._attribute_set) != len(attributes): + raise ValueError("duplicate attributes are not allowed") + + def get_attributes_for_oid( + self, oid: ObjectIdentifier + ) -> typing.List[NameAttribute]: + return [i for i in self if i.oid == oid] + + def rfc4514_string( + self, attr_name_overrides: typing.Optional[_OidNameMap] = None + ) -> str: + """ + Format as RFC4514 Distinguished Name string. + + Within each RDN, attributes are joined by '+', although that is rarely + used in certificates. + """ + return "+".join( + attr.rfc4514_string(attr_name_overrides) + for attr in self._attributes + ) + + def __eq__(self, other: object) -> bool: + if not isinstance(other, RelativeDistinguishedName): + return NotImplemented + + return self._attribute_set == other._attribute_set + + def __ne__(self, other: object) -> bool: + return not self == other + + def __hash__(self) -> int: + return hash(self._attribute_set) + + def __iter__(self) -> typing.Iterator[NameAttribute]: + return iter(self._attributes) + + def __len__(self) -> int: + return len(self._attributes) + + def __repr__(self) -> str: + return "<RelativeDistinguishedName({})>".format(self.rfc4514_string()) + + +class Name(object): + @typing.overload + def __init__(self, attributes: typing.Iterable[NameAttribute]) -> None: + ... + + @typing.overload + def __init__( + self, attributes: typing.Iterable[RelativeDistinguishedName] + ) -> None: + ... + + def __init__( + self, + attributes: typing.Iterable[ + typing.Union[NameAttribute, RelativeDistinguishedName] + ], + ) -> None: + attributes = list(attributes) + if all(isinstance(x, NameAttribute) for x in attributes): + self._attributes = [ + RelativeDistinguishedName([typing.cast(NameAttribute, x)]) + for x in attributes + ] + elif all(isinstance(x, RelativeDistinguishedName) for x in attributes): + self._attributes = typing.cast( + typing.List[RelativeDistinguishedName], attributes + ) + else: + raise TypeError( + "attributes must be a list of NameAttribute" + " or a list RelativeDistinguishedName" + ) + + def rfc4514_string( + self, attr_name_overrides: typing.Optional[_OidNameMap] = None + ) -> str: + """ + Format as RFC4514 Distinguished Name string. + For example 'CN=foobar.com,O=Foo Corp,C=US' + + An X.509 name is a two-level structure: a list of sets of attributes. + Each list element is separated by ',' and within each list element, set + elements are separated by '+'. The latter is almost never used in + real world certificates. According to RFC4514 section 2.1 the + RDNSequence must be reversed when converting to string representation. + """ + return ",".join( + attr.rfc4514_string(attr_name_overrides) + for attr in reversed(self._attributes) + ) + + def get_attributes_for_oid( + self, oid: ObjectIdentifier + ) -> typing.List[NameAttribute]: + return [i for i in self if i.oid == oid] + + @property + def rdns(self) -> typing.List[RelativeDistinguishedName]: + return self._attributes + + def public_bytes(self, backend: typing.Any = None) -> bytes: + return rust_x509.encode_name_bytes(self) + + def __eq__(self, other: object) -> bool: + if not isinstance(other, Name): + return NotImplemented + + return self._attributes == other._attributes + + def __ne__(self, other: object) -> bool: + return not self == other + + def __hash__(self) -> int: + # TODO: this is relatively expensive, if this looks like a bottleneck + # for you, consider optimizing! + return hash(tuple(self._attributes)) + + def __iter__(self) -> typing.Iterator[NameAttribute]: + for rdn in self._attributes: + for ava in rdn: + yield ava + + def __len__(self) -> int: + return sum(len(rdn) for rdn in self._attributes) + + def __repr__(self) -> str: + rdns = ",".join(attr.rfc4514_string() for attr in self._attributes) + return "<Name({})>".format(rdns) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/x509/ocsp.py b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/x509/ocsp.py new file mode 100644 index 00000000..8eec4c0c --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/x509/ocsp.py @@ -0,0 +1,483 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + + +import abc +import datetime +import typing + +from cryptography import utils +from cryptography import x509 +from cryptography.hazmat.bindings._rust import ocsp +from cryptography.hazmat.primitives import hashes, serialization +from cryptography.x509.base import ( + PRIVATE_KEY_TYPES, + _EARLIEST_UTC_TIME, + _convert_to_naive_utc_time, + _reject_duplicate_extension, +) + + +class OCSPResponderEncoding(utils.Enum): + HASH = "By Hash" + NAME = "By Name" + + +class OCSPResponseStatus(utils.Enum): + SUCCESSFUL = 0 + MALFORMED_REQUEST = 1 + INTERNAL_ERROR = 2 + TRY_LATER = 3 + SIG_REQUIRED = 5 + UNAUTHORIZED = 6 + + +_ALLOWED_HASHES = ( + hashes.SHA1, + hashes.SHA224, + hashes.SHA256, + hashes.SHA384, + hashes.SHA512, +) + + +def _verify_algorithm(algorithm): + if not isinstance(algorithm, _ALLOWED_HASHES): + raise ValueError( + "Algorithm must be SHA1, SHA224, SHA256, SHA384, or SHA512" + ) + + +class OCSPCertStatus(utils.Enum): + GOOD = 0 + REVOKED = 1 + UNKNOWN = 2 + + +class _SingleResponse(object): + def __init__( + self, + cert, + issuer, + algorithm, + cert_status, + this_update, + next_update, + revocation_time, + revocation_reason, + ): + if not isinstance(cert, x509.Certificate) or not isinstance( + issuer, x509.Certificate + ): + raise TypeError("cert and issuer must be a Certificate") + + _verify_algorithm(algorithm) + if not isinstance(this_update, datetime.datetime): + raise TypeError("this_update must be a datetime object") + if next_update is not None and not isinstance( + next_update, datetime.datetime + ): + raise TypeError("next_update must be a datetime object or None") + + self._cert = cert + self._issuer = issuer + self._algorithm = algorithm + self._this_update = this_update + self._next_update = next_update + + if not isinstance(cert_status, OCSPCertStatus): + raise TypeError( + "cert_status must be an item from the OCSPCertStatus enum" + ) + if cert_status is not OCSPCertStatus.REVOKED: + if revocation_time is not None: + raise ValueError( + "revocation_time can only be provided if the certificate " + "is revoked" + ) + if revocation_reason is not None: + raise ValueError( + "revocation_reason can only be provided if the certificate" + " is revoked" + ) + else: + if not isinstance(revocation_time, datetime.datetime): + raise TypeError("revocation_time must be a datetime object") + + revocation_time = _convert_to_naive_utc_time(revocation_time) + if revocation_time < _EARLIEST_UTC_TIME: + raise ValueError( + "The revocation_time must be on or after" + " 1950 January 1." + ) + + if revocation_reason is not None and not isinstance( + revocation_reason, x509.ReasonFlags + ): + raise TypeError( + "revocation_reason must be an item from the ReasonFlags " + "enum or None" + ) + + self._cert_status = cert_status + self._revocation_time = revocation_time + self._revocation_reason = revocation_reason + + +class OCSPRequest(metaclass=abc.ABCMeta): + @abc.abstractproperty + def issuer_key_hash(self) -> bytes: + """ + The hash of the issuer public key + """ + + @abc.abstractproperty + def issuer_name_hash(self) -> bytes: + """ + The hash of the issuer name + """ + + @abc.abstractproperty + def hash_algorithm(self) -> hashes.HashAlgorithm: + """ + The hash algorithm used in the issuer name and key hashes + """ + + @abc.abstractproperty + def serial_number(self) -> int: + """ + The serial number of the cert whose status is being checked + """ + + @abc.abstractmethod + def public_bytes(self, encoding: serialization.Encoding) -> bytes: + """ + Serializes the request to DER + """ + + @abc.abstractproperty + def extensions(self) -> x509.Extensions: + """ + The list of request extensions. Not single request extensions. + """ + + +class OCSPResponse(metaclass=abc.ABCMeta): + @abc.abstractproperty + def response_status(self) -> OCSPResponseStatus: + """ + The status of the response. This is a value from the OCSPResponseStatus + enumeration + """ + + @abc.abstractproperty + def signature_algorithm_oid(self) -> x509.ObjectIdentifier: + """ + The ObjectIdentifier of the signature algorithm + """ + + @abc.abstractproperty + def signature_hash_algorithm( + self, + ) -> typing.Optional[hashes.HashAlgorithm]: + """ + Returns a HashAlgorithm corresponding to the type of the digest signed + """ + + @abc.abstractproperty + def signature(self) -> bytes: + """ + The signature bytes + """ + + @abc.abstractproperty + def tbs_response_bytes(self) -> bytes: + """ + The tbsResponseData bytes + """ + + @abc.abstractproperty + def certificates(self) -> typing.List[x509.Certificate]: + """ + A list of certificates used to help build a chain to verify the OCSP + response. This situation occurs when the OCSP responder uses a delegate + certificate. + """ + + @abc.abstractproperty + def responder_key_hash(self) -> typing.Optional[bytes]: + """ + The responder's key hash or None + """ + + @abc.abstractproperty + def responder_name(self) -> typing.Optional[x509.Name]: + """ + The responder's Name or None + """ + + @abc.abstractproperty + def produced_at(self) -> datetime.datetime: + """ + The time the response was produced + """ + + @abc.abstractproperty + def certificate_status(self) -> OCSPCertStatus: + """ + The status of the certificate (an element from the OCSPCertStatus enum) + """ + + @abc.abstractproperty + def revocation_time(self) -> typing.Optional[datetime.datetime]: + """ + The date of when the certificate was revoked or None if not + revoked. + """ + + @abc.abstractproperty + def revocation_reason(self) -> typing.Optional[x509.ReasonFlags]: + """ + The reason the certificate was revoked or None if not specified or + not revoked. + """ + + @abc.abstractproperty + def this_update(self) -> datetime.datetime: + """ + The most recent time at which the status being indicated is known by + the responder to have been correct + """ + + @abc.abstractproperty + def next_update(self) -> typing.Optional[datetime.datetime]: + """ + The time when newer information will be available + """ + + @abc.abstractproperty + def issuer_key_hash(self) -> bytes: + """ + The hash of the issuer public key + """ + + @abc.abstractproperty + def issuer_name_hash(self) -> bytes: + """ + The hash of the issuer name + """ + + @abc.abstractproperty + def hash_algorithm(self) -> hashes.HashAlgorithm: + """ + The hash algorithm used in the issuer name and key hashes + """ + + @abc.abstractproperty + def serial_number(self) -> int: + """ + The serial number of the cert whose status is being checked + """ + + @abc.abstractproperty + def extensions(self) -> x509.Extensions: + """ + The list of response extensions. Not single response extensions. + """ + + @abc.abstractproperty + def single_extensions(self) -> x509.Extensions: + """ + The list of single response extensions. Not response extensions. + """ + + @abc.abstractmethod + def public_bytes(self, encoding: serialization.Encoding) -> bytes: + """ + Serializes the response to DER + """ + + +class OCSPRequestBuilder(object): + def __init__( + self, + request: typing.Optional[ + typing.Tuple[ + x509.Certificate, x509.Certificate, hashes.HashAlgorithm + ] + ] = None, + extensions: typing.List[x509.Extension[x509.ExtensionType]] = [], + ) -> None: + self._request = request + self._extensions = extensions + + def add_certificate( + self, + cert: x509.Certificate, + issuer: x509.Certificate, + algorithm: hashes.HashAlgorithm, + ) -> "OCSPRequestBuilder": + if self._request is not None: + raise ValueError("Only one certificate can be added to a request") + + _verify_algorithm(algorithm) + if not isinstance(cert, x509.Certificate) or not isinstance( + issuer, x509.Certificate + ): + raise TypeError("cert and issuer must be a Certificate") + + return OCSPRequestBuilder((cert, issuer, algorithm), self._extensions) + + def add_extension( + self, extval: x509.ExtensionType, critical: bool + ) -> "OCSPRequestBuilder": + if not isinstance(extval, x509.ExtensionType): + raise TypeError("extension must be an ExtensionType") + + extension = x509.Extension(extval.oid, critical, extval) + _reject_duplicate_extension(extension, self._extensions) + + return OCSPRequestBuilder( + self._request, self._extensions + [extension] + ) + + def build(self) -> OCSPRequest: + if self._request is None: + raise ValueError("You must add a certificate before building") + + return ocsp.create_ocsp_request(self) + + +class OCSPResponseBuilder(object): + def __init__( + self, + response: typing.Optional[_SingleResponse] = None, + responder_id: typing.Optional[ + typing.Tuple[x509.Certificate, OCSPResponderEncoding] + ] = None, + certs: typing.Optional[typing.List[x509.Certificate]] = None, + extensions: typing.List[x509.Extension[x509.ExtensionType]] = [], + ): + self._response = response + self._responder_id = responder_id + self._certs = certs + self._extensions = extensions + + def add_response( + self, + cert: x509.Certificate, + issuer: x509.Certificate, + algorithm: hashes.HashAlgorithm, + cert_status: OCSPCertStatus, + this_update: datetime.datetime, + next_update: typing.Optional[datetime.datetime], + revocation_time: typing.Optional[datetime.datetime], + revocation_reason: typing.Optional[x509.ReasonFlags], + ) -> "OCSPResponseBuilder": + if self._response is not None: + raise ValueError("Only one response per OCSPResponse.") + + singleresp = _SingleResponse( + cert, + issuer, + algorithm, + cert_status, + this_update, + next_update, + revocation_time, + revocation_reason, + ) + return OCSPResponseBuilder( + singleresp, + self._responder_id, + self._certs, + self._extensions, + ) + + def responder_id( + self, encoding: OCSPResponderEncoding, responder_cert: x509.Certificate + ) -> "OCSPResponseBuilder": + if self._responder_id is not None: + raise ValueError("responder_id can only be set once") + if not isinstance(responder_cert, x509.Certificate): + raise TypeError("responder_cert must be a Certificate") + if not isinstance(encoding, OCSPResponderEncoding): + raise TypeError( + "encoding must be an element from OCSPResponderEncoding" + ) + + return OCSPResponseBuilder( + self._response, + (responder_cert, encoding), + self._certs, + self._extensions, + ) + + def certificates( + self, certs: typing.Iterable[x509.Certificate] + ) -> "OCSPResponseBuilder": + if self._certs is not None: + raise ValueError("certificates may only be set once") + certs = list(certs) + if len(certs) == 0: + raise ValueError("certs must not be an empty list") + if not all(isinstance(x, x509.Certificate) for x in certs): + raise TypeError("certs must be a list of Certificates") + return OCSPResponseBuilder( + self._response, + self._responder_id, + certs, + self._extensions, + ) + + def add_extension( + self, extval: x509.ExtensionType, critical: bool + ) -> "OCSPResponseBuilder": + if not isinstance(extval, x509.ExtensionType): + raise TypeError("extension must be an ExtensionType") + + extension = x509.Extension(extval.oid, critical, extval) + _reject_duplicate_extension(extension, self._extensions) + + return OCSPResponseBuilder( + self._response, + self._responder_id, + self._certs, + self._extensions + [extension], + ) + + def sign( + self, + private_key: PRIVATE_KEY_TYPES, + algorithm: typing.Optional[hashes.HashAlgorithm], + ) -> OCSPResponse: + if self._response is None: + raise ValueError("You must add a response before signing") + if self._responder_id is None: + raise ValueError("You must add a responder_id before signing") + + return ocsp.create_ocsp_response( + OCSPResponseStatus.SUCCESSFUL, self, private_key, algorithm + ) + + @classmethod + def build_unsuccessful( + cls, response_status: OCSPResponseStatus + ) -> OCSPResponse: + if not isinstance(response_status, OCSPResponseStatus): + raise TypeError( + "response_status must be an item from OCSPResponseStatus" + ) + if response_status is OCSPResponseStatus.SUCCESSFUL: + raise ValueError("response_status cannot be SUCCESSFUL") + + return ocsp.create_ocsp_response(response_status, None, None, None) + + +def load_der_ocsp_request(data: bytes) -> OCSPRequest: + return ocsp.load_der_ocsp_request(data) + + +def load_der_ocsp_response(data: bytes) -> OCSPResponse: + return ocsp.load_der_ocsp_response(data) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/x509/oid.py b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/x509/oid.py new file mode 100644 index 00000000..9bfac75a --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/cryptography/cryptography/x509/oid.py @@ -0,0 +1,32 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from cryptography.hazmat._oid import ( + AttributeOID, + AuthorityInformationAccessOID, + CRLEntryExtensionOID, + CertificatePoliciesOID, + ExtendedKeyUsageOID, + ExtensionOID, + NameOID, + OCSPExtensionOID, + ObjectIdentifier, + SignatureAlgorithmOID, + SubjectInformationAccessOID, +) + + +__all__ = [ + "AttributeOID", + "AuthorityInformationAccessOID", + "CRLEntryExtensionOID", + "CertificatePoliciesOID", + "ExtendedKeyUsageOID", + "ExtensionOID", + "NameOID", + "OCSPExtensionOID", + "ObjectIdentifier", + "SignatureAlgorithmOID", + "SubjectInformationAccessOID", +] diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/decrypt_win32.exe b/arch-config/.config/calibre/plugins/DeACSM/modules/decrypt_win32.exe new file mode 100644 index 00000000..897773b5 Binary files /dev/null and b/arch-config/.config/calibre/plugins/DeACSM/modules/decrypt_win32.exe differ diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/decrypt_win64.exe b/arch-config/.config/calibre/plugins/DeACSM/modules/decrypt_win64.exe new file mode 100644 index 00000000..b8961368 Binary files /dev/null and b/arch-config/.config/calibre/plugins/DeACSM/modules/decrypt_win64.exe differ diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/module_id.txt b/arch-config/.config/calibre/plugins/DeACSM/modules/module_id.txt new file mode 100644 index 00000000..6a53fabb --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/module_id.txt @@ -0,0 +1 @@ +2021-12-15-01 \ No newline at end of file diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/LICENSE b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/LICENSE new file mode 100644 index 00000000..8038d9a7 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2015-2019 Will Bond <will@wbond.net> + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/PKG-INFO b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/PKG-INFO new file mode 100644 index 00000000..8a7dfd3c --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/PKG-INFO @@ -0,0 +1,382 @@ +Metadata-Version: 2.1 +Name: oscrypto +Version: 1.2.1 +Summary: TLS (SSL) sockets, key generation, encryption, decryption, signing, verification and KDFs using the OS crypto libraries. Does not require a compiler, and relies on the OS for patching. Works on Windows, OS X and Linux/BSD. +Home-page: https://github.com/wbond/oscrypto +Author: wbond +Author-email: will@wbond.net +License: MIT +Description: # oscrypto + + A compilation-free, always up-to-date encryption library for Python that works + on Windows, OS X, Linux and BSD. Supports the following versions of Python: + 2.6, 2.7, 3.2, 3.3, 3.4, 3.5, 3.6, 3.7, 3.8 and pypy. + + - [Supported Operating Systems](#supported-operationg-systems) + - [Features](#features) + - [Why Another Python Crypto Library?](#why-another-python-crypto-library) + - [Related Crypto Libraries](#related-crypto-libraries) + - [Current Release](#current-release) + - [Dependencies](#dependencies) + - [Installation](#installation) + - [License](#license) + - [Documentation](#documentation) + - [Continuous Integration](#continuous-integration) + - [Testing](#testing) + - [Development](#development) + - [CI Tasks](#ci-tasks) + + [![GitHub Actions CI](https://github.com/wbond/oscrypto/workflows/CI/badge.svg)](https://github.com/wbond/oscrypto/actions?workflow=CI) + [![Travis CI](https://api.travis-ci.org/wbond/oscrypto.svg?branch=master)](https://travis-ci.org/wbond/oscrypto) + [![AppVeyor](https://ci.appveyor.com/api/projects/status/github/wbond/oscrypto?branch=master&svg=true)](https://ci.appveyor.com/project/wbond/oscrypto) + [![CircleCI](https://circleci.com/gh/wbond/oscrypto.svg?style=shield)](https://circleci.com/gh/wbond/oscrypto) + [![PyPI](https://img.shields.io/pypi/v/oscrypto.svg)](https://pypi.python.org/pypi/oscrypto) + + ## Supported Operating Systems + + The library integrates with the encryption library that is part of the operating + system. This means that a compiler is never needed, and OS security updates take + care of patching vulnerabilities. Supported operating systems include: + + - Windows XP or newer + - Uses: + - [Cryptography API: Next Generation (CNG)](https://msdn.microsoft.com/en-us/library/windows/desktop/aa376210(v=vs.85).aspx) + - [Secure Channel](https://msdn.microsoft.com/en-us/library/windows/desktop/aa380123(v=vs.85).aspx) for TLS + - [CryptoAPI](https://msdn.microsoft.com/en-us/library/windows/desktop/aa380256(v=vs.85).aspx) for trust lists and XP support + - Tested on: + - Windows XP (no SNI) + - Windows 7 + - Windows 8.1 + - Windows Server 2012 + - Windows 10 + - OS X 10.7 or newer + - Uses: + - [Security.framework](https://developer.apple.com/library/prerelease/mac/documentation/Security/Reference/SecurityFrameworkReference/index.html) + - [Secure Transport](https://developer.apple.com/library/prerelease/mac/documentation/Security/Reference/secureTransportRef/index.html#//apple_ref/doc/uid/TP30000155) for TLS + - [CommonCrypto](http://www.opensource.apple.com/source/CommonCrypto/CommonCrypto-55010/CommonCrypto/) for PBKDF2 + - OpenSSL (or LibreSSL on macOS 10.13) for the PKCS #12 KDF + - Tested on: + - OS X 10.7 + - OS X 10.8 + - OS X 10.9 + - OS X 10.10 + - OS X 10.11 + - OS X 10.11 with OpenSSL 1.1.0 + - macOS 10.12 + - macOS 10.13 with LibreSSL 2.2.7 + - macOS 10.14 + - macOS 10.15 + - macOS 11 + - Linux or BSD + - Uses one of: + - [OpenSSL 0.9.8](https://www.openssl.org/docs/man0.9.8/) + - [OpenSSL 1.0.x](https://www.openssl.org/docs/man1.0.0/) + - [OpenSSL 1.1.0](https://www.openssl.org/docs/man1.1.0/) + - [LibreSSL](http://www.libressl.org/) + - Tested on: + - Arch Linux with OpenSSL 1.0.2 + - OpenBSD 5.7 with LibreSSL + - Ubuntu 10.04 with OpenSSL 0.9.8 + - Ubuntu 12.04 with OpenSSL 1.0.1 + - Ubuntu 15.04 with OpenSSL 1.0.1 + - Ubuntu 16.04 with OpenSSL 1.0.2 on Raspberry Pi 3 (armhf) + - Ubuntu 18.04 with OpenSSL 1.1.x (amd64, arm64, ppc64el) + + *OS X 10.6 will not be supported due to a lack of available + cryptographic primitives and due to lack of vendor support.* + + ## Features + + Currently the following features are implemented. Many of these should only be + used for integration with existing/legacy systems. If you don't know which you + should, or should not use, please see [Learning](docs/readme.md#learning). + + - [TLSv1.x socket wrappers](docs/tls.md) + - Certificate verification performed by OS trust roots + - Custom CA certificate support + - SNI support (except Windows XP) + - Session reuse via IDs/tickets + - Modern cipher suites (RC4, DES, anon and NULL ciphers disabled) + - Weak DH parameters and certificate signatures rejected + - SSLv3 disabled by default, SSLv2 unimplemented + - CRL/OCSP revocation checks consistenty disabled + - [Exporting OS trust roots](docs/trust_list.md) + - PEM-formatted CA certs from the OS for OpenSSL-based code + - [Encryption/decryption](docs/symmetric.md) + - AES (128, 192, 256), CBC mode, PKCS7 padding + - AES (128, 192, 256), CBC mode, no padding + - TripleDES 3-key, CBC mode, PKCS5 padding + - TripleDes 2-key, CBC mode, PKCS5 padding + - DES, CBC mode, PKCS5 padding + - RC2 (40-128), CBC mode, PKCS5 padding + - RC4 (40-128) + - RSA PKCSv1.5 + - RSA OAEP (SHA1 only) + - [Generating public/private key pairs](docs/asymmetric.md) + - RSA (1024, 2048, 3072, 4096 bit) + - DSA (1024 bit on all platforms - 2048, 3072 bit with OpenSSL 1.x or + Windows 8) + - EC (secp256r1, secp384r1, secp521r1 curves) + - [Generating DH parameters](docs/asymmetric.md) + - [Signing and verification](docs/asymmetric.md) + - RSA PKCSv1.5 + - RSA PSS + - DSA + - EC + - [Loading and normalizing DER and PEM formatted keys](docs/keys.md) + - RSA public and private keys + - DSA public and private keys + - EC public and private keys + - X.509 Certificates + - PKCS#12 archives (`.pfx`/`.p12`) + - [Key derivation](docs/kdf.md) + - PBKDF2 + - PBKDF1 + - PKCS#12 KDF + - [Random byte generation](docs/util.md) + + The feature set was largely driven by the technologies used related to + generating and validating X.509 certificates. The various CBC encryption schemes + and KDFs are used to load encrypted private keys, and the various RSA padding + schemes are part of X.509 signatures. + + For modern cryptography not tied to an existing system, please see the + [Modern Cryptography](docs/readme.md#modern-cryptography) section of the docs. + + *Please note that this library does not include modern block modes such as CTR + and GCM due to lack of support from both OS X and OpenSSL 0.9.8.* + + ## Why Another Python Crypto Library? + + In short, the existing cryptography libraries for Python didn't fit the needs of + a couple of projects I was working on. Primarily these are applications + distributed to end-users who aren't programmers, that need to handle TLS and + various technologies related to X.509 certificates. + + If your system is not tied to AES, TLS, X.509, or related technologies, you + probably want [more modern cryptography](docs/readme.md#modern-cryptography). + + Depending on your needs, the [cryptography](https://cryptography.io) package may + be a good (or better) fit. + + Some things that make oscrypto unique: + + - No compiler needed, ever. No need to pre-compile shared libraries. Just + distribute the Python source files, any way you want. + - Uses the operating system's crypto library - does not require OpenSSL on + Windows or OS X. + - Relies on the operating system for security patching. You don't need to + rebuild all of your apps every time there is a new TLS vulnerability. + - Intentionally limited in scope to crypto primitives. Other libraries + built upon it deal with certificate path validation, creating certificates + and CSRs, constructing CMS structures. + - Built on top of a fast, pure-Python ASN.1 parser, + [asn1crypto](https://github.com/wbond/asn1crypto). + - TLS functionality uses the operating system's trust list/CA certs and is + pre-configured with sane defaults + - Public APIs are simple and use strict type checks to avoid errors + + Some downsides include: + + - Does not currently implement: + - standalone DH key exchange + - various encryption modes such as GCM, CCM, CTR, CFB, OFB, ECB + - key wrapping + - CMAC + - HKDF + - Non-TLS functionality is architected for dealing with data that fits in + memory and is available all at once + - Developed by a single developer + + ## Related Crypto Libraries + + *oscrypto* is part of the modularcrypto family of Python packages: + + - [asn1crypto](https://github.com/wbond/asn1crypto) + - [oscrypto](https://github.com/wbond/oscrypto) + - [csrbuilder](https://github.com/wbond/csrbuilder) + - [certbuilder](https://github.com/wbond/certbuilder) + - [crlbuilder](https://github.com/wbond/crlbuilder) + - [ocspbuilder](https://github.com/wbond/ocspbuilder) + - [certvalidator](https://github.com/wbond/certvalidator) + + ## Current Release + + 1.2.1 - [changelog](changelog.md) + + ## Dependencies + + - [*asn1crypto*](https://github.com/wbond/asn1crypto) + - Python 2.6, 2.7, 3.2, 3.3, 3.4, 3.5, 3.6, 3.7, 3.8 or pypy + + ## Installation + + ```bash + pip install oscrypto + ``` + + ## License + + *oscrypto* is licensed under the terms of the MIT license. See the + [LICENSE](LICENSE) file for the exact license text. + + ## Documentation + + [*oscrypto* documentation](docs/readme.md) + + ## Continuous Integration + + Various combinations of platforms and versions of Python are tested via: + + - [AppVeyor](https://ci.appveyor.com/project/wbond/oscrypto/history) + - [CircleCI](https://circleci.com/gh/wbond/oscrypto) + - [GitHub Actions](https://github.com/wbond/oscrypto/actions) + - [Travis CI](https://travis-ci.org/wbond/oscrypto/builds) + + ## Testing + + Tests are written using `unittest` and require no third-party packages. + + Depending on what type of source is available for the package, the following + commands can be used to run the test suite. + + ### Git Repository + + When working within a Git working copy, or an archive of the Git repository, + the full test suite is run via: + + ```bash + python run.py tests + ``` + + To run only some tests, pass a regular expression as a parameter to `tests`. + + ```bash + python run.py tests aes + ``` + + To run tests multiple times, in order to catch edge-case bugs, pass an integer + to `tests`. If combined with a regular expression for filtering, pass the + repeat count after the regular expression. + + ```bash + python run.py tests 20 + python run.py tests aes 20 + ``` + + To run tests using a custom build of OpenSSL, or to use OpenSSL on Windows or + Mac, add `use_openssl` after `run.py`, like: + + ```bash + python run.py use_openssl=/path/to/libcrypto.dylib,/path/to/libssl.dylib tests + ``` + + ### PyPi Source Distribution + + When working within an extracted source distribution (aka `.tar.gz`) from + PyPi, the full test suite is run via: + + ```bash + python setup.py test + ``` + + ### Package + + When the package has been installed via pip (or another method), the package + `oscrypto_tests` may be installed and invoked to run the full test suite: + + ```bash + pip install oscrypto_tests + python -m oscrypto_tests + ``` + + ## Development + + To install the package used for linting, execute: + + ```bash + pip install --user -r requires/lint + ``` + + The following command will run the linter: + + ```bash + python run.py lint + ``` + + Support for code coverage can be installed via: + + ```bash + pip install --user -r requires/coverage + ``` + + Coverage is measured by running: + + ```bash + python run.py coverage + ``` + + To install the packages requires to generate the API documentation, run: + + ```bash + pip install --user -r requires/api_docs + ``` + + The documentation can then be generated by running: + + ```bash + python run.py api_docs + ``` + + To install the necessary packages for releasing a new version on PyPI, run: + + ```bash + pip install --user -r requires/release + ``` + + Releases are created by: + + - Making a git tag in [semver](http://semver.org/) format + - Running the command: + + ```bash + python run.py release + ``` + + Existing releases can be found at https://pypi.python.org/pypi/oscrypto. + + ## CI Tasks + + A task named `deps` exists to download and stage all necessary testing + dependencies. On posix platforms, `curl` is used for downloads and on Windows + PowerShell with `Net.WebClient` is used. This configuration sidesteps issues + related to getting pip to work properly and messing with `site-packages` for + the version of Python being used. + + The `ci` task runs `lint` (if flake8 is avaiable for the version of Python) and + `coverage` (or `tests` if coverage is not available for the version of Python). + If the current directory is a clean git working copy, the coverage data is + submitted to codecov.io. + + ```bash + python run.py deps + python run.py ci + ``` + +Keywords: crypto pki tls ssl x509 certificate encrypt decrypt sign verify rsa dsa ec dh +Platform: UNKNOWN +Classifier: Development Status :: 5 - Production/Stable +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: MIT License +Classifier: Programming Language :: Python :: 2.6 +Classifier: Programming Language :: Python :: 2.7 +Classifier: Programming Language :: Python :: 3.2 +Classifier: Programming Language :: Python :: 3.3 +Classifier: Programming Language :: Python :: 3.4 +Classifier: Programming Language :: Python :: 3.5 +Classifier: Programming Language :: Python :: 3.6 +Classifier: Programming Language :: Python :: 3.7 +Classifier: Programming Language :: Python :: 3.8 +Classifier: Programming Language :: Python :: Implementation :: PyPy +Classifier: Topic :: Security :: Cryptography +Description-Content-Type: text/markdown diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/changelog.md b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/changelog.md new file mode 100644 index 00000000..57eeb731 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/changelog.md @@ -0,0 +1,271 @@ +# changelog + +## 1.2.1 + + - Fix running in an environment with a custom OpenSSL install on macOS 10.15 + - Fix compatibility with macOS 11, where `ctype.find_library()` no longer + works due to system `.dylib`s no longer being present on the filesystem + - Handle the Mac `EPROTOTYPE` error that may be returned when a TLS + connection is terminated + - Fixed the `oscrypto-tests` sdist on PyPi to work properly to generate a + .whl + +## 1.2.0 + + - Allow `oscrypto.use_ctypes()`, `oscrypto.use_openssl()` and + `oscrypto.use_winlegacy()` to be called after initialization as long as the + configuration does not change + +## 1.1.1 + + - Use versioned libcrypto.dylib and libssl.dylib on macOS Catalina to prevent + segfaults + - Fix warnings reported when using with cffi 1.13.2 + +## 1.1.0 + + - Added `oscrypto.load_order()`, which returns a `list` of unicode strings + of the names of the fully-qualified module names for all of submodules of + the package. The module names are listed in their dependency load order. + This is primarily intended for the sake of implementing hot reloading. + +## 1.0.0 + + - Backwards Compatibility Breaks + - `oscrypto.backend()` will now return `"mac"` instead of `"osx"` when + running on a Mac and not explicitly configured to use OpenSSL + - Enhancements + - Added functionality to calculate public keys from private keys since that + was removed from asn1crypto: + - `asn1crypto.keys.PrivateKeyInfo().unwrap()` is now + `asymmetric.PrivateKey().unwrap()` + - `asn1crypto.keys.PrivateKeyInfo().public_key` is now + `asymmetric.PrivateKey().public_key.unwrap()` + - `asn1crypto.keys.PrivateKeyInfo().public_key_info` is now + `asymmetric.PrivateKey().public_key.asn1` + - `asn1crypto.keys.PrivateKeyInfo().fingerprint` is now + `asymmetric.PrivateKey().fingerprint` + - `asn1crypto.keys.PublicKeyInfo().unwrap()` is now + `asymmetric.PublicKey().unwrap()` + - `asn1crypto.keys.PublicKeyInfo().fingerprint` is now + `asymmetric.PublicKey().fingerprint` + - Added `oscrypto.use_ctypes()` to avoid CFFI if desired + - Added `tls.TLSSocket().port` property + - Improved handling of disconnects with `tls.TLSSocket()` + - Improved error messages when dealing with failures originating in OpenSSL + - Allow PEM-encoded files to have leading whitespace when loaded via + `keys.parse_private()`, `keys.parse_public()` and + `keys.parse_certificate()` + - Restructured internal imports of asn1crypto to make vendoring easier + - No longer touch the user keychain on Macs when generating keys, instead + use a temporary one + - Bug Fixes + - Fixed compatibility with Python 3.7+ + - Fixed compatibility with LibreSSL version 2.2.x+ + - Fixed a bug where `tls.TLSSocket().read_until()` that would sometimes read + more data from the socket than necessary + - Fixed a buffer overflow when reading data from an OpenSSL memory bio + - Fixed a bug in `util.pbkdf2()` that would cause incorrect output in some + situations when run on Windows XP or with OpenSSL 0.9.8 + - Fixed `aes_cbc_no_padding_encrypt()` so it can be executed when the backend + is OpenSSL + - A `SecTrustRef` obtained from `SSLCopyPeerTrust()` on Mac is now + properly released + - Packaging + - `wheel`, `sdist` and `bdist_egg` releases now all include LICENSE, + `sdist` includes docs + - Added `oscrypto_tests` package to PyPi + +## 0.19.1 + + - Fixed a bug where `trust_list.get_path()` would not call the `cert_callback` + when a certificate was exported + - Fixed an issue on OS X/macOS where a certificate with an explicit any + purpose trust OID would not be exported since it didn't contain the OID + for SSL + +## 0.19.0 + + - Backwards compatibility break: `trust_list.get_path()` not longer accepts + the parameter `map_vendor_oids`, and only includes CA certificates that + the OS marks as trusted for TLS server authentication. This change was + made due to (at least some versions of) OpenSSL not verifying a server + certificate if the CA bundle includes a `TRUSTED CERTIFICATE` entry, + which is how the trust information was exported. Since trust information + can no longer be exported to disk, the list of certificates must be + filtered, and since the intent of this function was always to provide a + list of CA certs for use by OpenSSL when creating TLS connection, this + change in functionality is in line with the original intent. + - `asymmetric.rsa_pkcs1v15_verify()` and `asymmetric.rsa_rss_verify()` will + now raise a `SignatureError` when there is a key size mismatch. + +## 0.18.0 + + - `trust_list.get_path()` and `trust_list.get_list()` now accept a parameter + `cert_callback`, which is a callback that will be called once for each + certificate in the trust store. If the certificate will not be exported, a + reason will be provided. + - Added `oscrypto.version` for version introspection without side-effects + - Now uses `asn1crypto.algos.DSASignature` instead of self-contained ASN.1 + definition + +## 0.17.3 + + - Work around an issue on OS X where SecureTransport would try to read non-TLS + data as TLS records, causing hangs with `tls.TLSSocket()` + - Handle an alternate way the Windows SChannel API can fail when the DH params + for a TLS handshake are too small + - Fix a bug with cffi on OS X and converting a CFString to a UTF-8 byte string + +## 0.17.2 + + - Handle `errSecInvalidTrustSettings` errors on macOS exporting trust roots + - Prevent a `KeyError` on macOS when exporting trust roots and trust settings + are present for certificates not in the list + +## 0.17.1 + + - Expose `LibraryNotFoundError` via `errors.LibraryNotFoundError` + +## 0.17.0 + + - Added support for OpenSSL 1.1.0 + - Allow using OpenSSL on OS X and Windows + - Prevent FFI library references from being garbage collected before parent + `asymmetric.PublicKey`, `asymmetric.PrivateKey` and `asymmetric.Certificate` + objects + - Improved handling of `errSecAuthFailed` error that occurs when calling + `asymmetric.generate_*()` functions on OS X in some virtualenvs + +## 0.16.2 + + - Allow `cffi` files to be removed from source tree when embedding + +## 0.16.1 + + - Updated [asn1crypto](https://github.com/wbond/asn1crypto) dependency to + `0.18.1`. + +## 0.16.0 + + - Backwards compatibility break: `trust_list.get_list()` now returns a list of + 3-element tuples containing the certificate byte string, a set of trust OIDs + and a set of reject OIDs. Previously it returned a list of certificate byte + strings. + - `trust_list` now makes OS trust information OIDs available via the + `trust_list.get_list()` function, and writes OpenSSL-compatible trust + information to the CA certs file when calling `trust_info.get_path()` on + Windows and OS X. + - Removed reliance on opaque OpenSSL struct information for compatibility with + upcoming OpenSSL 1.1.0 release + - Improved handling of client authentication and socket read errors when using + OpenSSL + - Added Windows XP support + +## 0.15.0 + + - Added `asymmetric.generate_dh_parameters()` and + `asymmetric.dump_dh_parameters()` + - Improve disconnection handling of `tls.TLSSocket` on Windows + - Ensure that certificates signed using MD5 and MD2 are rejected on Windows + when using the `extra_trust_roots` parameter of `tls.TLSSession` + +## 0.14.2 + + - Fixed `trust_list` to work with new Security.framework behavior on OS X + 10.11 El Capitan + - Fixed an occasional bug with `tls.TLSSocket()` on Windows when using TLSv1.2 + and the server negotiated using a `DHE_RSA` key exchange + - Fixed a bug on Windows 10 where a TLS handshake would fail if the TLS record + was not completely received within one call to `socket.recv()` + - Fixed a bug where a private key would not be encoded with PEM encoding when + requested, if no passphrase was provided to `asymmetric.dump_private_key()` + +## 0.14.1 + + - Fixed a bug where `asymmetric.generate_pair()` would raise an exception on + OS X when the system Python was used to create a virtualenv + +## 0.14.0 + + - `tls.TLSSocket()` now has a default connect, read and write timeout of `10` + seconds + - Fixed bugs with `manual_validation` keyword param for `tls.TLSSession()` on + all three platforms + - Fixed a bug in `asymmetric.PublicKey.self_signed` that would always force + signature verification + - Improved parsing of TLS records during handshakes to improve error messaging + - `tls.TLSSocket()` on OS X now respects `KeyboardInterrupt` while in a read + or write callback + - TLS connections on Windows will fallback to TLSv1.1 if TLSv1.2 is negotiated + but a trust root with an MD2 or MD5 certificate is part of the certificate + path. Previously the connection would fail. + - TLS connections with optional client authentication no longer fail on Windows + - `trust_list.get_list()` on Windows now returns a de-duplicated list + +## 0.13.1 + + - Improved handling of signature errors to always raise `errors.SignatureError` + - Fixed a bug with `trust_list.get_list()` on Windows not returning + certificates that were valid for all uses + +## 0.13.0 + + - Backwards compatibility break: `trust_list.get_list()` now returns a list of + `asn1crypto.x509.Certificate` objects instead of a list of byte strings + - `trust_list.get_list()` now returns a copy of the list to prevent accidental + modification of the list + - Added `tls.TLSSocket.hostname` + +## 0.12.0 + + - Fixed Python 2.6 support on Windows and Linux + - Fixed handling of some TLS error conditions with Python 2 on Windows + - Corrected handling of incomplete DSA keys on Windows + - Fixed a bug converting a `FILETIME` struct with Python 2 on Windows to a + `datetime` object + - Fixed a cast/free bug with cffi and CPython on Windows that incorrectly + reported some TLS certificates as invalid + - Fixed a bug with exporting the trust list from Windows on Python 2 x64 + - Fixed detection of weak DH params in a TLS connection on OS X 10.7-10.9 + - OS X 10.7-10.9 no longer use CRL/OCSP to check for revocation, making the + functionality consistent with Linux, Window and OS X 10.10 and newer + - Fixed OS X 10.7 TLS validation when using `extra_trust_roots` in a + `tls.TLSSession` + +## 0.11.1 + + - Handles specific weak DH keys error code in newer versions of OpenSSL + - Added `__str__()` and `__unicode__()` to TLS exceptions + +## 0.11.0 + + - Added TLS functionality + - Added Python 2.6 support + - Added `asymmetric.Certificate.self_signed` + - Added "raw" RSA signing/verification to `asymmetric.rsa_pkcs1v15_sign()` and + `asymmetric.rsa_pkcs1v15_verify()` functions + - Fixes for compatibility bugs with OS X 10.7 + - Fixes for compatibility bugs with pypy3 + - Fixes for compatibility bugs with cffi 0.8.6 + +## 0.10.0 + + - `oscrypto.public_key` renamed to `oscrypto.asymmetric` + - `.algo` attribute of `asymmetric.PublicKey`, `asymmetric.PrivateKey` and + `asymmetric.Certificate` classes renamed to `.algorithm` + - `parse_public()`, `parse_private()`, `parse_certificate()` and + `parse_pkcs12()` all now return just an asn1crypto object instead of a + 2-element tuple with the algorithm name + - Added the `asymmetric.generate_pair()` function + - Added the functions: + - `asymmetric.dump_certificate()` + - `asymmetric.dump_public_key()` + - `asymmetric.dump_private_key()` + - `asymmetric.dump_openssl_private_key()` + - Added the `kdf.pbkdf2_iteration_calculator()` function + - Added the `setup.py clean` command + +## 0.9.0 + + - Initial release diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto.egg-info/LICENSE b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto.egg-info/LICENSE new file mode 100644 index 00000000..8038d9a7 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto.egg-info/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2015-2019 Will Bond <will@wbond.net> + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto.egg-info/PKG-INFO b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto.egg-info/PKG-INFO new file mode 100644 index 00000000..8a7dfd3c --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto.egg-info/PKG-INFO @@ -0,0 +1,382 @@ +Metadata-Version: 2.1 +Name: oscrypto +Version: 1.2.1 +Summary: TLS (SSL) sockets, key generation, encryption, decryption, signing, verification and KDFs using the OS crypto libraries. Does not require a compiler, and relies on the OS for patching. Works on Windows, OS X and Linux/BSD. +Home-page: https://github.com/wbond/oscrypto +Author: wbond +Author-email: will@wbond.net +License: MIT +Description: # oscrypto + + A compilation-free, always up-to-date encryption library for Python that works + on Windows, OS X, Linux and BSD. Supports the following versions of Python: + 2.6, 2.7, 3.2, 3.3, 3.4, 3.5, 3.6, 3.7, 3.8 and pypy. + + - [Supported Operating Systems](#supported-operationg-systems) + - [Features](#features) + - [Why Another Python Crypto Library?](#why-another-python-crypto-library) + - [Related Crypto Libraries](#related-crypto-libraries) + - [Current Release](#current-release) + - [Dependencies](#dependencies) + - [Installation](#installation) + - [License](#license) + - [Documentation](#documentation) + - [Continuous Integration](#continuous-integration) + - [Testing](#testing) + - [Development](#development) + - [CI Tasks](#ci-tasks) + + [![GitHub Actions CI](https://github.com/wbond/oscrypto/workflows/CI/badge.svg)](https://github.com/wbond/oscrypto/actions?workflow=CI) + [![Travis CI](https://api.travis-ci.org/wbond/oscrypto.svg?branch=master)](https://travis-ci.org/wbond/oscrypto) + [![AppVeyor](https://ci.appveyor.com/api/projects/status/github/wbond/oscrypto?branch=master&svg=true)](https://ci.appveyor.com/project/wbond/oscrypto) + [![CircleCI](https://circleci.com/gh/wbond/oscrypto.svg?style=shield)](https://circleci.com/gh/wbond/oscrypto) + [![PyPI](https://img.shields.io/pypi/v/oscrypto.svg)](https://pypi.python.org/pypi/oscrypto) + + ## Supported Operating Systems + + The library integrates with the encryption library that is part of the operating + system. This means that a compiler is never needed, and OS security updates take + care of patching vulnerabilities. Supported operating systems include: + + - Windows XP or newer + - Uses: + - [Cryptography API: Next Generation (CNG)](https://msdn.microsoft.com/en-us/library/windows/desktop/aa376210(v=vs.85).aspx) + - [Secure Channel](https://msdn.microsoft.com/en-us/library/windows/desktop/aa380123(v=vs.85).aspx) for TLS + - [CryptoAPI](https://msdn.microsoft.com/en-us/library/windows/desktop/aa380256(v=vs.85).aspx) for trust lists and XP support + - Tested on: + - Windows XP (no SNI) + - Windows 7 + - Windows 8.1 + - Windows Server 2012 + - Windows 10 + - OS X 10.7 or newer + - Uses: + - [Security.framework](https://developer.apple.com/library/prerelease/mac/documentation/Security/Reference/SecurityFrameworkReference/index.html) + - [Secure Transport](https://developer.apple.com/library/prerelease/mac/documentation/Security/Reference/secureTransportRef/index.html#//apple_ref/doc/uid/TP30000155) for TLS + - [CommonCrypto](http://www.opensource.apple.com/source/CommonCrypto/CommonCrypto-55010/CommonCrypto/) for PBKDF2 + - OpenSSL (or LibreSSL on macOS 10.13) for the PKCS #12 KDF + - Tested on: + - OS X 10.7 + - OS X 10.8 + - OS X 10.9 + - OS X 10.10 + - OS X 10.11 + - OS X 10.11 with OpenSSL 1.1.0 + - macOS 10.12 + - macOS 10.13 with LibreSSL 2.2.7 + - macOS 10.14 + - macOS 10.15 + - macOS 11 + - Linux or BSD + - Uses one of: + - [OpenSSL 0.9.8](https://www.openssl.org/docs/man0.9.8/) + - [OpenSSL 1.0.x](https://www.openssl.org/docs/man1.0.0/) + - [OpenSSL 1.1.0](https://www.openssl.org/docs/man1.1.0/) + - [LibreSSL](http://www.libressl.org/) + - Tested on: + - Arch Linux with OpenSSL 1.0.2 + - OpenBSD 5.7 with LibreSSL + - Ubuntu 10.04 with OpenSSL 0.9.8 + - Ubuntu 12.04 with OpenSSL 1.0.1 + - Ubuntu 15.04 with OpenSSL 1.0.1 + - Ubuntu 16.04 with OpenSSL 1.0.2 on Raspberry Pi 3 (armhf) + - Ubuntu 18.04 with OpenSSL 1.1.x (amd64, arm64, ppc64el) + + *OS X 10.6 will not be supported due to a lack of available + cryptographic primitives and due to lack of vendor support.* + + ## Features + + Currently the following features are implemented. Many of these should only be + used for integration with existing/legacy systems. If you don't know which you + should, or should not use, please see [Learning](docs/readme.md#learning). + + - [TLSv1.x socket wrappers](docs/tls.md) + - Certificate verification performed by OS trust roots + - Custom CA certificate support + - SNI support (except Windows XP) + - Session reuse via IDs/tickets + - Modern cipher suites (RC4, DES, anon and NULL ciphers disabled) + - Weak DH parameters and certificate signatures rejected + - SSLv3 disabled by default, SSLv2 unimplemented + - CRL/OCSP revocation checks consistenty disabled + - [Exporting OS trust roots](docs/trust_list.md) + - PEM-formatted CA certs from the OS for OpenSSL-based code + - [Encryption/decryption](docs/symmetric.md) + - AES (128, 192, 256), CBC mode, PKCS7 padding + - AES (128, 192, 256), CBC mode, no padding + - TripleDES 3-key, CBC mode, PKCS5 padding + - TripleDes 2-key, CBC mode, PKCS5 padding + - DES, CBC mode, PKCS5 padding + - RC2 (40-128), CBC mode, PKCS5 padding + - RC4 (40-128) + - RSA PKCSv1.5 + - RSA OAEP (SHA1 only) + - [Generating public/private key pairs](docs/asymmetric.md) + - RSA (1024, 2048, 3072, 4096 bit) + - DSA (1024 bit on all platforms - 2048, 3072 bit with OpenSSL 1.x or + Windows 8) + - EC (secp256r1, secp384r1, secp521r1 curves) + - [Generating DH parameters](docs/asymmetric.md) + - [Signing and verification](docs/asymmetric.md) + - RSA PKCSv1.5 + - RSA PSS + - DSA + - EC + - [Loading and normalizing DER and PEM formatted keys](docs/keys.md) + - RSA public and private keys + - DSA public and private keys + - EC public and private keys + - X.509 Certificates + - PKCS#12 archives (`.pfx`/`.p12`) + - [Key derivation](docs/kdf.md) + - PBKDF2 + - PBKDF1 + - PKCS#12 KDF + - [Random byte generation](docs/util.md) + + The feature set was largely driven by the technologies used related to + generating and validating X.509 certificates. The various CBC encryption schemes + and KDFs are used to load encrypted private keys, and the various RSA padding + schemes are part of X.509 signatures. + + For modern cryptography not tied to an existing system, please see the + [Modern Cryptography](docs/readme.md#modern-cryptography) section of the docs. + + *Please note that this library does not include modern block modes such as CTR + and GCM due to lack of support from both OS X and OpenSSL 0.9.8.* + + ## Why Another Python Crypto Library? + + In short, the existing cryptography libraries for Python didn't fit the needs of + a couple of projects I was working on. Primarily these are applications + distributed to end-users who aren't programmers, that need to handle TLS and + various technologies related to X.509 certificates. + + If your system is not tied to AES, TLS, X.509, or related technologies, you + probably want [more modern cryptography](docs/readme.md#modern-cryptography). + + Depending on your needs, the [cryptography](https://cryptography.io) package may + be a good (or better) fit. + + Some things that make oscrypto unique: + + - No compiler needed, ever. No need to pre-compile shared libraries. Just + distribute the Python source files, any way you want. + - Uses the operating system's crypto library - does not require OpenSSL on + Windows or OS X. + - Relies on the operating system for security patching. You don't need to + rebuild all of your apps every time there is a new TLS vulnerability. + - Intentionally limited in scope to crypto primitives. Other libraries + built upon it deal with certificate path validation, creating certificates + and CSRs, constructing CMS structures. + - Built on top of a fast, pure-Python ASN.1 parser, + [asn1crypto](https://github.com/wbond/asn1crypto). + - TLS functionality uses the operating system's trust list/CA certs and is + pre-configured with sane defaults + - Public APIs are simple and use strict type checks to avoid errors + + Some downsides include: + + - Does not currently implement: + - standalone DH key exchange + - various encryption modes such as GCM, CCM, CTR, CFB, OFB, ECB + - key wrapping + - CMAC + - HKDF + - Non-TLS functionality is architected for dealing with data that fits in + memory and is available all at once + - Developed by a single developer + + ## Related Crypto Libraries + + *oscrypto* is part of the modularcrypto family of Python packages: + + - [asn1crypto](https://github.com/wbond/asn1crypto) + - [oscrypto](https://github.com/wbond/oscrypto) + - [csrbuilder](https://github.com/wbond/csrbuilder) + - [certbuilder](https://github.com/wbond/certbuilder) + - [crlbuilder](https://github.com/wbond/crlbuilder) + - [ocspbuilder](https://github.com/wbond/ocspbuilder) + - [certvalidator](https://github.com/wbond/certvalidator) + + ## Current Release + + 1.2.1 - [changelog](changelog.md) + + ## Dependencies + + - [*asn1crypto*](https://github.com/wbond/asn1crypto) + - Python 2.6, 2.7, 3.2, 3.3, 3.4, 3.5, 3.6, 3.7, 3.8 or pypy + + ## Installation + + ```bash + pip install oscrypto + ``` + + ## License + + *oscrypto* is licensed under the terms of the MIT license. See the + [LICENSE](LICENSE) file for the exact license text. + + ## Documentation + + [*oscrypto* documentation](docs/readme.md) + + ## Continuous Integration + + Various combinations of platforms and versions of Python are tested via: + + - [AppVeyor](https://ci.appveyor.com/project/wbond/oscrypto/history) + - [CircleCI](https://circleci.com/gh/wbond/oscrypto) + - [GitHub Actions](https://github.com/wbond/oscrypto/actions) + - [Travis CI](https://travis-ci.org/wbond/oscrypto/builds) + + ## Testing + + Tests are written using `unittest` and require no third-party packages. + + Depending on what type of source is available for the package, the following + commands can be used to run the test suite. + + ### Git Repository + + When working within a Git working copy, or an archive of the Git repository, + the full test suite is run via: + + ```bash + python run.py tests + ``` + + To run only some tests, pass a regular expression as a parameter to `tests`. + + ```bash + python run.py tests aes + ``` + + To run tests multiple times, in order to catch edge-case bugs, pass an integer + to `tests`. If combined with a regular expression for filtering, pass the + repeat count after the regular expression. + + ```bash + python run.py tests 20 + python run.py tests aes 20 + ``` + + To run tests using a custom build of OpenSSL, or to use OpenSSL on Windows or + Mac, add `use_openssl` after `run.py`, like: + + ```bash + python run.py use_openssl=/path/to/libcrypto.dylib,/path/to/libssl.dylib tests + ``` + + ### PyPi Source Distribution + + When working within an extracted source distribution (aka `.tar.gz`) from + PyPi, the full test suite is run via: + + ```bash + python setup.py test + ``` + + ### Package + + When the package has been installed via pip (or another method), the package + `oscrypto_tests` may be installed and invoked to run the full test suite: + + ```bash + pip install oscrypto_tests + python -m oscrypto_tests + ``` + + ## Development + + To install the package used for linting, execute: + + ```bash + pip install --user -r requires/lint + ``` + + The following command will run the linter: + + ```bash + python run.py lint + ``` + + Support for code coverage can be installed via: + + ```bash + pip install --user -r requires/coverage + ``` + + Coverage is measured by running: + + ```bash + python run.py coverage + ``` + + To install the packages requires to generate the API documentation, run: + + ```bash + pip install --user -r requires/api_docs + ``` + + The documentation can then be generated by running: + + ```bash + python run.py api_docs + ``` + + To install the necessary packages for releasing a new version on PyPI, run: + + ```bash + pip install --user -r requires/release + ``` + + Releases are created by: + + - Making a git tag in [semver](http://semver.org/) format + - Running the command: + + ```bash + python run.py release + ``` + + Existing releases can be found at https://pypi.python.org/pypi/oscrypto. + + ## CI Tasks + + A task named `deps` exists to download and stage all necessary testing + dependencies. On posix platforms, `curl` is used for downloads and on Windows + PowerShell with `Net.WebClient` is used. This configuration sidesteps issues + related to getting pip to work properly and messing with `site-packages` for + the version of Python being used. + + The `ci` task runs `lint` (if flake8 is avaiable for the version of Python) and + `coverage` (or `tests` if coverage is not available for the version of Python). + If the current directory is a clean git working copy, the coverage data is + submitted to codecov.io. + + ```bash + python run.py deps + python run.py ci + ``` + +Keywords: crypto pki tls ssl x509 certificate encrypt decrypt sign verify rsa dsa ec dh +Platform: UNKNOWN +Classifier: Development Status :: 5 - Production/Stable +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: MIT License +Classifier: Programming Language :: Python :: 2.6 +Classifier: Programming Language :: Python :: 2.7 +Classifier: Programming Language :: Python :: 3.2 +Classifier: Programming Language :: Python :: 3.3 +Classifier: Programming Language :: Python :: 3.4 +Classifier: Programming Language :: Python :: 3.5 +Classifier: Programming Language :: Python :: 3.6 +Classifier: Programming Language :: Python :: 3.7 +Classifier: Programming Language :: Python :: 3.8 +Classifier: Programming Language :: Python :: Implementation :: PyPy +Classifier: Topic :: Security :: Cryptography +Description-Content-Type: text/markdown diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto.egg-info/SOURCES.txt b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto.egg-info/SOURCES.txt new file mode 100644 index 00000000..ed47eb00 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto.egg-info/SOURCES.txt @@ -0,0 +1,92 @@ +setup.py +oscrypto/__init__.py +oscrypto/_asn1.py +oscrypto/_asymmetric.py +oscrypto/_cipher_suites.py +oscrypto/_ecdsa.py +oscrypto/_errors.py +oscrypto/_ffi.py +oscrypto/_int.py +oscrypto/_pkcs1.py +oscrypto/_pkcs12.py +oscrypto/_pkcs5.py +oscrypto/_rand.py +oscrypto/_tls.py +oscrypto/_types.py +oscrypto/asymmetric.py +oscrypto/errors.py +oscrypto/kdf.py +oscrypto/keys.py +oscrypto/symmetric.py +oscrypto/tls.py +oscrypto/trust_list.py +oscrypto/util.py +oscrypto/version.py +oscrypto.egg-info/LICENSE +oscrypto.egg-info/PKG-INFO +oscrypto.egg-info/SOURCES.txt +oscrypto.egg-info/dependency_links.txt +oscrypto.egg-info/requires.txt +oscrypto.egg-info/top_level.txt +oscrypto/../LICENSE +oscrypto/../changelog.md +oscrypto/../readme.md +oscrypto/../docs/asymmetric.md +oscrypto/../docs/kdf.md +oscrypto/../docs/keys.md +oscrypto/../docs/oscrypto.md +oscrypto/../docs/readme.md +oscrypto/../docs/symmetric.md +oscrypto/../docs/tls.md +oscrypto/../docs/trust_list.md +oscrypto/../docs/util.md +oscrypto/_linux_bsd/__init__.py +oscrypto/_linux_bsd/trust_list.py +oscrypto/_mac/__init__.py +oscrypto/_mac/_common_crypto.py +oscrypto/_mac/_common_crypto_cffi.py +oscrypto/_mac/_common_crypto_ctypes.py +oscrypto/_mac/_core_foundation.py +oscrypto/_mac/_core_foundation_cffi.py +oscrypto/_mac/_core_foundation_ctypes.py +oscrypto/_mac/_security.py +oscrypto/_mac/_security_cffi.py +oscrypto/_mac/_security_ctypes.py +oscrypto/_mac/asymmetric.py +oscrypto/_mac/symmetric.py +oscrypto/_mac/tls.py +oscrypto/_mac/trust_list.py +oscrypto/_mac/util.py +oscrypto/_openssl/__init__.py +oscrypto/_openssl/_libcrypto.py +oscrypto/_openssl/_libcrypto_cffi.py +oscrypto/_openssl/_libcrypto_ctypes.py +oscrypto/_openssl/_libssl.py +oscrypto/_openssl/_libssl_cffi.py +oscrypto/_openssl/_libssl_ctypes.py +oscrypto/_openssl/asymmetric.py +oscrypto/_openssl/symmetric.py +oscrypto/_openssl/tls.py +oscrypto/_openssl/util.py +oscrypto/_win/__init__.py +oscrypto/_win/_advapi32.py +oscrypto/_win/_advapi32_cffi.py +oscrypto/_win/_advapi32_ctypes.py +oscrypto/_win/_cng.py +oscrypto/_win/_cng_cffi.py +oscrypto/_win/_cng_ctypes.py +oscrypto/_win/_crypt32.py +oscrypto/_win/_crypt32_cffi.py +oscrypto/_win/_crypt32_ctypes.py +oscrypto/_win/_decode.py +oscrypto/_win/_kernel32.py +oscrypto/_win/_kernel32_cffi.py +oscrypto/_win/_kernel32_ctypes.py +oscrypto/_win/_secur32.py +oscrypto/_win/_secur32_cffi.py +oscrypto/_win/_secur32_ctypes.py +oscrypto/_win/asymmetric.py +oscrypto/_win/symmetric.py +oscrypto/_win/tls.py +oscrypto/_win/trust_list.py +oscrypto/_win/util.py \ No newline at end of file diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto.egg-info/dependency_links.txt b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto.egg-info/dependency_links.txt new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto.egg-info/dependency_links.txt @@ -0,0 +1 @@ + diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto.egg-info/requires.txt b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto.egg-info/requires.txt new file mode 100644 index 00000000..2f752680 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto.egg-info/requires.txt @@ -0,0 +1 @@ +asn1crypto>=1.0.0 diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto.egg-info/top_level.txt b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto.egg-info/top_level.txt new file mode 100644 index 00000000..98a5c4dd --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto.egg-info/top_level.txt @@ -0,0 +1 @@ +oscrypto diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/__init__.py b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/__init__.py new file mode 100644 index 00000000..eb273139 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/__init__.py @@ -0,0 +1,304 @@ +# coding: utf-8 +from __future__ import unicode_literals, division, absolute_import, print_function + +import os +import platform +import sys +import threading + +from ._types import str_cls, type_name +from .errors import LibraryNotFoundError +from .version import __version__, __version_info__ + + +__all__ = [ + '__version__', + '__version_info__', + 'backend', + 'ffi', + 'load_order', + 'use_ctypes', + 'use_openssl', + 'use_winlegacy', +] + + +_backend_lock = threading.Lock() +_module_values = { + 'backend': None, + 'backend_config': None, + 'ffi': None +} + + +def backend(): + """ + :return: + A unicode string of the backend being used: "openssl", "mac", "win", + "winlegacy" + """ + + if _module_values['backend'] is not None: + return _module_values['backend'] + + with _backend_lock: + if _module_values['backend'] is not None: + return _module_values['backend'] + + if sys.platform == 'win32': + # Windows XP was major version 5, Vista was 6 + if sys.getwindowsversion()[0] < 6: + _module_values['backend'] = 'winlegacy' + else: + _module_values['backend'] = 'win' + elif sys.platform == 'darwin': + _module_values['backend'] = 'mac' + else: + _module_values['backend'] = 'openssl' + + return _module_values['backend'] + + +def _backend_config(): + """ + :return: + A dict of config info for the backend. Only currently used by "openssl", + it may contains zero or more of the following keys: + - "libcrypto_path" + - "libssl_path" + """ + + if backend() != 'openssl': + return {} + + if _module_values['backend_config'] is not None: + return _module_values['backend_config'] + + with _backend_lock: + if _module_values['backend_config'] is not None: + return _module_values['backend_config'] + + _module_values['backend_config'] = {} + return _module_values['backend_config'] + + +def use_openssl(libcrypto_path, libssl_path, trust_list_path=None): + """ + Forces using OpenSSL dynamic libraries on OS X (.dylib) or Windows (.dll), + or using a specific dynamic library on Linux/BSD (.so). + + This can also be used to configure oscrypto to use LibreSSL dynamic + libraries. + + This method must be called before any oscrypto submodules are imported. + + :param libcrypto_path: + A unicode string of the file path to the OpenSSL/LibreSSL libcrypto + dynamic library. + + :param libssl_path: + A unicode string of the file path to the OpenSSL/LibreSSL libssl + dynamic library. + + :param trust_list_path: + An optional unicode string of the path to a file containing + OpenSSL-compatible CA certificates in PEM format. If this is not + provided and the platform is OS X or Windows, the system trust roots + will be exported from the OS and used for all TLS connections. + + :raises: + ValueError - when one of the paths is not a unicode string + OSError - when the trust_list_path does not exist on the filesystem + oscrypto.errors.LibraryNotFoundError - when one of the path does not exist on the filesystem + RuntimeError - when this function is called after another part of oscrypto has been imported + """ + + if not isinstance(libcrypto_path, str_cls): + raise ValueError('libcrypto_path must be a unicode string, not %s' % type_name(libcrypto_path)) + + if not isinstance(libssl_path, str_cls): + raise ValueError('libssl_path must be a unicode string, not %s' % type_name(libssl_path)) + + if not os.path.exists(libcrypto_path): + raise LibraryNotFoundError('libcrypto does not exist at %s' % libcrypto_path) + + if not os.path.exists(libssl_path): + raise LibraryNotFoundError('libssl does not exist at %s' % libssl_path) + + if trust_list_path is not None: + if not isinstance(trust_list_path, str_cls): + raise ValueError('trust_list_path must be a unicode string, not %s' % type_name(trust_list_path)) + if not os.path.exists(trust_list_path): + raise OSError('trust_list_path does not exist at %s' % trust_list_path) + + with _backend_lock: + new_config = { + 'libcrypto_path': libcrypto_path, + 'libssl_path': libssl_path, + 'trust_list_path': trust_list_path, + } + + if _module_values['backend'] == 'openssl' and _module_values['backend_config'] == new_config: + return + + if _module_values['backend'] is not None: + raise RuntimeError('Another part of oscrypto has already been imported, unable to force use of OpenSSL') + + _module_values['backend'] = 'openssl' + _module_values['backend_config'] = new_config + + +def use_winlegacy(): + """ + Forces use of the legacy Windows CryptoAPI. This should only be used on + Windows XP or for testing. It is less full-featured than the Cryptography + Next Generation (CNG) API, and as a result the elliptic curve and PSS + padding features are implemented in pure Python. This isn't ideal, but it + a shim for end-user client code. No one is going to run a server on Windows + XP anyway, right?! + + :raises: + EnvironmentError - when this function is called on an operating system other than Windows + RuntimeError - when this function is called after another part of oscrypto has been imported + """ + + if sys.platform != 'win32': + plat = platform.system() or sys.platform + if plat == 'Darwin': + plat = 'OS X' + raise EnvironmentError('The winlegacy backend can only be used on Windows, not %s' % plat) + + with _backend_lock: + if _module_values['backend'] == 'winlegacy': + return + + if _module_values['backend'] is not None: + raise RuntimeError( + 'Another part of oscrypto has already been imported, unable to force use of Windows legacy CryptoAPI' + ) + + _module_values['backend'] = 'winlegacy' + + +def use_ctypes(): + """ + Forces use of ctypes instead of cffi for the FFI layer + + :raises: + RuntimeError - when this function is called after another part of oscrypto has been imported + """ + + with _backend_lock: + if _module_values['ffi'] == 'ctypes': + return + + if _module_values['backend'] is not None: + raise RuntimeError( + 'Another part of oscrypto has already been imported, unable to force use of ctypes' + ) + + _module_values['ffi'] = 'ctypes' + + +def ffi(): + """ + Returns the FFI module being used + + :return: + A unicode string of "cffi" or "ctypes" + """ + + if _module_values['ffi'] is not None: + return _module_values['ffi'] + + with _backend_lock: + try: + import cffi # noqa: F401 + _module_values['ffi'] = 'cffi' + except (ImportError): + _module_values['ffi'] = 'ctypes' + + return _module_values['ffi'] + + +def load_order(): + """ + Returns a list of the module and sub-module names for oscrypto in + dependency load order, for the sake of live reloading code + + :return: + A list of unicode strings of module names, as they would appear in + sys.modules, ordered by which module should be reloaded first + """ + + return [ + 'oscrypto._asn1', + 'oscrypto._cipher_suites', + 'oscrypto._errors', + 'oscrypto._int', + 'oscrypto._types', + 'oscrypto.errors', + 'oscrypto.version', + 'oscrypto', + 'oscrypto._ffi', + 'oscrypto._pkcs12', + 'oscrypto._pkcs5', + 'oscrypto._rand', + 'oscrypto._tls', + 'oscrypto._linux_bsd.trust_list', + 'oscrypto._mac._common_crypto_cffi', + 'oscrypto._mac._common_crypto_ctypes', + 'oscrypto._mac._common_crypto', + 'oscrypto._mac._core_foundation_cffi', + 'oscrypto._mac._core_foundation_ctypes', + 'oscrypto._mac._core_foundation', + 'oscrypto._mac._security_cffi', + 'oscrypto._mac._security_ctypes', + 'oscrypto._mac._security', + 'oscrypto._mac.trust_list', + 'oscrypto._mac.util', + 'oscrypto._openssl._libcrypto_cffi', + 'oscrypto._openssl._libcrypto_ctypes', + 'oscrypto._openssl._libcrypto', + 'oscrypto._openssl._libssl_cffi', + 'oscrypto._openssl._libssl_ctypes', + 'oscrypto._openssl._libssl', + 'oscrypto._openssl.util', + 'oscrypto._win._cng_cffi', + 'oscrypto._win._cng_ctypes', + 'oscrypto._win._cng', + 'oscrypto._win._decode', + 'oscrypto._win._advapi32_cffi', + 'oscrypto._win._advapi32_ctypes', + 'oscrypto._win._advapi32', + 'oscrypto._win._kernel32_cffi', + 'oscrypto._win._kernel32_ctypes', + 'oscrypto._win._kernel32', + 'oscrypto._win._secur32_cffi', + 'oscrypto._win._secur32_ctypes', + 'oscrypto._win._secur32', + 'oscrypto._win._crypt32_cffi', + 'oscrypto._win._crypt32_ctypes', + 'oscrypto._win._crypt32', + 'oscrypto._win.trust_list', + 'oscrypto._win.util', + 'oscrypto.trust_list', + 'oscrypto.util', + 'oscrypto.kdf', + 'oscrypto._mac.symmetric', + 'oscrypto._openssl.symmetric', + 'oscrypto._win.symmetric', + 'oscrypto.symmetric', + 'oscrypto._asymmetric', + 'oscrypto._ecdsa', + 'oscrypto._pkcs1', + 'oscrypto._mac.asymmetric', + 'oscrypto._openssl.asymmetric', + 'oscrypto._win.asymmetric', + 'oscrypto.asymmetric', + 'oscrypto.keys', + 'oscrypto._mac.tls', + 'oscrypto._openssl.tls', + 'oscrypto._win.tls', + 'oscrypto.tls', + ] diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/__pycache__/__init__.cpython-310.pyc b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 00000000..003212c7 Binary files /dev/null and b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/__pycache__/__init__.cpython-310.pyc differ diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/__pycache__/_asn1.cpython-310.pyc b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/__pycache__/_asn1.cpython-310.pyc new file mode 100644 index 00000000..d2a38a6f Binary files /dev/null and b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/__pycache__/_asn1.cpython-310.pyc differ diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/__pycache__/_asymmetric.cpython-310.pyc b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/__pycache__/_asymmetric.cpython-310.pyc new file mode 100644 index 00000000..b19158f8 Binary files /dev/null and b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/__pycache__/_asymmetric.cpython-310.pyc differ diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/__pycache__/_errors.cpython-310.pyc b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/__pycache__/_errors.cpython-310.pyc new file mode 100644 index 00000000..285f6b2c Binary files /dev/null and b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/__pycache__/_errors.cpython-310.pyc differ diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/__pycache__/_ffi.cpython-310.pyc b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/__pycache__/_ffi.cpython-310.pyc new file mode 100644 index 00000000..15358ee9 Binary files /dev/null and b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/__pycache__/_ffi.cpython-310.pyc differ diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/__pycache__/_rand.cpython-310.pyc b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/__pycache__/_rand.cpython-310.pyc new file mode 100644 index 00000000..1418e04c Binary files /dev/null and b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/__pycache__/_rand.cpython-310.pyc differ diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/__pycache__/_types.cpython-310.pyc b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/__pycache__/_types.cpython-310.pyc new file mode 100644 index 00000000..8f9f7d5b Binary files /dev/null and b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/__pycache__/_types.cpython-310.pyc differ diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/__pycache__/asymmetric.cpython-310.pyc b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/__pycache__/asymmetric.cpython-310.pyc new file mode 100644 index 00000000..4365aa40 Binary files /dev/null and b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/__pycache__/asymmetric.cpython-310.pyc differ diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/__pycache__/errors.cpython-310.pyc b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/__pycache__/errors.cpython-310.pyc new file mode 100644 index 00000000..20c0c53b Binary files /dev/null and b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/__pycache__/errors.cpython-310.pyc differ diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/__pycache__/kdf.cpython-310.pyc b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/__pycache__/kdf.cpython-310.pyc new file mode 100644 index 00000000..26bc62b9 Binary files /dev/null and b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/__pycache__/kdf.cpython-310.pyc differ diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/__pycache__/keys.cpython-310.pyc b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/__pycache__/keys.cpython-310.pyc new file mode 100644 index 00000000..e670413a Binary files /dev/null and b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/__pycache__/keys.cpython-310.pyc differ diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/__pycache__/symmetric.cpython-310.pyc b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/__pycache__/symmetric.cpython-310.pyc new file mode 100644 index 00000000..d99f16ff Binary files /dev/null and b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/__pycache__/symmetric.cpython-310.pyc differ diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/__pycache__/util.cpython-310.pyc b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/__pycache__/util.cpython-310.pyc new file mode 100644 index 00000000..409b3905 Binary files /dev/null and b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/__pycache__/util.cpython-310.pyc differ diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/__pycache__/version.cpython-310.pyc b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/__pycache__/version.cpython-310.pyc new file mode 100644 index 00000000..542c22ea Binary files /dev/null and b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/__pycache__/version.cpython-310.pyc differ diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_asn1.py b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_asn1.py new file mode 100644 index 00000000..d79f635f --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_asn1.py @@ -0,0 +1,80 @@ +# coding: utf-8 +from __future__ import unicode_literals, division, absolute_import, print_function + +# This file exists strictly to make it easier to vendor a combination of +# oscrypto and asn1crypto + +from asn1crypto import algos, cms, core, keys, pem, pkcs12, util, x509 + +DHParameters = algos.DHParameters +DSASignature = algos.DSASignature +KeyExchangeAlgorithm = algos.KeyExchangeAlgorithm +Pbkdf2Salt = algos.Pbkdf2Salt + +EncryptedData = cms.EncryptedData + +Integer = core.Integer +Null = core.Null +OctetString = core.OctetString + +DSAParams = keys.DSAParams +DSAPrivateKey = keys.DSAPrivateKey +ECDomainParameters = keys.ECDomainParameters +ECPointBitString = keys.ECPointBitString +ECPrivateKey = keys.ECPrivateKey +EncryptedPrivateKeyInfo = keys.EncryptedPrivateKeyInfo +PrivateKeyAlgorithm = keys.PrivateKeyAlgorithm +PrivateKeyInfo = keys.PrivateKeyInfo +PublicKeyAlgorithm = keys.PublicKeyAlgorithm +PublicKeyInfo = keys.PublicKeyInfo +RSAPrivateKey = keys.RSAPrivateKey +RSAPublicKey = keys.RSAPublicKey + +int_from_bytes = util.int_from_bytes +int_to_bytes = util.int_to_bytes +OrderedDict = util.OrderedDict +timezone = util.timezone + +armor = pem.armor +unarmor = pem.unarmor + +CertBag = pkcs12.CertBag +Pfx = pkcs12.Pfx +SafeContents = pkcs12.SafeContents + +Certificate = x509.Certificate +TrustedCertificate = x509.TrustedCertificate + +__all__ = [ + 'armor', + 'CertBag', + 'Certificate', + 'DHParameters', + 'DSAParams', + 'DSAPrivateKey', + 'DSASignature', + 'ECDomainParameters', + 'ECPointBitString', + 'ECPrivateKey', + 'EncryptedData', + 'EncryptedPrivateKeyInfo', + 'int_from_bytes', + 'int_to_bytes', + 'Integer', + 'KeyExchangeAlgorithm', + 'Null', + 'OctetString', + 'OrderedDict', + 'Pbkdf2Salt', + 'Pfx', + 'PrivateKeyAlgorithm', + 'PrivateKeyInfo', + 'PublicKeyAlgorithm', + 'PublicKeyInfo', + 'RSAPrivateKey', + 'RSAPublicKey', + 'SafeContents', + 'timezone', + 'TrustedCertificate', + 'unarmor', +] diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_asymmetric.py b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_asymmetric.py new file mode 100644 index 00000000..1e7cca4b --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_asymmetric.py @@ -0,0 +1,1038 @@ +# coding: utf-8 +from __future__ import unicode_literals, division, absolute_import, print_function + +import hashlib +import hmac +import re +import binascii + +from ._asn1 import ( + CertBag, + Certificate, + DSAPrivateKey, + ECPrivateKey, + EncryptedData, + EncryptedPrivateKeyInfo, + Integer, + OctetString, + Pfx, + PrivateKeyInfo, + PublicKeyInfo, + RSAPrivateKey, + RSAPublicKey, + SafeContents, + unarmor, +) + +from .kdf import pbkdf1, pbkdf2, pkcs12_kdf +from .symmetric import ( + aes_cbc_pkcs7_decrypt, + des_cbc_pkcs5_decrypt, + rc2_cbc_pkcs5_decrypt, + rc4_decrypt, + tripledes_cbc_pkcs5_decrypt, +) +from .util import constant_compare +from ._errors import pretty_message +from ._types import byte_cls, str_cls, type_name + + +class _PrivateKeyBase(): + + asn1 = None + _fingerprint = None + + def unwrap(self): + """ + Unwraps the private key into an asn1crypto.keys.RSAPrivateKey, + asn1crypto.keys.DSAPrivateKey or asn1crypto.keys.ECPrivateKey object + + :return: + An asn1crypto.keys.RSAPrivateKey, asn1crypto.keys.DSAPrivateKey or + asn1crypto.keys.ECPrivateKey object + """ + + if self.algorithm == 'rsa': + return self.asn1['private_key'].parsed + + if self.algorithm == 'dsa': + params = self.asn1['private_key_algorithm']['parameters'] + return DSAPrivateKey({ + 'version': 0, + 'p': params['p'], + 'q': params['q'], + 'g': params['g'], + 'public_key': self.public_key.unwrap(), + 'private_key': self.asn1['private_key'].parsed, + }) + + if self.algorithm == 'ec': + output = self.asn1['private_key'].parsed + output['parameters'] = self.asn1['private_key_algorithm']['parameters'] + output['public_key'] = self.public_key.unwrap() + return output + + @property + def algorithm(self): + """ + :return: + A unicode string of "rsa", "dsa" or "ec" + """ + + return self.asn1.algorithm + + @property + def curve(self): + """ + :return: + A unicode string of EC curve name + """ + + return self.asn1.curve[1] + + @property + def bit_size(self): + """ + :return: + The number of bits in the key, as an integer + """ + + return self.asn1.bit_size + + @property + def byte_size(self): + """ + :return: + The number of bytes in the key, as an integer + """ + + return self.asn1.byte_size + + +class _PublicKeyBase(): + + asn1 = None + _fingerprint = None + + def unwrap(self): + """ + Unwraps a public key into an asn1crypto.keys.RSAPublicKey, + asn1crypto.core.Integer (for DSA) or asn1crypto.keys.ECPointBitString + object + + :return: + An asn1crypto.keys.RSAPublicKey, asn1crypto.core.Integer or + asn1crypto.keys.ECPointBitString object + """ + + if self.algorithm == 'ec': + return self.asn1['public_key'] + return self.asn1['public_key'].parsed + + @property + def fingerprint(self): + """ + Creates a fingerprint that can be compared with a private key to see if + the two form a pair. + + This fingerprint is not compatible with fingerprints generated by any + other software. + + :return: + A byte string that is a sha256 hash of selected components (based + on the key type) + """ + + if self._fingerprint is None: + self._fingerprint = _fingerprint(self.asn1, None) + return self._fingerprint + + @property + def algorithm(self): + """ + :return: + A unicode string of "rsa", "dsa" or "ec" + """ + + return self.asn1.algorithm + + @property + def curve(self): + """ + :return: + A unicode string of EC curve name + """ + + return self.asn1.curve[1] + + @property + def bit_size(self): + """ + :return: + The number of bits in the key, as an integer + """ + + return self.asn1.bit_size + + @property + def byte_size(self): + """ + :return: + The number of bytes in the key, as an integer + """ + + return self.asn1.byte_size + + +class _CertificateBase(): + + asn1 = None + + @property + def algorithm(self): + """ + :return: + A unicode string of "rsa", "dsa" or "ec" + """ + + return self.public_key.algorithm + + @property + def curve(self): + """ + :return: + A unicode string of EC curve name + """ + + return self.public_key.curve + + @property + def bit_size(self): + """ + :return: + The number of bits in the public key, as an integer + """ + + return self.public_key.bit_size + + @property + def byte_size(self): + """ + :return: + The number of bytes in the public key, as an integer + """ + + return self.public_key.byte_size + + +def _unwrap_private_key_info(key_info): + """ + Unwraps an asn1crypto.keys.PrivateKeyInfo object into an + asn1crypto.keys.RSAPrivateKey, asn1crypto.keys.DSAPrivateKey + or asn1crypto.keys.ECPrivateKey. + + :param key_info: + An asn1crypto.keys.PrivateKeyInfo object + + :return: + One of: + - asn1crypto.keys.RSAPrivateKey + - asn1crypto.keys.DSAPrivateKey + - asn1crypto.keys.ECPrivateKey + """ + + if key_info.algorithm == 'rsa': + return key_info['private_key'].parsed + + if key_info.algorithm == 'dsa': + params = key_info['private_key_algorithm']['parameters'] + parsed = key_info['private_key'].parsed + return DSAPrivateKey({ + 'version': 0, + 'p': params['p'], + 'q': params['q'], + 'g': params['g'], + 'public_key': Integer(pow( + params['g'].native, + parsed.native, + params['p'].native + )), + 'private_key': parsed, + }) + + if key_info.algorithm == 'ec': + parsed = key_info['private_key'].parsed + parsed['parameters'] = key_info['private_key_algorithm']['parameters'] + return parsed + + raise ValueError('Unsupported key_info.algorithm "%s"' % key_info.algorithm) + + +def _fingerprint(key_object, load_private_key): + """ + Returns a fingerprint used for correlating public keys and private keys + + :param key_object: + An asn1crypto.keys.PrivateKeyInfo or asn1crypto.keys.PublicKeyInfo + + :raises: + ValueError - when the key_object is not of the proper type + + ;return: + A byte string fingerprint + """ + + if isinstance(key_object, PrivateKeyInfo): + key = key_object['private_key'].parsed + + if key_object.algorithm == 'rsa': + to_hash = '%d:%d' % ( + key['modulus'].native, + key['public_exponent'].native, + ) + + elif key_object.algorithm == 'dsa': + params = key_object['private_key_algorithm']['parameters'] + public_key = Integer(pow( + params['g'].native, + key_object['private_key'].parsed.native, + params['p'].native + )) + + to_hash = '%d:%d:%d:%d' % ( + params['p'].native, + params['q'].native, + params['g'].native, + public_key.native, + ) + + elif key_object.algorithm == 'ec': + public_key = key['public_key'].native + if public_key is None: + # This is gross, but since the EC public key is optional, + # and we need to load the private key and use the crypto lib + # to get the public key, we have to import the platform-specific + # asymmetric implementation. This is the reason a bunch of the + # imports are module imports, so we don't get an import cycle. + public_key_object = load_private_key(key_object).public_key + public_key = public_key_object.asn1['public_key'].parsed.native + + to_hash = '%s:' % key_object.curve[1] + to_hash = to_hash.encode('utf-8') + to_hash += public_key + + if isinstance(to_hash, str_cls): + to_hash = to_hash.encode('utf-8') + + return hashlib.sha256(to_hash).digest() + + if isinstance(key_object, PublicKeyInfo): + if key_object.algorithm == 'rsa': + key = key_object['public_key'].parsed + + to_hash = '%d:%d' % ( + key['modulus'].native, + key['public_exponent'].native, + ) + + elif key_object.algorithm == 'dsa': + key = key_object['public_key'].parsed + params = key_object['algorithm']['parameters'] + + to_hash = '%d:%d:%d:%d' % ( + params['p'].native, + params['q'].native, + params['g'].native, + key.native, + ) + + elif key_object.algorithm == 'ec': + public_key = key_object['public_key'].native + + to_hash = '%s:' % key_object.curve[1] + to_hash = to_hash.encode('utf-8') + to_hash += public_key + + if isinstance(to_hash, str_cls): + to_hash = to_hash.encode('utf-8') + + return hashlib.sha256(to_hash).digest() + + raise ValueError(pretty_message( + ''' + key_object must be an instance of the + asn1crypto.keys.PrivateKeyInfo or asn1crypto.keys.PublicKeyInfo + classes, not %s + ''', + type_name(key_object) + )) + + +crypto_funcs = { + 'rc2': rc2_cbc_pkcs5_decrypt, + 'rc4': rc4_decrypt, + 'des': des_cbc_pkcs5_decrypt, + 'tripledes': tripledes_cbc_pkcs5_decrypt, + 'aes': aes_cbc_pkcs7_decrypt, +} + + +def parse_public(data): + """ + Loads a public key from a DER or PEM-formatted file. Supports RSA, DSA and + EC public keys. For RSA keys, both the old RSAPublicKey and + SubjectPublicKeyInfo structures are supported. Also allows extracting a + public key from an X.509 certificate. + + :param data: + A byte string to load the public key from + + :raises: + ValueError - when the data does not appear to contain a public key + + :return: + An asn1crypto.keys.PublicKeyInfo object + """ + + if not isinstance(data, byte_cls): + raise TypeError(pretty_message( + ''' + data must be a byte string, not %s + ''', + type_name(data) + )) + + key_type = None + + # Appears to be PEM formatted + if re.match(b'\\s*-----', data) is not None: + key_type, algo, data = _unarmor_pem(data) + + if key_type == 'private key': + raise ValueError(pretty_message( + ''' + The data specified does not appear to be a public key or + certificate, but rather a private key + ''' + )) + + # When a public key returning from _unarmor_pem has a known algorithm + # of RSA, that means the DER structure is of the type RSAPublicKey, so + # we need to wrap it in the PublicKeyInfo structure. + if algo == 'rsa': + return PublicKeyInfo.wrap(data, 'rsa') + + if key_type is None or key_type == 'public key': + try: + pki = PublicKeyInfo.load(data) + # Call .native to fully parse since asn1crypto is lazy + pki.native + return pki + except (ValueError): + pass # Data was not PublicKeyInfo + + try: + rpk = RSAPublicKey.load(data) + # Call .native to fully parse since asn1crypto is lazy + rpk.native + return PublicKeyInfo.wrap(rpk, 'rsa') + except (ValueError): + pass # Data was not an RSAPublicKey + + if key_type is None or key_type == 'certificate': + try: + parsed_cert = Certificate.load(data) + key_info = parsed_cert['tbs_certificate']['subject_public_key_info'] + return key_info + except (ValueError): + pass # Data was not a cert + + raise ValueError('The data specified does not appear to be a known public key or certificate format') + + +def parse_certificate(data): + """ + Loads a certificate from a DER or PEM-formatted file. Supports X.509 + certificates only. + + :param data: + A byte string to load the certificate from + + :raises: + ValueError - when the data does not appear to contain a certificate + + :return: + An asn1crypto.x509.Certificate object + """ + + if not isinstance(data, byte_cls): + raise TypeError(pretty_message( + ''' + data must be a byte string, not %s + ''', + type_name(data) + )) + + key_type = None + + # Appears to be PEM formatted + if re.match(b'\\s*-----', data) is not None: + key_type, _, data = _unarmor_pem(data) + + if key_type == 'private key': + raise ValueError(pretty_message( + ''' + The data specified does not appear to be a certificate, but + rather a private key + ''' + )) + + if key_type == 'public key': + raise ValueError(pretty_message( + ''' + The data specified does not appear to be a certificate, but + rather a public key + ''' + )) + + if key_type is None or key_type == 'certificate': + try: + return Certificate.load(data) + except (ValueError): + pass # Data was not a Certificate + + raise ValueError(pretty_message( + ''' + The data specified does not appear to be a known certificate format + ''' + )) + + +def parse_private(data, password=None): + """ + Loads a private key from a DER or PEM-formatted file. Supports RSA, DSA and + EC private keys. Works with the follow formats: + + - RSAPrivateKey (PKCS#1) + - ECPrivateKey (SECG SEC1 V2) + - DSAPrivateKey (OpenSSL) + - PrivateKeyInfo (RSA/DSA/EC - PKCS#8) + - EncryptedPrivateKeyInfo (RSA/DSA/EC - PKCS#8) + - Encrypted RSAPrivateKey (PEM only, OpenSSL) + - Encrypted DSAPrivateKey (PEM only, OpenSSL) + - Encrypted ECPrivateKey (PEM only, OpenSSL) + + :param data: + A byte string to load the private key from + + :param password: + The password to unencrypt the private key + + :raises: + ValueError - when the data does not appear to contain a private key, or the password is invalid + + :return: + An asn1crypto.keys.PrivateKeyInfo object + """ + + if not isinstance(data, byte_cls): + raise TypeError(pretty_message( + ''' + data must be a byte string, not %s + ''', + type_name(data) + )) + + if password is not None: + if not isinstance(password, byte_cls): + raise TypeError(pretty_message( + ''' + password must be a byte string, not %s + ''', + type_name(password) + )) + else: + password = b'' + + # Appears to be PEM formatted + if re.match(b'\\s*-----', data) is not None: + key_type, _, data = _unarmor_pem(data, password) + + if key_type == 'public key': + raise ValueError(pretty_message( + ''' + The data specified does not appear to be a private key, but + rather a public key + ''' + )) + + if key_type == 'certificate': + raise ValueError(pretty_message( + ''' + The data specified does not appear to be a private key, but + rather a certificate + ''' + )) + + try: + pki = PrivateKeyInfo.load(data) + # Call .native to fully parse since asn1crypto is lazy + pki.native + return pki + except (ValueError): + pass # Data was not PrivateKeyInfo + + try: + parsed_wrapper = EncryptedPrivateKeyInfo.load(data) + encryption_algorithm_info = parsed_wrapper['encryption_algorithm'] + encrypted_data = parsed_wrapper['encrypted_data'].native + decrypted_data = _decrypt_encrypted_data(encryption_algorithm_info, encrypted_data, password) + pki = PrivateKeyInfo.load(decrypted_data) + # Call .native to fully parse since asn1crypto is lazy + pki.native + return pki + except (ValueError): + pass # Data was not EncryptedPrivateKeyInfo + + try: + parsed = RSAPrivateKey.load(data) + # Call .native to fully parse since asn1crypto is lazy + parsed.native + return PrivateKeyInfo.wrap(parsed, 'rsa') + except (ValueError): + pass # Data was not an RSAPrivateKey + + try: + parsed = DSAPrivateKey.load(data) + # Call .native to fully parse since asn1crypto is lazy + parsed.native + return PrivateKeyInfo.wrap(parsed, 'dsa') + except (ValueError): + pass # Data was not a DSAPrivateKey + + try: + parsed = ECPrivateKey.load(data) + # Call .native to fully parse since asn1crypto is lazy + parsed.native + return PrivateKeyInfo.wrap(parsed, 'ec') + except (ValueError): + pass # Data was not an ECPrivateKey + + raise ValueError(pretty_message( + ''' + The data specified does not appear to be a known private key format + ''' + )) + + +def _unarmor_pem(data, password=None): + """ + Removes PEM-encoding from a public key, private key or certificate. If the + private key is encrypted, the password will be used to decrypt it. + + :param data: + A byte string of the PEM-encoded data + + :param password: + A byte string of the encryption password, or None + + :return: + A 3-element tuple in the format: (key_type, algorithm, der_bytes). The + key_type will be a unicode string of "public key", "private key" or + "certificate". The algorithm will be a unicode string of "rsa", "dsa" + or "ec". + """ + + object_type, headers, der_bytes = unarmor(data) + + type_regex = '^((DSA|EC|RSA) PRIVATE KEY|ENCRYPTED PRIVATE KEY|PRIVATE KEY|PUBLIC KEY|RSA PUBLIC KEY|CERTIFICATE)' + armor_type = re.match(type_regex, object_type) + if not armor_type: + raise ValueError(pretty_message( + ''' + data does not seem to contain a PEM-encoded certificate, private + key or public key + ''' + )) + + pem_header = armor_type.group(1) + + data = data.strip() + + # RSA private keys are encrypted after being DER-encoded, but before base64 + # encoding, so they need to be hanlded specially + if pem_header in set(['RSA PRIVATE KEY', 'DSA PRIVATE KEY', 'EC PRIVATE KEY']): + algo = armor_type.group(2).lower() + return ('private key', algo, _unarmor_pem_openssl_private(headers, der_bytes, password)) + + key_type = pem_header.lower() + algo = None + if key_type == 'encrypted private key': + key_type = 'private key' + elif key_type == 'rsa public key': + key_type = 'public key' + algo = 'rsa' + + return (key_type, algo, der_bytes) + + +def _unarmor_pem_openssl_private(headers, data, password): + """ + Parses a PKCS#1 private key, or encrypted private key + + :param headers: + A dict of "Name: Value" lines from right after the PEM header + + :param data: + A byte string of the DER-encoded PKCS#1 private key + + :param password: + A byte string of the password to use if the private key is encrypted + + :return: + A byte string of the DER-encoded private key + """ + + enc_algo = None + enc_iv_hex = None + enc_iv = None + + if 'DEK-Info' in headers: + params = headers['DEK-Info'] + if params.find(',') != -1: + enc_algo, enc_iv_hex = params.strip().split(',') + else: + enc_algo = 'RC4' + + if not enc_algo: + return data + + if enc_iv_hex: + enc_iv = binascii.unhexlify(enc_iv_hex.encode('ascii')) + enc_algo = enc_algo.lower() + + enc_key_length = { + 'aes-128-cbc': 16, + 'aes-128': 16, + 'aes-192-cbc': 24, + 'aes-192': 24, + 'aes-256-cbc': 32, + 'aes-256': 32, + 'rc4': 16, + 'rc4-64': 8, + 'rc4-40': 5, + 'rc2-64-cbc': 8, + 'rc2-40-cbc': 5, + 'rc2-cbc': 16, + 'rc2': 16, + 'des-ede3-cbc': 24, + 'des-ede3': 24, + 'des3': 24, + 'des-ede-cbc': 16, + 'des-cbc': 8, + 'des': 8, + }[enc_algo] + + enc_key = hashlib.md5(password + enc_iv[0:8]).digest() + while enc_key_length > len(enc_key): + enc_key += hashlib.md5(enc_key + password + enc_iv[0:8]).digest() + enc_key = enc_key[0:enc_key_length] + + enc_algo_name = { + 'aes-128-cbc': 'aes', + 'aes-128': 'aes', + 'aes-192-cbc': 'aes', + 'aes-192': 'aes', + 'aes-256-cbc': 'aes', + 'aes-256': 'aes', + 'rc4': 'rc4', + 'rc4-64': 'rc4', + 'rc4-40': 'rc4', + 'rc2-64-cbc': 'rc2', + 'rc2-40-cbc': 'rc2', + 'rc2-cbc': 'rc2', + 'rc2': 'rc2', + 'des-ede3-cbc': 'tripledes', + 'des-ede3': 'tripledes', + 'des3': 'tripledes', + 'des-ede-cbc': 'tripledes', + 'des-cbc': 'des', + 'des': 'des', + }[enc_algo] + decrypt_func = crypto_funcs[enc_algo_name] + + if enc_algo_name == 'rc4': + return decrypt_func(enc_key, data) + + return decrypt_func(enc_key, data, enc_iv) + + +def _parse_pkcs12(data, password, load_private_key): + """ + Parses a PKCS#12 ANS.1 DER-encoded structure and extracts certs and keys + + :param data: + A byte string of a DER-encoded PKCS#12 file + + :param password: + A byte string of the password to any encrypted data + + :param load_private_key: + A callable that will accept a byte string and return an + oscrypto.asymmetric.PrivateKey object + + :raises: + ValueError - when any of the parameters are of the wrong type or value + OSError - when an error is returned by one of the OS decryption functions + + :return: + A three-element tuple of: + 1. An asn1crypto.keys.PrivateKeyInfo object + 2. An asn1crypto.x509.Certificate object + 3. A list of zero or more asn1crypto.x509.Certificate objects that are + "extra" certificates, possibly intermediates from the cert chain + """ + + if not isinstance(data, byte_cls): + raise TypeError(pretty_message( + ''' + data must be a byte string, not %s + ''', + type_name(data) + )) + + if password is not None: + if not isinstance(password, byte_cls): + raise TypeError(pretty_message( + ''' + password must be a byte string, not %s + ''', + type_name(password) + )) + else: + password = b'' + + certs = {} + private_keys = {} + + pfx = Pfx.load(data) + + auth_safe = pfx['auth_safe'] + if auth_safe['content_type'].native != 'data': + raise ValueError(pretty_message( + ''' + Only password-protected PKCS12 files are currently supported + ''' + )) + authenticated_safe = pfx.authenticated_safe + + mac_data = pfx['mac_data'] + if mac_data: + mac_algo = mac_data['mac']['digest_algorithm']['algorithm'].native + key_length = { + 'sha1': 20, + 'sha224': 28, + 'sha256': 32, + 'sha384': 48, + 'sha512': 64, + 'sha512_224': 28, + 'sha512_256': 32, + }[mac_algo] + mac_key = pkcs12_kdf( + mac_algo, + password, + mac_data['mac_salt'].native, + mac_data['iterations'].native, + key_length, + 3 # ID 3 is for generating an HMAC key + ) + hash_mod = getattr(hashlib, mac_algo) + computed_hmac = hmac.new(mac_key, auth_safe['content'].contents, hash_mod).digest() + stored_hmac = mac_data['mac']['digest'].native + if not constant_compare(computed_hmac, stored_hmac): + raise ValueError('Password provided is invalid') + + for content_info in authenticated_safe: + content = content_info['content'] + + if isinstance(content, OctetString): + _parse_safe_contents(content.native, certs, private_keys, password, load_private_key) + + elif isinstance(content, EncryptedData): + encrypted_content_info = content['encrypted_content_info'] + + encryption_algorithm_info = encrypted_content_info['content_encryption_algorithm'] + encrypted_content = encrypted_content_info['encrypted_content'].native + decrypted_content = _decrypt_encrypted_data(encryption_algorithm_info, encrypted_content, password) + + _parse_safe_contents(decrypted_content, certs, private_keys, password, load_private_key) + + else: + raise ValueError(pretty_message( + ''' + Public-key-based PKCS12 files are not currently supported + ''' + )) + + key_fingerprints = set(private_keys.keys()) + cert_fingerprints = set(certs.keys()) + + common_fingerprints = sorted(list(key_fingerprints & cert_fingerprints)) + + key = None + cert = None + other_certs = [] + + if len(common_fingerprints) >= 1: + fingerprint = common_fingerprints[0] + key = private_keys[fingerprint] + cert = certs[fingerprint] + other_certs = [certs[f] for f in certs if f != fingerprint] + return (key, cert, other_certs) + + if len(private_keys) > 0: + first_key = sorted(list(private_keys.keys()))[0] + key = private_keys[first_key] + + if len(certs) > 0: + first_key = sorted(list(certs.keys()))[0] + cert = certs[first_key] + del certs[first_key] + + if len(certs) > 0: + other_certs = sorted(list(certs.values()), key=lambda c: c.subject.human_friendly) + + return (key, cert, other_certs) + + +def _parse_safe_contents(safe_contents, certs, private_keys, password, load_private_key): + """ + Parses a SafeContents PKCS#12 ANS.1 structure and extracts certs and keys + + :param safe_contents: + A byte string of ber-encoded SafeContents, or a asn1crypto.pkcs12.SafeContents + parsed object + + :param certs: + A dict to store certificates in + + :param keys: + A dict to store keys in + + :param password: + A byte string of the password to any encrypted data + + :param load_private_key: + A callable that will accept a byte string and return an + oscrypto.asymmetric.PrivateKey object + """ + + if isinstance(safe_contents, byte_cls): + safe_contents = SafeContents.load(safe_contents) + + for safe_bag in safe_contents: + bag_value = safe_bag['bag_value'] + + if isinstance(bag_value, CertBag): + if bag_value['cert_id'].native == 'x509': + cert = bag_value['cert_value'].parsed + public_key_info = cert['tbs_certificate']['subject_public_key_info'] + certs[_fingerprint(public_key_info, None)] = bag_value['cert_value'].parsed + + elif isinstance(bag_value, PrivateKeyInfo): + private_keys[_fingerprint(bag_value, load_private_key)] = bag_value + + elif isinstance(bag_value, EncryptedPrivateKeyInfo): + encryption_algorithm_info = bag_value['encryption_algorithm'] + encrypted_key_bytes = bag_value['encrypted_data'].native + decrypted_key_bytes = _decrypt_encrypted_data(encryption_algorithm_info, encrypted_key_bytes, password) + private_key = PrivateKeyInfo.load(decrypted_key_bytes) + private_keys[_fingerprint(private_key, load_private_key)] = private_key + + elif isinstance(bag_value, SafeContents): + _parse_safe_contents(bag_value, certs, private_keys, password, load_private_key) + + else: + # We don't care about CRL bags or secret bags + pass + + +def _decrypt_encrypted_data(encryption_algorithm_info, encrypted_content, password): + """ + Decrypts encrypted ASN.1 data + + :param encryption_algorithm_info: + An instance of asn1crypto.pkcs5.Pkcs5EncryptionAlgorithm + + :param encrypted_content: + A byte string of the encrypted content + + :param password: + A byte string of the encrypted content's password + + :return: + A byte string of the decrypted plaintext + """ + + decrypt_func = crypto_funcs[encryption_algorithm_info.encryption_cipher] + + # Modern, PKCS#5 PBES2-based encryption + if encryption_algorithm_info.kdf == 'pbkdf2': + + if encryption_algorithm_info.encryption_cipher == 'rc5': + raise ValueError(pretty_message( + ''' + PBES2 encryption scheme utilizing RC5 encryption is not supported + ''' + )) + + enc_key = pbkdf2( + encryption_algorithm_info.kdf_hmac, + password, + encryption_algorithm_info.kdf_salt, + encryption_algorithm_info.kdf_iterations, + encryption_algorithm_info.key_length + ) + enc_iv = encryption_algorithm_info.encryption_iv + + plaintext = decrypt_func(enc_key, encrypted_content, enc_iv) + + elif encryption_algorithm_info.kdf == 'pbkdf1': + derived_output = pbkdf1( + encryption_algorithm_info.kdf_hmac, + password, + encryption_algorithm_info.kdf_salt, + encryption_algorithm_info.kdf_iterations, + encryption_algorithm_info.key_length + 8 + ) + enc_key = derived_output[0:8] + enc_iv = derived_output[8:16] + + plaintext = decrypt_func(enc_key, encrypted_content, enc_iv) + + elif encryption_algorithm_info.kdf == 'pkcs12_kdf': + enc_key = pkcs12_kdf( + encryption_algorithm_info.kdf_hmac, + password, + encryption_algorithm_info.kdf_salt, + encryption_algorithm_info.kdf_iterations, + encryption_algorithm_info.key_length, + 1 # ID 1 is for generating a key + ) + + # Since RC4 is a stream cipher, we don't use an IV + if encryption_algorithm_info.encryption_cipher == 'rc4': + plaintext = decrypt_func(enc_key, encrypted_content) + + else: + enc_iv = pkcs12_kdf( + encryption_algorithm_info.kdf_hmac, + password, + encryption_algorithm_info.kdf_salt, + encryption_algorithm_info.kdf_iterations, + encryption_algorithm_info.encryption_block_size, + 2 # ID 2 is for generating an IV + ) + plaintext = decrypt_func(enc_key, encrypted_content, enc_iv) + + return plaintext diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_cipher_suites.py b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_cipher_suites.py new file mode 100644 index 00000000..c7cdea98 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_cipher_suites.py @@ -0,0 +1,337 @@ +# coding: utf-8 +from __future__ import unicode_literals, division, absolute_import, print_function + + +__all__ = [ + 'CIPHER_SUITE_MAP', +] + + +CIPHER_SUITE_MAP = { + b'\x00\x00': 'TLS_NULL_WITH_NULL_NULL', + b'\x00\x01': 'TLS_RSA_WITH_NULL_MD5', + b'\x00\x02': 'TLS_RSA_WITH_NULL_SHA', + b'\x00\x03': 'TLS_RSA_EXPORT_WITH_RC4_40_MD5', + b'\x00\x04': 'TLS_RSA_WITH_RC4_128_MD5', + b'\x00\x05': 'TLS_RSA_WITH_RC4_128_SHA', + b'\x00\x06': 'TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5', + b'\x00\x07': 'TLS_RSA_WITH_IDEA_CBC_SHA', + b'\x00\x08': 'TLS_RSA_EXPORT_WITH_DES40_CBC_SHA', + b'\x00\x09': 'TLS_RSA_WITH_DES_CBC_SHA', + b'\x00\x0A': 'TLS_RSA_WITH_3DES_EDE_CBC_SHA', + b'\x00\x0B': 'TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA', + b'\x00\x0C': 'TLS_DH_DSS_WITH_DES_CBC_SHA', + b'\x00\x0D': 'TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA', + b'\x00\x0E': 'TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA', + b'\x00\x0F': 'TLS_DH_RSA_WITH_DES_CBC_SHA', + b'\x00\x10': 'TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA', + b'\x00\x11': 'TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA', + b'\x00\x12': 'TLS_DHE_DSS_WITH_DES_CBC_SHA', + b'\x00\x13': 'TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA', + b'\x00\x14': 'TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA', + b'\x00\x15': 'TLS_DHE_RSA_WITH_DES_CBC_SHA', + b'\x00\x16': 'TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA', + b'\x00\x17': 'TLS_DH_anon_EXPORT_WITH_RC4_40_MD5', + b'\x00\x18': 'TLS_DH_anon_WITH_RC4_128_MD5', + b'\x00\x19': 'TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA', + b'\x00\x1A': 'TLS_DH_anon_WITH_DES_CBC_SHA', + b'\x00\x1B': 'TLS_DH_anon_WITH_3DES_EDE_CBC_SHA', + b'\x00\x1E': 'TLS_KRB5_WITH_DES_CBC_SHA', + b'\x00\x1F': 'TLS_KRB5_WITH_3DES_EDE_CBC_SHA', + b'\x00\x20': 'TLS_KRB5_WITH_RC4_128_SHA', + b'\x00\x21': 'TLS_KRB5_WITH_IDEA_CBC_SHA', + b'\x00\x22': 'TLS_KRB5_WITH_DES_CBC_MD5', + b'\x00\x23': 'TLS_KRB5_WITH_3DES_EDE_CBC_MD5', + b'\x00\x24': 'TLS_KRB5_WITH_RC4_128_MD5', + b'\x00\x25': 'TLS_KRB5_WITH_IDEA_CBC_MD5', + b'\x00\x26': 'TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA', + b'\x00\x27': 'TLS_KRB5_EXPORT_WITH_RC2_CBC_40_SHA', + b'\x00\x28': 'TLS_KRB5_EXPORT_WITH_RC4_40_SHA', + b'\x00\x29': 'TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5', + b'\x00\x2A': 'TLS_KRB5_EXPORT_WITH_RC2_CBC_40_MD5', + b'\x00\x2B': 'TLS_KRB5_EXPORT_WITH_RC4_40_MD5', + b'\x00\x2C': 'TLS_PSK_WITH_NULL_SHA', + b'\x00\x2D': 'TLS_DHE_PSK_WITH_NULL_SHA', + b'\x00\x2E': 'TLS_RSA_PSK_WITH_NULL_SHA', + b'\x00\x2F': 'TLS_RSA_WITH_AES_128_CBC_SHA', + b'\x00\x30': 'TLS_DH_DSS_WITH_AES_128_CBC_SHA', + b'\x00\x31': 'TLS_DH_RSA_WITH_AES_128_CBC_SHA', + b'\x00\x32': 'TLS_DHE_DSS_WITH_AES_128_CBC_SHA', + b'\x00\x33': 'TLS_DHE_RSA_WITH_AES_128_CBC_SHA', + b'\x00\x34': 'TLS_DH_anon_WITH_AES_128_CBC_SHA', + b'\x00\x35': 'TLS_RSA_WITH_AES_256_CBC_SHA', + b'\x00\x36': 'TLS_DH_DSS_WITH_AES_256_CBC_SHA', + b'\x00\x37': 'TLS_DH_RSA_WITH_AES_256_CBC_SHA', + b'\x00\x38': 'TLS_DHE_DSS_WITH_AES_256_CBC_SHA', + b'\x00\x39': 'TLS_DHE_RSA_WITH_AES_256_CBC_SHA', + b'\x00\x3A': 'TLS_DH_anon_WITH_AES_256_CBC_SHA', + b'\x00\x3B': 'TLS_RSA_WITH_NULL_SHA256', + b'\x00\x3C': 'TLS_RSA_WITH_AES_128_CBC_SHA256', + b'\x00\x3D': 'TLS_RSA_WITH_AES_256_CBC_SHA256', + b'\x00\x3E': 'TLS_DH_DSS_WITH_AES_128_CBC_SHA256', + b'\x00\x3F': 'TLS_DH_RSA_WITH_AES_128_CBC_SHA256', + b'\x00\x40': 'TLS_DHE_DSS_WITH_AES_128_CBC_SHA256', + b'\x00\x41': 'TLS_RSA_WITH_CAMELLIA_128_CBC_SHA', + b'\x00\x42': 'TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA', + b'\x00\x43': 'TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA', + b'\x00\x44': 'TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA', + b'\x00\x45': 'TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA', + b'\x00\x46': 'TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA', + b'\x00\x67': 'TLS_DHE_RSA_WITH_AES_128_CBC_SHA256', + b'\x00\x68': 'TLS_DH_DSS_WITH_AES_256_CBC_SHA256', + b'\x00\x69': 'TLS_DH_RSA_WITH_AES_256_CBC_SHA256', + b'\x00\x6A': 'TLS_DHE_DSS_WITH_AES_256_CBC_SHA256', + b'\x00\x6B': 'TLS_DHE_RSA_WITH_AES_256_CBC_SHA256', + b'\x00\x6C': 'TLS_DH_anon_WITH_AES_128_CBC_SHA256', + b'\x00\x6D': 'TLS_DH_anon_WITH_AES_256_CBC_SHA256', + b'\x00\x84': 'TLS_RSA_WITH_CAMELLIA_256_CBC_SHA', + b'\x00\x85': 'TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA', + b'\x00\x86': 'TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA', + b'\x00\x87': 'TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA', + b'\x00\x88': 'TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA', + b'\x00\x89': 'TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA', + b'\x00\x8A': 'TLS_PSK_WITH_RC4_128_SHA', + b'\x00\x8B': 'TLS_PSK_WITH_3DES_EDE_CBC_SHA', + b'\x00\x8C': 'TLS_PSK_WITH_AES_128_CBC_SHA', + b'\x00\x8D': 'TLS_PSK_WITH_AES_256_CBC_SHA', + b'\x00\x8E': 'TLS_DHE_PSK_WITH_RC4_128_SHA', + b'\x00\x8F': 'TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA', + b'\x00\x90': 'TLS_DHE_PSK_WITH_AES_128_CBC_SHA', + b'\x00\x91': 'TLS_DHE_PSK_WITH_AES_256_CBC_SHA', + b'\x00\x92': 'TLS_RSA_PSK_WITH_RC4_128_SHA', + b'\x00\x93': 'TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA', + b'\x00\x94': 'TLS_RSA_PSK_WITH_AES_128_CBC_SHA', + b'\x00\x95': 'TLS_RSA_PSK_WITH_AES_256_CBC_SHA', + b'\x00\x96': 'TLS_RSA_WITH_SEED_CBC_SHA', + b'\x00\x97': 'TLS_DH_DSS_WITH_SEED_CBC_SHA', + b'\x00\x98': 'TLS_DH_RSA_WITH_SEED_CBC_SHA', + b'\x00\x99': 'TLS_DHE_DSS_WITH_SEED_CBC_SHA', + b'\x00\x9A': 'TLS_DHE_RSA_WITH_SEED_CBC_SHA', + b'\x00\x9B': 'TLS_DH_anon_WITH_SEED_CBC_SHA', + b'\x00\x9C': 'TLS_RSA_WITH_AES_128_GCM_SHA256', + b'\x00\x9D': 'TLS_RSA_WITH_AES_256_GCM_SHA384', + b'\x00\x9E': 'TLS_DHE_RSA_WITH_AES_128_GCM_SHA256', + b'\x00\x9F': 'TLS_DHE_RSA_WITH_AES_256_GCM_SHA384', + b'\x00\xA0': 'TLS_DH_RSA_WITH_AES_128_GCM_SHA256', + b'\x00\xA1': 'TLS_DH_RSA_WITH_AES_256_GCM_SHA384', + b'\x00\xA2': 'TLS_DHE_DSS_WITH_AES_128_GCM_SHA256', + b'\x00\xA3': 'TLS_DHE_DSS_WITH_AES_256_GCM_SHA384', + b'\x00\xA4': 'TLS_DH_DSS_WITH_AES_128_GCM_SHA256', + b'\x00\xA5': 'TLS_DH_DSS_WITH_AES_256_GCM_SHA384', + b'\x00\xA6': 'TLS_DH_anon_WITH_AES_128_GCM_SHA256', + b'\x00\xA7': 'TLS_DH_anon_WITH_AES_256_GCM_SHA384', + b'\x00\xA8': 'TLS_PSK_WITH_AES_128_GCM_SHA256', + b'\x00\xA9': 'TLS_PSK_WITH_AES_256_GCM_SHA384', + b'\x00\xAA': 'TLS_DHE_PSK_WITH_AES_128_GCM_SHA256', + b'\x00\xAB': 'TLS_DHE_PSK_WITH_AES_256_GCM_SHA384', + b'\x00\xAC': 'TLS_RSA_PSK_WITH_AES_128_GCM_SHA256', + b'\x00\xAD': 'TLS_RSA_PSK_WITH_AES_256_GCM_SHA384', + b'\x00\xAE': 'TLS_PSK_WITH_AES_128_CBC_SHA256', + b'\x00\xAF': 'TLS_PSK_WITH_AES_256_CBC_SHA384', + b'\x00\xB0': 'TLS_PSK_WITH_NULL_SHA256', + b'\x00\xB1': 'TLS_PSK_WITH_NULL_SHA384', + b'\x00\xB2': 'TLS_DHE_PSK_WITH_AES_128_CBC_SHA256', + b'\x00\xB3': 'TLS_DHE_PSK_WITH_AES_256_CBC_SHA384', + b'\x00\xB4': 'TLS_DHE_PSK_WITH_NULL_SHA256', + b'\x00\xB5': 'TLS_DHE_PSK_WITH_NULL_SHA384', + b'\x00\xB6': 'TLS_RSA_PSK_WITH_AES_128_CBC_SHA256', + b'\x00\xB7': 'TLS_RSA_PSK_WITH_AES_256_CBC_SHA384', + b'\x00\xB8': 'TLS_RSA_PSK_WITH_NULL_SHA256', + b'\x00\xB9': 'TLS_RSA_PSK_WITH_NULL_SHA384', + b'\x00\xBA': 'TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256', + b'\x00\xBB': 'TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256', + b'\x00\xBC': 'TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256', + b'\x00\xBD': 'TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256', + b'\x00\xBE': 'TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256', + b'\x00\xBF': 'TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256', + b'\x00\xC0': 'TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256', + b'\x00\xC1': 'TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256', + b'\x00\xC2': 'TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256', + b'\x00\xC3': 'TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256', + b'\x00\xC4': 'TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256', + b'\x00\xC5': 'TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256', + b'\x00\xFF': 'TLS_EMPTY_RENEGOTIATION_INFO_SCSV', + b'\x13\x01': 'TLS_AES_128_GCM_SHA256', + b'\x13\x02': 'TLS_AES_256_GCM_SHA384', + b'\x13\x03': 'TLS_CHACHA20_POLY1305_SHA256', + b'\x13\x04': 'TLS_AES_128_CCM_SHA256', + b'\x13\x05': 'TLS_AES_128_CCM_8_SHA256', + b'\xC0\x01': 'TLS_ECDH_ECDSA_WITH_NULL_SHA', + b'\xC0\x02': 'TLS_ECDH_ECDSA_WITH_RC4_128_SHA', + b'\xC0\x03': 'TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA', + b'\xC0\x04': 'TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA', + b'\xC0\x05': 'TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA', + b'\xC0\x06': 'TLS_ECDHE_ECDSA_WITH_NULL_SHA', + b'\xC0\x07': 'TLS_ECDHE_ECDSA_WITH_RC4_128_SHA', + b'\xC0\x08': 'TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA', + b'\xC0\x09': 'TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA', + b'\xC0\x0A': 'TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA', + b'\xC0\x0B': 'TLS_ECDH_RSA_WITH_NULL_SHA', + b'\xC0\x0C': 'TLS_ECDH_RSA_WITH_RC4_128_SHA', + b'\xC0\x0D': 'TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA', + b'\xC0\x0E': 'TLS_ECDH_RSA_WITH_AES_128_CBC_SHA', + b'\xC0\x0F': 'TLS_ECDH_RSA_WITH_AES_256_CBC_SHA', + b'\xC0\x10': 'TLS_ECDHE_RSA_WITH_NULL_SHA', + b'\xC0\x11': 'TLS_ECDHE_RSA_WITH_RC4_128_SHA', + b'\xC0\x12': 'TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA', + b'\xC0\x13': 'TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA', + b'\xC0\x14': 'TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA', + b'\xC0\x15': 'TLS_ECDH_anon_WITH_NULL_SHA', + b'\xC0\x16': 'TLS_ECDH_anon_WITH_RC4_128_SHA', + b'\xC0\x17': 'TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA', + b'\xC0\x18': 'TLS_ECDH_anon_WITH_AES_128_CBC_SHA', + b'\xC0\x19': 'TLS_ECDH_anon_WITH_AES_256_CBC_SHA', + b'\xC0\x1A': 'TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA', + b'\xC0\x1B': 'TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA', + b'\xC0\x1C': 'TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA', + b'\xC0\x1D': 'TLS_SRP_SHA_WITH_AES_128_CBC_SHA', + b'\xC0\x1E': 'TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA', + b'\xC0\x1F': 'TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA', + b'\xC0\x20': 'TLS_SRP_SHA_WITH_AES_256_CBC_SHA', + b'\xC0\x21': 'TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA', + b'\xC0\x22': 'TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA', + b'\xC0\x23': 'TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256', + b'\xC0\x24': 'TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384', + b'\xC0\x25': 'TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256', + b'\xC0\x26': 'TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384', + b'\xC0\x27': 'TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256', + b'\xC0\x28': 'TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384', + b'\xC0\x29': 'TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256', + b'\xC0\x2A': 'TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384', + b'\xC0\x2B': 'TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256', + b'\xC0\x2C': 'TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384', + b'\xC0\x2D': 'TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256', + b'\xC0\x2E': 'TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384', + b'\xC0\x2F': 'TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256', + b'\xC0\x30': 'TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384', + b'\xC0\x31': 'TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256', + b'\xC0\x32': 'TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384', + b'\xC0\x33': 'TLS_ECDHE_PSK_WITH_RC4_128_SHA', + b'\xC0\x34': 'TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA', + b'\xC0\x35': 'TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA', + b'\xC0\x36': 'TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA', + b'\xC0\x37': 'TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256', + b'\xC0\x38': 'TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384', + b'\xC0\x39': 'TLS_ECDHE_PSK_WITH_NULL_SHA', + b'\xC0\x3A': 'TLS_ECDHE_PSK_WITH_NULL_SHA256', + b'\xC0\x3B': 'TLS_ECDHE_PSK_WITH_NULL_SHA384', + b'\xC0\x3C': 'TLS_RSA_WITH_ARIA_128_CBC_SHA256', + b'\xC0\x3D': 'TLS_RSA_WITH_ARIA_256_CBC_SHA384', + b'\xC0\x3E': 'TLS_DH_DSS_WITH_ARIA_128_CBC_SHA256', + b'\xC0\x3F': 'TLS_DH_DSS_WITH_ARIA_256_CBC_SHA384', + b'\xC0\x40': 'TLS_DH_RSA_WITH_ARIA_128_CBC_SHA256', + b'\xC0\x41': 'TLS_DH_RSA_WITH_ARIA_256_CBC_SHA384', + b'\xC0\x42': 'TLS_DHE_DSS_WITH_ARIA_128_CBC_SHA256', + b'\xC0\x43': 'TLS_DHE_DSS_WITH_ARIA_256_CBC_SHA384', + b'\xC0\x44': 'TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256', + b'\xC0\x45': 'TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384', + b'\xC0\x46': 'TLS_DH_anon_WITH_ARIA_128_CBC_SHA256', + b'\xC0\x47': 'TLS_DH_anon_WITH_ARIA_256_CBC_SHA384', + b'\xC0\x48': 'TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256', + b'\xC0\x49': 'TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384', + b'\xC0\x4A': 'TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256', + b'\xC0\x4B': 'TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384', + b'\xC0\x4C': 'TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256', + b'\xC0\x4D': 'TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384', + b'\xC0\x4E': 'TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256', + b'\xC0\x4F': 'TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384', + b'\xC0\x50': 'TLS_RSA_WITH_ARIA_128_GCM_SHA256', + b'\xC0\x51': 'TLS_RSA_WITH_ARIA_256_GCM_SHA384', + b'\xC0\x52': 'TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256', + b'\xC0\x53': 'TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384', + b'\xC0\x54': 'TLS_DH_RSA_WITH_ARIA_128_GCM_SHA256', + b'\xC0\x55': 'TLS_DH_RSA_WITH_ARIA_256_GCM_SHA384', + b'\xC0\x56': 'TLS_DHE_DSS_WITH_ARIA_128_GCM_SHA256', + b'\xC0\x57': 'TLS_DHE_DSS_WITH_ARIA_256_GCM_SHA384', + b'\xC0\x58': 'TLS_DH_DSS_WITH_ARIA_128_GCM_SHA256', + b'\xC0\x59': 'TLS_DH_DSS_WITH_ARIA_256_GCM_SHA384', + b'\xC0\x5A': 'TLS_DH_anon_WITH_ARIA_128_GCM_SHA256', + b'\xC0\x5B': 'TLS_DH_anon_WITH_ARIA_256_GCM_SHA384', + b'\xC0\x5C': 'TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256', + b'\xC0\x5D': 'TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384', + b'\xC0\x5E': 'TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256', + b'\xC0\x5F': 'TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384', + b'\xC0\x60': 'TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256', + b'\xC0\x61': 'TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384', + b'\xC0\x62': 'TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256', + b'\xC0\x63': 'TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384', + b'\xC0\x64': 'TLS_PSK_WITH_ARIA_128_CBC_SHA256', + b'\xC0\x65': 'TLS_PSK_WITH_ARIA_256_CBC_SHA384', + b'\xC0\x66': 'TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256', + b'\xC0\x67': 'TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384', + b'\xC0\x68': 'TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256', + b'\xC0\x69': 'TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384', + b'\xC0\x6A': 'TLS_PSK_WITH_ARIA_128_GCM_SHA256', + b'\xC0\x6B': 'TLS_PSK_WITH_ARIA_256_GCM_SHA384', + b'\xC0\x6C': 'TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256', + b'\xC0\x6D': 'TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384', + b'\xC0\x6E': 'TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256', + b'\xC0\x6F': 'TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384', + b'\xC0\x70': 'TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256', + b'\xC0\x71': 'TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384', + b'\xC0\x72': 'TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256', + b'\xC0\x73': 'TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384', + b'\xC0\x74': 'TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256', + b'\xC0\x75': 'TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384', + b'\xC0\x76': 'TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256', + b'\xC0\x77': 'TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384', + b'\xC0\x78': 'TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256', + b'\xC0\x79': 'TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384', + b'\xC0\x7A': 'TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256', + b'\xC0\x7B': 'TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384', + b'\xC0\x7C': 'TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256', + b'\xC0\x7D': 'TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384', + b'\xC0\x7E': 'TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256', + b'\xC0\x7F': 'TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384', + b'\xC0\x80': 'TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256', + b'\xC0\x81': 'TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384', + b'\xC0\x82': 'TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256', + b'\xC0\x83': 'TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384', + b'\xC0\x84': 'TLS_DH_anon_WITH_CAMELLIA_128_GCM_SHA256', + b'\xC0\x85': 'TLS_DH_anon_WITH_CAMELLIA_256_GCM_SHA384', + b'\xC0\x86': 'TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256', + b'\xC0\x87': 'TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384', + b'\xC0\x88': 'TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256', + b'\xC0\x89': 'TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384', + b'\xC0\x8A': 'TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256', + b'\xC0\x8B': 'TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384', + b'\xC0\x8C': 'TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256', + b'\xC0\x8D': 'TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384', + b'\xC0\x8E': 'TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256', + b'\xC0\x8F': 'TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384', + b'\xC0\x90': 'TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256', + b'\xC0\x91': 'TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384', + b'\xC0\x92': 'TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256', + b'\xC0\x93': 'TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384', + b'\xC0\x94': 'TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256', + b'\xC0\x95': 'TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384', + b'\xC0\x96': 'TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256', + b'\xC0\x97': 'TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384', + b'\xC0\x98': 'TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256', + b'\xC0\x99': 'TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384', + b'\xC0\x9A': 'TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256', + b'\xC0\x9B': 'TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384', + b'\xC0\x9C': 'TLS_RSA_WITH_AES_128_CCM', + b'\xC0\x9D': 'TLS_RSA_WITH_AES_256_CCM', + b'\xC0\x9E': 'TLS_DHE_RSA_WITH_AES_128_CCM', + b'\xC0\x9F': 'TLS_DHE_RSA_WITH_AES_256_CCM', + b'\xC0\xA0': 'TLS_RSA_WITH_AES_128_CCM_8', + b'\xC0\xA1': 'TLS_RSA_WITH_AES_256_CCM_8', + b'\xC0\xA2': 'TLS_DHE_RSA_WITH_AES_128_CCM_8', + b'\xC0\xA3': 'TLS_DHE_RSA_WITH_AES_256_CCM_8', + b'\xC0\xA4': 'TLS_PSK_WITH_AES_128_CCM', + b'\xC0\xA5': 'TLS_PSK_WITH_AES_256_CCM', + b'\xC0\xA6': 'TLS_DHE_PSK_WITH_AES_128_CCM', + b'\xC0\xA7': 'TLS_DHE_PSK_WITH_AES_256_CCM', + b'\xC0\xA8': 'TLS_PSK_WITH_AES_128_CCM_8', + b'\xC0\xA9': 'TLS_PSK_WITH_AES_256_CCM_8', + b'\xC0\xAA': 'TLS_PSK_DHE_WITH_AES_128_CCM_8', + b'\xC0\xAB': 'TLS_PSK_DHE_WITH_AES_256_CCM_8', + b'\xCC\xA8': 'TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256', + b'\xCC\xA9': 'TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256', + b'\xCC\xAA': 'TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256', + b'\xCC\xAB': 'TLS_PSK_WITH_CHACHA20_POLY1305_SHA256', + b'\xCC\xAC': 'TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256', + b'\xCC\xAD': 'TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256', + b'\xCC\xAE': 'TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256', +} diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_ecdsa.py b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_ecdsa.py new file mode 100644 index 00000000..66cbbeec --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_ecdsa.py @@ -0,0 +1,811 @@ +# coding: utf-8 +from __future__ import unicode_literals, division, absolute_import, print_function + +import hashlib +import hmac +import sys + +from . import backend +from ._asn1 import ( + Certificate, + DSASignature, + ECDomainParameters, + ECPointBitString, + ECPrivateKey, + int_from_bytes, + PrivateKeyAlgorithm, + PrivateKeyInfo, + PublicKeyAlgorithm, + PublicKeyInfo, +) +from ._errors import pretty_message +from ._types import type_name, byte_cls +from .util import rand_bytes +from .errors import SignatureError + +if sys.version_info < (3,): + chr_cls = chr + range = xrange # noqa + +else: + def chr_cls(num): + return bytes([num]) + + +_backend = backend() + + +if _backend != 'winlegacy': + # This pure-Python ECDSA code is only suitable for use on client machines, + # and is only needed on Windows 5.x (XP/2003). For testing sake it is + # possible to force use of it on newer versions of Windows. + raise SystemError('Pure-python ECDSA code is only for Windows XP/2003') + + +__all__ = [ + 'ec_generate_pair', + 'ec_compute_public_key_point', + 'ec_public_key_info', + 'ecdsa_sign', + 'ecdsa_verify', +] + + +CURVE_BYTES = { + 'secp256r1': 32, + 'secp384r1': 48, + 'secp521r1': 66, +} + +CURVE_EXTRA_BITS = { + 'secp256r1': 0, + 'secp384r1': 0, + 'secp521r1': 7, +} + + +def ec_generate_pair(curve): + """ + Generates a EC public/private key pair + + :param curve: + A unicode string. Valid values include "secp256r1", "secp384r1" and + "secp521r1". + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + + :return: + A 2-element tuple of (asn1crypto.keys.PublicKeyInfo, + asn1crypto.keys.PrivateKeyInfo) + """ + + if curve not in set(['secp256r1', 'secp384r1', 'secp521r1']): + raise ValueError(pretty_message( + ''' + curve must be one of "secp256r1", "secp384r1", "secp521r1", not %s + ''', + repr(curve) + )) + + curve_num_bytes = CURVE_BYTES[curve] + curve_base_point = { + 'secp256r1': SECP256R1_BASE_POINT, + 'secp384r1': SECP384R1_BASE_POINT, + 'secp521r1': SECP521R1_BASE_POINT, + }[curve] + + while True: + private_key_bytes = rand_bytes(curve_num_bytes) + private_key_int = int_from_bytes(private_key_bytes, signed=False) + + if private_key_int > 0 and private_key_int < curve_base_point.order: + break + + private_key_info = PrivateKeyInfo({ + 'version': 0, + 'private_key_algorithm': PrivateKeyAlgorithm({ + 'algorithm': 'ec', + 'parameters': ECDomainParameters( + name='named', + value=curve + ) + }), + 'private_key': ECPrivateKey({ + 'version': 'ecPrivkeyVer1', + 'private_key': private_key_int + }), + }) + + ec_point = ec_compute_public_key_point(private_key_info) + private_key_info['private_key'].parsed['public_key'] = ec_point.copy() + + return (ec_public_key_info(ec_point, curve), private_key_info) + + +def ec_compute_public_key_point(private_key): + """ + Constructs the PublicKeyInfo for a PrivateKeyInfo + + :param private_key: + An asn1crypto.keys.PrivateKeyInfo object + + :raises: + ValueError - when any of the parameters contain an invalid value + + :return: + An asn1crypto.keys.ECPointBitString object + """ + + if not isinstance(private_key, PrivateKeyInfo): + raise TypeError(pretty_message( + ''' + private_key must be an instance of the + asn1crypto.keys.PrivateKeyInfo class, not %s + ''', + type_name(private_key) + )) + + curve_type, details = private_key.curve + + if curve_type == 'implicit_ca': + raise ValueError(pretty_message( + ''' + Unable to compute public key for EC key using Implicit CA + parameters + ''' + )) + + if curve_type == 'specified': + raise ValueError(pretty_message( + ''' + Unable to compute public key for EC key over a specified field + ''' + )) + + elif curve_type == 'named': + if details not in set(['secp256r1', 'secp384r1', 'secp521r1']): + raise ValueError(pretty_message( + ''' + Named curve must be one of "secp256r1", "secp384r1", "secp521r1", not %s + ''', + repr(details) + )) + + base_point = { + 'secp256r1': SECP256R1_BASE_POINT, + 'secp384r1': SECP384R1_BASE_POINT, + 'secp521r1': SECP521R1_BASE_POINT, + }[details] + + public_point = base_point * private_key['private_key'].parsed['private_key'].native + return ECPointBitString.from_coords(public_point.x, public_point.y) + + +def ec_public_key_info(public_key_point, curve): + """ + Constructs the PublicKeyInfo for an ECPointBitString + + :param private_key: + An asn1crypto.keys.ECPointBitString object + + :param curve: + A unicode string of the curve name - one of secp256r1, secp384r1 or secp521r1 + + :raises: + ValueError - when any of the parameters contain an invalid value + + :return: + An asn1crypto.keys.PublicKeyInfo object + """ + + if curve not in set(['secp256r1', 'secp384r1', 'secp521r1']): + raise ValueError(pretty_message( + ''' + curve must be one of "secp256r1", "secp384r1", "secp521r1", not %s + ''', + repr(curve) + )) + + return PublicKeyInfo({ + 'algorithm': PublicKeyAlgorithm({ + 'algorithm': 'ec', + 'parameters': ECDomainParameters( + name='named', + value=curve + ) + }), + 'public_key': public_key_point, + }) + + +def ecdsa_sign(private_key, data, hash_algorithm): + """ + Generates an ECDSA signature in pure Python (thus slow) + + :param private_key: + The PrivateKey to generate the signature with + + :param data: + A byte string of the data the signature is for + + :param hash_algorithm: + A unicode string of "sha1", "sha256", "sha384" or "sha512" + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + + :return: + A byte string of the signature + """ + + if not hasattr(private_key, 'asn1') or not isinstance(private_key.asn1, PrivateKeyInfo): + raise TypeError(pretty_message( + ''' + private_key must be an instance of the + oscrypto.asymmetric.PrivateKey class, not %s + ''', + type_name(private_key) + )) + + curve_name = private_key.curve + if curve_name not in set(['secp256r1', 'secp384r1', 'secp521r1']): + raise ValueError(pretty_message( + ''' + private_key does not use one of the named curves secp256r1, + secp384r1 or secp521r1 + ''' + )) + + if not isinstance(data, byte_cls): + raise TypeError(pretty_message( + ''' + data must be a byte string, not %s + ''', + type_name(data) + )) + + if hash_algorithm not in set(['sha1', 'sha224', 'sha256', 'sha384', 'sha512']): + raise ValueError(pretty_message( + ''' + hash_algorithm must be one of "sha1", "sha224", "sha256", "sha384", + "sha512", not %s + ''', + repr(hash_algorithm) + )) + + hash_func = getattr(hashlib, hash_algorithm) + + ec_private_key = private_key.asn1['private_key'].parsed + private_key_bytes = ec_private_key['private_key'].contents + private_key_int = ec_private_key['private_key'].native + + curve_num_bytes = CURVE_BYTES[curve_name] + curve_base_point = { + 'secp256r1': SECP256R1_BASE_POINT, + 'secp384r1': SECP384R1_BASE_POINT, + 'secp521r1': SECP521R1_BASE_POINT, + }[curve_name] + + n = curve_base_point.order + + # RFC 6979 section 3.2 + + # a. + digest = hash_func(data).digest() + hash_length = len(digest) + + h = int_from_bytes(digest, signed=False) % n + + # b. + V = b'\x01' * hash_length + + # c. + K = b'\x00' * hash_length + + # d. + K = hmac.new(K, V + b'\x00' + private_key_bytes + digest, hash_func).digest() + + # e. + V = hmac.new(K, V, hash_func).digest() + + # f. + K = hmac.new(K, V + b'\x01' + private_key_bytes + digest, hash_func).digest() + + # g. + V = hmac.new(K, V, hash_func).digest() + + # h. + r = 0 + s = 0 + while True: + # h. 1 + T = b'' + + # h. 2 + while len(T) < curve_num_bytes: + V = hmac.new(K, V, hash_func).digest() + T += V + + # h. 3 + k = int_from_bytes(T[0:curve_num_bytes], signed=False) + if k == 0 or k >= n: + continue + + # Calculate the signature in the loop in case we need a new k + r = (curve_base_point * k).x % n + if r == 0: + continue + + s = (inverse_mod(k, n) * (h + (private_key_int * r) % n)) % n + if s == 0: + continue + + break + + return DSASignature({'r': r, 's': s}).dump() + + +def ecdsa_verify(certificate_or_public_key, signature, data, hash_algorithm): + """ + Verifies an ECDSA signature in pure Python (thus slow) + + :param certificate_or_public_key: + A Certificate or PublicKey instance to verify the signature with + + :param signature: + A byte string of the signature to verify + + :param data: + A byte string of the data the signature is for + + :param hash_algorithm: + A unicode string of "md5", "sha1", "sha256", "sha384" or "sha512" + + :raises: + oscrypto.errors.SignatureError - when the signature is determined to be invalid + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + """ + + has_asn1 = hasattr(certificate_or_public_key, 'asn1') + if not has_asn1 or not isinstance(certificate_or_public_key.asn1, (PublicKeyInfo, Certificate)): + raise TypeError(pretty_message( + ''' + certificate_or_public_key must be an instance of the + oscrypto.asymmetric.PublicKey or oscrypto.asymmetric.Certificate + classes, not %s + ''', + type_name(certificate_or_public_key) + )) + + curve_name = certificate_or_public_key.curve + if curve_name not in set(['secp256r1', 'secp384r1', 'secp521r1']): + raise ValueError(pretty_message( + ''' + certificate_or_public_key does not use one of the named curves + secp256r1, secp384r1 or secp521r1 + ''' + )) + + if not isinstance(signature, byte_cls): + raise TypeError(pretty_message( + ''' + signature must be a byte string, not %s + ''', + type_name(signature) + )) + + if not isinstance(data, byte_cls): + raise TypeError(pretty_message( + ''' + data must be a byte string, not %s + ''', + type_name(data) + )) + + if hash_algorithm not in set(['sha1', 'sha224', 'sha256', 'sha384', 'sha512']): + raise ValueError(pretty_message( + ''' + hash_algorithm must be one of "sha1", "sha224", "sha256", "sha384", + "sha512", not %s + ''', + repr(hash_algorithm) + )) + + asn1 = certificate_or_public_key.asn1 + if isinstance(asn1, Certificate): + asn1 = asn1.public_key + + curve_base_point = { + 'secp256r1': SECP256R1_BASE_POINT, + 'secp384r1': SECP384R1_BASE_POINT, + 'secp521r1': SECP521R1_BASE_POINT, + }[curve_name] + + x, y = asn1['public_key'].to_coords() + n = curve_base_point.order + + # Validates that the point is valid + public_key_point = PrimePoint(curve_base_point.curve, x, y, n) + + try: + signature = DSASignature.load(signature) + r = signature['r'].native + s = signature['s'].native + except (ValueError): + raise SignatureError('Signature is invalid') + + invalid = 0 + + # Check r is valid + invalid |= r < 1 + invalid |= r >= n + + # Check s is valid + invalid |= s < 1 + invalid |= s >= n + + if invalid: + raise SignatureError('Signature is invalid') + + hash_func = getattr(hashlib, hash_algorithm) + + digest = hash_func(data).digest() + + z = int_from_bytes(digest, signed=False) % n + w = inverse_mod(s, n) + u1 = (z * w) % n + u2 = (r * w) % n + hash_point = (curve_base_point * u1) + (public_key_point * u2) + if r != (hash_point.x % n): + raise SignatureError('Signature is invalid') + + +""" +Classes and objects to represent prime-field elliptic curves and points on them. +Exports the following items: + + - PrimeCurve() + - PrimePoint() + - SECP192R1_CURVE + - SECP192R1_BASE_POINT + - SECP224R1_CURVE + - SECP224R1_BASE_POINT + - SECP256R1_CURVE + - SECP256R1_BASE_POINT + - SECP384R1_CURVE + - SECP384R1_BASE_POINT + - SECP521R1_CURVE + - SECP521R1_BASE_POINT + +The curve constants are all PrimeCurve() objects and the base point constants +are all PrimePoint() objects. + +Some of the following source code is derived from +http://webpages.charter.net/curryfans/peter/downloads.html, but has been heavily +modified to fit into this projects lint settings. The original project license +is listed below: + +Copyright (c) 2014 Peter Pearson + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +""" + + +def inverse_mod(a, p): + """ + Compute the modular inverse of a (mod p) + + :param a: + An integer + + :param p: + An integer + + :return: + An integer + """ + + if a < 0 or p <= a: + a = a % p + + # From Ferguson and Schneier, roughly: + + c, d = a, p + uc, vc, ud, vd = 1, 0, 0, 1 + while c != 0: + q, c, d = divmod(d, c) + (c,) + uc, vc, ud, vd = ud - q * uc, vd - q * vc, uc, vc + + # At this point, d is the GCD, and ud*a+vd*p = d. + # If d == 1, this means that ud is a inverse. + + assert d == 1 + if ud > 0: + return ud + else: + return ud + p + + +class PrimeCurve(): + """ + Elliptic curve over a prime field. Characteristic two field curves are not + supported. + """ + + def __init__(self, p, a, b): + """ + The curve of points satisfying y^2 = x^3 + a*x + b (mod p) + + :param p: + The prime number as an integer + + :param a: + The component a as an integer + + :param b: + The component b as an integer + """ + + self.p = p + self.a = a + self.b = b + + def contains(self, point): + """ + :param point: + A Point object + + :return: + Boolean if the point is on this curve + """ + + y2 = point.y * point.y + x3 = point.x * point.x * point.x + return (y2 - (x3 + self.a * point.x + self.b)) % self.p == 0 + + +class PrimePoint(): + """ + A point on a prime-field elliptic curve + """ + + def __init__(self, curve, x, y, order=None): + """ + :param curve: + A PrimeCurve object + + :param x: + The x coordinate of the point as an integer + + :param y: + The y coordinate of the point as an integer + + :param order: + The order of the point, as an integer - optional + """ + + self.curve = curve + self.x = x + self.y = y + self.order = order + + # self.curve is allowed to be None only for INFINITY: + if self.curve: + if not self.curve.contains(self): + raise ValueError('Invalid EC point') + + if self.order: + if self * self.order != INFINITY: + raise ValueError('Invalid EC point') + + def __cmp__(self, other): + """ + :param other: + A PrimePoint object + + :return: + 0 if identical, 1 otherwise + """ + if self.curve == other.curve and self.x == other.x and self.y == other.y: + return 0 + else: + return 1 + + def __add__(self, other): + """ + :param other: + A PrimePoint object + + :return: + A PrimePoint object + """ + + # X9.62 B.3: + + if other == INFINITY: + return self + if self == INFINITY: + return other + assert self.curve == other.curve + if self.x == other.x: + if (self.y + other.y) % self.curve.p == 0: + return INFINITY + else: + return self.double() + + p = self.curve.p + + l_ = ((other.y - self.y) * inverse_mod(other.x - self.x, p)) % p + + x3 = (l_ * l_ - self.x - other.x) % p + y3 = (l_ * (self.x - x3) - self.y) % p + + return PrimePoint(self.curve, x3, y3) + + def __mul__(self, other): + """ + :param other: + An integer to multiple the Point by + + :return: + A PrimePoint object + """ + + def leftmost_bit(x): + assert x > 0 + result = 1 + while result <= x: + result = 2 * result + return result // 2 + + e = other + if self.order: + e = e % self.order + if e == 0: + return INFINITY + if self == INFINITY: + return INFINITY + assert e > 0 + + # From X9.62 D.3.2: + + e3 = 3 * e + negative_self = PrimePoint(self.curve, self.x, -self.y, self.order) + i = leftmost_bit(e3) // 2 + result = self + # print "Multiplying %s by %d (e3 = %d):" % ( self, other, e3 ) + while i > 1: + result = result.double() + if (e3 & i) != 0 and (e & i) == 0: + result = result + self + if (e3 & i) == 0 and (e & i) != 0: + result = result + negative_self + # print ". . . i = %d, result = %s" % ( i, result ) + i = i // 2 + + return result + + def __rmul__(self, other): + """ + :param other: + An integer to multiple the Point by + + :return: + A PrimePoint object + """ + + return self * other + + def double(self): + """ + :return: + A PrimePoint object that is twice this point + """ + + # X9.62 B.3: + + p = self.curve.p + a = self.curve.a + + l_ = ((3 * self.x * self.x + a) * inverse_mod(2 * self.y, p)) % p + + x3 = (l_ * l_ - 2 * self.x) % p + y3 = (l_ * (self.x - x3) - self.y) % p + + return PrimePoint(self.curve, x3, y3) + + +# This one point is the Point At Infinity for all purposes: +INFINITY = PrimePoint(None, None, None) + + +# NIST Curve P-192: +SECP192R1_CURVE = PrimeCurve( + 6277101735386680763835789423207666416083908700390324961279, + -3, + 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1 +) +SECP192R1_BASE_POINT = PrimePoint( + SECP192R1_CURVE, + 0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, + 0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811, + 6277101735386680763835789423176059013767194773182842284081 +) + + +# NIST Curve P-224: +SECP224R1_CURVE = PrimeCurve( + 26959946667150639794667015087019630673557916260026308143510066298881, + -3, + 0xb4050a850c04b3abf54132565044b0b7d7bfd8ba270b39432355ffb4 +) +SECP224R1_BASE_POINT = PrimePoint( + SECP224R1_CURVE, + 0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21, + 0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34, + 26959946667150639794667015087019625940457807714424391721682722368061 +) + + +# NIST Curve P-256: +SECP256R1_CURVE = PrimeCurve( + 115792089210356248762697446949407573530086143415290314195533631308867097853951, + -3, + 0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b +) +SECP256R1_BASE_POINT = PrimePoint( + SECP256R1_CURVE, + 0x6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296, + 0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5, + 115792089210356248762697446949407573529996955224135760342422259061068512044369 +) + + +# NIST Curve P-384: +SECP384R1_CURVE = PrimeCurve( + 39402006196394479212279040100143613805079739270465446667948293404245721771496870329047266088258938001861606973112319, # noqa + -3, + 0xb3312fa7e23ee7e4988e056be3f82d19181d9c6efe8141120314088f5013875ac656398d8a2ed19d2a85c8edd3ec2aef +) +SECP384R1_BASE_POINT = PrimePoint( + SECP384R1_CURVE, + 0xaa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a385502f25dbf55296c3a545e3872760ab7, + 0x3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e5f, + 39402006196394479212279040100143613805079739270465446667946905279627659399113263569398956308152294913554433653942643 +) + + +# NIST Curve P-521: +SECP521R1_CURVE = PrimeCurve( + 6864797660130609714981900799081393217269435300143305409394463459185543183397656052122559640661454554977296311391480858037121987999716643812574028291115057151, # noqa + -3, + 0x051953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef109e156193951ec7e937b1652c0bd3bb1bf073573df883d2c34f1ef451fd46b503f00 # noqa +) +SECP521R1_BASE_POINT = PrimePoint( + SECP521R1_CURVE, + 0xc6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3dbaa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66, # noqa + 0x11839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e662c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650, # noqa + 6864797660130609714981900799081393217269435300143305409394463459185543183397655394245057746333217197532963996371363321113864768612440380340372808892707005449 # noqa +) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_errors.py b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_errors.py new file mode 100644 index 00000000..42aefa2d --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_errors.py @@ -0,0 +1,50 @@ +# coding: utf-8 + +""" +Helper for formatting exception messages. Exports the following items: + + - pretty_message() +""" + +from __future__ import unicode_literals, division, absolute_import, print_function + +import re +import textwrap + + +__all__ = [ + 'pretty_message', +] + + +def pretty_message(string, *params): + """ + Takes a multi-line string and does the following: + + - dedents + - converts newlines with text before and after into a single line + - strips leading and trailing whitespace + + :param string: + The string to format + + :param *params: + Params to interpolate into the string + + :return: + The formatted string + """ + + output = textwrap.dedent(string) + + # Unwrap lines, taking into account bulleted lists, ordered lists and + # underlines consisting of = signs + if output.find('\n') != -1: + output = re.sub('(?<=\\S)\n(?=[^ \n\t\\d\\*\\-=])', ' ', output) + + if params: + output = output % params + + output = output.strip() + + return output diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_ffi.py b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_ffi.py new file mode 100644 index 00000000..fe6bdeef --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_ffi.py @@ -0,0 +1,437 @@ +# coding: utf-8 + +""" +Exceptions and compatibility shims for consistently using ctypes and cffi +""" + +from __future__ import unicode_literals, division, absolute_import, print_function + +import sys +import platform + +from ctypes.util import find_library + +from . import ffi +from ._types import str_cls, byte_cls, int_types, bytes_to_list + + +__all__ = [ + 'array_from_pointer', + 'array_set', + 'buffer_from_bytes', + 'buffer_from_unicode', + 'buffer_pointer', + 'byte_array', + 'byte_string_from_buffer', + 'bytes_from_buffer', + 'callback', + 'cast', + 'deref', + 'errno', + 'FFIEngineError', + 'get_library', + 'is_null', + 'native', + 'new', + 'null', + 'pointer_set', + 'ref', + 'register_ffi', + 'sizeof', + 'struct', + 'struct_bytes', + 'struct_from_buffer', + 'unwrap', + 'write_to_buffer', +] + + +if ffi() == 'cffi': + from cffi import FFI + + _ffi_registry = {} + + ffi = FFI() + + def register_ffi(library, ffi_obj): + _ffi_registry[library] = ffi_obj + + def _get_ffi(library): + if library in _ffi_registry: + return _ffi_registry[library] + return ffi + + def buffer_from_bytes(initializer): + if sys.platform == 'win32': + return ffi.new('unsigned char[]', initializer) + return ffi.new('char[]', initializer) + + def buffer_from_unicode(initializer): + return ffi.new('wchar_t []', initializer) + + def write_to_buffer(buffer, data, offset=0): + buffer[offset:offset + len(data)] = data + + def buffer_pointer(buffer): + return ffi.new('char *[]', [buffer]) + + def cast(library, type_, value): + ffi_obj = _get_ffi(library) + return ffi_obj.cast(type_, value) + + def sizeof(library, value): + ffi_obj = _get_ffi(library) + return ffi_obj.sizeof(value) + + def bytes_from_buffer(buffer, maxlen=None): + if maxlen is not None: + return ffi.buffer(buffer, maxlen)[:] + return ffi.buffer(buffer)[:] + + def byte_string_from_buffer(buffer): + return ffi.string(buffer) + + def byte_array(byte_string): + return byte_string + + def pointer_set(pointer_, value): + pointer_[0] = value + + def array_set(array, value): + for index, val in enumerate(value): + array[index] = val + + def null(): + return ffi.NULL + + def is_null(point): + if point is None: + return True + if point == ffi.NULL: + return True + if ffi.getctype(ffi.typeof(point)) == 'void *': + return False + if point[0] == ffi.NULL: + return True + return False + + def errno(): + return ffi.errno + + def new(library, type_, value=None): + ffi_obj = _get_ffi(library) + + params = [] + if value is not None: + params.append(value) + if type_ in set(['BCRYPT_KEY_HANDLE', 'BCRYPT_ALG_HANDLE']): + return ffi_obj.cast(type_, 0) + return ffi_obj.new(type_, *params) + + def ref(value, offset=0): + return value + offset + + def native(type_, value): + if type_ == str_cls: + return ffi.string(value) + if type_ == byte_cls: + return ffi.buffer(value)[:] + return type_(value) + + def deref(point): + return point[0] + + def unwrap(point): + return point[0] + + def struct(library, name): + ffi_obj = _get_ffi(library) + return ffi_obj.new('%s *' % name) + + def struct_bytes(struct_): + return ffi.buffer(struct_)[:] + + def struct_from_buffer(library, name, buffer): + ffi_obj = _get_ffi(library) + new_struct_pointer = ffi_obj.new('%s *' % name) + new_struct = new_struct_pointer[0] + struct_size = sizeof(library, new_struct) + struct_buffer = ffi_obj.buffer(new_struct_pointer) + struct_buffer[:] = ffi_obj.buffer(buffer, struct_size)[:] + return new_struct_pointer + + def array_from_pointer(library, name, point, size): + ffi_obj = _get_ffi(library) + array = ffi_obj.cast('%s[%s]' % (name, size), point) + total_bytes = ffi_obj.sizeof(array) + if total_bytes == 0: + return [] + output = [] + + string_types = { + 'LPSTR': True, + 'LPCSTR': True, + 'LPWSTR': True, + 'LPCWSTR': True, + 'char *': True, + 'wchar_t *': True, + } + string_type = name in string_types + + for i in range(0, size): + value = array[i] + if string_type: + value = ffi_obj.string(value) + output.append(value) + return output + + def callback(library, signature_name, func): + ffi_obj = _get_ffi(library) + return ffi_obj.callback(signature_name, func) + + engine = 'cffi' + +else: + + import ctypes + from ctypes import pointer, c_int, c_char_p, c_uint, c_void_p, c_wchar_p + + _pointer_int_types = int_types + (c_char_p, ctypes.POINTER(ctypes.c_byte)) + + _pointer_types = { + 'void *': True, + 'wchar_t *': True, + 'char *': True, + 'char **': True, + } + _type_map = { + 'void *': c_void_p, + 'wchar_t *': c_wchar_p, + 'char *': c_char_p, + 'char **': ctypes.POINTER(c_char_p), + 'int': c_int, + 'unsigned int': c_uint, + 'size_t': ctypes.c_size_t, + 'uint32_t': ctypes.c_uint32, + } + if sys.platform == 'win32': + from ctypes import wintypes + _pointer_types.update({ + 'LPSTR': True, + 'LPWSTR': True, + 'LPCSTR': True, + 'LPCWSTR': True, + }) + _type_map.update({ + 'BYTE': ctypes.c_byte, + 'LPSTR': c_char_p, + 'LPWSTR': c_wchar_p, + 'LPCSTR': c_char_p, + 'LPCWSTR': c_wchar_p, + 'ULONG': wintypes.ULONG, + 'DWORD': wintypes.DWORD, + 'char *': ctypes.POINTER(ctypes.c_byte), + 'char **': ctypes.POINTER(ctypes.POINTER(ctypes.c_byte)), + }) + + def _type_info(library, type_): + is_double_pointer = type_[-3:] == ' **' + if is_double_pointer: + type_ = type_[:-1] + is_pointer = type_[-2:] == ' *' and type_ not in _pointer_types + if is_pointer: + type_ = type_[:-2] + + is_array = type_.find('[') != -1 + if is_array: + is_array = type_[type_.find('[') + 1:type_.find(']')] + if is_array == '': + is_array = True + else: + is_array = int(is_array) + type_ = type_[0:type_.find('[')] + + if type_ in _type_map: + type_ = _type_map[type_] + else: + type_ = getattr(library, type_) + + if is_double_pointer: + type_ = ctypes.POINTER(type_) + + return (is_pointer, is_array, type_) + + def register_ffi(library, ffi_obj): + pass + + def buffer_from_bytes(initializer): + return ctypes.create_string_buffer(initializer) + + def buffer_from_unicode(initializer): + return ctypes.create_unicode_buffer(initializer) + + def write_to_buffer(buffer, data, offset=0): + if isinstance(buffer, ctypes.POINTER(ctypes.c_byte)): + ctypes.memmove(buffer, data, len(data)) + return + + if offset == 0: + buffer.value = data + else: + buffer.value = buffer.raw[0:offset] + data + + def buffer_pointer(buffer): + return pointer(ctypes.cast(buffer, c_char_p)) + + def cast(library, type_, value): + is_pointer, is_array, type_ = _type_info(library, type_) + + if is_pointer: + type_ = ctypes.POINTER(type_) + elif is_array: + type_ = type_ * is_array + + return ctypes.cast(value, type_) + + def sizeof(library, value): + return ctypes.sizeof(value) + + def bytes_from_buffer(buffer, maxlen=None): + if isinstance(buffer, _pointer_int_types): + return ctypes.string_at(buffer, maxlen) + if maxlen is not None: + return buffer.raw[0:maxlen] + return buffer.raw + + def byte_string_from_buffer(buffer): + return buffer.value + + def byte_array(byte_string): + return (ctypes.c_byte * len(byte_string))(*bytes_to_list(byte_string)) + + def pointer_set(pointer_, value): + pointer_.contents.value = value + + def array_set(array, value): + for index, val in enumerate(value): + array[index] = val + + def null(): + return None + + def is_null(point): + return not bool(point) + + def errno(): + return ctypes.get_errno() + + def new(library, type_, value=None): + is_pointer, is_array, type_ = _type_info(library, type_) + if is_array: + if is_array is True: + type_ = type_ * value + value = None + else: + type_ = type_ * is_array + + params = [] + if value is not None: + params.append(value) + output = type_(*params) + + if is_pointer: + output = pointer(output) + + return output + + def ref(value, offset=0): + if offset == 0: + return ctypes.byref(value) + return ctypes.cast(ctypes.addressof(value) + offset, ctypes.POINTER(ctypes.c_byte)) + + def native(type_, value): + if isinstance(value, type_): + return value + if sys.version_info < (3,) and type_ == int and isinstance(value, int_types): + return value + if isinstance(value, ctypes.Array) and value._type_ == ctypes.c_byte: + return ctypes.string_at(ctypes.addressof(value), value._length_) + return type_(value.value) + + def deref(point): + return point[0] + + def unwrap(point): + return point.contents + + def struct(library, name): + return pointer(getattr(library, name)()) + + def struct_bytes(struct_): + return ctypes.string_at(struct_, ctypes.sizeof(struct_.contents)) + + def struct_from_buffer(library, type_, buffer): + class_ = getattr(library, type_) + value = class_() + ctypes.memmove(ctypes.addressof(value), buffer, ctypes.sizeof(class_)) + return ctypes.pointer(value) + + def array_from_pointer(library, type_, point, size): + _, _, type_ = _type_info(library, type_) + array = ctypes.cast(point, ctypes.POINTER(type_)) + output = [] + for i in range(0, size): + output.append(array[i]) + return output + + def callback(library, signature_type, func): + return getattr(library, signature_type)(func) + + engine = 'ctypes' + + +def get_library(name, dylib_name, version): + """ + Retrieve the C library path with special handling for Mac + + :param name: + A unicode string of the library to search the system for + + :param dylib_name: + Mac only - a unicode string of the unversioned dylib name + + :param version: + Mac only - a unicode string of the dylib version to use. Used on macOS + 10.15+ when the unversioned dylib is found, since unversioned + OpenSSL/LibreSSL are just placeholders, and a versioned dylib must be + imported. Used on macOS 10.16+ when find_library() doesn't return a + result, due to system dylibs not being present on the filesystem any + longer. + + :return: + A unicode string of the path to the library + """ + + library = find_library(name) + + if sys.platform == 'darwin': + unversioned = '/usr/lib/%s' % dylib_name + versioned = unversioned.replace('.dylib', '.%s.dylib' % version) + mac_ver = tuple(map(int, platform.mac_ver()[0].split('.'))) + if not library and mac_ver >= (10, 16): + # On macOS 10.16+, find_library doesn't work, so we set a static path + library = versioned + elif mac_ver >= (10, 15) and library == unversioned: + # On macOS 10.15+, we want to strongly version since unversioned libcrypto has a non-stable ABI + library = versioned + + return library + + +class FFIEngineError(Exception): + + """ + An exception when trying to instantiate ctypes or cffi + """ + + pass diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_int.py b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_int.py new file mode 100644 index 00000000..0721c34e --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_int.py @@ -0,0 +1,35 @@ +# coding: utf-8 + +""" +Function to fill ensure integers converted to a byte string are a specific +width. Exports the following items: + + - fill_width() +""" + +from __future__ import unicode_literals, division, absolute_import, print_function + + +__all__ = [ + 'fill_width', +] + + +def fill_width(bytes_, width): + """ + Ensure a byte string representing a positive integer is a specific width + (in bytes) + + :param bytes_: + The integer byte string + + :param width: + The desired width as an integer + + :return: + A byte string of the width specified + """ + + while len(bytes_) < width: + bytes_ = b'\x00' + bytes_ + return bytes_ diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_linux_bsd/__init__.py b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_linux_bsd/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_linux_bsd/trust_list.py b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_linux_bsd/trust_list.py new file mode 100644 index 00000000..4f4185ec --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_linux_bsd/trust_list.py @@ -0,0 +1,120 @@ +# coding: utf-8 +from __future__ import unicode_literals, division, absolute_import, print_function + +import os + +from .._asn1 import Certificate, TrustedCertificate, unarmor +from .._errors import pretty_message + + +__all__ = [ + 'extract_from_system', + 'system_path', +] + + +def system_path(): + """ + Tries to find a CA certs bundle in common locations + + :raises: + OSError - when no valid CA certs bundle was found on the filesystem + + :return: + The full filesystem path to a CA certs bundle file + """ + + ca_path = None + + # Common CA cert paths + paths = [ + '/usr/lib/ssl/certs/ca-certificates.crt', + '/etc/ssl/certs/ca-certificates.crt', + '/etc/ssl/certs/ca-bundle.crt', + '/etc/pki/tls/certs/ca-bundle.crt', + '/etc/ssl/ca-bundle.pem', + '/usr/local/share/certs/ca-root-nss.crt', + '/etc/ssl/cert.pem' + ] + + # First try SSL_CERT_FILE + if 'SSL_CERT_FILE' in os.environ: + paths.insert(0, os.environ['SSL_CERT_FILE']) + + for path in paths: + if os.path.exists(path) and os.path.getsize(path) > 0: + ca_path = path + break + + if not ca_path: + raise OSError(pretty_message( + ''' + Unable to find a CA certs bundle in common locations - try + setting the SSL_CERT_FILE environmental variable + ''' + )) + + return ca_path + + +def extract_from_system(cert_callback=None, callback_only_on_failure=False): + """ + Extracts trusted CA certs from the system CA cert bundle + + :param cert_callback: + A callback that is called once for each certificate in the trust store. + It should accept two parameters: an asn1crypto.x509.Certificate object, + and a reason. The reason will be None if the certificate is being + exported, otherwise it will be a unicode string of the reason it won't. + + :param callback_only_on_failure: + A boolean - if the callback should only be called when a certificate is + not exported. + + :return: + A list of 3-element tuples: + - 0: a byte string of a DER-encoded certificate + - 1: a set of unicode strings that are OIDs of purposes to trust the + certificate for + - 2: a set of unicode strings that are OIDs of purposes to reject the + certificate for + """ + + all_purposes = '2.5.29.37.0' + ca_path = system_path() + + output = [] + with open(ca_path, 'rb') as f: + for armor_type, _, cert_bytes in unarmor(f.read(), multiple=True): + # Without more info, a certificate is trusted for all purposes + if armor_type == 'CERTIFICATE': + if cert_callback: + cert_callback(Certificate.load(cert_bytes), None) + output.append((cert_bytes, set(), set())) + + # The OpenSSL TRUSTED CERTIFICATE construct adds OIDs for trusted + # and rejected purposes, so we extract that info. + elif armor_type == 'TRUSTED CERTIFICATE': + cert, aux = TrustedCertificate.load(cert_bytes) + reject_all = False + trust_oids = set() + reject_oids = set() + for purpose in aux['trust']: + if purpose.dotted == all_purposes: + trust_oids = set([purpose.dotted]) + break + trust_oids.add(purpose.dotted) + for purpose in aux['reject']: + if purpose.dotted == all_purposes: + reject_all = True + break + reject_oids.add(purpose.dotted) + if reject_all: + if cert_callback: + cert_callback(cert, 'explicitly distrusted') + continue + if cert_callback and not callback_only_on_failure: + cert_callback(cert, None) + output.append((cert.dump(), trust_oids, reject_oids)) + + return output diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_mac/__init__.py b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_mac/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_mac/_common_crypto.py b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_mac/_common_crypto.py new file mode 100644 index 00000000..3b290b89 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_mac/_common_crypto.py @@ -0,0 +1,24 @@ +# coding: utf-8 +from __future__ import unicode_literals, division, absolute_import, print_function + +from .. import ffi + +if ffi() == 'cffi': + from ._common_crypto_cffi import CommonCrypto +else: + from ._common_crypto_ctypes import CommonCrypto + + +__all__ = [ + 'CommonCrypto', + 'CommonCryptoConst', +] + + +class CommonCryptoConst(): + kCCPBKDF2 = 2 + kCCPRFHmacAlgSHA1 = 1 + kCCPRFHmacAlgSHA224 = 2 + kCCPRFHmacAlgSHA256 = 3 + kCCPRFHmacAlgSHA384 = 4 + kCCPRFHmacAlgSHA512 = 5 diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_mac/_common_crypto_cffi.py b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_mac/_common_crypto_cffi.py new file mode 100644 index 00000000..30c768b1 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_mac/_common_crypto_cffi.py @@ -0,0 +1,29 @@ +# coding: utf-8 +from __future__ import unicode_literals, division, absolute_import, print_function + +from .._ffi import register_ffi + +from cffi import FFI + + +__all__ = [ + 'CommonCrypto', +] + + +ffi = FFI() +ffi.cdef(""" + typedef uint32_t CCPBKDFAlgorithm; + + typedef uint32_t CCPseudoRandomAlgorithm; + typedef unsigned int uint; + + int CCKeyDerivationPBKDF(CCPBKDFAlgorithm algorithm, const char *password, size_t passwordLen, + const char *salt, size_t saltLen, CCPseudoRandomAlgorithm prf, uint rounds, + char *derivedKey, size_t derivedKeyLen); +""") + +common_crypto_path = '/usr/lib/system/libcommonCrypto.dylib' + +CommonCrypto = ffi.dlopen(common_crypto_path) +register_ffi(CommonCrypto, ffi) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_mac/_common_crypto_ctypes.py b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_mac/_common_crypto_ctypes.py new file mode 100644 index 00000000..2b4ee8c8 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_mac/_common_crypto_ctypes.py @@ -0,0 +1,32 @@ +# coding: utf-8 +from __future__ import unicode_literals, division, absolute_import, print_function + +from ctypes import CDLL, c_uint32, c_char_p, c_size_t, c_int, c_uint + +from .._ffi import FFIEngineError + + +__all__ = [ + 'CommonCrypto', +] + + +common_crypto_path = '/usr/lib/system/libcommonCrypto.dylib' + +CommonCrypto = CDLL(common_crypto_path, use_errno=True) + +try: + CommonCrypto.CCKeyDerivationPBKDF.argtypes = [ + c_uint32, + c_char_p, + c_size_t, + c_char_p, + c_size_t, + c_uint32, + c_uint, + c_char_p, + c_size_t + ] + CommonCrypto.CCKeyDerivationPBKDF.restype = c_int +except (AttributeError): + raise FFIEngineError('Error initializing ctypes') diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_mac/_core_foundation.py b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_mac/_core_foundation.py new file mode 100644 index 00000000..06b61a11 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_mac/_core_foundation.py @@ -0,0 +1,228 @@ +# coding: utf-8 +from __future__ import unicode_literals, division, absolute_import, print_function + +from .. import ffi +from .._ffi import is_null, unwrap + +if ffi() == 'cffi': + from ._core_foundation_cffi import CoreFoundation, CFHelpers +else: + from ._core_foundation_ctypes import CoreFoundation, CFHelpers + + +_all__ = [ + 'CFHelpers', + 'CoreFoundation', + 'handle_cf_error', +] + + +def handle_cf_error(error_pointer): + """ + Checks a CFErrorRef and throws an exception if there is an error to report + + :param error_pointer: + A CFErrorRef + + :raises: + OSError - when the CFErrorRef contains an error + """ + + if is_null(error_pointer): + return + + error = unwrap(error_pointer) + if is_null(error): + return + + cf_string_domain = CoreFoundation.CFErrorGetDomain(error) + domain = CFHelpers.cf_string_to_unicode(cf_string_domain) + CoreFoundation.CFRelease(cf_string_domain) + num = CoreFoundation.CFErrorGetCode(error) + + cf_string_ref = CoreFoundation.CFErrorCopyDescription(error) + output = CFHelpers.cf_string_to_unicode(cf_string_ref) + CoreFoundation.CFRelease(cf_string_ref) + + if output is None: + if domain == 'NSOSStatusErrorDomain': + code_map = { + -2147416010: 'ACL add failed', + -2147416025: 'ACL base certs not supported', + -2147416019: 'ACL challenge callback failed', + -2147416015: 'ACL change failed', + -2147416012: 'ACL delete failed', + -2147416017: 'ACL entry tag not found', + -2147416011: 'ACL replace failed', + -2147416021: 'ACL subject type not supported', + -2147415789: 'Algid mismatch', + -2147415726: 'Already logged in', + -2147415040: 'Apple add application ACL subject', + -2147415036: 'Apple invalid key end date', + -2147415037: 'Apple invalid key start date', + -2147415039: 'Apple public key incomplete', + -2147415038: 'Apple signature mismatch', + -2147415034: 'Apple SSLv2 rollback', + -2147415802: 'Attach handle busy', + -2147415731: 'Block size mismatch', + -2147415722: 'Crypto data callback failed', + -2147415804: 'Device error', + -2147415835: 'Device failed', + -2147415803: 'Device memory error', + -2147415836: 'Device reset', + -2147415728: 'Device verify failed', + -2147416054: 'Function failed', + -2147416057: 'Function not implemented', + -2147415807: 'Input length error', + -2147415837: 'Insufficient client identification', + -2147416063: 'Internal error', + -2147416027: 'Invalid access credentials', + -2147416026: 'Invalid ACL base certs', + -2147416020: 'Invalid ACL challenge callback', + -2147416016: 'Invalid ACL edit mode', + -2147416018: 'Invalid ACL entry tag', + -2147416022: 'Invalid ACL subject value', + -2147415759: 'Invalid algorithm', + -2147415678: 'Invalid attr access credentials', + -2147415704: 'Invalid attr alg params', + -2147415686: 'Invalid attr base', + -2147415738: 'Invalid attr block size', + -2147415680: 'Invalid attr dl db handle', + -2147415696: 'Invalid attr effective bits', + -2147415692: 'Invalid attr end date', + -2147415752: 'Invalid attr init vector', + -2147415682: 'Invalid attr iteration count', + -2147415754: 'Invalid attr key', + -2147415740: 'Invalid attr key length', + -2147415700: 'Invalid attr key type', + -2147415702: 'Invalid attr label', + -2147415698: 'Invalid attr mode', + -2147415708: 'Invalid attr output size', + -2147415748: 'Invalid attr padding', + -2147415742: 'Invalid attr passphrase', + -2147415688: 'Invalid attr prime', + -2147415674: 'Invalid attr private key format', + -2147415676: 'Invalid attr public key format', + -2147415746: 'Invalid attr random', + -2147415706: 'Invalid attr rounds', + -2147415750: 'Invalid attr salt', + -2147415744: 'Invalid attr seed', + -2147415694: 'Invalid attr start date', + -2147415684: 'Invalid attr subprime', + -2147415672: 'Invalid attr symmetric key format', + -2147415690: 'Invalid attr version', + -2147415670: 'Invalid attr wrapped key format', + -2147415760: 'Invalid context', + -2147416000: 'Invalid context handle', + -2147415976: 'Invalid crypto data', + -2147415994: 'Invalid data', + -2147415768: 'Invalid data count', + -2147415723: 'Invalid digest algorithm', + -2147416059: 'Invalid input pointer', + -2147415766: 'Invalid input vector', + -2147415792: 'Invalid key', + -2147415780: 'Invalid keyattr mask', + -2147415782: 'Invalid keyusage mask', + -2147415790: 'Invalid key class', + -2147415776: 'Invalid key format', + -2147415778: 'Invalid key label', + -2147415783: 'Invalid key pointer', + -2147415791: 'Invalid key reference', + -2147415727: 'Invalid login name', + -2147416014: 'Invalid new ACL entry', + -2147416013: 'Invalid new ACL owner', + -2147416058: 'Invalid output pointer', + -2147415765: 'Invalid output vector', + -2147415978: 'Invalid passthrough id', + -2147416060: 'Invalid pointer', + -2147416024: 'Invalid sample value', + -2147415733: 'Invalid signature', + -2147415787: 'Key blob type incorrect', + -2147415786: 'Key header inconsistent', + -2147415724: 'Key label already exists', + -2147415788: 'Key usage incorrect', + -2147416061: 'Mds error', + -2147416062: 'Memory error', + -2147415677: 'Missing attr access credentials', + -2147415703: 'Missing attr alg params', + -2147415685: 'Missing attr base', + -2147415737: 'Missing attr block size', + -2147415679: 'Missing attr dl db handle', + -2147415695: 'Missing attr effective bits', + -2147415691: 'Missing attr end date', + -2147415751: 'Missing attr init vector', + -2147415681: 'Missing attr iteration count', + -2147415753: 'Missing attr key', + -2147415739: 'Missing attr key length', + -2147415699: 'Missing attr key type', + -2147415701: 'Missing attr label', + -2147415697: 'Missing attr mode', + -2147415707: 'Missing attr output size', + -2147415747: 'Missing attr padding', + -2147415741: 'Missing attr passphrase', + -2147415687: 'Missing attr prime', + -2147415673: 'Missing attr private key format', + -2147415675: 'Missing attr public key format', + -2147415745: 'Missing attr random', + -2147415705: 'Missing attr rounds', + -2147415749: 'Missing attr salt', + -2147415743: 'Missing attr seed', + -2147415693: 'Missing attr start date', + -2147415683: 'Missing attr subprime', + -2147415671: 'Missing attr symmetric key format', + -2147415689: 'Missing attr version', + -2147415669: 'Missing attr wrapped key format', + -2147415801: 'Not logged in', + -2147415840: 'No user interaction', + -2147416029: 'Object ACL not supported', + -2147416028: 'Object ACL required', + -2147416030: 'Object manip auth denied', + -2147416031: 'Object use auth denied', + -2147416032: 'Operation auth denied', + -2147416055: 'OS access denied', + -2147415806: 'Output length error', + -2147415725: 'Private key already exists', + -2147415730: 'Private key not found', + -2147415989: 'Privilege not granted', + -2147415805: 'Privilege not supported', + -2147415729: 'Public key inconsistent', + -2147415732: 'Query size unknown', + -2147416023: 'Sample value not supported', + -2147416056: 'Self check failed', + -2147415838: 'Service not available', + -2147415736: 'Staged operation in progress', + -2147415735: 'Staged operation not started', + -2147415779: 'Unsupported keyattr mask', + -2147415781: 'Unsupported keyusage mask', + -2147415785: 'Unsupported key format', + -2147415777: 'Unsupported key label', + -2147415784: 'Unsupported key size', + -2147415839: 'User canceled', + -2147415767: 'Vector of bufs unsupported', + -2147415734: 'Verify failed', + } + if num in code_map: + output = code_map[num] + + if not output: + output = '%s %s' % (domain, num) + + raise OSError(output) + + +CFHelpers.register_native_mapping( + CoreFoundation.CFStringGetTypeID(), + CFHelpers.cf_string_to_unicode +) +CFHelpers.register_native_mapping( + CoreFoundation.CFNumberGetTypeID(), + CFHelpers.cf_number_to_number +) +CFHelpers.register_native_mapping( + CoreFoundation.CFDataGetTypeID(), + CFHelpers.cf_data_to_bytes +) +CFHelpers.register_native_mapping( + CoreFoundation.CFDictionaryGetTypeID(), + CFHelpers.cf_dictionary_to_dict +) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_mac/_core_foundation_cffi.py b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_mac/_core_foundation_cffi.py new file mode 100644 index 00000000..d0c79513 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_mac/_core_foundation_cffi.py @@ -0,0 +1,375 @@ +# coding: utf-8 +from __future__ import unicode_literals, division, absolute_import, print_function + +from .._ffi import ( + buffer_from_bytes, + byte_string_from_buffer, + deref, + is_null, + new, + register_ffi, +) + +from cffi import FFI + + +__all__ = [ + 'CFHelpers', + 'CoreFoundation', +] + + +ffi = FFI() +ffi.cdef(""" + typedef bool Boolean; + typedef long CFIndex; + typedef unsigned long CFStringEncoding; + typedef unsigned long CFNumberType; + typedef unsigned long CFTypeID; + + typedef void *CFTypeRef; + typedef CFTypeRef CFArrayRef; + typedef CFTypeRef CFDataRef; + typedef CFTypeRef CFStringRef; + typedef CFTypeRef CFNumberRef; + typedef CFTypeRef CFBooleanRef; + typedef CFTypeRef CFDictionaryRef; + typedef CFTypeRef CFErrorRef; + typedef CFTypeRef CFAllocatorRef; + + typedef struct { + CFIndex version; + void *retain; + void *release; + void *copyDescription; + void *equal; + void *hash; + } CFDictionaryKeyCallBacks; + + typedef struct { + CFIndex version; + void *retain; + void *release; + void *copyDescription; + void *equal; + } CFDictionaryValueCallBacks; + + typedef struct { + CFIndex version; + void *retain; + void *release; + void *copyDescription; + void *equal; + } CFArrayCallBacks; + + CFIndex CFDataGetLength(CFDataRef theData); + const char *CFDataGetBytePtr(CFDataRef theData); + CFDataRef CFDataCreate(CFAllocatorRef allocator, const char *bytes, CFIndex length); + + CFDictionaryRef CFDictionaryCreate(CFAllocatorRef allocator, const void **keys, const void **values, + CFIndex numValues, const CFDictionaryKeyCallBacks *keyCallBacks, + const CFDictionaryValueCallBacks *valueCallBacks); + CFIndex CFDictionaryGetCount(CFDictionaryRef theDict); + + const char *CFStringGetCStringPtr(CFStringRef theString, CFStringEncoding encoding); + Boolean CFStringGetCString(CFStringRef theString, char *buffer, CFIndex bufferSize, CFStringEncoding encoding); + CFStringRef CFStringCreateWithCString(CFAllocatorRef alloc, const char *cStr, CFStringEncoding encoding); + + CFNumberRef CFNumberCreate(CFAllocatorRef allocator, CFNumberType theType, const void *valuePtr); + + CFStringRef CFCopyTypeIDDescription(CFTypeID type_id); + + void CFRelease(CFTypeRef cf); + void CFRetain(CFTypeRef cf); + + CFStringRef CFErrorCopyDescription(CFErrorRef err); + CFStringRef CFErrorGetDomain(CFErrorRef err); + CFIndex CFErrorGetCode(CFErrorRef err); + + Boolean CFBooleanGetValue(CFBooleanRef boolean); + + CFTypeID CFDictionaryGetTypeID(void); + CFTypeID CFNumberGetTypeID(void); + CFTypeID CFStringGetTypeID(void); + CFTypeID CFDataGetTypeID(void); + + CFArrayRef CFArrayCreate(CFAllocatorRef allocator, const void **values, CFIndex numValues, + const CFArrayCallBacks *callBacks); + CFIndex CFArrayGetCount(CFArrayRef theArray); + CFTypeRef CFArrayGetValueAtIndex(CFArrayRef theArray, CFIndex idx); + CFNumberType CFNumberGetType(CFNumberRef number); + Boolean CFNumberGetValue(CFNumberRef number, CFNumberType theType, void *valuePtr); + CFIndex CFDictionaryGetKeysAndValues(CFDictionaryRef theDict, const void **keys, const void **values); + CFTypeID CFGetTypeID(CFTypeRef cf); + + extern CFAllocatorRef kCFAllocatorDefault; + extern CFArrayCallBacks kCFTypeArrayCallBacks; + extern CFBooleanRef kCFBooleanTrue; + extern CFDictionaryKeyCallBacks kCFTypeDictionaryKeyCallBacks; + extern CFDictionaryValueCallBacks kCFTypeDictionaryValueCallBacks; +""") + +core_foundation_path = '/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation' + +CoreFoundation = ffi.dlopen(core_foundation_path) +register_ffi(CoreFoundation, ffi) + +kCFNumberCFIndexType = 14 +kCFStringEncodingUTF8 = 0x08000100 + + +class CFHelpers(): + """ + Namespace for core foundation helpers + """ + + _native_map = {} + + @classmethod + def register_native_mapping(cls, type_id, callback): + """ + Register a function to convert a core foundation data type into its + equivalent in python + + :param type_id: + The CFTypeId for the type + + :param callback: + A callback to pass the CFType object to + """ + + cls._native_map[int(type_id)] = callback + + @staticmethod + def cf_number_to_number(value): + """ + Converts a CFNumber object to a python float or integer + + :param value: + The CFNumber object + + :return: + A python number (float or integer) + """ + + type_ = CoreFoundation.CFNumberGetType(value) + type_name_ = { + 1: 'int8_t', # kCFNumberSInt8Type + 2: 'in16_t', # kCFNumberSInt16Type + 3: 'int32_t', # kCFNumberSInt32Type + 4: 'int64_t', # kCFNumberSInt64Type + 5: 'float', # kCFNumberFloat32Type + 6: 'double', # kCFNumberFloat64Type + 7: 'char', # kCFNumberCharType + 8: 'short', # kCFNumberShortType + 9: 'int', # kCFNumberIntType + 10: 'long', # kCFNumberLongType + 11: 'long long', # kCFNumberLongLongType + 12: 'float', # kCFNumberFloatType + 13: 'double', # kCFNumberDoubleType + 14: 'long', # kCFNumberCFIndexType + 15: 'int', # kCFNumberNSIntegerType + 16: 'double', # kCFNumberCGFloatType + }[type_] + output = new(CoreFoundation, type_name_ + ' *') + CoreFoundation.CFNumberGetValue(value, type_, output) + return deref(output) + + @staticmethod + def cf_dictionary_to_dict(dictionary): + """ + Converts a CFDictionary object into a python dictionary + + :param dictionary: + The CFDictionary to convert + + :return: + A python dict + """ + + dict_length = CoreFoundation.CFDictionaryGetCount(dictionary) + + keys = new(CoreFoundation, 'CFTypeRef[%s]' % dict_length) + values = new(CoreFoundation, 'CFTypeRef[%s]' % dict_length) + CoreFoundation.CFDictionaryGetKeysAndValues( + dictionary, + keys, + values + ) + + output = {} + for index in range(0, dict_length): + output[CFHelpers.native(keys[index])] = CFHelpers.native(values[index]) + + return output + + @classmethod + def native(cls, value): + """ + Converts a CF* object into its python equivalent + + :param value: + The CF* object to convert + + :return: + The native python object + """ + + type_id = CoreFoundation.CFGetTypeID(value) + if type_id in cls._native_map: + return cls._native_map[type_id](value) + else: + return value + + @staticmethod + def cf_string_to_unicode(value): + """ + Creates a python unicode string from a CFString object + + :param value: + The CFString to convert + + :return: + A python unicode string + """ + + string_ptr = CoreFoundation.CFStringGetCStringPtr( + value, + kCFStringEncodingUTF8 + ) + string = None if is_null(string_ptr) else ffi.string(string_ptr) + if string is None: + buffer = buffer_from_bytes(1024) + result = CoreFoundation.CFStringGetCString( + value, + buffer, + 1024, + kCFStringEncodingUTF8 + ) + if not result: + raise OSError('Error copying C string from CFStringRef') + string = byte_string_from_buffer(buffer) + if string is not None: + string = string.decode('utf-8') + return string + + @staticmethod + def cf_string_from_unicode(string): + """ + Creates a CFStringRef object from a unicode string + + :param string: + The unicode string to create the CFString object from + + :return: + A CFStringRef + """ + + return CoreFoundation.CFStringCreateWithCString( + CoreFoundation.kCFAllocatorDefault, + string.encode('utf-8'), + kCFStringEncodingUTF8 + ) + + @staticmethod + def cf_data_to_bytes(value): + """ + Extracts a bytestring from a CFData object + + :param value: + A CFData object + + :return: + A byte string + """ + + start = CoreFoundation.CFDataGetBytePtr(value) + num_bytes = CoreFoundation.CFDataGetLength(value) + return ffi.buffer(start, num_bytes)[:] + + @staticmethod + def cf_data_from_bytes(bytes_): + """ + Creates a CFDataRef object from a byte string + + :param bytes_: + The data to create the CFData object from + + :return: + A CFDataRef + """ + + return CoreFoundation.CFDataCreate( + CoreFoundation.kCFAllocatorDefault, + bytes_, + len(bytes_) + ) + + @staticmethod + def cf_dictionary_from_pairs(pairs): + """ + Creates a CFDictionaryRef object from a list of 2-element tuples + representing the key and value. Each key should be a CFStringRef and each + value some sort of CF* type. + + :param pairs: + A list of 2-element tuples + + :return: + A CFDictionaryRef + """ + + length = len(pairs) + keys = [] + values = [] + for pair in pairs: + key, value = pair + keys.append(key) + values.append(value) + return CoreFoundation.CFDictionaryCreate( + CoreFoundation.kCFAllocatorDefault, + keys, + values, + length, + ffi.addressof(CoreFoundation.kCFTypeDictionaryKeyCallBacks), + ffi.addressof(CoreFoundation.kCFTypeDictionaryValueCallBacks) + ) + + @staticmethod + def cf_array_from_list(values): + """ + Creates a CFArrayRef object from a list of CF* type objects. + + :param values: + A list of CF* type object + + :return: + A CFArrayRef + """ + + length = len(values) + return CoreFoundation.CFArrayCreate( + CoreFoundation.kCFAllocatorDefault, + values, + length, + ffi.addressof(CoreFoundation.kCFTypeArrayCallBacks) + ) + + @staticmethod + def cf_number_from_integer(integer): + """ + Creates a CFNumber object from an integer + + :param integer: + The integer to create the CFNumber for + + :return: + A CFNumber + """ + + integer_as_long = ffi.new('long *', integer) + return CoreFoundation.CFNumberCreate( + CoreFoundation.kCFAllocatorDefault, + kCFNumberCFIndexType, + integer_as_long + ) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_mac/_core_foundation_ctypes.py b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_mac/_core_foundation_ctypes.py new file mode 100644 index 00000000..683934e7 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_mac/_core_foundation_ctypes.py @@ -0,0 +1,487 @@ +# coding: utf-8 +from __future__ import unicode_literals, division, absolute_import, print_function + +from ctypes import c_void_p, c_long, c_uint32, c_char_p, c_byte, c_ulong, c_bool +from ctypes import CDLL, string_at, cast, POINTER, byref +import ctypes + +from .._ffi import FFIEngineError, buffer_from_bytes, byte_string_from_buffer + + +__all__ = [ + 'CFHelpers', + 'CoreFoundation', +] + + +core_foundation_path = '/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation' + +CoreFoundation = CDLL(core_foundation_path, use_errno=True) + +CFIndex = c_long +CFStringEncoding = c_uint32 +CFArray = c_void_p +CFData = c_void_p +CFString = c_void_p +CFNumber = c_void_p +CFDictionary = c_void_p +CFError = c_void_p +CFType = c_void_p +CFTypeID = c_ulong +CFBoolean = c_void_p +CFNumberType = c_uint32 + +CFTypeRef = POINTER(CFType) +CFArrayRef = POINTER(CFArray) +CFDataRef = POINTER(CFData) +CFStringRef = POINTER(CFString) +CFNumberRef = POINTER(CFNumber) +CFBooleanRef = POINTER(CFBoolean) +CFDictionaryRef = POINTER(CFDictionary) +CFErrorRef = POINTER(CFError) +CFAllocatorRef = c_void_p +CFDictionaryKeyCallBacks = c_void_p +CFDictionaryValueCallBacks = c_void_p +CFArrayCallBacks = c_void_p + +pointer_p = POINTER(c_void_p) + +try: + CoreFoundation.CFDataGetLength.argtypes = [ + CFDataRef + ] + CoreFoundation.CFDataGetLength.restype = CFIndex + + CoreFoundation.CFDataGetBytePtr.argtypes = [ + CFDataRef + ] + CoreFoundation.CFDataGetBytePtr.restype = c_void_p + + CoreFoundation.CFDataCreate.argtypes = [ + CFAllocatorRef, + c_char_p, + CFIndex + ] + CoreFoundation.CFDataCreate.restype = CFDataRef + + CoreFoundation.CFDictionaryCreate.argtypes = [ + CFAllocatorRef, + CFStringRef, + CFTypeRef, + CFIndex, + CFDictionaryKeyCallBacks, + CFDictionaryValueCallBacks + ] + CoreFoundation.CFDictionaryCreate.restype = CFDictionaryRef + + CoreFoundation.CFDictionaryGetCount.argtypes = [ + CFDictionaryRef + ] + CoreFoundation.CFDictionaryGetCount.restype = CFIndex + + CoreFoundation.CFStringGetCStringPtr.argtypes = [ + CFStringRef, + CFStringEncoding + ] + CoreFoundation.CFStringGetCStringPtr.restype = c_char_p + + CoreFoundation.CFStringGetCString.argtypes = [ + CFStringRef, + c_char_p, + CFIndex, + CFStringEncoding + ] + CoreFoundation.CFStringGetCString.restype = c_bool + + CoreFoundation.CFStringCreateWithCString.argtypes = [ + CFAllocatorRef, + c_char_p, + CFStringEncoding + ] + CoreFoundation.CFStringCreateWithCString.restype = CFStringRef + + CoreFoundation.CFNumberCreate.argtypes = [ + CFAllocatorRef, + CFNumberType, + c_void_p + ] + CoreFoundation.CFNumberCreate.restype = CFNumberRef + + CoreFoundation.CFCopyTypeIDDescription.argtypes = [ + CFTypeID + ] + CoreFoundation.CFCopyTypeIDDescription.restype = CFStringRef + + CoreFoundation.CFRelease.argtypes = [ + CFTypeRef + ] + CoreFoundation.CFRelease.restype = None + + CoreFoundation.CFRetain.argtypes = [ + CFTypeRef + ] + CoreFoundation.CFRetain.restype = None + + CoreFoundation.CFErrorCopyDescription.argtypes = [ + CFErrorRef + ] + CoreFoundation.CFErrorCopyDescription.restype = CFStringRef + + CoreFoundation.CFErrorGetDomain.argtypes = [ + CFErrorRef + ] + CoreFoundation.CFErrorGetDomain.restype = CFStringRef + + CoreFoundation.CFErrorGetCode.argtypes = [ + CFErrorRef + ] + CoreFoundation.CFErrorGetCode.restype = CFIndex + + CoreFoundation.CFBooleanGetValue.argtypes = [ + CFBooleanRef + ] + CoreFoundation.CFBooleanGetValue.restype = c_byte + + CoreFoundation.CFDictionaryGetTypeID.argtypes = [] + CoreFoundation.CFDictionaryGetTypeID.restype = CFTypeID + + CoreFoundation.CFNumberGetTypeID.argtypes = [] + CoreFoundation.CFNumberGetTypeID.restype = CFTypeID + + CoreFoundation.CFStringGetTypeID.argtypes = [] + CoreFoundation.CFStringGetTypeID.restype = CFTypeID + + CoreFoundation.CFDataGetTypeID.argtypes = [] + CoreFoundation.CFDataGetTypeID.restype = CFTypeID + + CoreFoundation.CFArrayCreate.argtypes = [ + CFAllocatorRef, + POINTER(c_void_p), + CFIndex, + CFArrayCallBacks + ] + CoreFoundation.CFArrayCreate.restype = CFArrayRef + + CoreFoundation.CFArrayGetCount.argtypes = [ + CFArrayRef + ] + CoreFoundation.CFArrayGetCount.restype = CFIndex + + CoreFoundation.CFArrayGetValueAtIndex.argtypes = [ + CFArrayRef, + CFIndex + ] + CoreFoundation.CFArrayGetValueAtIndex.restype = CFTypeRef + + CoreFoundation.CFNumberGetType.argtypes = [ + CFNumberRef + ] + CoreFoundation.CFNumberGetType.restype = CFNumberType + + CoreFoundation.CFNumberGetValue.argtypes = [ + CFNumberRef, + CFNumberType, + c_void_p + ] + CoreFoundation.CFNumberGetValue.restype = c_bool + + CoreFoundation.CFDictionaryGetKeysAndValues.argtypes = [ + CFDictionaryRef, + pointer_p, + pointer_p + ] + CoreFoundation.CFDictionaryGetKeysAndValues.restype = CFIndex + + CoreFoundation.CFGetTypeID.argtypes = [ + CFTypeRef + ] + CoreFoundation.CFGetTypeID.restype = CFTypeID + + setattr(CoreFoundation, 'kCFAllocatorDefault', CFAllocatorRef.in_dll(CoreFoundation, 'kCFAllocatorDefault')) + setattr(CoreFoundation, 'kCFBooleanTrue', CFTypeRef.in_dll(CoreFoundation, 'kCFBooleanTrue')) + + kCFTypeDictionaryKeyCallBacks = c_void_p.in_dll(CoreFoundation, 'kCFTypeDictionaryKeyCallBacks') + kCFTypeDictionaryValueCallBacks = c_void_p.in_dll(CoreFoundation, 'kCFTypeDictionaryValueCallBacks') + kCFTypeArrayCallBacks = c_void_p.in_dll(CoreFoundation, 'kCFTypeArrayCallBacks') + +except (AttributeError): + raise FFIEngineError('Error initializing ctypes') + +setattr(CoreFoundation, 'CFDataRef', CFDataRef) +setattr(CoreFoundation, 'CFErrorRef', CFErrorRef) +setattr(CoreFoundation, 'CFArrayRef', CFArrayRef) +kCFNumberCFIndexType = CFNumberType(14) +kCFStringEncodingUTF8 = CFStringEncoding(0x08000100) + + +def _cast_pointer_p(value): + """ + Casts a value to a pointer of a pointer + + :param value: + A ctypes object + + :return: + A POINTER(c_void_p) object + """ + + return cast(value, pointer_p) + + +class CFHelpers(): + """ + Namespace for core foundation helpers + """ + + _native_map = {} + + @classmethod + def register_native_mapping(cls, type_id, callback): + """ + Register a function to convert a core foundation data type into its + equivalent in python + + :param type_id: + The CFTypeId for the type + + :param callback: + A callback to pass the CFType object to + """ + + cls._native_map[int(type_id)] = callback + + @staticmethod + def cf_number_to_number(value): + """ + Converts a CFNumber object to a python float or integer + + :param value: + The CFNumber object + + :return: + A python number (float or integer) + """ + + type_ = CoreFoundation.CFNumberGetType(_cast_pointer_p(value)) + c_type = { + 1: c_byte, # kCFNumberSInt8Type + 2: ctypes.c_short, # kCFNumberSInt16Type + 3: ctypes.c_int32, # kCFNumberSInt32Type + 4: ctypes.c_int64, # kCFNumberSInt64Type + 5: ctypes.c_float, # kCFNumberFloat32Type + 6: ctypes.c_double, # kCFNumberFloat64Type + 7: c_byte, # kCFNumberCharType + 8: ctypes.c_short, # kCFNumberShortType + 9: ctypes.c_int, # kCFNumberIntType + 10: c_long, # kCFNumberLongType + 11: ctypes.c_longlong, # kCFNumberLongLongType + 12: ctypes.c_float, # kCFNumberFloatType + 13: ctypes.c_double, # kCFNumberDoubleType + 14: c_long, # kCFNumberCFIndexType + 15: ctypes.c_int, # kCFNumberNSIntegerType + 16: ctypes.c_double, # kCFNumberCGFloatType + }[type_] + output = c_type(0) + CoreFoundation.CFNumberGetValue(_cast_pointer_p(value), type_, byref(output)) + return output.value + + @staticmethod + def cf_dictionary_to_dict(dictionary): + """ + Converts a CFDictionary object into a python dictionary + + :param dictionary: + The CFDictionary to convert + + :return: + A python dict + """ + + dict_length = CoreFoundation.CFDictionaryGetCount(dictionary) + + keys = (CFTypeRef * dict_length)() + values = (CFTypeRef * dict_length)() + CoreFoundation.CFDictionaryGetKeysAndValues( + dictionary, + _cast_pointer_p(keys), + _cast_pointer_p(values) + ) + + output = {} + for index in range(0, dict_length): + output[CFHelpers.native(keys[index])] = CFHelpers.native(values[index]) + + return output + + @classmethod + def native(cls, value): + """ + Converts a CF* object into its python equivalent + + :param value: + The CF* object to convert + + :return: + The native python object + """ + + type_id = CoreFoundation.CFGetTypeID(value) + if type_id in cls._native_map: + return cls._native_map[type_id](value) + else: + return value + + @staticmethod + def cf_string_to_unicode(value): + """ + Creates a python unicode string from a CFString object + + :param value: + The CFString to convert + + :return: + A python unicode string + """ + + string = CoreFoundation.CFStringGetCStringPtr( + _cast_pointer_p(value), + kCFStringEncodingUTF8 + ) + if string is None: + buffer = buffer_from_bytes(1024) + result = CoreFoundation.CFStringGetCString( + _cast_pointer_p(value), + buffer, + 1024, + kCFStringEncodingUTF8 + ) + if not result: + raise OSError('Error copying C string from CFStringRef') + string = byte_string_from_buffer(buffer) + if string is not None: + string = string.decode('utf-8') + return string + + @staticmethod + def cf_string_from_unicode(string): + """ + Creates a CFStringRef object from a unicode string + + :param string: + The unicode string to create the CFString object from + + :return: + A CFStringRef + """ + + return CoreFoundation.CFStringCreateWithCString( + CoreFoundation.kCFAllocatorDefault, + string.encode('utf-8'), + kCFStringEncodingUTF8 + ) + + @staticmethod + def cf_data_to_bytes(value): + """ + Extracts a bytestring from a CFData object + + :param value: + A CFData object + + :return: + A byte string + """ + + start = CoreFoundation.CFDataGetBytePtr(value) + num_bytes = CoreFoundation.CFDataGetLength(value) + return string_at(start, num_bytes) + + @staticmethod + def cf_data_from_bytes(bytes_): + """ + Creates a CFDataRef object from a byte string + + :param bytes_: + The data to create the CFData object from + + :return: + A CFDataRef + """ + + return CoreFoundation.CFDataCreate( + CoreFoundation.kCFAllocatorDefault, + bytes_, + len(bytes_) + ) + + @staticmethod + def cf_dictionary_from_pairs(pairs): + """ + Creates a CFDictionaryRef object from a list of 2-element tuples + representing the key and value. Each key should be a CFStringRef and each + value some sort of CF* type. + + :param pairs: + A list of 2-element tuples + + :return: + A CFDictionaryRef + """ + + length = len(pairs) + keys = [] + values = [] + for pair in pairs: + key, value = pair + keys.append(key) + values.append(value) + keys = (CFStringRef * length)(*keys) + values = (CFTypeRef * length)(*values) + return CoreFoundation.CFDictionaryCreate( + CoreFoundation.kCFAllocatorDefault, + _cast_pointer_p(byref(keys)), + _cast_pointer_p(byref(values)), + length, + kCFTypeDictionaryKeyCallBacks, + kCFTypeDictionaryValueCallBacks + ) + + @staticmethod + def cf_array_from_list(values): + """ + Creates a CFArrayRef object from a list of CF* type objects. + + :param values: + A list of CF* type object + + :return: + A CFArrayRef + """ + + length = len(values) + values = (CFTypeRef * length)(*values) + return CoreFoundation.CFArrayCreate( + CoreFoundation.kCFAllocatorDefault, + _cast_pointer_p(byref(values)), + length, + kCFTypeArrayCallBacks + ) + + @staticmethod + def cf_number_from_integer(integer): + """ + Creates a CFNumber object from an integer + + :param integer: + The integer to create the CFNumber for + + :return: + A CFNumber + """ + + integer_as_long = c_long(integer) + return CoreFoundation.CFNumberCreate( + CoreFoundation.kCFAllocatorDefault, + kCFNumberCFIndexType, + byref(integer_as_long) + ) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_mac/_security.py b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_mac/_security.py new file mode 100644 index 00000000..03ef22a2 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_mac/_security.py @@ -0,0 +1,150 @@ +# coding: utf-8 +from __future__ import unicode_literals, division, absolute_import, print_function + +from .. import ffi +from .._ffi import null +from ..errors import TLSDisconnectError, TLSGracefulDisconnectError + +if ffi() == 'cffi': + from ._security_cffi import Security, version_info as osx_version_info + from ._core_foundation_cffi import CoreFoundation, CFHelpers +else: + from ._security_ctypes import Security, version_info as osx_version_info + from ._core_foundation_ctypes import CoreFoundation, CFHelpers + + +__all__ = [ + 'handle_sec_error', + 'osx_version_info', + 'Security', + 'SecurityConst', +] + + +def handle_sec_error(error, exception_class=None): + """ + Checks a Security OSStatus error code and throws an exception if there is an + error to report + + :param error: + An OSStatus + + :param exception_class: + The exception class to use for the exception if an error occurred + + :raises: + OSError - when the OSStatus contains an error + """ + + if error == 0: + return + + if error in set([SecurityConst.errSSLClosedNoNotify, SecurityConst.errSSLClosedAbort]): + raise TLSDisconnectError('The remote end closed the connection') + if error == SecurityConst.errSSLClosedGraceful: + raise TLSGracefulDisconnectError('The remote end closed the connection') + + cf_error_string = Security.SecCopyErrorMessageString(error, null()) + output = CFHelpers.cf_string_to_unicode(cf_error_string) + CoreFoundation.CFRelease(cf_error_string) + + if output is None or output == '': + output = 'OSStatus %s' % error + + if exception_class is None: + exception_class = OSError + + raise exception_class(output) + + +def _extract_policy_properties(value): + properties_dict = Security.SecPolicyCopyProperties(value) + return CFHelpers.cf_dictionary_to_dict(properties_dict) + + +CFHelpers.register_native_mapping( + Security.SecPolicyGetTypeID(), + _extract_policy_properties +) + + +class SecurityConst(): + kSecTrustSettingsDomainUser = 0 + kSecTrustSettingsDomainAdmin = 1 + kSecTrustSettingsDomainSystem = 2 + + kSecTrustResultProceed = 1 + kSecTrustResultUnspecified = 4 + kSecTrustOptionImplicitAnchors = 0x00000040 + + kSecFormatOpenSSL = 1 + + kSecItemTypePrivateKey = 1 + kSecItemTypePublicKey = 2 + + kSSLSessionOptionBreakOnServerAuth = 0 + + kSSLProtocol2 = 1 + kSSLProtocol3 = 2 + kTLSProtocol1 = 4 + kTLSProtocol11 = 7 + kTLSProtocol12 = 8 + + kSSLClientSide = 1 + kSSLStreamType = 0 + + errSSLProtocol = -9800 + errSSLWouldBlock = -9803 + errSSLClosedGraceful = -9805 + errSSLClosedNoNotify = -9816 + errSSLClosedAbort = -9806 + + errSSLXCertChainInvalid = -9807 + errSSLCrypto = -9809 + errSSLInternal = -9810 + errSSLCertExpired = -9814 + errSSLCertNotYetValid = -9815 + errSSLUnknownRootCert = -9812 + errSSLNoRootCert = -9813 + errSSLHostNameMismatch = -9843 + errSSLPeerHandshakeFail = -9824 + errSSLPeerProtocolVersion = -9836 + errSSLPeerUserCancelled = -9839 + errSSLWeakPeerEphemeralDHKey = -9850 + errSSLServerAuthCompleted = -9841 + errSSLRecordOverflow = -9847 + + CSSMERR_APPLETP_HOSTNAME_MISMATCH = -2147408896 + CSSMERR_TP_CERT_EXPIRED = -2147409654 + CSSMERR_TP_CERT_NOT_VALID_YET = -2147409653 + CSSMERR_TP_CERT_REVOKED = -2147409652 + CSSMERR_TP_NOT_TRUSTED = -2147409622 + + CSSM_CERT_X_509v3 = 0x00000004 + + APPLE_TP_REVOCATION_CRL = b'*\x86H\x86\xf7cd\x01\x06' + APPLE_TP_REVOCATION_OCSP = b'*\x86H\x86\xf7cd\x01\x07' + + CSSM_APPLE_TP_OCSP_OPTS_VERSION = 0 + CSSM_TP_ACTION_OCSP_DISABLE_NET = 0x00000004 + CSSM_TP_ACTION_OCSP_CACHE_READ_DISABLE = 0x00000008 + + CSSM_APPLE_TP_CRL_OPTS_VERSION = 0 + + errSecVerifyFailed = -67808 + errSecNoTrustSettings = -25263 + errSecItemNotFound = -25300 + errSecInvalidTrustSettings = -25262 + + kSecPaddingNone = 0 + kSecPaddingPKCS1 = 1 + + CSSM_KEYUSE_SIGN = 0x00000004 + CSSM_KEYUSE_VERIFY = 0x00000008 + + CSSM_ALGID_DH = 2 + CSSM_ALGID_RSA = 42 + CSSM_ALGID_DSA = 43 + CSSM_ALGID_ECDSA = 73 + CSSM_KEYATTR_PERMANENT = 0x00000001 + CSSM_KEYATTR_EXTRACTABLE = 0x00000020 diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_mac/_security_cffi.py b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_mac/_security_cffi.py new file mode 100644 index 00000000..d277d988 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_mac/_security_cffi.py @@ -0,0 +1,238 @@ +# coding: utf-8 +from __future__ import unicode_literals, division, absolute_import, print_function + +import platform + +from .._ffi import register_ffi + +from cffi import FFI + + +__all__ = [ + 'Security', + 'version', + 'version_info', +] + + +version = platform.mac_ver()[0] +version_info = tuple(map(int, version.split('.'))) + +if version_info < (10, 7): + raise OSError('Only OS X 10.7 and newer are supported, not %s.%s' % (version_info[0], version_info[1])) + +ffi = FFI() +ffi.cdef(""" + typedef bool Boolean; + typedef long CFIndex; + typedef int32_t OSStatus; + typedef unsigned long CFTypeID; + typedef uint32_t SecTrustSettingsDomain; + typedef uint32_t SecPadding; + typedef uint32_t SecItemImportExportFlags; + typedef uint32_t SecKeyImportExportFlags; + typedef uint32_t SecExternalFormat; + typedef uint32_t SecExternalItemType; + typedef uint32_t CSSM_ALGORITHMS; + typedef uint64_t CSSM_CC_HANDLE; + typedef uint32_t CSSM_KEYUSE; + typedef uint32_t CSSM_CERT_TYPE; + typedef uint32_t SSLProtocol; + typedef uint32_t SSLCipherSuite; + typedef uint32_t SecTrustResultType; + + typedef void *CFTypeRef; + typedef CFTypeRef CFArrayRef; + typedef CFTypeRef CFDataRef; + typedef CFTypeRef CFStringRef; + typedef CFTypeRef CFDictionaryRef; + typedef CFTypeRef CFErrorRef; + typedef CFTypeRef CFAllocatorRef; + + typedef ... *SecKeyRef; + typedef ... *SecCertificateRef; + typedef ... *SecTransformRef; + typedef ... *SecRandomRef; + typedef ... *SecPolicyRef; + typedef ... *SecPolicySearchRef; + typedef ... *SecAccessRef; + typedef struct + { + uint32_t version; + SecKeyImportExportFlags flags; + CFTypeRef passphrase; + CFStringRef alertTitle; + CFStringRef alertPrompt; + SecAccessRef accessRef; + CFArrayRef keyUsage; + CFArrayRef keyAttributes; + } SecItemImportExportKeyParameters; + typedef ... *SecKeychainRef; + typedef ... *SSLContextRef; + typedef ... *SecTrustRef; + typedef uint32_t SSLConnectionRef; + + typedef struct { + uint32_t Length; + char *Data; + } CSSM_DATA, CSSM_OID; + + typedef struct { + uint32_t Version; + uint32_t Flags; + CSSM_DATA *LocalResponder; + CSSM_DATA *LocalResponderCert; + } CSSM_APPLE_TP_OCSP_OPTIONS; + + typedef struct { + uint32_t Version; + uint32_t CrlFlags; + void *crlStore; + } CSSM_APPLE_TP_CRL_OPTIONS; + + OSStatus SecKeychainCreate(char *path, uint32_t pass_len, void *pass, + Boolean prompt, SecAccessRef initialAccess, SecKeychainRef *keychain); + OSStatus SecKeychainDelete(SecKeychainRef keychain); + int SecRandomCopyBytes(SecRandomRef rnd, size_t count, char *bytes); + SecKeyRef SecKeyCreateFromData(CFDictionaryRef parameters, CFDataRef keyData, CFErrorRef *error); + SecTransformRef SecEncryptTransformCreate(SecKeyRef keyRef, CFErrorRef *error); + SecTransformRef SecDecryptTransformCreate(SecKeyRef keyRef, CFErrorRef *error); + Boolean SecTransformSetAttribute(SecTransformRef transformRef, CFStringRef key, CFTypeRef value, CFErrorRef *error); + CFTypeRef SecTransformExecute(SecTransformRef transformRef, CFErrorRef *errorRef); + SecTransformRef SecVerifyTransformCreate(SecKeyRef key, CFDataRef signature, CFErrorRef *error); + SecTransformRef SecSignTransformCreate(SecKeyRef key, CFErrorRef *error); + SecCertificateRef SecCertificateCreateWithData(CFAllocatorRef allocator, CFDataRef data); + OSStatus SecCertificateCopyPublicKey(SecCertificateRef certificate, SecKeyRef *key); + CFStringRef SecCopyErrorMessageString(OSStatus status, void *reserved); + OSStatus SecTrustCopyAnchorCertificates(CFArrayRef *anchors); + CFDataRef SecCertificateCopyData(SecCertificateRef certificate); + OSStatus SecTrustSettingsCopyCertificates(SecTrustSettingsDomain domain, CFArrayRef *certArray); + OSStatus SecTrustSettingsCopyTrustSettings(SecCertificateRef certRef, SecTrustSettingsDomain domain, + CFArrayRef *trustSettings); + CFDictionaryRef SecPolicyCopyProperties(SecPolicyRef policyRef); + CFTypeID SecPolicyGetTypeID(void); + OSStatus SecKeyEncrypt(SecKeyRef key, SecPadding padding, const char *plainText, size_t plainTextLen, + char *cipherText, size_t *cipherTextLen); + OSStatus SecKeyDecrypt(SecKeyRef key, SecPadding padding, const char *cipherText, size_t cipherTextLen, + char *plainText, size_t *plainTextLen); + OSStatus SecKeyRawSign(SecKeyRef key, SecPadding padding, const char *dataToSign, size_t dataToSignLen, + char *sig, size_t * sigLen); + OSStatus SecKeyRawVerify(SecKeyRef key, SecPadding padding, const char *signedData, size_t signedDataLen, + const char *sig, size_t sigLen); + OSStatus SecItemImport(CFDataRef importedData, CFStringRef fileNameOrExtension, + SecExternalFormat *inputFormat, SecExternalItemType *itemType, + SecItemImportExportFlags flags, const SecItemImportExportKeyParameters *keyParams, + SecKeychainRef importKeychain, CFArrayRef *outItems); + OSStatus SecItemExport(CFTypeRef secItemOrArray, SecExternalFormat outputFormat, SecItemImportExportFlags flags, + const SecItemImportExportKeyParameters *keyParams, CFDataRef *exportedData); + OSStatus SecAccessCreate(CFStringRef descriptor, CFArrayRef trustedlist, SecAccessRef *accessRef); + OSStatus SecKeyCreatePair(SecKeychainRef keychainRef, CSSM_ALGORITHMS algorithm, uint32_t keySizeInBits, + CSSM_CC_HANDLE contextHandle, CSSM_KEYUSE publicKeyUsage, uint32_t publicKeyAttr, + CSSM_KEYUSE privateKeyUsage, uint32_t privateKeyAttr, SecAccessRef initialAccess, + SecKeyRef* publicKeyRef, SecKeyRef* privateKeyRef); + OSStatus SecKeychainItemDelete(SecKeyRef itemRef); + + typedef OSStatus (*SSLReadFunc)(SSLConnectionRef connection, char *data, size_t *dataLength); + typedef OSStatus (*SSLWriteFunc)(SSLConnectionRef connection, const char *data, size_t *dataLength); + OSStatus SSLSetIOFuncs(SSLContextRef context, SSLReadFunc readFunc, SSLWriteFunc writeFunc); + + OSStatus SSLSetPeerID(SSLContextRef context, const char *peerID, size_t peerIDLen); + + OSStatus SSLSetConnection(SSLContextRef context, SSLConnectionRef connection); + OSStatus SSLSetPeerDomainName(SSLContextRef context, const char *peerName, size_t peerNameLen); + OSStatus SSLHandshake(SSLContextRef context); + OSStatus SSLGetBufferedReadSize(SSLContextRef context, size_t *bufSize); + OSStatus SSLRead(SSLContextRef context, char *data, size_t dataLength, size_t *processed); + OSStatus SSLWrite(SSLContextRef context, const char *data, size_t dataLength, size_t *processed); + OSStatus SSLClose(SSLContextRef context); + + OSStatus SSLGetNumberSupportedCiphers(SSLContextRef context, size_t *numCiphers); + OSStatus SSLGetSupportedCiphers(SSLContextRef context, SSLCipherSuite *ciphers, size_t *numCiphers); + OSStatus SSLSetEnabledCiphers(SSLContextRef context, const SSLCipherSuite *ciphers, size_t numCiphers); + OSStatus SSLGetNumberEnabledCiphers(SSLContextRef context, size_t *numCiphers); + OSStatus SSLGetEnabledCiphers(SSLContextRef context, SSLCipherSuite *ciphers, size_t *numCiphers); + + OSStatus SSLGetNegotiatedCipher(SSLContextRef context, SSLCipherSuite *cipherSuite); + OSStatus SSLGetNegotiatedProtocolVersion(SSLContextRef context, SSLProtocol *protocol); + + OSStatus SSLCopyPeerTrust(SSLContextRef context, SecTrustRef *trust); + OSStatus SecTrustGetCssmResultCode(SecTrustRef trust, OSStatus *resultCode); + CFIndex SecTrustGetCertificateCount(SecTrustRef trust); + SecCertificateRef SecTrustGetCertificateAtIndex(SecTrustRef trust, CFIndex ix); + OSStatus SecTrustSetAnchorCertificates(SecTrustRef trust, CFArrayRef anchorCertificates); + OSStatus SecTrustSetAnchorCertificatesOnly(SecTrustRef trust, Boolean anchorCertificatesOnly); + OSStatus SecTrustSetPolicies(SecTrustRef trust, CFArrayRef policies); + SecPolicyRef SecPolicyCreateSSL(Boolean server, CFStringRef hostname); + OSStatus SecPolicySearchCreate(CSSM_CERT_TYPE certType, const CSSM_OID *policyOID, const CSSM_DATA *value, + SecPolicySearchRef *searchRef); + OSStatus SecPolicySearchCopyNext(SecPolicySearchRef searchRef, SecPolicyRef *policyRef); + OSStatus SecPolicySetValue(SecPolicyRef policyRef, const CSSM_DATA *value); + OSStatus SecTrustEvaluate(SecTrustRef trust, SecTrustResultType *result); + + extern SecRandomRef kSecRandomDefault; + + extern CFStringRef kSecPaddingKey; + extern CFStringRef kSecPaddingPKCS7Key; + extern CFStringRef kSecPaddingPKCS5Key; + extern CFStringRef kSecPaddingPKCS1Key; + extern CFStringRef kSecPaddingOAEPKey; + extern CFStringRef kSecPaddingNoneKey; + extern CFStringRef kSecModeCBCKey; + extern CFStringRef kSecTransformInputAttributeName; + extern CFStringRef kSecDigestTypeAttribute; + extern CFStringRef kSecDigestLengthAttribute; + extern CFStringRef kSecIVKey; + + extern CFStringRef kSecAttrIsExtractable; + + extern CFStringRef kSecDigestSHA1; + extern CFStringRef kSecDigestSHA2; + extern CFStringRef kSecDigestMD5; + + extern CFStringRef kSecAttrKeyType; + + extern CFTypeRef kSecAttrKeyTypeRSA; + extern CFTypeRef kSecAttrKeyTypeDSA; + extern CFTypeRef kSecAttrKeyTypeECDSA; + + extern CFStringRef kSecAttrKeySizeInBits; + extern CFStringRef kSecAttrLabel; + + extern CFTypeRef kSecAttrCanSign; + extern CFTypeRef kSecAttrCanVerify; + + extern CFTypeRef kSecAttrKeyTypeAES; + extern CFTypeRef kSecAttrKeyTypeRC4; + extern CFTypeRef kSecAttrKeyTypeRC2; + extern CFTypeRef kSecAttrKeyType3DES; + extern CFTypeRef kSecAttrKeyTypeDES; +""") + +if version_info < (10, 8): + ffi.cdef(""" + OSStatus SSLNewContext(Boolean isServer, SSLContextRef *contextPtr); + OSStatus SSLDisposeContext(SSLContextRef context); + + OSStatus SSLSetEnableCertVerify(SSLContextRef context, Boolean enableVerify); + + OSStatus SSLSetProtocolVersionEnabled(SSLContextRef context, SSLProtocol protocol, Boolean enable); + """) +else: + ffi.cdef(""" + typedef uint32_t SSLProtocolSide; + typedef uint32_t SSLConnectionType; + typedef uint32_t SSLSessionOption; + + SSLContextRef SSLCreateContext(CFAllocatorRef alloc, SSLProtocolSide protocolSide, + SSLConnectionType connectionType); + + OSStatus SSLSetSessionOption(SSLContextRef context, SSLSessionOption option, Boolean value); + + OSStatus SSLSetProtocolVersionMin(SSLContextRef context, SSLProtocol minVersion); + OSStatus SSLSetProtocolVersionMax(SSLContextRef context, SSLProtocol maxVersion); + """) + +security_path = '/System/Library/Frameworks/Security.framework/Security' + +Security = ffi.dlopen(security_path) +register_ffi(Security, ffi) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_mac/_security_ctypes.py b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_mac/_security_ctypes.py new file mode 100644 index 00000000..ee1be002 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_mac/_security_ctypes.py @@ -0,0 +1,628 @@ +# coding: utf-8 +from __future__ import unicode_literals, division, absolute_import, print_function + +import platform +from ctypes import c_void_p, c_int32, c_char_p, c_size_t, c_byte, c_int, c_uint32, c_uint64, c_ulong, c_long, c_bool +from ctypes import CDLL, POINTER, CFUNCTYPE, Structure + +from .._ffi import FFIEngineError + + +__all__ = [ + 'Security', + 'version', + 'version_info', +] + + +version = platform.mac_ver()[0] +version_info = tuple(map(int, platform.mac_ver()[0].split('.'))) + +if version_info < (10, 7): + raise OSError('Only OS X 10.7 and newer are supported, not %s.%s' % (version_info[0], version_info[1])) + +security_path = '/System/Library/Frameworks/Security.framework/Security' + +Security = CDLL(security_path, use_errno=True) + +Boolean = c_bool +CFIndex = c_long +CFData = c_void_p +CFString = c_void_p +CFArray = c_void_p +CFDictionary = c_void_p +CFError = c_void_p +CFType = c_void_p +CFTypeID = c_ulong + +CFTypeRef = POINTER(CFType) +CFAllocatorRef = c_void_p + +OSStatus = c_int32 + +CFDataRef = POINTER(CFData) +CFStringRef = POINTER(CFString) +CFArrayRef = POINTER(CFArray) +CFDictionaryRef = POINTER(CFDictionary) +CFErrorRef = POINTER(CFError) + +SecKeyRef = POINTER(c_void_p) +SecCertificateRef = POINTER(c_void_p) +SecTransformRef = POINTER(c_void_p) +SecRandomRef = c_void_p +SecTrustSettingsDomain = c_uint32 +SecItemImportExportFlags = c_uint32 +SecKeyImportExportFlags = c_uint32 +SecExternalFormat = c_uint32 +SecExternalItemType = c_uint32 +SecPadding = c_uint32 +SSLProtocol = c_uint32 +SSLCipherSuite = c_uint32 +SecPolicyRef = POINTER(c_void_p) +CSSM_CC_HANDLE = c_uint64 +CSSM_ALGORITHMS = c_uint32 +CSSM_KEYUSE = c_uint32 +SecAccessRef = POINTER(c_void_p) +SecKeychainRef = POINTER(c_void_p) +SSLContextRef = POINTER(c_void_p) +SecTrustRef = POINTER(c_void_p) +SSLConnectionRef = c_uint32 +SecTrustResultType = c_uint32 +SecTrustOptionFlags = c_uint32 +SecPolicySearchRef = c_void_p +CSSM_CERT_TYPE = c_uint32 + + +class CSSM_DATA(Structure): # noqa + _fields_ = [ + ('Length', c_uint32), + ('Data', c_char_p) + ] + + +CSSM_OID = CSSM_DATA + + +class CSSM_APPLE_TP_OCSP_OPTIONS(Structure): # noqa + _fields_ = [ + ('Version', c_uint32), + ('Flags', c_uint32), + ('LocalResponder', POINTER(CSSM_DATA)), + ('LocalResponderCert', POINTER(CSSM_DATA)), + ] + + +class CSSM_APPLE_TP_CRL_OPTIONS(Structure): # noqa + _fields_ = [ + ('Version', c_uint32), + ('CrlFlags', c_uint32), + ('crlStore', c_void_p), + ] + + +class SecItemImportExportKeyParameters(Structure): + _fields_ = [ + ('version', c_uint32), + ('flags', SecKeyImportExportFlags), + ('passphrase', CFTypeRef), + ('alertTitle', CFStringRef), + ('alertPrompt', CFStringRef), + ('accessRef', SecAccessRef), + ('keyUsage', CFArrayRef), + ('keyAttributes', CFArrayRef), + ] + + +try: + Security.SecKeychainCreate.argtypes = [ + c_char_p, + c_uint32, + c_void_p, + Boolean, + SecAccessRef, + POINTER(SecKeychainRef) + ] + Security.SecKeychainCreate.restype = OSStatus + + Security.SecKeychainDelete.argtypes = [SecKeychainRef] + Security.SecKeychainDelete.restype = OSStatus + + Security.SecRandomCopyBytes.argtypes = [ + SecRandomRef, + c_size_t, + c_char_p + ] + Security.SecRandomCopyBytes.restype = c_int + + Security.SecKeyCreateFromData.argtypes = [ + CFDictionaryRef, + CFDataRef, + POINTER(CFErrorRef) + ] + Security.SecKeyCreateFromData.restype = SecKeyRef + + Security.SecEncryptTransformCreate.argtypes = [ + SecKeyRef, + POINTER(CFErrorRef) + ] + Security.SecEncryptTransformCreate.restype = SecTransformRef + + Security.SecDecryptTransformCreate.argtypes = [ + SecKeyRef, + POINTER(CFErrorRef) + ] + Security.SecDecryptTransformCreate.restype = SecTransformRef + + Security.SecTransformSetAttribute.argtypes = [ + SecTransformRef, + CFStringRef, + CFTypeRef, + POINTER(CFErrorRef) + ] + Security.SecTransformSetAttribute.restype = Boolean + + Security.SecTransformExecute.argtypes = [ + SecTransformRef, + POINTER(CFErrorRef) + ] + Security.SecTransformExecute.restype = CFTypeRef + + Security.SecVerifyTransformCreate.argtypes = [ + SecKeyRef, + CFDataRef, + POINTER(CFErrorRef) + ] + Security.SecVerifyTransformCreate.restype = SecTransformRef + + Security.SecSignTransformCreate.argtypes = [ + SecKeyRef, + POINTER(CFErrorRef) + ] + Security.SecSignTransformCreate.restype = SecTransformRef + + Security.SecCertificateCreateWithData.argtypes = [ + CFAllocatorRef, + CFDataRef + ] + Security.SecCertificateCreateWithData.restype = SecCertificateRef + + Security.SecCertificateCopyPublicKey.argtypes = [ + SecCertificateRef, + POINTER(SecKeyRef) + ] + Security.SecCertificateCopyPublicKey.restype = OSStatus + + Security.SecCopyErrorMessageString.argtypes = [ + OSStatus, + c_void_p + ] + Security.SecCopyErrorMessageString.restype = CFStringRef + + Security.SecTrustCopyAnchorCertificates.argtypes = [ + POINTER(CFArrayRef) + ] + Security.SecTrustCopyAnchorCertificates.restype = OSStatus + + Security.SecCertificateCopyData.argtypes = [ + SecCertificateRef + ] + Security.SecCertificateCopyData.restype = CFDataRef + + Security.SecTrustSettingsCopyCertificates.argtypes = [ + SecTrustSettingsDomain, + POINTER(CFArrayRef) + ] + Security.SecTrustSettingsCopyCertificates.restype = OSStatus + + Security.SecTrustSettingsCopyTrustSettings.argtypes = [ + SecCertificateRef, + SecTrustSettingsDomain, + POINTER(CFArrayRef) + ] + Security.SecTrustSettingsCopyTrustSettings.restype = OSStatus + + Security.SecPolicyCopyProperties.argtypes = [ + SecPolicyRef + ] + Security.SecPolicyCopyProperties.restype = CFDictionaryRef + + Security.SecPolicyGetTypeID.argtypes = [] + Security.SecPolicyGetTypeID.restype = CFTypeID + + Security.SecKeyEncrypt.argtypes = [ + SecKeyRef, + SecPadding, + c_char_p, + c_size_t, + c_char_p, + POINTER(c_size_t) + ] + Security.SecKeyEncrypt.restype = OSStatus + + Security.SecKeyDecrypt.argtypes = [ + SecKeyRef, + SecPadding, + c_char_p, + c_size_t, + c_char_p, + POINTER(c_size_t) + ] + Security.SecKeyDecrypt.restype = OSStatus + + Security.SecKeyRawSign.argtypes = [ + SecKeyRef, + SecPadding, + c_char_p, + c_size_t, + c_char_p, + POINTER(c_size_t) + ] + Security.SecKeyRawSign.restype = OSStatus + + Security.SecKeyRawVerify.argtypes = [ + SecKeyRef, + SecPadding, + c_char_p, + c_size_t, + c_char_p, + c_size_t + ] + Security.SecKeyRawVerify.restype = OSStatus + + Security.SecAccessCreate.argtypes = [ + CFStringRef, + CFArrayRef, + POINTER(SecAccessRef) + ] + Security.SecAccessCreate.restype = OSStatus + + Security.SecKeyCreatePair.argtypes = [ + SecKeychainRef, + CSSM_ALGORITHMS, + c_uint32, + CSSM_CC_HANDLE, + CSSM_KEYUSE, + c_uint32, + CSSM_KEYUSE, + c_uint32, + SecAccessRef, + POINTER(SecKeyRef), + POINTER(SecKeyRef) + ] + Security.SecKeyCreatePair.restype = OSStatus + + Security.SecItemImport.argtypes = [ + CFDataRef, + CFStringRef, + POINTER(SecExternalFormat), + POINTER(SecExternalItemType), + SecItemImportExportFlags, + POINTER(SecItemImportExportKeyParameters), + SecKeychainRef, + POINTER(CFArrayRef) + ] + Security.SecItemImport.restype = OSStatus + + Security.SecItemExport.argtypes = [ + CFTypeRef, + SecExternalFormat, + SecItemImportExportFlags, + POINTER(SecItemImportExportKeyParameters), + POINTER(CFDataRef) + ] + Security.SecItemExport.restype = OSStatus + + Security.SecKeychainItemDelete.argtypes = [ + SecKeyRef + ] + Security.SecKeychainItemDelete.restype = OSStatus + + SSLReadFunc = CFUNCTYPE(OSStatus, SSLConnectionRef, POINTER(c_byte), POINTER(c_size_t)) + SSLWriteFunc = CFUNCTYPE(OSStatus, SSLConnectionRef, POINTER(c_byte), POINTER(c_size_t)) + + Security.SSLSetIOFuncs.argtypes = [ + SSLContextRef, + SSLReadFunc, + SSLWriteFunc + ] + Security.SSLSetIOFuncs.restype = OSStatus + + Security.SSLSetPeerID.argtypes = [ + SSLContextRef, + c_char_p, + c_size_t + ] + Security.SSLSetPeerID.restype = OSStatus + + Security.SSLSetCertificateAuthorities.argtypes = [ + SSLContextRef, + CFTypeRef, + Boolean + ] + Security.SSLSetCertificateAuthorities.restype = OSStatus + + Security.SecTrustSetPolicies.argtypes = [ + SecTrustRef, + CFArrayRef + ] + Security.SecTrustSetPolicies.restype = OSStatus + + Security.SecPolicyCreateSSL.argtypes = [ + Boolean, + CFStringRef + ] + Security.SecPolicyCreateSSL.restype = SecPolicyRef + + Security.SecPolicySearchCreate.argtypes = [ + CSSM_CERT_TYPE, + POINTER(CSSM_OID), + POINTER(CSSM_DATA), + POINTER(SecPolicySearchRef) + ] + Security.SecPolicySearchCreate.restype = OSStatus + + Security.SecPolicySearchCopyNext.argtypes = [ + SecPolicySearchRef, + POINTER(SecPolicyRef) + ] + Security.SecPolicySearchCopyNext.restype = OSStatus + + Security.SecPolicySetValue.argtypes = [ + SecPolicyRef, + POINTER(CSSM_DATA) + ] + Security.SecPolicySetValue.restype = OSStatus + + Security.SSLSetConnection.argtypes = [ + SSLContextRef, + SSLConnectionRef + ] + Security.SSLSetConnection.restype = OSStatus + + Security.SSLSetPeerDomainName.argtypes = [ + SSLContextRef, + c_char_p, + c_size_t + ] + Security.SSLSetPeerDomainName.restype = OSStatus + + Security.SSLHandshake.argtypes = [ + SSLContextRef + ] + Security.SSLHandshake.restype = OSStatus + + Security.SSLGetBufferedReadSize.argtypes = [ + SSLContextRef, + POINTER(c_size_t) + ] + Security.SSLGetBufferedReadSize.restype = OSStatus + + Security.SSLRead.argtypes = [ + SSLContextRef, + c_char_p, + c_size_t, + POINTER(c_size_t) + ] + Security.SSLRead.restype = OSStatus + + Security.SSLWrite.argtypes = [ + SSLContextRef, + c_char_p, + c_size_t, + POINTER(c_size_t) + ] + Security.SSLWrite.restype = OSStatus + + Security.SSLClose.argtypes = [ + SSLContextRef + ] + Security.SSLClose.restype = OSStatus + + Security.SSLGetNumberSupportedCiphers.argtypes = [ + SSLContextRef, + POINTER(c_size_t) + ] + Security.SSLGetNumberSupportedCiphers.restype = OSStatus + + Security.SSLGetSupportedCiphers.argtypes = [ + SSLContextRef, + POINTER(SSLCipherSuite), + POINTER(c_size_t) + ] + Security.SSLGetSupportedCiphers.restype = OSStatus + + Security.SSLSetEnabledCiphers.argtypes = [ + SSLContextRef, + POINTER(SSLCipherSuite), + c_size_t + ] + Security.SSLSetEnabledCiphers.restype = OSStatus + + Security.SSLGetNumberEnabledCiphers.argtype = [ + SSLContextRef, + POINTER(c_size_t) + ] + Security.SSLGetNumberEnabledCiphers.restype = OSStatus + + Security.SSLGetEnabledCiphers.argtypes = [ + SSLContextRef, + POINTER(SSLCipherSuite), + POINTER(c_size_t) + ] + Security.SSLGetEnabledCiphers.restype = OSStatus + + Security.SSLGetNegotiatedCipher.argtypes = [ + SSLContextRef, + POINTER(SSLCipherSuite) + ] + Security.SSLGetNegotiatedCipher.restype = OSStatus + + Security.SSLGetNegotiatedProtocolVersion.argtypes = [ + SSLContextRef, + POINTER(SSLProtocol) + ] + Security.SSLGetNegotiatedProtocolVersion.restype = OSStatus + + Security.SSLCopyPeerTrust.argtypes = [ + SSLContextRef, + POINTER(SecTrustRef) + ] + Security.SSLCopyPeerTrust.restype = OSStatus + + Security.SecTrustGetCssmResultCode.argtypes = [ + SecTrustRef, + POINTER(OSStatus) + ] + Security.SecTrustGetCssmResultCode.restype = OSStatus + + Security.SecTrustGetCertificateCount.argtypes = [ + SecTrustRef + ] + Security.SecTrustGetCertificateCount.restype = CFIndex + + Security.SecTrustGetCertificateAtIndex.argtypes = [ + SecTrustRef, + CFIndex + ] + Security.SecTrustGetCertificateAtIndex.restype = SecCertificateRef + + Security.SecTrustSetAnchorCertificates.argtypes = [ + SecTrustRef, + CFArrayRef + ] + Security.SecTrustSetAnchorCertificates.restype = OSStatus + + Security.SecTrustSetAnchorCertificatesOnly.argstypes = [ + SecTrustRef, + Boolean + ] + Security.SecTrustSetAnchorCertificatesOnly.restype = OSStatus + + Security.SecTrustEvaluate.argtypes = [ + SecTrustRef, + POINTER(SecTrustResultType) + ] + Security.SecTrustEvaluate.restype = OSStatus + + if version_info < (10, 8): + Security.SSLNewContext.argtypes = [ + Boolean, + POINTER(SSLContextRef) + ] + Security.SSLNewContext.restype = OSStatus + + Security.SSLDisposeContext.argtypes = [ + SSLContextRef + ] + Security.SSLDisposeContext.restype = OSStatus + + Security.SSLSetEnableCertVerify.argtypes = [ + SSLContextRef, + Boolean + ] + Security.SSLSetEnableCertVerify.restype = OSStatus + + Security.SSLSetProtocolVersionEnabled.argtypes = [ + SSLContextRef, + SSLProtocol, + Boolean + ] + Security.SSLSetProtocolVersionEnabled.restype = OSStatus + + else: + SSLProtocolSide = c_uint32 + SSLConnectionType = c_uint32 + SSLSessionOption = c_uint32 + + Security.SSLCreateContext.argtypes = [ + CFAllocatorRef, + SSLProtocolSide, + SSLConnectionType + ] + Security.SSLCreateContext.restype = SSLContextRef + + Security.SSLSetSessionOption.argtypes = [ + SSLContextRef, + SSLSessionOption, + Boolean + ] + Security.SSLSetSessionOption.restype = OSStatus + + Security.SSLSetProtocolVersionMin.argtypes = [ + SSLContextRef, + SSLProtocol + ] + Security.SSLSetProtocolVersionMin.restype = OSStatus + + Security.SSLSetProtocolVersionMax.argtypes = [ + SSLContextRef, + SSLProtocol + ] + Security.SSLSetProtocolVersionMax.restype = OSStatus + + setattr(Security, 'SSLReadFunc', SSLReadFunc) + setattr(Security, 'SSLWriteFunc', SSLWriteFunc) + setattr(Security, 'SSLContextRef', SSLContextRef) + setattr(Security, 'SSLProtocol', SSLProtocol) + setattr(Security, 'SSLCipherSuite', SSLCipherSuite) + setattr(Security, 'SecTrustRef', SecTrustRef) + setattr(Security, 'SecTrustResultType', SecTrustResultType) + setattr(Security, 'OSStatus', OSStatus) + + setattr(Security, 'SecAccessRef', SecAccessRef) + setattr(Security, 'SecKeychainRef', SecKeychainRef) + setattr(Security, 'SecKeyRef', SecKeyRef) + + setattr(Security, 'SecPolicySearchRef', SecPolicySearchRef) + setattr(Security, 'SecPolicyRef', SecPolicyRef) + + setattr(Security, 'CSSM_DATA', CSSM_DATA) + setattr(Security, 'CSSM_OID', CSSM_OID) + setattr(Security, 'CSSM_APPLE_TP_OCSP_OPTIONS', CSSM_APPLE_TP_OCSP_OPTIONS) + setattr(Security, 'CSSM_APPLE_TP_CRL_OPTIONS', CSSM_APPLE_TP_CRL_OPTIONS) + setattr(Security, 'SecItemImportExportKeyParameters', SecItemImportExportKeyParameters) + + setattr(Security, 'kSecRandomDefault', SecRandomRef.in_dll(Security, 'kSecRandomDefault')) + + setattr(Security, 'kSecPaddingKey', CFStringRef.in_dll(Security, 'kSecPaddingKey')) + setattr(Security, 'kSecPaddingPKCS7Key', CFStringRef.in_dll(Security, 'kSecPaddingPKCS7Key')) + setattr(Security, 'kSecPaddingPKCS5Key', CFStringRef.in_dll(Security, 'kSecPaddingPKCS5Key')) + setattr(Security, 'kSecPaddingPKCS1Key', CFStringRef.in_dll(Security, 'kSecPaddingPKCS1Key')) + setattr(Security, 'kSecPaddingOAEPKey', CFStringRef.in_dll(Security, 'kSecPaddingOAEPKey')) + setattr(Security, 'kSecPaddingNoneKey', CFStringRef.in_dll(Security, 'kSecPaddingNoneKey')) + setattr(Security, 'kSecModeCBCKey', CFStringRef.in_dll(Security, 'kSecModeCBCKey')) + setattr( + Security, + 'kSecTransformInputAttributeName', + CFStringRef.in_dll(Security, 'kSecTransformInputAttributeName') + ) + setattr(Security, 'kSecDigestTypeAttribute', CFStringRef.in_dll(Security, 'kSecDigestTypeAttribute')) + setattr(Security, 'kSecDigestLengthAttribute', CFStringRef.in_dll(Security, 'kSecDigestLengthAttribute')) + setattr(Security, 'kSecIVKey', CFStringRef.in_dll(Security, 'kSecIVKey')) + + setattr(Security, 'kSecAttrIsExtractable', CFStringRef.in_dll(Security, 'kSecAttrIsExtractable')) + + setattr(Security, 'kSecDigestSHA1', CFStringRef.in_dll(Security, 'kSecDigestSHA1')) + setattr(Security, 'kSecDigestSHA2', CFStringRef.in_dll(Security, 'kSecDigestSHA2')) + setattr(Security, 'kSecDigestMD5', CFStringRef.in_dll(Security, 'kSecDigestMD5')) + + setattr(Security, 'kSecAttrKeyType', CFStringRef.in_dll(Security, 'kSecAttrKeyType')) + + setattr(Security, 'kSecAttrKeyTypeRSA', CFTypeRef.in_dll(Security, 'kSecAttrKeyTypeRSA')) + setattr(Security, 'kSecAttrKeyTypeDSA', CFTypeRef.in_dll(Security, 'kSecAttrKeyTypeDSA')) + setattr(Security, 'kSecAttrKeyTypeECDSA', CFTypeRef.in_dll(Security, 'kSecAttrKeyTypeECDSA')) + + setattr(Security, 'kSecAttrKeySizeInBits', CFStringRef.in_dll(Security, 'kSecAttrKeySizeInBits')) + setattr(Security, 'kSecAttrLabel', CFStringRef.in_dll(Security, 'kSecAttrLabel')) + + setattr(Security, 'kSecAttrCanSign', CFTypeRef.in_dll(Security, 'kSecAttrCanSign')) + setattr(Security, 'kSecAttrCanVerify', CFTypeRef.in_dll(Security, 'kSecAttrCanVerify')) + + setattr(Security, 'kSecAttrKeyTypeAES', CFTypeRef.in_dll(Security, 'kSecAttrKeyTypeAES')) + setattr(Security, 'kSecAttrKeyTypeRC4', CFTypeRef.in_dll(Security, 'kSecAttrKeyTypeRC4')) + setattr(Security, 'kSecAttrKeyTypeRC2', CFTypeRef.in_dll(Security, 'kSecAttrKeyTypeRC2')) + setattr(Security, 'kSecAttrKeyType3DES', CFTypeRef.in_dll(Security, 'kSecAttrKeyType3DES')) + setattr(Security, 'kSecAttrKeyTypeDES', CFTypeRef.in_dll(Security, 'kSecAttrKeyTypeDES')) + +except (AttributeError): + raise FFIEngineError('Error initializing ctypes') diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_mac/asymmetric.py b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_mac/asymmetric.py new file mode 100644 index 00000000..1d30aa19 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_mac/asymmetric.py @@ -0,0 +1,1983 @@ +# coding: utf-8 +from __future__ import unicode_literals, division, absolute_import, print_function +from base64 import b32encode +import os +import shutil +import tempfile + +from .._asn1 import ( + Certificate as Asn1Certificate, + ECDomainParameters, + Integer, + KeyExchangeAlgorithm, + Null, + PrivateKeyInfo, + PublicKeyAlgorithm, + PublicKeyInfo, + RSAPublicKey, +) +from .._asymmetric import ( + _CertificateBase, + _fingerprint, + _parse_pkcs12, + _PrivateKeyBase, + _PublicKeyBase, + _unwrap_private_key_info, + parse_certificate, + parse_private, + parse_public, +) +from .._errors import pretty_message +from .._ffi import new, unwrap, bytes_from_buffer, buffer_from_bytes, deref, null, is_null, pointer_set +from ._security import Security, SecurityConst, handle_sec_error, osx_version_info +from ._core_foundation import CoreFoundation, CFHelpers, handle_cf_error +from .util import rand_bytes +from ..errors import AsymmetricKeyError, IncompleteAsymmetricKeyError, SignatureError +from .._pkcs1 import add_pss_padding, verify_pss_padding, remove_pkcs1v15_encryption_padding +from .._types import type_name, str_cls, byte_cls, int_types + + +__all__ = [ + 'Certificate', + 'dsa_sign', + 'dsa_verify', + 'ecdsa_sign', + 'ecdsa_verify', + 'generate_pair', + 'load_certificate', + 'load_pkcs12', + 'load_private_key', + 'load_public_key', + 'parse_pkcs12', + 'PrivateKey', + 'PublicKey', + 'rsa_oaep_decrypt', + 'rsa_oaep_encrypt', + 'rsa_pkcs1v15_decrypt', + 'rsa_pkcs1v15_encrypt', + 'rsa_pkcs1v15_sign', + 'rsa_pkcs1v15_verify', + 'rsa_pss_sign', + 'rsa_pss_verify', +] + + +class PrivateKey(_PrivateKeyBase): + """ + Container for the OS crypto library representation of a private key + """ + + sec_key_ref = None + _public_key = None + + # A reference to the library used in the destructor to make sure it hasn't + # been garbage collected by the time this object is garbage collected + _lib = None + + def __init__(self, sec_key_ref, asn1): + """ + :param sec_key_ref: + A Security framework SecKeyRef value from loading/importing the + key + + :param asn1: + An asn1crypto.keys.PrivateKeyInfo object + """ + + self.sec_key_ref = sec_key_ref + self.asn1 = asn1 + self._lib = CoreFoundation + + @property + def public_key(self): + """ + :return: + A PublicKey object corresponding to this private key. + """ + + if self._public_key is None: + cf_data_private = None + try: + # We export here so that Security.framework will fill in the EC + # public key for us, instead of us having to compute it + cf_data_private_pointer = new(CoreFoundation, 'CFDataRef *') + result = Security.SecItemExport(self.sec_key_ref, 0, 0, null(), cf_data_private_pointer) + handle_sec_error(result) + cf_data_private = unwrap(cf_data_private_pointer) + private_key_bytes = CFHelpers.cf_data_to_bytes(cf_data_private) + + key = parse_private(private_key_bytes) + + if key.algorithm == 'rsa': + public_asn1 = PublicKeyInfo({ + 'algorithm': PublicKeyAlgorithm({ + 'algorithm': 'rsa', + 'parameters': Null() + }), + 'public_key': RSAPublicKey({ + 'modulus': key['private_key'].parsed['modulus'], + 'public_exponent': key['private_key'].parsed['public_exponent'], + }) + }) + + elif key.algorithm == 'dsa': + params = key['private_key_algorithm']['parameters'] + public_asn1 = PublicKeyInfo({ + 'algorithm': PublicKeyAlgorithm({ + 'algorithm': 'dsa', + 'parameters': params.copy() + }), + 'public_key': Integer(pow( + params['g'].native, + key['private_key'].parsed.native, + params['p'].native + )) + }) + + elif key.algorithm == 'ec': + public_asn1 = PublicKeyInfo({ + 'algorithm': PublicKeyAlgorithm({ + 'algorithm': 'ec', + 'parameters': ECDomainParameters( + name='named', + value=self.curve + ) + }), + 'public_key': key['private_key'].parsed['public_key'], + }) + + finally: + if cf_data_private: + CoreFoundation.CFRelease(cf_data_private) + + self._public_key = _load_key(public_asn1) + + return self._public_key + + @property + def fingerprint(self): + """ + Creates a fingerprint that can be compared with a public key to see if + the two form a pair. + + This fingerprint is not compatible with fingerprints generated by any + other software. + + :return: + A byte string that is a sha256 hash of selected components (based + on the key type) + """ + + if self._fingerprint is None: + self._fingerprint = _fingerprint(self.asn1, load_private_key) + return self._fingerprint + + def __del__(self): + if self.sec_key_ref: + self._lib.CFRelease(self.sec_key_ref) + self._lib = None + self.sec_key_ref = None + + +class PublicKey(_PublicKeyBase): + """ + Container for the OS crypto library representation of a public key + """ + + sec_key_ref = None + + # A reference to the library used in the destructor to make sure it hasn't + # been garbage collected by the time this object is garbage collected + _lib = None + + def __init__(self, sec_key_ref, asn1): + """ + :param sec_key_ref: + A Security framework SecKeyRef value from loading/importing the + key + + :param asn1: + An asn1crypto.keys.PublicKeyInfo object + """ + + self.sec_key_ref = sec_key_ref + self.asn1 = asn1 + self._lib = CoreFoundation + + def __del__(self): + if self.sec_key_ref: + self._lib.CFRelease(self.sec_key_ref) + self._lib = None + self.sec_key_ref = None + + +class Certificate(_CertificateBase): + """ + Container for the OS crypto library representation of a certificate + """ + + sec_certificate_ref = None + _public_key = None + _self_signed = None + + def __init__(self, sec_certificate_ref, asn1): + """ + :param sec_certificate_ref: + A Security framework SecCertificateRef value from loading/importing + the certificate + + :param asn1: + An asn1crypto.x509.Certificate object + """ + + self.sec_certificate_ref = sec_certificate_ref + self.asn1 = asn1 + + @property + def sec_key_ref(self): + """ + :return: + The SecKeyRef of the public key + """ + + return self.public_key.sec_key_ref + + @property + def public_key(self): + """ + :return: + The PublicKey object for the public key this certificate contains + """ + + if not self._public_key and self.sec_certificate_ref: + sec_public_key_ref_pointer = new(Security, 'SecKeyRef *') + res = Security.SecCertificateCopyPublicKey(self.sec_certificate_ref, sec_public_key_ref_pointer) + handle_sec_error(res) + sec_public_key_ref = unwrap(sec_public_key_ref_pointer) + self._public_key = PublicKey(sec_public_key_ref, self.asn1['tbs_certificate']['subject_public_key_info']) + + return self._public_key + + @property + def self_signed(self): + """ + :return: + A boolean - if the certificate is self-signed + """ + + if self._self_signed is None: + self._self_signed = False + if self.asn1.self_signed in set(['yes', 'maybe']): + + signature_algo = self.asn1['signature_algorithm'].signature_algo + hash_algo = self.asn1['signature_algorithm'].hash_algo + + if signature_algo == 'rsassa_pkcs1v15': + verify_func = rsa_pkcs1v15_verify + elif signature_algo == 'dsa': + verify_func = dsa_verify + elif signature_algo == 'ecdsa': + verify_func = ecdsa_verify + else: + raise OSError(pretty_message( + ''' + Unable to verify the signature of the certificate since + it uses the unsupported algorithm %s + ''', + signature_algo + )) + + try: + verify_func( + self.public_key, + self.asn1['signature_value'].native, + self.asn1['tbs_certificate'].dump(), + hash_algo + ) + self._self_signed = True + except (SignatureError): + pass + + return self._self_signed + + def __del__(self): + if self._public_key: + self._public_key.__del__() + self._public_key = None + + if self.sec_certificate_ref: + CoreFoundation.CFRelease(self.sec_certificate_ref) + self.sec_certificate_ref = None + + +def generate_pair(algorithm, bit_size=None, curve=None): + """ + Generates a public/private key pair + + :param algorithm: + The key algorithm - "rsa", "dsa" or "ec" + + :param bit_size: + An integer - used for "rsa" and "dsa". For "rsa" the value maye be 1024, + 2048, 3072 or 4096. For "dsa" the value may be 1024. + + :param curve: + A unicode string - used for "ec" keys. Valid values include "secp256r1", + "secp384r1" and "secp521r1". + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + + :return: + A 2-element tuple of (PublicKey, PrivateKey). The contents of each key + may be saved by calling .asn1.dump(). + """ + + if algorithm not in set(['rsa', 'dsa', 'ec']): + raise ValueError(pretty_message( + ''' + algorithm must be one of "rsa", "dsa", "ec", not %s + ''', + repr(algorithm) + )) + + if algorithm == 'rsa': + if bit_size not in set([1024, 2048, 3072, 4096]): + raise ValueError(pretty_message( + ''' + bit_size must be one of 1024, 2048, 3072, 4096, not %s + ''', + repr(bit_size) + )) + + elif algorithm == 'dsa': + if bit_size not in set([1024]): + raise ValueError(pretty_message( + ''' + bit_size must be 1024, not %s + ''', + repr(bit_size) + )) + + elif algorithm == 'ec': + if curve not in set(['secp256r1', 'secp384r1', 'secp521r1']): + raise ValueError(pretty_message( + ''' + curve must be one of "secp256r1", "secp384r1", "secp521r1", not %s + ''', + repr(curve) + )) + + cf_dict = None + public_key_ref = None + private_key_ref = None + cf_data_public = None + cf_data_private = None + cf_string = None + sec_access_ref = None + sec_keychain_ref = None + temp_dir = None + + try: + alg_id = { + 'dsa': SecurityConst.CSSM_ALGID_DSA, + 'ec': SecurityConst.CSSM_ALGID_ECDSA, + 'rsa': SecurityConst.CSSM_ALGID_RSA, + }[algorithm] + + if algorithm == 'ec': + key_size = { + 'secp256r1': 256, + 'secp384r1': 384, + 'secp521r1': 521, + }[curve] + else: + key_size = bit_size + + private_key_pointer = new(Security, 'SecKeyRef *') + public_key_pointer = new(Security, 'SecKeyRef *') + + cf_string = CFHelpers.cf_string_from_unicode("Temporary oscrypto key") + + # We used to use SecKeyGeneratePair() for everything but DSA keys, but due to changes + # in macOS security, we can't reliably access the default keychain, and instead + # get an "OSError: User interaction is not allowed." result. Because of this we now + # use SecKeyCreatePair() for everything, but we even use a throw-away keychain. + passphrase_len = 16 + rand_data = rand_bytes(10 + passphrase_len) + passphrase = rand_data[10:] + + temp_filename = b32encode(rand_data[:10]).decode('utf-8') + temp_dir = tempfile.mkdtemp() + temp_path = os.path.join(temp_dir, temp_filename).encode('utf-8') + + sec_keychain_ref_pointer = new(Security, 'SecKeychainRef *') + result = Security.SecKeychainCreate( + temp_path, + passphrase_len, + passphrase, + False, + null(), + sec_keychain_ref_pointer + ) + handle_sec_error(result) + sec_keychain_ref = unwrap(sec_keychain_ref_pointer) + + sec_access_ref_pointer = new(Security, 'SecAccessRef *') + result = Security.SecAccessCreate(cf_string, null(), sec_access_ref_pointer) + handle_sec_error(result) + sec_access_ref = unwrap(sec_access_ref_pointer) + + result = Security.SecKeyCreatePair( + sec_keychain_ref, + alg_id, + key_size, + 0, + SecurityConst.CSSM_KEYUSE_VERIFY, + SecurityConst.CSSM_KEYATTR_EXTRACTABLE | SecurityConst.CSSM_KEYATTR_PERMANENT, + SecurityConst.CSSM_KEYUSE_SIGN, + SecurityConst.CSSM_KEYATTR_EXTRACTABLE | SecurityConst.CSSM_KEYATTR_PERMANENT, + sec_access_ref, + public_key_pointer, + private_key_pointer + ) + handle_sec_error(result) + + public_key_ref = unwrap(public_key_pointer) + private_key_ref = unwrap(private_key_pointer) + + cf_data_public_pointer = new(CoreFoundation, 'CFDataRef *') + result = Security.SecItemExport(public_key_ref, 0, 0, null(), cf_data_public_pointer) + handle_sec_error(result) + cf_data_public = unwrap(cf_data_public_pointer) + public_key_bytes = CFHelpers.cf_data_to_bytes(cf_data_public) + + cf_data_private_pointer = new(CoreFoundation, 'CFDataRef *') + result = Security.SecItemExport(private_key_ref, 0, 0, null(), cf_data_private_pointer) + handle_sec_error(result) + cf_data_private = unwrap(cf_data_private_pointer) + private_key_bytes = CFHelpers.cf_data_to_bytes(cf_data_private) + + # Clean the new keys out of the keychain + result = Security.SecKeychainItemDelete(public_key_ref) + handle_sec_error(result) + result = Security.SecKeychainItemDelete(private_key_ref) + handle_sec_error(result) + + finally: + if cf_dict: + CoreFoundation.CFRelease(cf_dict) + if public_key_ref: + CoreFoundation.CFRelease(public_key_ref) + if private_key_ref: + CoreFoundation.CFRelease(private_key_ref) + if cf_data_public: + CoreFoundation.CFRelease(cf_data_public) + if cf_data_private: + CoreFoundation.CFRelease(cf_data_private) + if cf_string: + CoreFoundation.CFRelease(cf_string) + if sec_keychain_ref: + Security.SecKeychainDelete(sec_keychain_ref) + CoreFoundation.CFRelease(sec_keychain_ref) + if temp_dir: + shutil.rmtree(temp_dir) + if sec_access_ref: + CoreFoundation.CFRelease(sec_access_ref) + + return (load_public_key(public_key_bytes), load_private_key(private_key_bytes)) + + +def generate_dh_parameters(bit_size): + """ + Generates DH parameters for use with Diffie-Hellman key exchange. Returns + a structure in the format of DHParameter defined in PKCS#3, which is also + used by the OpenSSL dhparam tool. + + THIS CAN BE VERY TIME CONSUMING! + + :param bit_size: + The integer bit size of the parameters to generate. Must be between 512 + and 4096, and divisible by 64. Recommended secure value as of early 2016 + is 2048, with an absolute minimum of 1024. + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + + :return: + An asn1crypto.algos.DHParameters object. Use + oscrypto.asymmetric.dump_dh_parameters() to save to disk for usage with + web servers. + """ + + if not isinstance(bit_size, int_types): + raise TypeError(pretty_message( + ''' + bit_size must be an integer, not %s + ''', + type_name(bit_size) + )) + + if bit_size < 512: + raise ValueError('bit_size must be greater than or equal to 512') + + if bit_size > 4096: + raise ValueError('bit_size must be less than or equal to 4096') + + if bit_size % 64 != 0: + raise ValueError('bit_size must be a multiple of 64') + + public_key_ref = None + private_key_ref = None + cf_data_public = None + cf_data_private = None + cf_string = None + sec_keychain_ref = None + sec_access_ref = None + temp_dir = None + + try: + public_key_pointer = new(Security, 'SecKeyRef *') + private_key_pointer = new(Security, 'SecKeyRef *') + + cf_string = CFHelpers.cf_string_from_unicode("Temporary oscrypto key") + + passphrase_len = 16 + rand_data = rand_bytes(10 + passphrase_len) + passphrase = rand_data[10:] + + temp_filename = b32encode(rand_data[:10]).decode('utf-8') + temp_dir = tempfile.mkdtemp() + temp_path = os.path.join(temp_dir, temp_filename).encode('utf-8') + + sec_keychain_ref_pointer = new(Security, 'SecKeychainRef *') + result = Security.SecKeychainCreate( + temp_path, + passphrase_len, + passphrase, + False, + null(), + sec_keychain_ref_pointer + ) + handle_sec_error(result) + sec_keychain_ref = unwrap(sec_keychain_ref_pointer) + + sec_access_ref_pointer = new(Security, 'SecAccessRef *') + result = Security.SecAccessCreate(cf_string, null(), sec_access_ref_pointer) + handle_sec_error(result) + sec_access_ref = unwrap(sec_access_ref_pointer) + + result = Security.SecKeyCreatePair( + sec_keychain_ref, + SecurityConst.CSSM_ALGID_DH, + bit_size, + 0, + 0, + SecurityConst.CSSM_KEYATTR_EXTRACTABLE | SecurityConst.CSSM_KEYATTR_PERMANENT, + 0, + SecurityConst.CSSM_KEYATTR_EXTRACTABLE | SecurityConst.CSSM_KEYATTR_PERMANENT, + sec_access_ref, + public_key_pointer, + private_key_pointer + ) + handle_sec_error(result) + + public_key_ref = unwrap(public_key_pointer) + private_key_ref = unwrap(private_key_pointer) + + cf_data_private_pointer = new(CoreFoundation, 'CFDataRef *') + result = Security.SecItemExport(private_key_ref, 0, 0, null(), cf_data_private_pointer) + handle_sec_error(result) + cf_data_private = unwrap(cf_data_private_pointer) + private_key_bytes = CFHelpers.cf_data_to_bytes(cf_data_private) + + # Clean the new keys out of the keychain + result = Security.SecKeychainItemDelete(public_key_ref) + handle_sec_error(result) + + result = Security.SecKeychainItemDelete(private_key_ref) + handle_sec_error(result) + + return KeyExchangeAlgorithm.load(private_key_bytes)['parameters'] + + finally: + if public_key_ref: + CoreFoundation.CFRelease(public_key_ref) + if private_key_ref: + CoreFoundation.CFRelease(private_key_ref) + if cf_data_public: + CoreFoundation.CFRelease(cf_data_public) + if cf_data_private: + CoreFoundation.CFRelease(cf_data_private) + if cf_string: + CoreFoundation.CFRelease(cf_string) + if sec_keychain_ref: + Security.SecKeychainDelete(sec_keychain_ref) + CoreFoundation.CFRelease(sec_keychain_ref) + if temp_dir: + shutil.rmtree(temp_dir) + if sec_access_ref: + CoreFoundation.CFRelease(sec_access_ref) + + +def load_certificate(source): + """ + Loads an x509 certificate into a Certificate object + + :param source: + A byte string of file contents, a unicode string filename or an + asn1crypto.x509.Certificate object + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + + :return: + A Certificate object + """ + + if isinstance(source, Asn1Certificate): + certificate = source + + elif isinstance(source, byte_cls): + certificate = parse_certificate(source) + + elif isinstance(source, str_cls): + with open(source, 'rb') as f: + certificate = parse_certificate(f.read()) + + else: + raise TypeError(pretty_message( + ''' + source must be a byte string, unicode string or + asn1crypto.x509.Certificate object, not %s + ''', + type_name(source) + )) + + return _load_x509(certificate) + + +def _load_x509(certificate): + """ + Loads an ASN.1 object of an x509 certificate into a Certificate object + + :param certificate: + An asn1crypto.x509.Certificate object + + :return: + A Certificate object + """ + + source = certificate.dump() + + cf_source = None + try: + cf_source = CFHelpers.cf_data_from_bytes(source) + sec_key_ref = Security.SecCertificateCreateWithData(CoreFoundation.kCFAllocatorDefault, cf_source) + return Certificate(sec_key_ref, certificate) + + finally: + if cf_source: + CoreFoundation.CFRelease(cf_source) + + +def load_private_key(source, password=None): + """ + Loads a private key into a PrivateKey object + + :param source: + A byte string of file contents, a unicode string filename or an + asn1crypto.keys.PrivateKeyInfo object + + :param password: + A byte or unicode string to decrypt the private key file. Unicode + strings will be encoded using UTF-8. Not used is the source is a + PrivateKeyInfo object. + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + oscrypto.errors.AsymmetricKeyError - when the private key is incompatible with the OS crypto library + OSError - when an error is returned by the OS crypto library + + :return: + A PrivateKey object + """ + + if isinstance(source, PrivateKeyInfo): + private_object = source + + else: + if password is not None: + if isinstance(password, str_cls): + password = password.encode('utf-8') + if not isinstance(password, byte_cls): + raise TypeError(pretty_message( + ''' + password must be a byte string, not %s + ''', + type_name(password) + )) + + if isinstance(source, str_cls): + with open(source, 'rb') as f: + source = f.read() + + elif not isinstance(source, byte_cls): + raise TypeError(pretty_message( + ''' + source must be a byte string, unicode string or + asn1crypto.keys.PrivateKeyInfo object, not %s + ''', + type_name(source) + )) + + private_object = parse_private(source, password) + + return _load_key(private_object) + + +def load_public_key(source): + """ + Loads a public key into a PublicKey object + + :param source: + A byte string of file contents, a unicode string filename or an + asn1crypto.keys.PublicKeyInfo object + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + oscrypto.errors.AsymmetricKeyError - when the public key is incompatible with the OS crypto library + OSError - when an error is returned by the OS crypto library + + :return: + A PublicKey object + """ + + if isinstance(source, PublicKeyInfo): + public_key = source + + elif isinstance(source, byte_cls): + public_key = parse_public(source) + + elif isinstance(source, str_cls): + with open(source, 'rb') as f: + public_key = parse_public(f.read()) + + else: + raise TypeError(pretty_message( + ''' + source must be a byte string, unicode string or + asn1crypto.keys.PublicKeyInfo object, not %s + ''', + type_name(source) + )) + + return _load_key(public_key) + + +def _load_key(key_object): + """ + Common code to load public and private keys into PublicKey and PrivateKey + objects + + :param key_object: + An asn1crypto.keys.PublicKeyInfo or asn1crypto.keys.PrivateKeyInfo + object + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + oscrypto.errors.AsymmetricKeyError - when the key is incompatible with the OS crypto library + OSError - when an error is returned by the OS crypto library + + :return: + A PublicKey or PrivateKey object + """ + + if key_object.algorithm == 'ec': + curve_type, details = key_object.curve + if curve_type != 'named': + raise AsymmetricKeyError('OS X only supports EC keys using named curves') + if details not in set(['secp256r1', 'secp384r1', 'secp521r1']): + raise AsymmetricKeyError(pretty_message( + ''' + OS X only supports EC keys using the named curves secp256r1, + secp384r1 and secp521r1 + ''' + )) + + elif key_object.algorithm == 'dsa' and key_object.hash_algo == 'sha2': + raise AsymmetricKeyError(pretty_message( + ''' + OS X only supports DSA keys based on SHA1 (2048 bits or less) - this + key is based on SHA2 and is %s bits + ''', + key_object.bit_size + )) + + elif key_object.algorithm == 'dsa' and key_object.hash_algo is None: + raise IncompleteAsymmetricKeyError(pretty_message( + ''' + The DSA key does not contain the necessary p, q and g parameters + and can not be used + ''' + )) + + if isinstance(key_object, PublicKeyInfo): + source = key_object.dump() + item_type = SecurityConst.kSecItemTypePublicKey + + else: + source = _unwrap_private_key_info(key_object).dump() + item_type = SecurityConst.kSecItemTypePrivateKey + + cf_source = None + keys_array = None + attr_array = None + + try: + cf_source = CFHelpers.cf_data_from_bytes(source) + + format_pointer = new(Security, 'uint32_t *') + pointer_set(format_pointer, SecurityConst.kSecFormatOpenSSL) + type_pointer = new(Security, 'uint32_t *') + pointer_set(type_pointer, item_type) + keys_pointer = new(CoreFoundation, 'CFArrayRef *') + + attr_array = CFHelpers.cf_array_from_list([ + Security.kSecAttrIsExtractable + ]) + + import_export_params_pointer = new(Security, 'SecItemImportExportKeyParameters *') + import_export_params = unwrap(import_export_params_pointer) + import_export_params.version = 0 + import_export_params.flags = 0 + import_export_params.passphrase = null() + import_export_params.alertTitle = null() + import_export_params.alertPrompt = null() + import_export_params.accessRef = null() + import_export_params.keyUsage = null() + import_export_params.keyAttributes = attr_array + + res = Security.SecItemImport( + cf_source, + null(), + format_pointer, + type_pointer, + 0, + import_export_params_pointer, + null(), + keys_pointer + ) + handle_sec_error(res) + keys_array = unwrap(keys_pointer) + + length = CoreFoundation.CFArrayGetCount(keys_array) + if length > 0: + sec_key_ref = CoreFoundation.CFArrayGetValueAtIndex(keys_array, 0) + CoreFoundation.CFRetain(sec_key_ref) + + if item_type == SecurityConst.kSecItemTypePublicKey: + return PublicKey(sec_key_ref, key_object) + + if item_type == SecurityConst.kSecItemTypePrivateKey: + return PrivateKey(sec_key_ref, key_object) + + finally: + if attr_array: + CoreFoundation.CFRelease(attr_array) + if keys_array: + CoreFoundation.CFRelease(keys_array) + if cf_source: + CoreFoundation.CFRelease(cf_source) + + +def parse_pkcs12(data, password=None): + """ + Parses a PKCS#12 ANS.1 DER-encoded structure and extracts certs and keys + + :param data: + A byte string of a DER-encoded PKCS#12 file + + :param password: + A byte string of the password to any encrypted data + + :raises: + ValueError - when any of the parameters are of the wrong type or value + OSError - when an error is returned by one of the OS decryption functions + + :return: + A three-element tuple of: + 1. An asn1crypto.keys.PrivateKeyInfo object + 2. An asn1crypto.x509.Certificate object + 3. A list of zero or more asn1crypto.x509.Certificate objects that are + "extra" certificates, possibly intermediates from the cert chain + """ + + return _parse_pkcs12(data, password, load_private_key) + + +def load_pkcs12(source, password=None): + """ + Loads a .p12 or .pfx file into a PrivateKey object and one or more + Certificates objects + + :param source: + A byte string of file contents or a unicode string filename + + :param password: + A byte or unicode string to decrypt the PKCS12 file. Unicode strings + will be encoded using UTF-8. + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + oscrypto.errors.AsymmetricKeyError - when a contained key is incompatible with the OS crypto library + OSError - when an error is returned by the OS crypto library + + :return: + A three-element tuple containing (PrivateKey, Certificate, [Certificate, ...]) + """ + + if password is not None: + if isinstance(password, str_cls): + password = password.encode('utf-8') + if not isinstance(password, byte_cls): + raise TypeError(pretty_message( + ''' + password must be a byte string, not %s + ''', + type_name(password) + )) + + if isinstance(source, str_cls): + with open(source, 'rb') as f: + source = f.read() + + elif not isinstance(source, byte_cls): + raise TypeError(pretty_message( + ''' + source must be a byte string or a unicode string, not %s + ''', + type_name(source) + )) + + key_info, cert_info, extra_certs_info = parse_pkcs12(source, password) + + key = None + cert = None + + if key_info: + key = _load_key(key_info) + + if cert_info: + cert = _load_x509(cert_info) + + extra_certs = [_load_x509(info) for info in extra_certs_info] + + return (key, cert, extra_certs) + + +def rsa_pkcs1v15_encrypt(certificate_or_public_key, data): + """ + Encrypts a byte string using an RSA public key or certificate. Uses PKCS#1 + v1.5 padding. + + :param certificate_or_public_key: + A PublicKey or Certificate object + + :param data: + A byte string, with a maximum length 11 bytes less than the key length + (in bytes) + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + + :return: + A byte string of the encrypted data + """ + + if not isinstance(certificate_or_public_key, (Certificate, PublicKey)): + raise TypeError(pretty_message( + ''' + certificate_or_public_key must be an instance of the Certificate or + PublicKey class, not %s + ''', + type_name(certificate_or_public_key) + )) + + if not isinstance(data, byte_cls): + raise TypeError(pretty_message( + ''' + data must be a byte string, not %s + ''', + type_name(data) + )) + + key_length = certificate_or_public_key.byte_size + buffer = buffer_from_bytes(key_length) + output_length = new(Security, 'size_t *', key_length) + result = Security.SecKeyEncrypt( + certificate_or_public_key.sec_key_ref, + SecurityConst.kSecPaddingPKCS1, + data, + len(data), + buffer, + output_length + ) + handle_sec_error(result) + + return bytes_from_buffer(buffer, deref(output_length)) + + +def rsa_pkcs1v15_decrypt(private_key, ciphertext): + """ + Decrypts a byte string using an RSA private key. Uses PKCS#1 v1.5 padding. + + :param private_key: + A PrivateKey object + + :param ciphertext: + A byte string of the encrypted data + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + + :return: + A byte string of the original plaintext + """ + + if not isinstance(private_key, PrivateKey): + raise TypeError(pretty_message( + ''' + private_key must an instance of the PrivateKey class, not %s + ''', + type_name(private_key) + )) + + if not isinstance(ciphertext, byte_cls): + raise TypeError(pretty_message( + ''' + data must be a byte string, not %s + ''', + type_name(ciphertext) + )) + + key_length = private_key.byte_size + buffer = buffer_from_bytes(key_length) + output_length = new(Security, 'size_t *', key_length) + + if osx_version_info < (10, 8): + padding = SecurityConst.kSecPaddingNone + else: + padding = SecurityConst.kSecPaddingPKCS1 + + result = Security.SecKeyDecrypt( + private_key.sec_key_ref, + padding, + ciphertext, + len(ciphertext), + buffer, + output_length + ) + handle_sec_error(result) + + output = bytes_from_buffer(buffer, deref(output_length)) + + if osx_version_info < (10, 8): + output = remove_pkcs1v15_encryption_padding(key_length, output) + + return output + + +def rsa_oaep_encrypt(certificate_or_public_key, data): + """ + Encrypts a byte string using an RSA public key or certificate. Uses PKCS#1 + OAEP padding with SHA1. + + :param certificate_or_public_key: + A PublicKey or Certificate object + + :param data: + A byte string, with a maximum length 41 bytes (or more) less than the + key length (in bytes) + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + + :return: + A byte string of the encrypted data + """ + + return _encrypt(certificate_or_public_key, data, Security.kSecPaddingOAEPKey) + + +def rsa_oaep_decrypt(private_key, ciphertext): + """ + Decrypts a byte string using an RSA private key. Uses PKCS#1 OAEP padding + with SHA1. + + :param private_key: + A PrivateKey object + + :param ciphertext: + A byte string of the encrypted data + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + + :return: + A byte string of the original plaintext + """ + + return _decrypt(private_key, ciphertext, Security.kSecPaddingOAEPKey) + + +def _encrypt(certificate_or_public_key, data, padding): + """ + Encrypts plaintext using an RSA public key or certificate + + :param certificate_or_public_key: + A Certificate or PublicKey object + + :param data: + The plaintext - a byte string + + :param padding: + The padding mode to use, specified as a kSecPadding*Key value + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + + :return: + A byte string of the ciphertext + """ + + if not isinstance(certificate_or_public_key, (Certificate, PublicKey)): + raise TypeError(pretty_message( + ''' + certificate_or_public_key must be an instance of the Certificate or + PublicKey class, not %s + ''', + type_name(certificate_or_public_key) + )) + + if not isinstance(data, byte_cls): + raise TypeError(pretty_message( + ''' + data must be a byte string, not %s + ''', + type_name(data) + )) + + if not padding: + raise ValueError('padding must be specified') + + cf_data = None + sec_transform = None + + try: + cf_data = CFHelpers.cf_data_from_bytes(data) + + error_pointer = new(CoreFoundation, 'CFErrorRef *') + sec_transform = Security.SecEncryptTransformCreate( + certificate_or_public_key.sec_key_ref, + error_pointer + ) + handle_cf_error(error_pointer) + + if padding: + Security.SecTransformSetAttribute( + sec_transform, + Security.kSecPaddingKey, + padding, + error_pointer + ) + handle_cf_error(error_pointer) + + Security.SecTransformSetAttribute( + sec_transform, + Security.kSecTransformInputAttributeName, + cf_data, + error_pointer + ) + handle_cf_error(error_pointer) + + ciphertext = Security.SecTransformExecute(sec_transform, error_pointer) + handle_cf_error(error_pointer) + + return CFHelpers.cf_data_to_bytes(ciphertext) + + finally: + if cf_data: + CoreFoundation.CFRelease(cf_data) + if sec_transform: + CoreFoundation.CFRelease(sec_transform) + + +def _decrypt(private_key, ciphertext, padding): + """ + Decrypts RSA ciphertext using a private key + + :param private_key: + A PrivateKey object + + :param ciphertext: + The ciphertext - a byte string + + :param padding: + The padding mode to use, specified as a kSecPadding*Key value + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + + :return: + A byte string of the plaintext + """ + + if not isinstance(private_key, PrivateKey): + raise TypeError(pretty_message( + ''' + private_key must be an instance of the PrivateKey class, not %s + ''', + type_name(private_key) + )) + + if not isinstance(ciphertext, byte_cls): + raise TypeError(pretty_message( + ''' + ciphertext must be a byte string, not %s + ''', + type_name(ciphertext) + )) + + if not padding: + raise ValueError('padding must be specified') + + cf_data = None + sec_transform = None + + try: + cf_data = CFHelpers.cf_data_from_bytes(ciphertext) + + error_pointer = new(CoreFoundation, 'CFErrorRef *') + sec_transform = Security.SecDecryptTransformCreate( + private_key.sec_key_ref, + error_pointer + ) + handle_cf_error(error_pointer) + + Security.SecTransformSetAttribute( + sec_transform, + Security.kSecPaddingKey, + padding, + error_pointer + ) + handle_cf_error(error_pointer) + + Security.SecTransformSetAttribute( + sec_transform, + Security.kSecTransformInputAttributeName, + cf_data, + error_pointer + ) + handle_cf_error(error_pointer) + + plaintext = Security.SecTransformExecute(sec_transform, error_pointer) + handle_cf_error(error_pointer) + + return CFHelpers.cf_data_to_bytes(plaintext) + + finally: + if cf_data: + CoreFoundation.CFRelease(cf_data) + if sec_transform: + CoreFoundation.CFRelease(sec_transform) + + +def rsa_pkcs1v15_verify(certificate_or_public_key, signature, data, hash_algorithm): + """ + Verifies an RSASSA-PKCS-v1.5 signature. + + When the hash_algorithm is "raw", the operation is identical to RSA + public key decryption. That is: the data is not hashed and no ASN.1 + structure with an algorithm identifier of the hash algorithm is placed in + the encrypted byte string. + + :param certificate_or_public_key: + A Certificate or PublicKey instance to verify the signature with + + :param signature: + A byte string of the signature to verify + + :param data: + A byte string of the data the signature is for + + :param hash_algorithm: + A unicode string of "md5", "sha1", "sha224", "sha256", "sha384", "sha512" or "raw" + + :raises: + oscrypto.errors.SignatureError - when the signature is determined to be invalid + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + """ + + if certificate_or_public_key.algorithm != 'rsa': + raise ValueError('The key specified is not an RSA public key') + + return _verify(certificate_or_public_key, signature, data, hash_algorithm) + + +def rsa_pss_verify(certificate_or_public_key, signature, data, hash_algorithm): + """ + Verifies an RSASSA-PSS signature. For the PSS padding the mask gen algorithm + will be mgf1 using the same hash algorithm as the signature. The salt length + with be the length of the hash algorithm, and the trailer field with be the + standard 0xBC byte. + + :param certificate_or_public_key: + A Certificate or PublicKey instance to verify the signature with + + :param signature: + A byte string of the signature to verify + + :param data: + A byte string of the data the signature is for + + :param hash_algorithm: + A unicode string of "md5", "sha1", "sha224", "sha256", "sha384" or "sha512" + + :raises: + oscrypto.errors.SignatureError - when the signature is determined to be invalid + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + """ + + if not isinstance(certificate_or_public_key, (Certificate, PublicKey)): + raise TypeError(pretty_message( + ''' + certificate_or_public_key must be an instance of the Certificate or + PublicKey class, not %s + ''', + type_name(certificate_or_public_key) + )) + + if not isinstance(data, byte_cls): + raise TypeError(pretty_message( + ''' + data must be a byte string, not %s + ''', + type_name(data) + )) + + if certificate_or_public_key.algorithm != 'rsa': + raise ValueError('The key specified is not an RSA public key') + + hash_length = { + 'sha1': 20, + 'sha224': 28, + 'sha256': 32, + 'sha384': 48, + 'sha512': 64 + }.get(hash_algorithm, 0) + + key_length = certificate_or_public_key.byte_size + buffer = buffer_from_bytes(key_length) + output_length = new(Security, 'size_t *', key_length) + result = Security.SecKeyEncrypt( + certificate_or_public_key.sec_key_ref, + SecurityConst.kSecPaddingNone, + signature, + len(signature), + buffer, + output_length + ) + handle_sec_error(result) + + plaintext = bytes_from_buffer(buffer, deref(output_length)) + if not verify_pss_padding(hash_algorithm, hash_length, certificate_or_public_key.bit_size, data, plaintext): + raise SignatureError('Signature is invalid') + + +def dsa_verify(certificate_or_public_key, signature, data, hash_algorithm): + """ + Verifies a DSA signature + + :param certificate_or_public_key: + A Certificate or PublicKey instance to verify the signature with + + :param signature: + A byte string of the signature to verify + + :param data: + A byte string of the data the signature is for + + :param hash_algorithm: + A unicode string of "md5", "sha1", "sha224", "sha256", "sha384" or "sha512" + + :raises: + oscrypto.errors.SignatureError - when the signature is determined to be invalid + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + """ + + if certificate_or_public_key.algorithm != 'dsa': + raise ValueError('The key specified is not a DSA public key') + + return _verify(certificate_or_public_key, signature, data, hash_algorithm) + + +def ecdsa_verify(certificate_or_public_key, signature, data, hash_algorithm): + """ + Verifies an ECDSA signature + + :param certificate_or_public_key: + A Certificate or PublicKey instance to verify the signature with + + :param signature: + A byte string of the signature to verify + + :param data: + A byte string of the data the signature is for + + :param hash_algorithm: + A unicode string of "md5", "sha1", "sha224", "sha256", "sha384" or "sha512" + + :raises: + oscrypto.errors.SignatureError - when the signature is determined to be invalid + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + """ + + if certificate_or_public_key.algorithm != 'ec': + raise ValueError('The key specified is not an EC public key') + + return _verify(certificate_or_public_key, signature, data, hash_algorithm) + + +def _verify(certificate_or_public_key, signature, data, hash_algorithm): + """ + Verifies an RSA, DSA or ECDSA signature + + :param certificate_or_public_key: + A Certificate or PublicKey instance to verify the signature with + + :param signature: + A byte string of the signature to verify + + :param data: + A byte string of the data the signature is for + + :param hash_algorithm: + A unicode string of "md5", "sha1", "sha224", "sha256", "sha384" or "sha512" + + :raises: + oscrypto.errors.SignatureError - when the signature is determined to be invalid + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + """ + + if not isinstance(certificate_or_public_key, (Certificate, PublicKey)): + raise TypeError(pretty_message( + ''' + certificate_or_public_key must be an instance of the Certificate or + PublicKey class, not %s + ''', + type_name(certificate_or_public_key) + )) + + if not isinstance(signature, byte_cls): + raise TypeError(pretty_message( + ''' + signature must be a byte string, not %s + ''', + type_name(signature) + )) + + if not isinstance(data, byte_cls): + raise TypeError(pretty_message( + ''' + data must be a byte string, not %s + ''', + type_name(data) + )) + + valid_hash_algorithms = set(['md5', 'sha1', 'sha224', 'sha256', 'sha384', 'sha512']) + if certificate_or_public_key.algorithm == 'rsa': + valid_hash_algorithms |= set(['raw']) + + if hash_algorithm not in valid_hash_algorithms: + valid_hash_algorithms_error = '"md5", "sha1", "sha224", "sha256", "sha384", "sha512"' + if certificate_or_public_key.algorithm == 'rsa': + valid_hash_algorithms_error += ', "raw"' + raise ValueError(pretty_message( + ''' + hash_algorithm must be one of %s, not %s + ''', + valid_hash_algorithms_error, + repr(hash_algorithm) + )) + + if certificate_or_public_key.algorithm == 'rsa' and hash_algorithm == 'raw': + if len(data) > certificate_or_public_key.byte_size - 11: + raise ValueError(pretty_message( + ''' + data must be 11 bytes shorter than the key size when + hash_algorithm is "raw" - key size is %s bytes, but data + is %s bytes long + ''', + certificate_or_public_key.byte_size, + len(data) + )) + + result = Security.SecKeyRawVerify( + certificate_or_public_key.sec_key_ref, + SecurityConst.kSecPaddingPKCS1, + data, + len(data), + signature, + len(signature) + ) + # errSSLCrypto is returned in some situations on macOS 10.12 + if result == SecurityConst.errSecVerifyFailed or result == SecurityConst.errSSLCrypto: + raise SignatureError('Signature is invalid') + handle_sec_error(result) + return + + cf_signature = None + cf_data = None + cf_hash_length = None + sec_transform = None + + try: + error_pointer = new(CoreFoundation, 'CFErrorRef *') + cf_signature = CFHelpers.cf_data_from_bytes(signature) + sec_transform = Security.SecVerifyTransformCreate( + certificate_or_public_key.sec_key_ref, + cf_signature, + error_pointer + ) + handle_cf_error(error_pointer) + + hash_constant = { + 'md5': Security.kSecDigestMD5, + 'sha1': Security.kSecDigestSHA1, + 'sha224': Security.kSecDigestSHA2, + 'sha256': Security.kSecDigestSHA2, + 'sha384': Security.kSecDigestSHA2, + 'sha512': Security.kSecDigestSHA2 + }[hash_algorithm] + + Security.SecTransformSetAttribute( + sec_transform, + Security.kSecDigestTypeAttribute, + hash_constant, + error_pointer + ) + handle_cf_error(error_pointer) + + if hash_algorithm in set(['sha224', 'sha256', 'sha384', 'sha512']): + hash_length = { + 'sha224': 224, + 'sha256': 256, + 'sha384': 384, + 'sha512': 512 + }[hash_algorithm] + + cf_hash_length = CFHelpers.cf_number_from_integer(hash_length) + + Security.SecTransformSetAttribute( + sec_transform, + Security.kSecDigestLengthAttribute, + cf_hash_length, + error_pointer + ) + handle_cf_error(error_pointer) + + if certificate_or_public_key.algorithm == 'rsa': + Security.SecTransformSetAttribute( + sec_transform, + Security.kSecPaddingKey, + Security.kSecPaddingPKCS1Key, + error_pointer + ) + handle_cf_error(error_pointer) + + cf_data = CFHelpers.cf_data_from_bytes(data) + Security.SecTransformSetAttribute( + sec_transform, + Security.kSecTransformInputAttributeName, + cf_data, + error_pointer + ) + handle_cf_error(error_pointer) + + res = Security.SecTransformExecute(sec_transform, error_pointer) + if not is_null(error_pointer): + error = unwrap(error_pointer) + if not is_null(error): + raise SignatureError('Signature is invalid') + + res = bool(CoreFoundation.CFBooleanGetValue(res)) + + if not res: + raise SignatureError('Signature is invalid') + + finally: + if sec_transform: + CoreFoundation.CFRelease(sec_transform) + if cf_signature: + CoreFoundation.CFRelease(cf_signature) + if cf_data: + CoreFoundation.CFRelease(cf_data) + if cf_hash_length: + CoreFoundation.CFRelease(cf_hash_length) + + +def rsa_pkcs1v15_sign(private_key, data, hash_algorithm): + """ + Generates an RSASSA-PKCS-v1.5 signature. + + When the hash_algorithm is "raw", the operation is identical to RSA + private key encryption. That is: the data is not hashed and no ASN.1 + structure with an algorithm identifier of the hash algorithm is placed in + the encrypted byte string. + + :param private_key: + The PrivateKey to generate the signature with + + :param data: + A byte string of the data the signature is for + + :param hash_algorithm: + A unicode string of "md5", "sha1", "sha224", "sha256", "sha384", + "sha512" or "raw" + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + + :return: + A byte string of the signature + """ + + if private_key.algorithm != 'rsa': + raise ValueError('The key specified is not an RSA private key') + + return _sign(private_key, data, hash_algorithm) + + +def rsa_pss_sign(private_key, data, hash_algorithm): + """ + Generates an RSASSA-PSS signature. For the PSS padding the mask gen + algorithm will be mgf1 using the same hash algorithm as the signature. The + salt length with be the length of the hash algorithm, and the trailer field + with be the standard 0xBC byte. + + :param private_key: + The PrivateKey to generate the signature with + + :param data: + A byte string of the data the signature is for + + :param hash_algorithm: + A unicode string of "md5", "sha1", "sha224", "sha256", "sha384" or + "sha512" + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + + :return: + A byte string of the signature + """ + + if not isinstance(private_key, PrivateKey): + raise TypeError(pretty_message( + ''' + private_key must be an instance of the PrivateKey class, not %s + ''', + type_name(private_key) + )) + + if not isinstance(data, byte_cls): + raise TypeError(pretty_message( + ''' + data must be a byte string, not %s + ''', + type_name(data) + )) + + if private_key.algorithm != 'rsa': + raise ValueError('The key specified is not an RSA private key') + + hash_length = { + 'sha1': 20, + 'sha224': 28, + 'sha256': 32, + 'sha384': 48, + 'sha512': 64 + }.get(hash_algorithm, 0) + + encoded_data = add_pss_padding(hash_algorithm, hash_length, private_key.bit_size, data) + + key_length = private_key.byte_size + buffer = buffer_from_bytes(key_length) + output_length = new(Security, 'size_t *', key_length) + result = Security.SecKeyDecrypt( + private_key.sec_key_ref, + SecurityConst.kSecPaddingNone, + encoded_data, + len(encoded_data), + buffer, + output_length + ) + handle_sec_error(result) + + return bytes_from_buffer(buffer, deref(output_length)) + + +def dsa_sign(private_key, data, hash_algorithm): + """ + Generates a DSA signature + + :param private_key: + The PrivateKey to generate the signature with + + :param data: + A byte string of the data the signature is for + + :param hash_algorithm: + A unicode string of "md5", "sha1", "sha224", "sha256", "sha384" or + "sha512" + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + + :return: + A byte string of the signature + """ + + if private_key.algorithm != 'dsa': + raise ValueError('The key specified is not a DSA private key') + + return _sign(private_key, data, hash_algorithm) + + +def ecdsa_sign(private_key, data, hash_algorithm): + """ + Generates an ECDSA signature + + :param private_key: + The PrivateKey to generate the signature with + + :param data: + A byte string of the data the signature is for + + :param hash_algorithm: + A unicode string of "md5", "sha1", "sha224", "sha256", "sha384" or + "sha512" + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + + :return: + A byte string of the signature + """ + + if private_key.algorithm != 'ec': + raise ValueError('The key specified is not an EC private key') + + return _sign(private_key, data, hash_algorithm) + + +def _sign(private_key, data, hash_algorithm): + """ + Generates an RSA, DSA or ECDSA signature + + :param private_key: + The PrivateKey to generate the signature with + + :param data: + A byte string of the data the signature is for + + :param hash_algorithm: + A unicode string of "md5", "sha1", "sha224", "sha256", "sha384" or + "sha512" + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + + :return: + A byte string of the signature + """ + + if not isinstance(private_key, PrivateKey): + raise TypeError(pretty_message( + ''' + private_key must be an instance of PrivateKey, not %s + ''', + type_name(private_key) + )) + + if not isinstance(data, byte_cls): + raise TypeError(pretty_message( + ''' + data must be a byte string, not %s + ''', + type_name(data) + )) + + valid_hash_algorithms = set(['md5', 'sha1', 'sha224', 'sha256', 'sha384', 'sha512']) + if private_key.algorithm == 'rsa': + valid_hash_algorithms |= set(['raw']) + + if hash_algorithm not in valid_hash_algorithms: + valid_hash_algorithms_error = '"md5", "sha1", "sha224", "sha256", "sha384", "sha512"' + if private_key.algorithm == 'rsa': + valid_hash_algorithms_error += ', "raw"' + raise ValueError(pretty_message( + ''' + hash_algorithm must be one of %s, not %s + ''', + valid_hash_algorithms_error, + repr(hash_algorithm) + )) + + if private_key.algorithm == 'rsa' and hash_algorithm == 'raw': + if len(data) > private_key.byte_size - 11: + raise ValueError(pretty_message( + ''' + data must be 11 bytes shorter than the key size when + hash_algorithm is "raw" - key size is %s bytes, but + data is %s bytes long + ''', + private_key.byte_size, + len(data) + )) + + key_length = private_key.byte_size + buffer = buffer_from_bytes(key_length) + output_length = new(Security, 'size_t *', key_length) + result = Security.SecKeyRawSign( + private_key.sec_key_ref, + SecurityConst.kSecPaddingPKCS1, + data, + len(data), + buffer, + output_length + ) + handle_sec_error(result) + + return bytes_from_buffer(buffer, deref(output_length)) + + cf_signature = None + cf_data = None + cf_hash_length = None + sec_transform = None + + try: + error_pointer = new(CoreFoundation, 'CFErrorRef *') + sec_transform = Security.SecSignTransformCreate(private_key.sec_key_ref, error_pointer) + handle_cf_error(error_pointer) + + hash_constant = { + 'md5': Security.kSecDigestMD5, + 'sha1': Security.kSecDigestSHA1, + 'sha224': Security.kSecDigestSHA2, + 'sha256': Security.kSecDigestSHA2, + 'sha384': Security.kSecDigestSHA2, + 'sha512': Security.kSecDigestSHA2 + }[hash_algorithm] + + Security.SecTransformSetAttribute( + sec_transform, + Security.kSecDigestTypeAttribute, + hash_constant, + error_pointer + ) + handle_cf_error(error_pointer) + + if hash_algorithm in set(['sha224', 'sha256', 'sha384', 'sha512']): + hash_length = { + 'sha224': 224, + 'sha256': 256, + 'sha384': 384, + 'sha512': 512 + }[hash_algorithm] + + cf_hash_length = CFHelpers.cf_number_from_integer(hash_length) + + Security.SecTransformSetAttribute( + sec_transform, + Security.kSecDigestLengthAttribute, + cf_hash_length, + error_pointer + ) + handle_cf_error(error_pointer) + + if private_key.algorithm == 'rsa': + Security.SecTransformSetAttribute( + sec_transform, + Security.kSecPaddingKey, + Security.kSecPaddingPKCS1Key, + error_pointer + ) + handle_cf_error(error_pointer) + + cf_data = CFHelpers.cf_data_from_bytes(data) + Security.SecTransformSetAttribute( + sec_transform, + Security.kSecTransformInputAttributeName, + cf_data, + error_pointer + ) + handle_cf_error(error_pointer) + + cf_signature = Security.SecTransformExecute(sec_transform, error_pointer) + handle_cf_error(error_pointer) + + return CFHelpers.cf_data_to_bytes(cf_signature) + + finally: + if sec_transform: + CoreFoundation.CFRelease(sec_transform) + if cf_signature: + CoreFoundation.CFRelease(cf_signature) + if cf_data: + CoreFoundation.CFRelease(cf_data) + if cf_hash_length: + CoreFoundation.CFRelease(cf_hash_length) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_mac/symmetric.py b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_mac/symmetric.py new file mode 100644 index 00000000..431fef27 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_mac/symmetric.py @@ -0,0 +1,757 @@ +# coding: utf-8 +from __future__ import unicode_literals, division, absolute_import, print_function + +from .._errors import pretty_message +from .._ffi import new, null +from ._core_foundation import CoreFoundation, CFHelpers, handle_cf_error +from ._security import Security +from .util import rand_bytes +from .._types import type_name, byte_cls + + +__all__ = [ + 'aes_cbc_no_padding_decrypt', + 'aes_cbc_no_padding_encrypt', + 'aes_cbc_pkcs7_decrypt', + 'aes_cbc_pkcs7_encrypt', + 'des_cbc_pkcs5_decrypt', + 'des_cbc_pkcs5_encrypt', + 'rc2_cbc_pkcs5_decrypt', + 'rc2_cbc_pkcs5_encrypt', + 'rc4_decrypt', + 'rc4_encrypt', + 'tripledes_cbc_pkcs5_decrypt', + 'tripledes_cbc_pkcs5_encrypt', +] + + +def aes_cbc_no_padding_encrypt(key, data, iv): + """ + Encrypts plaintext using AES in CBC mode with a 128, 192 or 256 bit key and + no padding. This means the ciphertext must be an exact multiple of 16 bytes + long. + + :param key: + The encryption key - a byte string either 16, 24 or 32 bytes long + + :param data: + The plaintext - a byte string + + :param iv: + The initialization vector - either a byte string 16-bytes long or None + to generate an IV + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + + :return: + A tuple of two byte strings (iv, ciphertext) + """ + + if len(key) not in [16, 24, 32]: + raise ValueError(pretty_message( + ''' + key must be either 16, 24 or 32 bytes (128, 192 or 256 bits) long - is %s + ''', + len(key) + )) + + if not iv: + iv = rand_bytes(16) + elif len(iv) != 16: + raise ValueError(pretty_message( + ''' + iv must be 16 bytes long - is %s + ''', + len(iv) + )) + + if len(data) % 16 != 0: + raise ValueError(pretty_message( + ''' + data must be a multiple of 16 bytes long - is %s + ''', + len(data) + )) + + return (iv, _encrypt(Security.kSecAttrKeyTypeAES, key, data, iv, Security.kSecPaddingNoneKey)) + + +def aes_cbc_no_padding_decrypt(key, data, iv): + """ + Decrypts AES ciphertext in CBC mode using a 128, 192 or 256 bit key and no + padding. + + :param key: + The encryption key - a byte string either 16, 24 or 32 bytes long + + :param data: + The ciphertext - a byte string + + :param iv: + The initialization vector - a byte string 16-bytes long + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + + :return: + A byte string of the plaintext + """ + + if len(key) not in [16, 24, 32]: + raise ValueError(pretty_message( + ''' + key must be either 16, 24 or 32 bytes (128, 192 or 256 bits) long - is %s + ''', + len(key) + )) + + if len(iv) != 16: + raise ValueError(pretty_message( + ''' + iv must be 16 bytes long - is %s + ''', + len(iv) + )) + + return _decrypt(Security.kSecAttrKeyTypeAES, key, data, iv, Security.kSecPaddingNoneKey) + + +def aes_cbc_pkcs7_encrypt(key, data, iv): + """ + Encrypts plaintext using AES in CBC mode with a 128, 192 or 256 bit key and + PKCS#7 padding. + + :param key: + The encryption key - a byte string either 16, 24 or 32 bytes long + + :param data: + The plaintext - a byte string + + :param iv: + The initialization vector - either a byte string 16-bytes long or None + to generate an IV + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + + :return: + A tuple of two byte strings (iv, ciphertext) + """ + + if len(key) not in [16, 24, 32]: + raise ValueError(pretty_message( + ''' + key must be either 16, 24 or 32 bytes (128, 192 or 256 bits) long - is %s + ''', + len(key) + )) + + if not iv: + iv = rand_bytes(16) + elif len(iv) != 16: + raise ValueError(pretty_message( + ''' + iv must be 16 bytes long - is %s + ''', + len(iv) + )) + + return (iv, _encrypt(Security.kSecAttrKeyTypeAES, key, data, iv, Security.kSecPaddingPKCS7Key)) + + +def aes_cbc_pkcs7_decrypt(key, data, iv): + """ + Decrypts AES ciphertext in CBC mode using a 128, 192 or 256 bit key + + :param key: + The encryption key - a byte string either 16, 24 or 32 bytes long + + :param data: + The ciphertext - a byte string + + :param iv: + The initialization vector - a byte string 16-bytes long + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + + :return: + A byte string of the plaintext + """ + + if len(key) not in [16, 24, 32]: + raise ValueError(pretty_message( + ''' + key must be either 16, 24 or 32 bytes (128, 192 or 256 bits) + long - is %s + ''', + len(key) + )) + + if len(iv) != 16: + raise ValueError(pretty_message( + ''' + iv must be 16 bytes long - is %s + ''', + len(iv) + )) + + return _decrypt(Security.kSecAttrKeyTypeAES, key, data, iv, Security.kSecPaddingPKCS7Key) + + +def rc4_encrypt(key, data): + """ + Encrypts plaintext using RC4 with a 40-128 bit key + + :param key: + The encryption key - a byte string 5-16 bytes long + + :param data: + The plaintext - a byte string + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + + :return: + A byte string of the ciphertext + """ + + if len(key) < 5 or len(key) > 16: + raise ValueError(pretty_message( + ''' + key must be 5 to 16 bytes (40 to 128 bits) long - is %s + ''', + len(key) + )) + + return _encrypt(Security.kSecAttrKeyTypeRC4, key, data, None, None) + + +def rc4_decrypt(key, data): + """ + Decrypts RC4 ciphertext using a 40-128 bit key + + :param key: + The encryption key - a byte string 5-16 bytes long + + :param data: + The ciphertext - a byte string + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + + :return: + A byte string of the plaintext + """ + + if len(key) < 5 or len(key) > 16: + raise ValueError(pretty_message( + ''' + key must be 5 to 16 bytes (40 to 128 bits) long - is %s + ''', + len(key) + )) + + return _decrypt(Security.kSecAttrKeyTypeRC4, key, data, None, None) + + +def rc2_cbc_pkcs5_encrypt(key, data, iv): + """ + Encrypts plaintext using RC2 with a 64 bit key + + :param key: + The encryption key - a byte string 8 bytes long + + :param data: + The plaintext - a byte string + + :param iv: + The 8-byte initialization vector to use - a byte string - set as None + to generate an appropriate one + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + + :return: + A tuple of two byte strings (iv, ciphertext) + """ + + if len(key) < 5 or len(key) > 16: + raise ValueError(pretty_message( + ''' + key must be 5 to 16 bytes (40 to 128 bits) long - is %s + ''', + len(key) + )) + + if not iv: + iv = rand_bytes(8) + elif len(iv) != 8: + raise ValueError(pretty_message( + ''' + iv must be 8 bytes long - is %s + ''', + len(iv) + )) + + return (iv, _encrypt(Security.kSecAttrKeyTypeRC2, key, data, iv, Security.kSecPaddingPKCS5Key)) + + +def rc2_cbc_pkcs5_decrypt(key, data, iv): + """ + Decrypts RC2 ciphertext using a 64 bit key + + :param key: + The encryption key - a byte string 8 bytes long + + :param data: + The ciphertext - a byte string + + :param iv: + The initialization vector used for encryption - a byte string + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + + :return: + A byte string of the plaintext + """ + + if len(key) < 5 or len(key) > 16: + raise ValueError(pretty_message( + ''' + key must be 5 to 16 bytes (40 to 128 bits) long - is %s + ''', + len(key) + )) + + if len(iv) != 8: + raise ValueError(pretty_message( + ''' + iv must be 8 bytes long - is %s + ''', + len(iv) + )) + + return _decrypt(Security.kSecAttrKeyTypeRC2, key, data, iv, Security.kSecPaddingPKCS5Key) + + +def tripledes_cbc_pkcs5_encrypt(key, data, iv): + """ + Encrypts plaintext using 3DES in either 2 or 3 key mode + + :param key: + The encryption key - a byte string 16 or 24 bytes long (2 or 3 key mode) + + :param data: + The plaintext - a byte string + + :param iv: + The 8-byte initialization vector to use - a byte string - set as None + to generate an appropriate one + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + + :return: + A tuple of two byte strings (iv, ciphertext) + """ + + if len(key) != 16 and len(key) != 24: + raise ValueError(pretty_message( + ''' + key must be 16 bytes (2 key) or 24 bytes (3 key) long - %s + ''', + len(key) + )) + + if not iv: + iv = rand_bytes(8) + elif len(iv) != 8: + raise ValueError(pretty_message( + ''' + iv must be 8 bytes long - %s + ''', + len(iv) + )) + + # Expand 2-key to actual 24 byte byte string used by cipher + if len(key) == 16: + key = key + key[0:8] + + return (iv, _encrypt(Security.kSecAttrKeyType3DES, key, data, iv, Security.kSecPaddingPKCS5Key)) + + +def tripledes_cbc_pkcs5_decrypt(key, data, iv): + """ + Decrypts 3DES ciphertext in either 2 or 3 key mode + + :param key: + The encryption key - a byte string 16 or 24 bytes long (2 or 3 key mode) + + :param data: + The ciphertext - a byte string + + :param iv: + The initialization vector used for encryption - a byte string + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + + :return: + A byte string of the plaintext + """ + + if len(key) != 16 and len(key) != 24: + raise ValueError(pretty_message( + ''' + key must be 16 bytes (2 key) or 24 bytes (3 key) long - is %s + ''', + len(key) + )) + + if len(iv) != 8: + raise ValueError(pretty_message( + ''' + iv must be 8 bytes long - is %s + ''', + len(iv) + )) + + # Expand 2-key to actual 24 byte byte string used by cipher + if len(key) == 16: + key = key + key[0:8] + + return _decrypt(Security.kSecAttrKeyType3DES, key, data, iv, Security.kSecPaddingPKCS5Key) + + +def des_cbc_pkcs5_encrypt(key, data, iv): + """ + Encrypts plaintext using DES with a 56 bit key + + :param key: + The encryption key - a byte string 8 bytes long (includes error correction bits) + + :param data: + The plaintext - a byte string + + :param iv: + The 8-byte initialization vector to use - a byte string - set as None + to generate an appropriate one + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + + :return: + A tuple of two byte strings (iv, ciphertext) + """ + + if len(key) != 8: + raise ValueError(pretty_message( + ''' + key must be 8 bytes (56 bits + 8 parity bits) long - is %s + ''', + len(key) + )) + + if not iv: + iv = rand_bytes(8) + elif len(iv) != 8: + raise ValueError(pretty_message( + ''' + iv must be 8 bytes long - is %s + ''', + len(iv) + )) + + return (iv, _encrypt(Security.kSecAttrKeyTypeDES, key, data, iv, Security.kSecPaddingPKCS5Key)) + + +def des_cbc_pkcs5_decrypt(key, data, iv): + """ + Decrypts DES ciphertext using a 56 bit key + + :param key: + The encryption key - a byte string 8 bytes long (includes error correction bits) + + :param data: + The ciphertext - a byte string + + :param iv: + The initialization vector used for encryption - a byte string + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + + :return: + A byte string of the plaintext + """ + + if len(key) != 8: + raise ValueError(pretty_message( + ''' + key must be 8 bytes (56 bits + 8 parity bits) long - is %s + ''', + len(key) + )) + + if len(iv) != 8: + raise ValueError(pretty_message( + ''' + iv must be 8 bytes long - is %s + ''', + len(iv) + )) + + return _decrypt(Security.kSecAttrKeyTypeDES, key, data, iv, Security.kSecPaddingPKCS5Key) + + +def _encrypt(cipher, key, data, iv, padding): + """ + Encrypts plaintext + + :param cipher: + A kSecAttrKeyType* value that specifies the cipher to use + + :param key: + The encryption key - a byte string 5-16 bytes long + + :param data: + The plaintext - a byte string + + :param iv: + The initialization vector - a byte string - unused for RC4 + + :param padding: + The padding mode to use, specified as a kSecPadding*Key value - unused for RC4 + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + + :return: + A byte string of the ciphertext + """ + + if not isinstance(key, byte_cls): + raise TypeError(pretty_message( + ''' + key must be a byte string, not %s + ''', + type_name(key) + )) + + if not isinstance(data, byte_cls): + raise TypeError(pretty_message( + ''' + data must be a byte string, not %s + ''', + type_name(data) + )) + + if cipher != Security.kSecAttrKeyTypeRC4 and not isinstance(iv, byte_cls): + raise TypeError(pretty_message( + ''' + iv must be a byte string, not %s + ''', + type_name(iv) + )) + + if cipher != Security.kSecAttrKeyTypeRC4 and not padding: + raise ValueError('padding must be specified') + + cf_dict = None + cf_key = None + cf_data = None + cf_iv = None + sec_key = None + sec_transform = None + + try: + cf_dict = CFHelpers.cf_dictionary_from_pairs([(Security.kSecAttrKeyType, cipher)]) + cf_key = CFHelpers.cf_data_from_bytes(key) + cf_data = CFHelpers.cf_data_from_bytes(data) + + error_pointer = new(CoreFoundation, 'CFErrorRef *') + sec_key = Security.SecKeyCreateFromData(cf_dict, cf_key, error_pointer) + handle_cf_error(error_pointer) + + sec_transform = Security.SecEncryptTransformCreate(sec_key, error_pointer) + handle_cf_error(error_pointer) + + if cipher != Security.kSecAttrKeyTypeRC4: + Security.SecTransformSetAttribute(sec_transform, Security.kSecModeCBCKey, null(), error_pointer) + handle_cf_error(error_pointer) + + Security.SecTransformSetAttribute(sec_transform, Security.kSecPaddingKey, padding, error_pointer) + handle_cf_error(error_pointer) + + cf_iv = CFHelpers.cf_data_from_bytes(iv) + Security.SecTransformSetAttribute(sec_transform, Security.kSecIVKey, cf_iv, error_pointer) + handle_cf_error(error_pointer) + + Security.SecTransformSetAttribute( + sec_transform, + Security.kSecTransformInputAttributeName, + cf_data, + error_pointer + ) + handle_cf_error(error_pointer) + + ciphertext = Security.SecTransformExecute(sec_transform, error_pointer) + handle_cf_error(error_pointer) + + return CFHelpers.cf_data_to_bytes(ciphertext) + + finally: + if cf_dict: + CoreFoundation.CFRelease(cf_dict) + if cf_key: + CoreFoundation.CFRelease(cf_key) + if cf_data: + CoreFoundation.CFRelease(cf_data) + if cf_iv: + CoreFoundation.CFRelease(cf_iv) + if sec_key: + CoreFoundation.CFRelease(sec_key) + if sec_transform: + CoreFoundation.CFRelease(sec_transform) + + +def _decrypt(cipher, key, data, iv, padding): + """ + Decrypts AES/RC4/RC2/3DES/DES ciphertext + + :param cipher: + A kSecAttrKeyType* value that specifies the cipher to use + + :param key: + The encryption key - a byte string 5-16 bytes long + + :param data: + The ciphertext - a byte string + + :param iv: + The initialization vector - a byte string - unused for RC4 + + :param padding: + The padding mode to use, specified as a kSecPadding*Key value - unused for RC4 + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + + :return: + A byte string of the plaintext + """ + + if not isinstance(key, byte_cls): + raise TypeError(pretty_message( + ''' + key must be a byte string, not %s + ''', + type_name(key) + )) + + if not isinstance(data, byte_cls): + raise TypeError(pretty_message( + ''' + data must be a byte string, not %s + ''', + type_name(data) + )) + + if cipher != Security.kSecAttrKeyTypeRC4 and not isinstance(iv, byte_cls): + raise TypeError(pretty_message( + ''' + iv must be a byte string, not %s + ''', + type_name(iv) + )) + + if cipher != Security.kSecAttrKeyTypeRC4 and not padding: + raise ValueError('padding must be specified') + + cf_dict = None + cf_key = None + cf_data = None + cf_iv = None + sec_key = None + sec_transform = None + + try: + cf_dict = CFHelpers.cf_dictionary_from_pairs([(Security.kSecAttrKeyType, cipher)]) + cf_key = CFHelpers.cf_data_from_bytes(key) + cf_data = CFHelpers.cf_data_from_bytes(data) + + error_pointer = new(CoreFoundation, 'CFErrorRef *') + sec_key = Security.SecKeyCreateFromData(cf_dict, cf_key, error_pointer) + handle_cf_error(error_pointer) + + sec_transform = Security.SecDecryptTransformCreate(sec_key, error_pointer) + handle_cf_error(error_pointer) + + if cipher != Security.kSecAttrKeyTypeRC4: + Security.SecTransformSetAttribute(sec_transform, Security.kSecModeCBCKey, null(), error_pointer) + handle_cf_error(error_pointer) + + Security.SecTransformSetAttribute(sec_transform, Security.kSecPaddingKey, padding, error_pointer) + handle_cf_error(error_pointer) + + cf_iv = CFHelpers.cf_data_from_bytes(iv) + Security.SecTransformSetAttribute(sec_transform, Security.kSecIVKey, cf_iv, error_pointer) + handle_cf_error(error_pointer) + + Security.SecTransformSetAttribute( + sec_transform, + Security.kSecTransformInputAttributeName, + cf_data, + error_pointer + ) + handle_cf_error(error_pointer) + + plaintext = Security.SecTransformExecute(sec_transform, error_pointer) + handle_cf_error(error_pointer) + + return CFHelpers.cf_data_to_bytes(plaintext) + + finally: + if cf_dict: + CoreFoundation.CFRelease(cf_dict) + if cf_key: + CoreFoundation.CFRelease(cf_key) + if cf_data: + CoreFoundation.CFRelease(cf_data) + if cf_iv: + CoreFoundation.CFRelease(cf_iv) + if sec_key: + CoreFoundation.CFRelease(sec_key) + if sec_transform: + CoreFoundation.CFRelease(sec_transform) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_mac/tls.py b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_mac/tls.py new file mode 100644 index 00000000..a0ca540a --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_mac/tls.py @@ -0,0 +1,1513 @@ +# coding: utf-8 +from __future__ import unicode_literals, division, absolute_import, print_function + +import datetime +import sys +import re +import socket as socket_ +import select +import numbers +import errno +import weakref + +from ._security import Security, osx_version_info, handle_sec_error, SecurityConst +from ._core_foundation import CoreFoundation, handle_cf_error, CFHelpers +from .._asn1 import ( + Certificate as Asn1Certificate, + int_to_bytes, + timezone, +) +from .._errors import pretty_message +from .._ffi import ( + array_from_pointer, + array_set, + buffer_from_bytes, + bytes_from_buffer, + callback, + cast, + deref, + new, + null, + pointer_set, + struct, + struct_bytes, + unwrap, + write_to_buffer, +) +from .._types import type_name, str_cls, byte_cls, int_types +from .._cipher_suites import CIPHER_SUITE_MAP +from .util import rand_bytes +from ..errors import TLSError, TLSDisconnectError, TLSGracefulDisconnectError +from .._tls import ( + detect_client_auth_request, + detect_other_protocol, + extract_chain, + get_dh_params_length, + parse_session_info, + raise_client_auth, + raise_dh_params, + raise_disconnection, + raise_expired_not_yet_valid, + raise_handshake, + raise_hostname, + raise_no_issuer, + raise_protocol_error, + raise_protocol_version, + raise_revoked, + raise_self_signed, + raise_verification, + raise_weak_signature, +) +from .asymmetric import load_certificate, Certificate +from ..keys import parse_certificate + +if sys.version_info < (3,): + range = xrange # noqa + +if sys.version_info < (3, 7): + Pattern = re._pattern_type +else: + Pattern = re.Pattern + + +__all__ = [ + 'TLSSession', + 'TLSSocket', +] + + +_PROTOCOL_STRING_CONST_MAP = { + 'SSLv2': SecurityConst.kSSLProtocol2, + 'SSLv3': SecurityConst.kSSLProtocol3, + 'TLSv1': SecurityConst.kTLSProtocol1, + 'TLSv1.1': SecurityConst.kTLSProtocol11, + 'TLSv1.2': SecurityConst.kTLSProtocol12, +} + +_PROTOCOL_CONST_STRING_MAP = { + SecurityConst.kSSLProtocol2: 'SSLv2', + SecurityConst.kSSLProtocol3: 'SSLv3', + SecurityConst.kTLSProtocol1: 'TLSv1', + SecurityConst.kTLSProtocol11: 'TLSv1.1', + SecurityConst.kTLSProtocol12: 'TLSv1.2', +} + +_line_regex = re.compile(b'(\r\n|\r|\n)') +_cipher_blacklist_regex = re.compile('anon|PSK|SEED|RC4|MD5|NULL|CAMELLIA|ARIA|SRP|KRB5|EXPORT|(?<!3)DES|IDEA') +_connection_refs = weakref.WeakValueDictionary() +_socket_refs = {} + + +def _read_callback(connection_id, data_buffer, data_length_pointer): + """ + Callback called by Secure Transport to actually read the socket + + :param connection_id: + An integer identifing the connection + + :param data_buffer: + A char pointer FFI type to write the data to + + :param data_length_pointer: + A size_t pointer FFI type of the amount of data to read. Will be + overwritten with the amount of data read on return. + + :return: + An integer status code of the result - 0 for success + """ + + self = None + try: + self = _connection_refs.get(connection_id) + if not self: + socket = _socket_refs.get(connection_id) + else: + socket = self._socket + + if not self and not socket: + return 0 + + bytes_requested = deref(data_length_pointer) + + timeout = socket.gettimeout() + error = None + data = b'' + try: + while len(data) < bytes_requested: + # Python 2 on Travis CI seems to have issues with blocking on + # recv() for longer than the socket timeout value, so we select + if timeout is not None and timeout > 0.0: + read_ready, _, _ = select.select([socket], [], [], timeout) + if len(read_ready) == 0: + raise socket_.error(errno.EAGAIN, 'timed out') + chunk = socket.recv(bytes_requested - len(data)) + data += chunk + if chunk == b'': + if len(data) == 0: + if timeout is None: + return SecurityConst.errSSLClosedNoNotify + return SecurityConst.errSSLClosedAbort + break + except (socket_.error) as e: + error = e.errno + + if error is not None and error != errno.EAGAIN: + if error == errno.ECONNRESET or error == errno.EPIPE: + return SecurityConst.errSSLClosedNoNotify + return SecurityConst.errSSLClosedAbort + + if self and not self._done_handshake: + # SecureTransport doesn't bother to check if the TLS record header + # is valid before asking to read more data, which can result in + # connection hangs. Here we do basic checks to get around the issue. + if len(data) >= 3 and len(self._server_hello) == 0: + # Check to ensure it is an alert or handshake first + valid_record_type = data[0:1] in set([b'\x15', b'\x16']) + # Check if the protocol version is SSL 3.0 or TLS 1.0-1.3 + valid_protocol_version = data[1:3] in set([ + b'\x03\x00', + b'\x03\x01', + b'\x03\x02', + b'\x03\x03', + b'\x03\x04' + ]) + if not valid_record_type or not valid_protocol_version: + self._server_hello += data + _read_remaining(socket) + return SecurityConst.errSSLProtocol + self._server_hello += data + + write_to_buffer(data_buffer, data) + pointer_set(data_length_pointer, len(data)) + + if len(data) != bytes_requested: + return SecurityConst.errSSLWouldBlock + + return 0 + except (KeyboardInterrupt) as e: + if self: + self._exception = e + return SecurityConst.errSSLClosedAbort + + +def _read_remaining(socket): + """ + Reads everything available from the socket - used for debugging when there + is a protocol error + + :param socket: + The socket to read from + + :return: + A byte string of the remaining data + """ + + output = b'' + old_timeout = socket.gettimeout() + try: + socket.settimeout(0.0) + output += socket.recv(8192) + except (socket_.error): + pass + finally: + socket.settimeout(old_timeout) + return output + + +def _write_callback(connection_id, data_buffer, data_length_pointer): + """ + Callback called by Secure Transport to actually write to the socket + + :param connection_id: + An integer identifing the connection + + :param data_buffer: + A char pointer FFI type containing the data to write + + :param data_length_pointer: + A size_t pointer FFI type of the amount of data to write. Will be + overwritten with the amount of data actually written on return. + + :return: + An integer status code of the result - 0 for success + """ + + try: + self = _connection_refs.get(connection_id) + if not self: + socket = _socket_refs.get(connection_id) + else: + socket = self._socket + + if not self and not socket: + return 0 + + data_length = deref(data_length_pointer) + data = bytes_from_buffer(data_buffer, data_length) + + if self and not self._done_handshake: + self._client_hello += data + + error = None + try: + sent = socket.send(data) + except (socket_.error) as e: + error = e.errno + + if error is not None and error != errno.EAGAIN: + if error == errno.ECONNRESET or error == errno.EPIPE: + return SecurityConst.errSSLClosedNoNotify + return SecurityConst.errSSLClosedAbort + + if sent != data_length: + pointer_set(data_length_pointer, sent) + return SecurityConst.errSSLWouldBlock + + return 0 + except (KeyboardInterrupt) as e: + self._exception = e + return SecurityConst.errSSLPeerUserCancelled + + +_read_callback_pointer = callback(Security, 'SSLReadFunc', _read_callback) +_write_callback_pointer = callback(Security, 'SSLWriteFunc', _write_callback) + + +class TLSSession(object): + """ + A TLS session object that multiple TLSSocket objects can share for the + sake of session reuse + """ + + _protocols = None + _ciphers = None + _manual_validation = None + _extra_trust_roots = None + _peer_id = None + + def __init__(self, protocol=None, manual_validation=False, extra_trust_roots=None): + """ + :param protocol: + A unicode string or set of unicode strings representing allowable + protocols to negotiate with the server: + + - "TLSv1.2" + - "TLSv1.1" + - "TLSv1" + - "SSLv3" + + Default is: {"TLSv1", "TLSv1.1", "TLSv1.2"} + + :param manual_validation: + If certificate and certificate path validation should be skipped + and left to the developer to implement + + :param extra_trust_roots: + A list containing one or more certificates to be treated as trust + roots, in one of the following formats: + - A byte string of the DER encoded certificate + - A unicode string of the certificate filename + - An asn1crypto.x509.Certificate object + - An oscrypto.asymmetric.Certificate object + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + """ + + if not isinstance(manual_validation, bool): + raise TypeError(pretty_message( + ''' + manual_validation must be a boolean, not %s + ''', + type_name(manual_validation) + )) + + self._manual_validation = manual_validation + + if protocol is None: + protocol = set(['TLSv1', 'TLSv1.1', 'TLSv1.2']) + + if isinstance(protocol, str_cls): + protocol = set([protocol]) + elif not isinstance(protocol, set): + raise TypeError(pretty_message( + ''' + protocol must be a unicode string or set of unicode strings, + not %s + ''', + type_name(protocol) + )) + + unsupported_protocols = protocol - set(['SSLv3', 'TLSv1', 'TLSv1.1', 'TLSv1.2']) + if unsupported_protocols: + raise ValueError(pretty_message( + ''' + protocol must contain only the unicode strings "SSLv3", "TLSv1", + "TLSv1.1", "TLSv1.2", not %s + ''', + repr(unsupported_protocols) + )) + + self._protocols = protocol + + self._extra_trust_roots = [] + if extra_trust_roots: + for extra_trust_root in extra_trust_roots: + if isinstance(extra_trust_root, Certificate): + extra_trust_root = extra_trust_root.asn1 + elif isinstance(extra_trust_root, byte_cls): + extra_trust_root = parse_certificate(extra_trust_root) + elif isinstance(extra_trust_root, str_cls): + with open(extra_trust_root, 'rb') as f: + extra_trust_root = parse_certificate(f.read()) + elif not isinstance(extra_trust_root, Asn1Certificate): + raise TypeError(pretty_message( + ''' + extra_trust_roots must be a list of byte strings, unicode + strings, asn1crypto.x509.Certificate objects or + oscrypto.asymmetric.Certificate objects, not %s + ''', + type_name(extra_trust_root) + )) + self._extra_trust_roots.append(extra_trust_root) + + self._peer_id = rand_bytes(8) + + +class TLSSocket(object): + """ + A wrapper around a socket.socket that adds TLS + """ + + _socket = None + _session = None + _exception = None + + _session_context = None + + _decrypted_bytes = None + + _hostname = None + + _certificate = None + _intermediates = None + + _protocol = None + _cipher_suite = None + _compression = None + _session_id = None + _session_ticket = None + + _done_handshake = None + _server_hello = None + _client_hello = None + + _local_closed = False + _gracefully_closed = False + + _connection_id = None + + @classmethod + def wrap(cls, socket, hostname, session=None): + """ + Takes an existing socket and adds TLS + + :param socket: + A socket.socket object to wrap with TLS + + :param hostname: + A unicode string of the hostname or IP the socket is connected to + + :param session: + An existing TLSSession object to allow for session reuse, specific + protocol or manual certificate validation + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + """ + + if not isinstance(socket, socket_.socket): + raise TypeError(pretty_message( + ''' + socket must be an instance of socket.socket, not %s + ''', + type_name(socket) + )) + + if not isinstance(hostname, str_cls): + raise TypeError(pretty_message( + ''' + hostname must be a unicode string, not %s + ''', + type_name(hostname) + )) + + if session is not None and not isinstance(session, TLSSession): + raise TypeError(pretty_message( + ''' + session must be an instance of oscrypto.tls.TLSSession, not %s + ''', + type_name(session) + )) + + new_socket = cls(None, None, session=session) + new_socket._socket = socket + new_socket._hostname = hostname + new_socket._handshake() + + return new_socket + + def __init__(self, address, port, timeout=10, session=None): + """ + :param address: + A unicode string of the domain name or IP address to conenct to + + :param port: + An integer of the port number to connect to + + :param timeout: + An integer timeout to use for the socket + + :param session: + An oscrypto.tls.TLSSession object to allow for session reuse and + controlling the protocols and validation performed + """ + + self._done_handshake = False + self._server_hello = b'' + self._client_hello = b'' + + self._decrypted_bytes = b'' + + if address is None and port is None: + self._socket = None + + else: + if not isinstance(address, str_cls): + raise TypeError(pretty_message( + ''' + address must be a unicode string, not %s + ''', + type_name(address) + )) + + if not isinstance(port, int_types): + raise TypeError(pretty_message( + ''' + port must be an integer, not %s + ''', + type_name(port) + )) + + if timeout is not None and not isinstance(timeout, numbers.Number): + raise TypeError(pretty_message( + ''' + timeout must be a number, not %s + ''', + type_name(timeout) + )) + + self._socket = socket_.create_connection((address, port), timeout) + self._socket.settimeout(timeout) + + if session is None: + session = TLSSession() + + elif not isinstance(session, TLSSession): + raise TypeError(pretty_message( + ''' + session must be an instance of oscrypto.tls.TLSSession, not %s + ''', + type_name(session) + )) + + self._session = session + + if self._socket: + self._hostname = address + self._handshake() + + def _handshake(self): + """ + Perform an initial TLS handshake + """ + + session_context = None + ssl_policy_ref = None + crl_search_ref = None + crl_policy_ref = None + ocsp_search_ref = None + ocsp_policy_ref = None + policy_array_ref = None + trust_ref = None + + try: + if osx_version_info < (10, 8): + session_context_pointer = new(Security, 'SSLContextRef *') + result = Security.SSLNewContext(False, session_context_pointer) + handle_sec_error(result) + session_context = unwrap(session_context_pointer) + + else: + session_context = Security.SSLCreateContext( + null(), + SecurityConst.kSSLClientSide, + SecurityConst.kSSLStreamType + ) + + result = Security.SSLSetIOFuncs( + session_context, + _read_callback_pointer, + _write_callback_pointer + ) + handle_sec_error(result) + + self._connection_id = id(self) % 2147483647 + _connection_refs[self._connection_id] = self + _socket_refs[self._connection_id] = self._socket + result = Security.SSLSetConnection(session_context, self._connection_id) + handle_sec_error(result) + + utf8_domain = self._hostname.encode('utf-8') + result = Security.SSLSetPeerDomainName( + session_context, + utf8_domain, + len(utf8_domain) + ) + handle_sec_error(result) + + if osx_version_info >= (10, 10): + disable_auto_validation = self._session._manual_validation or self._session._extra_trust_roots + explicit_validation = (not self._session._manual_validation) and self._session._extra_trust_roots + else: + disable_auto_validation = True + explicit_validation = not self._session._manual_validation + + # Ensure requested protocol support is set for the session + if osx_version_info < (10, 8): + for protocol in ['SSLv2', 'SSLv3', 'TLSv1']: + protocol_const = _PROTOCOL_STRING_CONST_MAP[protocol] + enabled = protocol in self._session._protocols + result = Security.SSLSetProtocolVersionEnabled( + session_context, + protocol_const, + enabled + ) + handle_sec_error(result) + + if disable_auto_validation: + result = Security.SSLSetEnableCertVerify(session_context, False) + handle_sec_error(result) + + else: + protocol_consts = [_PROTOCOL_STRING_CONST_MAP[protocol] for protocol in self._session._protocols] + min_protocol = min(protocol_consts) + max_protocol = max(protocol_consts) + result = Security.SSLSetProtocolVersionMin( + session_context, + min_protocol + ) + handle_sec_error(result) + result = Security.SSLSetProtocolVersionMax( + session_context, + max_protocol + ) + handle_sec_error(result) + + if disable_auto_validation: + result = Security.SSLSetSessionOption( + session_context, + SecurityConst.kSSLSessionOptionBreakOnServerAuth, + True + ) + handle_sec_error(result) + + # Disable all sorts of bad cipher suites + supported_ciphers_pointer = new(Security, 'size_t *') + result = Security.SSLGetNumberSupportedCiphers(session_context, supported_ciphers_pointer) + handle_sec_error(result) + + supported_ciphers = deref(supported_ciphers_pointer) + + cipher_buffer = buffer_from_bytes(supported_ciphers * 4) + supported_cipher_suites_pointer = cast(Security, 'uint32_t *', cipher_buffer) + result = Security.SSLGetSupportedCiphers( + session_context, + supported_cipher_suites_pointer, + supported_ciphers_pointer + ) + handle_sec_error(result) + + supported_ciphers = deref(supported_ciphers_pointer) + supported_cipher_suites = array_from_pointer( + Security, + 'uint32_t', + supported_cipher_suites_pointer, + supported_ciphers + ) + good_ciphers = [] + for supported_cipher_suite in supported_cipher_suites: + cipher_suite = int_to_bytes(supported_cipher_suite, width=2) + cipher_suite_name = CIPHER_SUITE_MAP.get(cipher_suite, cipher_suite) + good_cipher = _cipher_blacklist_regex.search(cipher_suite_name) is None + if good_cipher: + good_ciphers.append(supported_cipher_suite) + + num_good_ciphers = len(good_ciphers) + good_ciphers_array = new(Security, 'uint32_t[]', num_good_ciphers) + array_set(good_ciphers_array, good_ciphers) + good_ciphers_pointer = cast(Security, 'uint32_t *', good_ciphers_array) + result = Security.SSLSetEnabledCiphers( + session_context, + good_ciphers_pointer, + num_good_ciphers + ) + handle_sec_error(result) + + # Set a peer id from the session to allow for session reuse, the hostname + # is appended to prevent a bug on OS X 10.7 where it tries to reuse a + # connection even if the hostnames are different. + peer_id = self._session._peer_id + self._hostname.encode('utf-8') + result = Security.SSLSetPeerID(session_context, peer_id, len(peer_id)) + handle_sec_error(result) + + handshake_result = Security.SSLHandshake(session_context) + if self._exception is not None: + exception = self._exception + self._exception = None + raise exception + while handshake_result == SecurityConst.errSSLWouldBlock: + handshake_result = Security.SSLHandshake(session_context) + if self._exception is not None: + exception = self._exception + self._exception = None + raise exception + + if osx_version_info < (10, 8) and osx_version_info >= (10, 7): + do_validation = explicit_validation and handshake_result == 0 + else: + do_validation = explicit_validation and handshake_result == SecurityConst.errSSLServerAuthCompleted + + if do_validation: + trust_ref_pointer = new(Security, 'SecTrustRef *') + result = Security.SSLCopyPeerTrust( + session_context, + trust_ref_pointer + ) + handle_sec_error(result) + trust_ref = unwrap(trust_ref_pointer) + + cf_string_hostname = CFHelpers.cf_string_from_unicode(self._hostname) + ssl_policy_ref = Security.SecPolicyCreateSSL(True, cf_string_hostname) + result = CoreFoundation.CFRelease(cf_string_hostname) + handle_cf_error(result) + + # Create a new policy for OCSP checking to disable it + ocsp_oid_pointer = struct(Security, 'CSSM_OID') + ocsp_oid = unwrap(ocsp_oid_pointer) + ocsp_oid.Length = len(SecurityConst.APPLE_TP_REVOCATION_OCSP) + ocsp_oid_buffer = buffer_from_bytes(SecurityConst.APPLE_TP_REVOCATION_OCSP) + ocsp_oid.Data = cast(Security, 'char *', ocsp_oid_buffer) + + ocsp_search_ref_pointer = new(Security, 'SecPolicySearchRef *') + result = Security.SecPolicySearchCreate( + SecurityConst.CSSM_CERT_X_509v3, + ocsp_oid_pointer, + null(), + ocsp_search_ref_pointer + ) + handle_sec_error(result) + ocsp_search_ref = unwrap(ocsp_search_ref_pointer) + + ocsp_policy_ref_pointer = new(Security, 'SecPolicyRef *') + result = Security.SecPolicySearchCopyNext(ocsp_search_ref, ocsp_policy_ref_pointer) + handle_sec_error(result) + ocsp_policy_ref = unwrap(ocsp_policy_ref_pointer) + + ocsp_struct_pointer = struct(Security, 'CSSM_APPLE_TP_OCSP_OPTIONS') + ocsp_struct = unwrap(ocsp_struct_pointer) + ocsp_struct.Version = SecurityConst.CSSM_APPLE_TP_OCSP_OPTS_VERSION + ocsp_struct.Flags = ( + SecurityConst.CSSM_TP_ACTION_OCSP_DISABLE_NET | + SecurityConst.CSSM_TP_ACTION_OCSP_CACHE_READ_DISABLE + ) + ocsp_struct_bytes = struct_bytes(ocsp_struct_pointer) + + cssm_data_pointer = struct(Security, 'CSSM_DATA') + cssm_data = unwrap(cssm_data_pointer) + cssm_data.Length = len(ocsp_struct_bytes) + ocsp_struct_buffer = buffer_from_bytes(ocsp_struct_bytes) + cssm_data.Data = cast(Security, 'char *', ocsp_struct_buffer) + + result = Security.SecPolicySetValue(ocsp_policy_ref, cssm_data_pointer) + handle_sec_error(result) + + # Create a new policy for CRL checking to disable it + crl_oid_pointer = struct(Security, 'CSSM_OID') + crl_oid = unwrap(crl_oid_pointer) + crl_oid.Length = len(SecurityConst.APPLE_TP_REVOCATION_CRL) + crl_oid_buffer = buffer_from_bytes(SecurityConst.APPLE_TP_REVOCATION_CRL) + crl_oid.Data = cast(Security, 'char *', crl_oid_buffer) + + crl_search_ref_pointer = new(Security, 'SecPolicySearchRef *') + result = Security.SecPolicySearchCreate( + SecurityConst.CSSM_CERT_X_509v3, + crl_oid_pointer, + null(), + crl_search_ref_pointer + ) + handle_sec_error(result) + crl_search_ref = unwrap(crl_search_ref_pointer) + + crl_policy_ref_pointer = new(Security, 'SecPolicyRef *') + result = Security.SecPolicySearchCopyNext(crl_search_ref, crl_policy_ref_pointer) + handle_sec_error(result) + crl_policy_ref = unwrap(crl_policy_ref_pointer) + + crl_struct_pointer = struct(Security, 'CSSM_APPLE_TP_CRL_OPTIONS') + crl_struct = unwrap(crl_struct_pointer) + crl_struct.Version = SecurityConst.CSSM_APPLE_TP_CRL_OPTS_VERSION + crl_struct.CrlFlags = 0 + crl_struct_bytes = struct_bytes(crl_struct_pointer) + + cssm_data_pointer = struct(Security, 'CSSM_DATA') + cssm_data = unwrap(cssm_data_pointer) + cssm_data.Length = len(crl_struct_bytes) + crl_struct_buffer = buffer_from_bytes(crl_struct_bytes) + cssm_data.Data = cast(Security, 'char *', crl_struct_buffer) + + result = Security.SecPolicySetValue(crl_policy_ref, cssm_data_pointer) + handle_sec_error(result) + + policy_array_ref = CFHelpers.cf_array_from_list([ + ssl_policy_ref, + crl_policy_ref, + ocsp_policy_ref + ]) + + result = Security.SecTrustSetPolicies(trust_ref, policy_array_ref) + handle_sec_error(result) + + if self._session._extra_trust_roots: + ca_cert_refs = [] + ca_certs = [] + for cert in self._session._extra_trust_roots: + ca_cert = load_certificate(cert) + ca_certs.append(ca_cert) + ca_cert_refs.append(ca_cert.sec_certificate_ref) + + result = Security.SecTrustSetAnchorCertificatesOnly(trust_ref, False) + handle_sec_error(result) + + array_ref = CFHelpers.cf_array_from_list(ca_cert_refs) + result = Security.SecTrustSetAnchorCertificates(trust_ref, array_ref) + handle_sec_error(result) + + result_pointer = new(Security, 'SecTrustResultType *') + result = Security.SecTrustEvaluate(trust_ref, result_pointer) + handle_sec_error(result) + + trust_result_code = deref(result_pointer) + invalid_chain_error_codes = set([ + SecurityConst.kSecTrustResultProceed, + SecurityConst.kSecTrustResultUnspecified + ]) + if trust_result_code not in invalid_chain_error_codes: + handshake_result = SecurityConst.errSSLXCertChainInvalid + else: + handshake_result = Security.SSLHandshake(session_context) + while handshake_result == SecurityConst.errSSLWouldBlock: + handshake_result = Security.SSLHandshake(session_context) + + self._done_handshake = True + + handshake_error_codes = set([ + SecurityConst.errSSLXCertChainInvalid, + SecurityConst.errSSLCertExpired, + SecurityConst.errSSLCertNotYetValid, + SecurityConst.errSSLUnknownRootCert, + SecurityConst.errSSLNoRootCert, + SecurityConst.errSSLHostNameMismatch, + SecurityConst.errSSLInternal, + ]) + + # In testing, only errSSLXCertChainInvalid was ever returned for + # all of these different situations, however we include the others + # for completeness. To get the real reason we have to use the + # certificate from the handshake and use the deprecated function + # SecTrustGetCssmResultCode(). + if handshake_result in handshake_error_codes: + if trust_ref: + CoreFoundation.CFRelease(trust_ref) + trust_ref = None + + trust_ref_pointer = new(Security, 'SecTrustRef *') + result = Security.SSLCopyPeerTrust( + session_context, + trust_ref_pointer + ) + handle_sec_error(result) + trust_ref = unwrap(trust_ref_pointer) + + result_code_pointer = new(Security, 'OSStatus *') + result = Security.SecTrustGetCssmResultCode(trust_ref, result_code_pointer) + result_code = deref(result_code_pointer) + + chain = extract_chain(self._server_hello) + + self_signed = False + revoked = False + expired = False + not_yet_valid = False + no_issuer = False + cert = None + bad_hostname = False + + if chain: + cert = chain[0] + oscrypto_cert = load_certificate(cert) + self_signed = oscrypto_cert.self_signed + revoked = result_code == SecurityConst.CSSMERR_TP_CERT_REVOKED + no_issuer = not self_signed and result_code == SecurityConst.CSSMERR_TP_NOT_TRUSTED + expired = result_code == SecurityConst.CSSMERR_TP_CERT_EXPIRED + not_yet_valid = result_code == SecurityConst.CSSMERR_TP_CERT_NOT_VALID_YET + bad_hostname = result_code == SecurityConst.CSSMERR_APPLETP_HOSTNAME_MISMATCH + + # On macOS 10.12, some expired certificates return errSSLInternal + if osx_version_info >= (10, 12): + validity = cert['tbs_certificate']['validity'] + not_before = validity['not_before'].chosen.native + not_after = validity['not_after'].chosen.native + utcnow = datetime.datetime.now(timezone.utc) + expired = not_after < utcnow + not_yet_valid = not_before > utcnow + + if chain and chain[0].hash_algo in set(['md5', 'md2']): + raise_weak_signature(chain[0]) + + if revoked: + raise_revoked(cert) + + if bad_hostname: + raise_hostname(cert, self._hostname) + + elif expired or not_yet_valid: + raise_expired_not_yet_valid(cert) + + elif no_issuer: + raise_no_issuer(cert) + + elif self_signed: + raise_self_signed(cert) + + if detect_client_auth_request(self._server_hello): + raise_client_auth() + + raise_verification(cert) + + if handshake_result == SecurityConst.errSSLPeerHandshakeFail: + if detect_client_auth_request(self._server_hello): + raise_client_auth() + raise_handshake() + + if handshake_result == SecurityConst.errSSLWeakPeerEphemeralDHKey: + raise_dh_params() + + if handshake_result == SecurityConst.errSSLPeerProtocolVersion: + raise_protocol_version() + + if handshake_result in set([SecurityConst.errSSLRecordOverflow, SecurityConst.errSSLProtocol]): + self._server_hello += _read_remaining(self._socket) + raise_protocol_error(self._server_hello) + + if handshake_result in set([SecurityConst.errSSLClosedNoNotify, SecurityConst.errSSLClosedAbort]): + if not self._done_handshake: + self._server_hello += _read_remaining(self._socket) + if detect_other_protocol(self._server_hello): + raise_protocol_error(self._server_hello) + raise_disconnection() + + if osx_version_info < (10, 10): + dh_params_length = get_dh_params_length(self._server_hello) + if dh_params_length is not None and dh_params_length < 1024: + raise_dh_params() + + would_block = handshake_result == SecurityConst.errSSLWouldBlock + server_auth_complete = handshake_result == SecurityConst.errSSLServerAuthCompleted + manual_validation = self._session._manual_validation and server_auth_complete + if not would_block and not manual_validation: + handle_sec_error(handshake_result, TLSError) + + self._session_context = session_context + + protocol_const_pointer = new(Security, 'SSLProtocol *') + result = Security.SSLGetNegotiatedProtocolVersion( + session_context, + protocol_const_pointer + ) + handle_sec_error(result) + protocol_const = deref(protocol_const_pointer) + + self._protocol = _PROTOCOL_CONST_STRING_MAP[protocol_const] + + cipher_int_pointer = new(Security, 'SSLCipherSuite *') + result = Security.SSLGetNegotiatedCipher( + session_context, + cipher_int_pointer + ) + handle_sec_error(result) + cipher_int = deref(cipher_int_pointer) + + cipher_bytes = int_to_bytes(cipher_int, width=2) + self._cipher_suite = CIPHER_SUITE_MAP.get(cipher_bytes, cipher_bytes) + + session_info = parse_session_info( + self._server_hello, + self._client_hello + ) + self._compression = session_info['compression'] + self._session_id = session_info['session_id'] + self._session_ticket = session_info['session_ticket'] + + except (OSError, socket_.error): + if session_context: + if osx_version_info < (10, 8): + result = Security.SSLDisposeContext(session_context) + handle_sec_error(result) + else: + result = CoreFoundation.CFRelease(session_context) + handle_cf_error(result) + + self._session_context = None + self.close() + + raise + + finally: + # Trying to release crl_search_ref or ocsp_search_ref results in + # a segmentation fault, so we do not do that + + if ssl_policy_ref: + result = CoreFoundation.CFRelease(ssl_policy_ref) + handle_cf_error(result) + ssl_policy_ref = None + + if crl_policy_ref: + result = CoreFoundation.CFRelease(crl_policy_ref) + handle_cf_error(result) + crl_policy_ref = None + + if ocsp_policy_ref: + result = CoreFoundation.CFRelease(ocsp_policy_ref) + handle_cf_error(result) + ocsp_policy_ref = None + + if policy_array_ref: + result = CoreFoundation.CFRelease(policy_array_ref) + handle_cf_error(result) + policy_array_ref = None + + if trust_ref: + CoreFoundation.CFRelease(trust_ref) + trust_ref = None + + def read(self, max_length): + """ + Reads data from the TLS-wrapped socket + + :param max_length: + The number of bytes to read - output may be less than this + + :raises: + socket.socket - when a non-TLS socket error occurs + oscrypto.errors.TLSError - when a TLS-related error occurs + oscrypto.errors.TLSDisconnectError - when the connection disconnects + oscrypto.errors.TLSGracefulDisconnectError - when the remote end gracefully closed the connection + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + + :return: + A byte string of the data read + """ + + if not isinstance(max_length, int_types): + raise TypeError(pretty_message( + ''' + max_length must be an integer, not %s + ''', + type_name(max_length) + )) + + if self._session_context is None: + # Even if the session is closed, we can use + # buffered data to respond to read requests + if self._decrypted_bytes != b'': + output = self._decrypted_bytes + self._decrypted_bytes = b'' + return output + + self._raise_closed() + + buffered_length = len(self._decrypted_bytes) + + # If we already have enough buffered data, just use that + if buffered_length >= max_length: + output = self._decrypted_bytes[0:max_length] + self._decrypted_bytes = self._decrypted_bytes[max_length:] + return output + + # Don't block if we have buffered data available, since it is ok to + # return less than the max_length + if buffered_length > 0 and not self.select_read(0): + output = self._decrypted_bytes + self._decrypted_bytes = b'' + return output + + # Only read enough to get the requested amount when + # combined with buffered data + to_read = max_length - len(self._decrypted_bytes) + + read_buffer = buffer_from_bytes(to_read) + processed_pointer = new(Security, 'size_t *') + result = Security.SSLRead( + self._session_context, + read_buffer, + to_read, + processed_pointer + ) + if self._exception is not None: + exception = self._exception + self._exception = None + raise exception + if result and result not in set([SecurityConst.errSSLWouldBlock, SecurityConst.errSSLClosedGraceful]): + handle_sec_error(result, TLSError) + + if result and result == SecurityConst.errSSLClosedGraceful: + self._gracefully_closed = True + self._shutdown(False) + self._raise_closed() + + bytes_read = deref(processed_pointer) + output = self._decrypted_bytes + bytes_from_buffer(read_buffer, bytes_read) + + self._decrypted_bytes = output[max_length:] + return output[0:max_length] + + def select_read(self, timeout=None): + """ + Blocks until the socket is ready to be read from, or the timeout is hit + + :param timeout: + A float - the period of time to wait for data to be read. None for + no time limit. + + :return: + A boolean - if data is ready to be read. Will only be False if + timeout is not None. + """ + + # If we have buffered data, we consider a read possible + if len(self._decrypted_bytes) > 0: + return True + + read_ready, _, _ = select.select([self._socket], [], [], timeout) + return len(read_ready) > 0 + + def read_until(self, marker): + """ + Reads data from the socket until a marker is found. Data read includes + the marker. + + :param marker: + A byte string or regex object from re.compile(). Used to determine + when to stop reading. Regex objects are more inefficient since + they must scan the entire byte string of read data each time data + is read off the socket. + + :return: + A byte string of the data read, including the marker + """ + + if not isinstance(marker, byte_cls) and not isinstance(marker, Pattern): + raise TypeError(pretty_message( + ''' + marker must be a byte string or compiled regex object, not %s + ''', + type_name(marker) + )) + + output = b'' + + is_regex = isinstance(marker, Pattern) + + while True: + if len(self._decrypted_bytes) > 0: + chunk = self._decrypted_bytes + self._decrypted_bytes = b'' + else: + to_read = self._os_buffered_size() or 8192 + chunk = self.read(to_read) + + offset = len(output) + output += chunk + + if is_regex: + match = marker.search(output) + if match is not None: + end = match.end() + break + else: + # If the marker was not found last time, we have to start + # at a position where the marker would have its final char + # in the newly read chunk + start = max(0, offset - len(marker) - 1) + match = output.find(marker, start) + if match != -1: + end = match + len(marker) + break + + self._decrypted_bytes = output[end:] + self._decrypted_bytes + return output[0:end] + + def _os_buffered_size(self): + """ + Returns the number of bytes of decrypted data stored in the Secure + Transport read buffer. This amount of data can be read from SSLRead() + without calling self._socket.recv(). + + :return: + An integer - the number of available bytes + """ + + num_bytes_pointer = new(Security, 'size_t *') + result = Security.SSLGetBufferedReadSize( + self._session_context, + num_bytes_pointer + ) + handle_sec_error(result) + + return deref(num_bytes_pointer) + + def read_line(self): + r""" + Reads a line from the socket, including the line ending of "\r\n", "\r", + or "\n" + + :return: + A byte string of the next line from the socket + """ + + return self.read_until(_line_regex) + + def read_exactly(self, num_bytes): + """ + Reads exactly the specified number of bytes from the socket + + :param num_bytes: + An integer - the exact number of bytes to read + + :return: + A byte string of the data that was read + """ + + output = b'' + remaining = num_bytes + while remaining > 0: + output += self.read(remaining) + remaining = num_bytes - len(output) + + return output + + def write(self, data): + """ + Writes data to the TLS-wrapped socket + + :param data: + A byte string to write to the socket + + :raises: + socket.socket - when a non-TLS socket error occurs + oscrypto.errors.TLSError - when a TLS-related error occurs + oscrypto.errors.TLSDisconnectError - when the connection disconnects + oscrypto.errors.TLSGracefulDisconnectError - when the remote end gracefully closed the connection + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + """ + + if self._session_context is None: + self._raise_closed() + + processed_pointer = new(Security, 'size_t *') + + data_len = len(data) + while data_len: + write_buffer = buffer_from_bytes(data) + result = Security.SSLWrite( + self._session_context, + write_buffer, + data_len, + processed_pointer + ) + if self._exception is not None: + exception = self._exception + self._exception = None + raise exception + handle_sec_error(result, TLSError) + + bytes_written = deref(processed_pointer) + data = data[bytes_written:] + data_len = len(data) + if data_len > 0: + self.select_write() + + def select_write(self, timeout=None): + """ + Blocks until the socket is ready to be written to, or the timeout is hit + + :param timeout: + A float - the period of time to wait for the socket to be ready to + written to. None for no time limit. + + :return: + A boolean - if the socket is ready for writing. Will only be False + if timeout is not None. + """ + + _, write_ready, _ = select.select([], [self._socket], [], timeout) + return len(write_ready) > 0 + + def _shutdown(self, manual): + """ + Shuts down the TLS session and then shuts down the underlying socket + + :param manual: + A boolean if the connection was manually shutdown + """ + + if self._session_context is None: + return + + # Ignore error during close in case other end closed already + result = Security.SSLClose(self._session_context) + + if osx_version_info < (10, 8): + result = Security.SSLDisposeContext(self._session_context) + handle_sec_error(result) + else: + result = CoreFoundation.CFRelease(self._session_context) + handle_cf_error(result) + + self._session_context = None + + if manual: + self._local_closed = True + + try: + self._socket.shutdown(socket_.SHUT_RDWR) + except (socket_.error): + pass + + def shutdown(self): + """ + Shuts down the TLS session and then shuts down the underlying socket + """ + + self._shutdown(True) + + def close(self): + """ + Shuts down the TLS session and socket and forcibly closes it + """ + + try: + self.shutdown() + + finally: + if self._socket: + try: + self._socket.close() + except (socket_.error): + pass + self._socket = None + + if self._connection_id in _socket_refs: + del _socket_refs[self._connection_id] + + def _read_certificates(self): + """ + Reads end-entity and intermediate certificate information from the + TLS session + """ + + trust_ref = None + cf_data_ref = None + result = None + + try: + trust_ref_pointer = new(Security, 'SecTrustRef *') + result = Security.SSLCopyPeerTrust( + self._session_context, + trust_ref_pointer + ) + handle_sec_error(result) + + trust_ref = unwrap(trust_ref_pointer) + + number_certs = Security.SecTrustGetCertificateCount(trust_ref) + + self._intermediates = [] + + for index in range(0, number_certs): + sec_certificate_ref = Security.SecTrustGetCertificateAtIndex( + trust_ref, + index + ) + cf_data_ref = Security.SecCertificateCopyData(sec_certificate_ref) + + cert_data = CFHelpers.cf_data_to_bytes(cf_data_ref) + + result = CoreFoundation.CFRelease(cf_data_ref) + handle_cf_error(result) + cf_data_ref = None + + cert = Asn1Certificate.load(cert_data) + + if index == 0: + self._certificate = cert + else: + self._intermediates.append(cert) + + finally: + if trust_ref: + result = CoreFoundation.CFRelease(trust_ref) + handle_cf_error(result) + if cf_data_ref: + result = CoreFoundation.CFRelease(cf_data_ref) + handle_cf_error(result) + + def _raise_closed(self): + """ + Raises an exception describing if the local or remote end closed the + connection + """ + + if self._local_closed: + raise TLSDisconnectError('The connection was already closed') + elif self._gracefully_closed: + raise TLSGracefulDisconnectError('The remote end closed the connection') + else: + raise TLSDisconnectError('The connection was closed') + + @property + def certificate(self): + """ + An asn1crypto.x509.Certificate object of the end-entity certificate + presented by the server + """ + + if self._session_context is None: + self._raise_closed() + + if self._certificate is None: + self._read_certificates() + + return self._certificate + + @property + def intermediates(self): + """ + A list of asn1crypto.x509.Certificate objects that were presented as + intermediates by the server + """ + + if self._session_context is None: + self._raise_closed() + + if self._certificate is None: + self._read_certificates() + + return self._intermediates + + @property + def cipher_suite(self): + """ + A unicode string of the IANA cipher suite name of the negotiated + cipher suite + """ + + return self._cipher_suite + + @property + def protocol(self): + """ + A unicode string of: "TLSv1.2", "TLSv1.1", "TLSv1", "SSLv3" + """ + + return self._protocol + + @property + def compression(self): + """ + A boolean if compression is enabled + """ + + return self._compression + + @property + def session_id(self): + """ + A unicode string of "new" or "reused" or None for no ticket + """ + + return self._session_id + + @property + def session_ticket(self): + """ + A unicode string of "new" or "reused" or None for no ticket + """ + + return self._session_ticket + + @property + def session(self): + """ + The oscrypto.tls.TLSSession object used for this connection + """ + + return self._session + + @property + def hostname(self): + """ + A unicode string of the TLS server domain name or IP address + """ + + return self._hostname + + @property + def port(self): + """ + An integer of the port number the socket is connected to + """ + + return self.socket.getpeername()[1] + + @property + def socket(self): + """ + The underlying socket.socket connection + """ + + if self._session_context is None: + self._raise_closed() + + return self._socket + + def __del__(self): + self.close() diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_mac/trust_list.py b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_mac/trust_list.py new file mode 100644 index 00000000..93943f00 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_mac/trust_list.py @@ -0,0 +1,208 @@ +# coding: utf-8 +from __future__ import unicode_literals, division, absolute_import, print_function + +import hashlib +import sys + +from .._asn1 import Certificate +from .._ffi import new, unwrap +from ._core_foundation import CoreFoundation, CFHelpers +from ._security import Security, SecurityConst, handle_sec_error + +if sys.version_info < (3,): + range = xrange # noqa + + +__all__ = [ + 'extract_from_system', + 'system_path', +] + + +def system_path(): + return None + + +def extract_from_system(cert_callback=None, callback_only_on_failure=False): + """ + Extracts trusted CA certificates from the OS X trusted root keychain. + + :param cert_callback: + A callback that is called once for each certificate in the trust store. + It should accept two parameters: an asn1crypto.x509.Certificate object, + and a reason. The reason will be None if the certificate is being + exported, otherwise it will be a unicode string of the reason it won't. + + :param callback_only_on_failure: + A boolean - if the callback should only be called when a certificate is + not exported. + + :raises: + OSError - when an error is returned by the OS crypto library + + :return: + A list of 3-element tuples: + - 0: a byte string of a DER-encoded certificate + - 1: a set of unicode strings that are OIDs of purposes to trust the + certificate for + - 2: a set of unicode strings that are OIDs of purposes to reject the + certificate for + """ + + certs_pointer_pointer = new(CoreFoundation, 'CFArrayRef *') + res = Security.SecTrustCopyAnchorCertificates(certs_pointer_pointer) + handle_sec_error(res) + + certs_pointer = unwrap(certs_pointer_pointer) + + certificates = {} + trust_info = {} + + all_purposes = '2.5.29.37.0' + default_trust = (set(), set()) + + length = CoreFoundation.CFArrayGetCount(certs_pointer) + for index in range(0, length): + cert_pointer = CoreFoundation.CFArrayGetValueAtIndex(certs_pointer, index) + der_cert, cert_hash = _cert_details(cert_pointer) + certificates[cert_hash] = der_cert + + CoreFoundation.CFRelease(certs_pointer) + + for domain in [SecurityConst.kSecTrustSettingsDomainUser, SecurityConst.kSecTrustSettingsDomainAdmin]: + cert_trust_settings_pointer_pointer = new(CoreFoundation, 'CFArrayRef *') + res = Security.SecTrustSettingsCopyCertificates(domain, cert_trust_settings_pointer_pointer) + if res == SecurityConst.errSecNoTrustSettings: + continue + handle_sec_error(res) + + cert_trust_settings_pointer = unwrap(cert_trust_settings_pointer_pointer) + + length = CoreFoundation.CFArrayGetCount(cert_trust_settings_pointer) + for index in range(0, length): + cert_pointer = CoreFoundation.CFArrayGetValueAtIndex(cert_trust_settings_pointer, index) + + trust_settings_pointer_pointer = new(CoreFoundation, 'CFArrayRef *') + res = Security.SecTrustSettingsCopyTrustSettings(cert_pointer, domain, trust_settings_pointer_pointer) + + # In OS X 10.11, this value started being seen. From the comments in + # the Security Framework Reference, the lack of any settings should + # indicate "always trust this certificate" + if res == SecurityConst.errSecItemNotFound: + continue + + # If the trust settings for a certificate are invalid, we need to + # assume the certificate should not be trusted + if res == SecurityConst.errSecInvalidTrustSettings: + der_cert, cert_hash = _cert_details(cert_pointer) + if cert_hash in certificates: + _cert_callback( + cert_callback, + certificates[cert_hash], + 'invalid trust settings' + ) + del certificates[cert_hash] + continue + + handle_sec_error(res) + + trust_settings_pointer = unwrap(trust_settings_pointer_pointer) + + trust_oids = set() + reject_oids = set() + settings_length = CoreFoundation.CFArrayGetCount(trust_settings_pointer) + for settings_index in range(0, settings_length): + settings_dict_entry = CoreFoundation.CFArrayGetValueAtIndex(trust_settings_pointer, settings_index) + settings_dict = CFHelpers.cf_dictionary_to_dict(settings_dict_entry) + + # No policy OID means the trust result is for all purposes + policy_oid = settings_dict.get('kSecTrustSettingsPolicy', {}).get('SecPolicyOid', all_purposes) + + # 0 = kSecTrustSettingsResultInvalid + # 1 = kSecTrustSettingsResultTrustRoot + # 2 = kSecTrustSettingsResultTrustAsRoot + # 3 = kSecTrustSettingsResultDeny + # 4 = kSecTrustSettingsResultUnspecified + trust_result = settings_dict.get('kSecTrustSettingsResult', 1) + should_trust = trust_result != 0 and trust_result != 3 + + if should_trust: + trust_oids.add(policy_oid) + else: + reject_oids.add(policy_oid) + + der_cert, cert_hash = _cert_details(cert_pointer) + + # If rejected for all purposes, we don't export the certificate + if all_purposes in reject_oids: + if cert_hash in certificates: + _cert_callback( + cert_callback, + certificates[cert_hash], + 'explicitly distrusted' + ) + del certificates[cert_hash] + else: + if all_purposes in trust_oids: + trust_oids = set([all_purposes]) + trust_info[cert_hash] = (trust_oids, reject_oids) + + CoreFoundation.CFRelease(trust_settings_pointer) + + CoreFoundation.CFRelease(cert_trust_settings_pointer) + + output = [] + for cert_hash in certificates: + if not callback_only_on_failure: + _cert_callback(cert_callback, certificates[cert_hash], None) + cert_trust_info = trust_info.get(cert_hash, default_trust) + output.append((certificates[cert_hash], cert_trust_info[0], cert_trust_info[1])) + return output + + +def _cert_callback(callback, der_cert, reason): + """ + Constructs an asn1crypto.x509.Certificate object and calls the export + callback + + :param callback: + The callback to call + + :param der_cert: + A byte string of the DER-encoded certificate + + :param reason: + None if cert is being exported, or a unicode string of the reason it + is not being exported + """ + + if not callback: + return + callback(Certificate.load(der_cert), reason) + + +def _cert_details(cert_pointer): + """ + Return the certificate and a hash of it + + :param cert_pointer: + A SecCertificateRef + + :return: + A 2-element tuple: + - [0]: A byte string of the SHA1 hash of the cert + - [1]: A byte string of the DER-encoded contents of the cert + """ + + data_pointer = None + + try: + data_pointer = Security.SecCertificateCopyData(cert_pointer) + der_cert = CFHelpers.cf_data_to_bytes(data_pointer) + cert_hash = hashlib.sha1(der_cert).digest() + + return (der_cert, cert_hash) + + finally: + if data_pointer is not None: + CoreFoundation.CFRelease(data_pointer) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_mac/util.py b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_mac/util.py new file mode 100644 index 00000000..34cc8c0e --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_mac/util.py @@ -0,0 +1,353 @@ +# coding: utf-8 +from __future__ import unicode_literals, division, absolute_import, print_function + +import os + +from .._errors import pretty_message +from .._ffi import buffer_from_bytes, bytes_from_buffer, errno, byte_string_from_buffer +from .._types import type_name, str_cls, byte_cls, int_types +from ..errors import LibraryNotFoundError +from ._common_crypto import CommonCrypto, CommonCryptoConst +from ._security import Security + + +__all__ = [ + 'pbkdf2', + 'pkcs12_kdf', + 'rand_bytes', +] + + +_encoding = 'utf-8' +_fallback_encodings = ['utf-8', 'cp1252'] + + +def _try_decode(value): + + try: + return str_cls(value, _encoding) + + # If the "correct" encoding did not work, try some defaults, and then just + # obliterate characters that we can't seen to decode properly + except (UnicodeDecodeError): + for encoding in _fallback_encodings: + try: + return str_cls(value, encoding, errors='strict') + except (UnicodeDecodeError): + pass + + return str_cls(value, errors='replace') + + +def _extract_error(): + """ + Extracts the last OS error message into a python unicode string + + :return: + A unicode string error message + """ + + error_num = errno() + + try: + error_string = os.strerror(error_num) + except (ValueError): + return str_cls(error_num) + + if isinstance(error_string, str_cls): + return error_string + + return _try_decode(error_string) + + +def pbkdf2(hash_algorithm, password, salt, iterations, key_length): + """ + PBKDF2 from PKCS#5 + + :param hash_algorithm: + The string name of the hash algorithm to use: "sha1", "sha224", "sha256", "sha384", "sha512" + + :param password: + A byte string of the password to use an input to the KDF + + :param salt: + A cryptographic random byte string + + :param iterations: + The numbers of iterations to use when deriving the key + + :param key_length: + The length of the desired key in bytes + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + + :return: + The derived key as a byte string + """ + + if not isinstance(password, byte_cls): + raise TypeError(pretty_message( + ''' + password must be a byte string, not %s + ''', + type_name(password) + )) + + if not isinstance(salt, byte_cls): + raise TypeError(pretty_message( + ''' + salt must be a byte string, not %s + ''', + type_name(salt) + )) + + if not isinstance(iterations, int_types): + raise TypeError(pretty_message( + ''' + iterations must be an integer, not %s + ''', + type_name(iterations) + )) + + if iterations < 1: + raise ValueError('iterations must be greater than 0') + + if not isinstance(key_length, int_types): + raise TypeError(pretty_message( + ''' + key_length must be an integer, not %s + ''', + type_name(key_length) + )) + + if key_length < 1: + raise ValueError('key_length must be greater than 0') + + if hash_algorithm not in set(['sha1', 'sha224', 'sha256', 'sha384', 'sha512']): + raise ValueError(pretty_message( + ''' + hash_algorithm must be one of "sha1", "sha224", "sha256", "sha384", + "sha512", not %s + ''', + repr(hash_algorithm) + )) + + algo = { + 'sha1': CommonCryptoConst.kCCPRFHmacAlgSHA1, + 'sha224': CommonCryptoConst.kCCPRFHmacAlgSHA224, + 'sha256': CommonCryptoConst.kCCPRFHmacAlgSHA256, + 'sha384': CommonCryptoConst.kCCPRFHmacAlgSHA384, + 'sha512': CommonCryptoConst.kCCPRFHmacAlgSHA512 + }[hash_algorithm] + + output_buffer = buffer_from_bytes(key_length) + result = CommonCrypto.CCKeyDerivationPBKDF( + CommonCryptoConst.kCCPBKDF2, + password, + len(password), + salt, + len(salt), + algo, + iterations, + output_buffer, + key_length + ) + if result != 0: + raise OSError(_extract_error()) + + return bytes_from_buffer(output_buffer) + + +pbkdf2.pure_python = False + + +def rand_bytes(length): + """ + Returns a number of random bytes suitable for cryptographic purposes + + :param length: + The desired number of bytes + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + + :return: + A byte string + """ + + if not isinstance(length, int_types): + raise TypeError(pretty_message( + ''' + length must be an integer, not %s + ''', + type_name(length) + )) + + if length < 1: + raise ValueError('length must be greater than 0') + + if length > 1024: + raise ValueError('length must not be greater than 1024') + + buffer = buffer_from_bytes(length) + result = Security.SecRandomCopyBytes(Security.kSecRandomDefault, length, buffer) + if result != 0: + raise OSError(_extract_error()) + + return bytes_from_buffer(buffer) + + +# If in a future version of OS X they remove OpenSSL, this try/except block +# will fall back to the pure Python implementation, which is just slower +try: + from .._openssl._libcrypto import libcrypto + + def _extract_openssl_error(): + """ + Extracts the last OpenSSL error message into a python unicode string + + :return: + A unicode string error message + """ + + error_num = libcrypto.ERR_get_error() + buffer = buffer_from_bytes(120) + libcrypto.ERR_error_string(error_num, buffer) + + # Since we are dealing with a string, it is NULL terminated + error_string = byte_string_from_buffer(buffer) + + return _try_decode(error_string) + + def pkcs12_kdf(hash_algorithm, password, salt, iterations, key_length, id_): + """ + KDF from RFC7292 appendix B.2 - https://tools.ietf.org/html/rfc7292#page-19 + + :param hash_algorithm: + The string name of the hash algorithm to use: "md5", "sha1", "sha224", "sha256", "sha384", "sha512" + + :param password: + A byte string of the password to use an input to the KDF + + :param salt: + A cryptographic random byte string + + :param iterations: + The numbers of iterations to use when deriving the key + + :param key_length: + The length of the desired key in bytes + + :param id_: + The ID of the usage - 1 for key, 2 for iv, 3 for mac + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + + :return: + The derived key as a byte string + """ + + if not isinstance(password, byte_cls): + raise TypeError(pretty_message( + ''' + password must be a byte string, not %s + ''', + type_name(password) + )) + + if not isinstance(salt, byte_cls): + raise TypeError(pretty_message( + ''' + salt must be a byte string, not %s + ''', + type_name(salt) + )) + + if not isinstance(iterations, int_types): + raise TypeError(pretty_message( + ''' + iterations must be an integer, not %s + ''', + type_name(iterations) + )) + + if iterations < 1: + raise ValueError(pretty_message( + ''' + iterations must be greater than 0 - is %s + ''', + repr(iterations) + )) + + if not isinstance(key_length, int_types): + raise TypeError(pretty_message( + ''' + key_length must be an integer, not %s + ''', + type_name(key_length) + )) + + if key_length < 1: + raise ValueError(pretty_message( + ''' + key_length must be greater than 0 - is %s + ''', + repr(key_length) + )) + + if hash_algorithm not in set(['md5', 'sha1', 'sha224', 'sha256', 'sha384', 'sha512']): + raise ValueError(pretty_message( + ''' + hash_algorithm must be one of "md5", "sha1", "sha224", "sha256", + "sha384", "sha512", not %s + ''', + repr(hash_algorithm) + )) + + if id_ not in set([1, 2, 3]): + raise ValueError(pretty_message( + ''' + id_ must be one of 1, 2, 3, not %s + ''', + repr(id_) + )) + + utf16_password = password.decode('utf-8').encode('utf-16be') + b'\x00\x00' + + digest_type = { + 'md5': libcrypto.EVP_md5, + 'sha1': libcrypto.EVP_sha1, + 'sha224': libcrypto.EVP_sha224, + 'sha256': libcrypto.EVP_sha256, + 'sha384': libcrypto.EVP_sha384, + 'sha512': libcrypto.EVP_sha512, + }[hash_algorithm]() + + output_buffer = buffer_from_bytes(key_length) + result = libcrypto.PKCS12_key_gen_uni( + utf16_password, + len(utf16_password), + salt, + len(salt), + id_, + iterations, + key_length, + output_buffer, + digest_type + ) + if result != 1: + raise OSError(_extract_openssl_error()) + + return bytes_from_buffer(output_buffer) + +except (LibraryNotFoundError): + + from .._pkcs12 import pkcs12_kdf diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_openssl/__init__.py b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_openssl/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_openssl/__pycache__/__init__.cpython-310.pyc b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_openssl/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 00000000..8827e6cd Binary files /dev/null and b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_openssl/__pycache__/__init__.cpython-310.pyc differ diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_openssl/__pycache__/_libcrypto.cpython-310.pyc b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_openssl/__pycache__/_libcrypto.cpython-310.pyc new file mode 100644 index 00000000..56cba2b8 Binary files /dev/null and b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_openssl/__pycache__/_libcrypto.cpython-310.pyc differ diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_openssl/__pycache__/_libcrypto_cffi.cpython-310.pyc b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_openssl/__pycache__/_libcrypto_cffi.cpython-310.pyc new file mode 100644 index 00000000..e1fb65cd Binary files /dev/null and b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_openssl/__pycache__/_libcrypto_cffi.cpython-310.pyc differ diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_openssl/__pycache__/asymmetric.cpython-310.pyc b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_openssl/__pycache__/asymmetric.cpython-310.pyc new file mode 100644 index 00000000..67ec5163 Binary files /dev/null and b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_openssl/__pycache__/asymmetric.cpython-310.pyc differ diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_openssl/__pycache__/symmetric.cpython-310.pyc b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_openssl/__pycache__/symmetric.cpython-310.pyc new file mode 100644 index 00000000..fb6832f2 Binary files /dev/null and b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_openssl/__pycache__/symmetric.cpython-310.pyc differ diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_openssl/__pycache__/util.cpython-310.pyc b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_openssl/__pycache__/util.cpython-310.pyc new file mode 100644 index 00000000..da881bab Binary files /dev/null and b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_openssl/__pycache__/util.cpython-310.pyc differ diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_openssl/_libcrypto.py b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_openssl/_libcrypto.py new file mode 100644 index 00000000..28816890 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_openssl/_libcrypto.py @@ -0,0 +1,131 @@ +# coding: utf-8 +from __future__ import unicode_literals, division, absolute_import, print_function + +from .. import ffi +from .._ffi import buffer_from_bytes, byte_string_from_buffer, null +from .._types import str_cls + +if ffi() == 'cffi': + from ._libcrypto_cffi import ( + libcrypto, + version as libcrypto_version, + version_info as libcrypto_version_info + ) +else: + from ._libcrypto_ctypes import ( + libcrypto, + version as libcrypto_version, + version_info as libcrypto_version_info + ) + + +__all__ = [ + 'handle_openssl_error', + 'libcrypto', + 'libcrypto_version', + 'libcrypto_version_info', + 'LibcryptoConst', + 'peek_openssl_error', +] + + +_encoding = 'utf-8' +_fallback_encodings = ['utf-8', 'cp1252'] + + +if libcrypto_version_info < (1, 1): + libcrypto.ERR_load_crypto_strings() +libcrypto.OPENSSL_config(null()) + + +def _try_decode(value): + + try: + return str_cls(value, _encoding) + + # If the "correct" encoding did not work, try some defaults, and then just + # obliterate characters that we can't seen to decode properly + except (UnicodeDecodeError): + for encoding in _fallback_encodings: + try: + return str_cls(value, encoding, errors='strict') + except (UnicodeDecodeError): + pass + + return str_cls(value, errors='replace') + + +def handle_openssl_error(result, exception_class=None): + """ + Checks if an error occured, and if so throws an OSError containing the + last OpenSSL error message + + :param result: + An integer result code - 1 or greater indicates success + + :param exception_class: + The exception class to use for the exception if an error occurred + + :raises: + OSError - when an OpenSSL error occurs + """ + + if result > 0: + return + + if exception_class is None: + exception_class = OSError + + error_num = libcrypto.ERR_get_error() + buffer = buffer_from_bytes(120) + libcrypto.ERR_error_string(error_num, buffer) + + # Since we are dealing with a string, it is NULL terminated + error_string = byte_string_from_buffer(buffer) + + raise exception_class(_try_decode(error_string)) + + +def peek_openssl_error(): + """ + Peeks into the error stack and pulls out the lib, func and reason + + :return: + A three-element tuple of integers (lib, func, reason) + """ + + error = libcrypto.ERR_peek_error() + lib = int((error >> 24) & 0xff) + func = int((error >> 12) & 0xfff) + reason = int(error & 0xfff) + + return (lib, func, reason) + + +class LibcryptoConst(): + EVP_CTRL_SET_RC2_KEY_BITS = 3 + + SSLEAY_VERSION = 0 + + RSA_PKCS1_PADDING = 1 + RSA_NO_PADDING = 3 + RSA_PKCS1_OAEP_PADDING = 4 + + # OpenSSL 0.9.x + EVP_MD_CTX_FLAG_PSS_MDLEN = -1 + + # OpenSSL 1.x.x + EVP_PKEY_CTRL_RSA_PADDING = 0x1001 + RSA_PKCS1_PSS_PADDING = 6 + EVP_PKEY_CTRL_RSA_PSS_SALTLEN = 0x1002 + EVP_PKEY_RSA = 6 + EVP_PKEY_OP_SIGN = 1 << 3 + EVP_PKEY_OP_VERIFY = 1 << 4 + + NID_X9_62_prime256v1 = 415 + NID_secp384r1 = 715 + NID_secp521r1 = 716 + + OPENSSL_EC_NAMED_CURVE = 1 + + DH_GENERATOR_2 = 2 diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_openssl/_libcrypto_cffi.py b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_openssl/_libcrypto_cffi.py new file mode 100644 index 00000000..25ea736f --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_openssl/_libcrypto_cffi.py @@ -0,0 +1,260 @@ +# coding: utf-8 +from __future__ import unicode_literals, division, absolute_import, print_function + +import re + +from .. import _backend_config +from .._errors import pretty_message +from .._ffi import get_library, register_ffi +from ..errors import LibraryNotFoundError + +from cffi import FFI + + +__all__ = [ + 'is_libressl', + 'libcrypto', + 'libressl_version', + 'libressl_version_info', + 'version', + 'version_info', +] + +libcrypto_path = _backend_config().get('libcrypto_path') +if libcrypto_path is None: + libcrypto_path = get_library('crypto', 'libcrypto.dylib', '42') +if not libcrypto_path: + raise LibraryNotFoundError('The library libcrypto could not be found') + +try: + vffi = FFI() + vffi.cdef("const char *SSLeay_version(int type);") + version_string = vffi.string(vffi.dlopen(libcrypto_path).SSLeay_version(0)).decode('utf-8') +except (AttributeError): + vffi = FFI() + vffi.cdef("const char *OpenSSL_version(int type);") + version_string = vffi.string(vffi.dlopen(libcrypto_path).OpenSSL_version(0)).decode('utf-8') + +is_libressl = 'LibreSSL' in version_string + +version_match = re.search('\\b(\\d\\.\\d\\.\\d[a-z]*)\\b', version_string) +if not version_match: + version_match = re.search('(?<=LibreSSL )(\\d\\.\\d(\\.\\d)?)\\b', version_string) +if not version_match: + raise LibraryNotFoundError('Error detecting the version of libcrypto') +version = version_match.group(1) +version_parts = re.sub('(\\d)([a-z]+)', '\\1.\\2', version).split('.') +version_info = tuple(int(part) if part.isdigit() else part for part in version_parts) + +# LibreSSL is compatible with libcrypto from OpenSSL 1.0.1 +libressl_version = '' +libressl_version_info = tuple() +if is_libressl: + libressl_version = version + libressl_version_info = version_info + version = '1.0.1' + version_info = (1, 0, 1) + +ffi = FFI() + +libcrypto = ffi.dlopen(libcrypto_path) +register_ffi(libcrypto, ffi) + +if version_info < (0, 9, 8): + raise LibraryNotFoundError(pretty_message( + ''' + OpenSSL versions older than 0.9.8 are not supported - found version %s + ''', + version + )) + +if version_info < (1, 1): + ffi.cdef(""" + void ERR_load_crypto_strings(void); + void ERR_free_strings(void); + """) + +# The typedef uintptr_t lines here allow us to check for a NULL pointer, +# without having to redefine the structs in our code. This is kind of a hack, +# but it should cause problems since we treat these as opaque. +ffi.cdef(""" + typedef ... EVP_MD; + typedef uintptr_t EVP_CIPHER_CTX; + typedef ... EVP_CIPHER; + typedef ... ENGINE; + typedef uintptr_t EVP_PKEY; + typedef uintptr_t X509; + typedef uintptr_t DH; + typedef uintptr_t RSA; + typedef uintptr_t DSA; + typedef uintptr_t EC_KEY; + typedef ... EVP_MD_CTX; + typedef ... EVP_PKEY_CTX; + typedef ... BN_GENCB; + typedef ... BIGNUM; + + unsigned long ERR_get_error(void); + char *ERR_error_string(unsigned long e, char *buf); + unsigned long ERR_peek_error(void); + + void OPENSSL_config(const char *config_name); + + EVP_CIPHER_CTX *EVP_CIPHER_CTX_new(void); + void EVP_CIPHER_CTX_free(EVP_CIPHER_CTX *ctx); + + int EVP_CIPHER_CTX_set_key_length(EVP_CIPHER_CTX *x, int keylen); + int EVP_CIPHER_CTX_set_padding(EVP_CIPHER_CTX *x, int padding); + int EVP_CIPHER_CTX_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr); + + const EVP_CIPHER *EVP_aes_128_cbc(void); + const EVP_CIPHER *EVP_aes_192_cbc(void); + const EVP_CIPHER *EVP_aes_256_cbc(void); + const EVP_CIPHER *EVP_des_cbc(void); + const EVP_CIPHER *EVP_des_ede_cbc(void); + const EVP_CIPHER *EVP_des_ede3_cbc(void); + const EVP_CIPHER *EVP_rc4(void); + const EVP_CIPHER *EVP_rc2_cbc(void); + + int EVP_EncryptInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, + ENGINE *impl, const char *key, + const char *iv); + int EVP_EncryptUpdate(EVP_CIPHER_CTX *ctx, char *out, int *outl, + const char *in, int inl); + int EVP_EncryptFinal_ex(EVP_CIPHER_CTX *ctx, char *out, int *outl); + + int EVP_DecryptInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, + ENGINE *impl, const char *key, + const char *iv); + int EVP_DecryptUpdate(EVP_CIPHER_CTX *ctx, char *out, int *outl, + const char *in, int inl); + int EVP_DecryptFinal_ex(EVP_CIPHER_CTX *ctx, char *out, int *outl); + + EVP_PKEY *d2i_AutoPrivateKey(EVP_PKEY **a, const char **pp, + long length); + EVP_PKEY *d2i_PUBKEY(EVP_PKEY **a, const char **pp, long length); + int i2d_PUBKEY(EVP_PKEY *a, char **pp); + void EVP_PKEY_free(EVP_PKEY *key); + + X509 *d2i_X509(X509 **px, const char **in, int len); + int i2d_X509(X509 *x, char **out); + EVP_PKEY *X509_get_pubkey(X509 *x); + void X509_free(X509 *a); + + int EVP_PKEY_size(EVP_PKEY *pkey); + RSA *EVP_PKEY_get1_RSA(EVP_PKEY *pkey); + void RSA_free(RSA *r); + + int RSA_public_encrypt(int flen, const char *from, + char *to, RSA *rsa, int padding); + int RSA_private_encrypt(int flen, const char *from, + char *to, RSA *rsa, int padding); + int RSA_public_decrypt(int flen, const char *from, + char *to, RSA *rsa, int padding); + int RSA_private_decrypt(int flen, const char *from, + char *to, RSA *rsa, int padding); + + int EVP_DigestUpdate(EVP_MD_CTX *ctx, const void *d, unsigned int cnt); + + const EVP_MD *EVP_md5(void); + const EVP_MD *EVP_sha1(void); + const EVP_MD *EVP_sha224(void); + const EVP_MD *EVP_sha256(void); + const EVP_MD *EVP_sha384(void); + const EVP_MD *EVP_sha512(void); + + int PKCS12_key_gen_uni(char *pass, int passlen, char *salt, + int saltlen, int id, int iter, int n, + char *out, const EVP_MD *md_type); + + void BN_free(BIGNUM *a); + int BN_dec2bn(BIGNUM **a, const char *str); + + DH *DH_new(void); + int DH_generate_parameters_ex(DH *dh, int prime_len, int generator, BN_GENCB *cb); + int i2d_DHparams(const DH *a, char **pp); + void DH_free(DH *dh); + + RSA *RSA_new(void); + int RSA_generate_key_ex(RSA *rsa, int bits, BIGNUM *e, BN_GENCB *cb); + int i2d_RSAPublicKey(RSA *a, char **pp); + int i2d_RSAPrivateKey(RSA *a, char **pp); + + DSA *DSA_new(void); + int DSA_generate_parameters_ex(DSA *dsa, int bits, + const char *seed, int seed_len, int *counter_ret, + unsigned long *h_ret, BN_GENCB *cb); + int DSA_generate_key(DSA *a); + int i2d_DSA_PUBKEY(const DSA *a, char **pp); + int i2d_DSAPrivateKey(const DSA *a, char **pp); + void DSA_free(DSA *dsa); + + EC_KEY *EC_KEY_new_by_curve_name(int nid); + int EC_KEY_generate_key(EC_KEY *key); + void EC_KEY_set_asn1_flag(EC_KEY *, int); + int i2d_ECPrivateKey(EC_KEY *key, char **out); + int i2o_ECPublicKey(EC_KEY *key, char **out); + void EC_KEY_free(EC_KEY *key); +""") + +if version_info < (1, 1): + ffi.cdef(""" + EVP_MD_CTX *EVP_MD_CTX_create(void); + void EVP_MD_CTX_destroy(EVP_MD_CTX *ctx); + """) +else: + ffi.cdef(""" + EVP_MD_CTX *EVP_MD_CTX_new(void); + void EVP_MD_CTX_free(EVP_MD_CTX *ctx); + """) + +if version_info < (1,): + ffi.cdef(""" + typedef ... *DSA_SIG; + typedef ... *ECDSA_SIG; + + DSA_SIG *DSA_do_sign(const char *dgst, int dlen, DSA *dsa); + ECDSA_SIG *ECDSA_do_sign(const char *dgst, int dgst_len, EC_KEY *eckey); + + DSA_SIG *d2i_DSA_SIG(DSA_SIG **v, const char **pp, long length); + ECDSA_SIG *d2i_ECDSA_SIG(ECDSA_SIG **v, const char **pp, long len); + + int i2d_DSA_SIG(const DSA_SIG *a, char **pp); + int i2d_ECDSA_SIG(const ECDSA_SIG *a, char **pp); + + int DSA_do_verify(const char *dgst, int dgst_len, DSA_SIG *sig, DSA *dsa); + int ECDSA_do_verify(const char *dgst, int dgst_len, const ECDSA_SIG *sig, EC_KEY *eckey); + + void DSA_SIG_free(DSA_SIG *a); + void ECDSA_SIG_free(ECDSA_SIG *a); + + DSA *EVP_PKEY_get1_DSA(EVP_PKEY *pkey); + EC_KEY *EVP_PKEY_get1_EC_KEY(EVP_PKEY *pkey); + + int RSA_verify_PKCS1_PSS(RSA *rsa, const char *mHash, + const EVP_MD *Hash, const char *EM, + int sLen); + int RSA_padding_add_PKCS1_PSS(RSA *rsa, char *EM, + const char *mHash, const EVP_MD *Hash, + int sLen); + + int EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl); + int EVP_SignFinal(EVP_MD_CTX *ctx, char *sig, unsigned int *s, EVP_PKEY *pkey); + int EVP_VerifyFinal(EVP_MD_CTX *ctx, char *sigbuf, unsigned int siglen, EVP_PKEY *pkey); + + void EVP_MD_CTX_set_flags(EVP_MD_CTX *ctx, int flags); + """) +else: + ffi.cdef(""" + int PKCS5_PBKDF2_HMAC(const char *pass, int passlen, + const char *salt, int saltlen, int iter, + const EVP_MD *digest, + int keylen, char *out); + + int EVP_DigestSignInit(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx, const EVP_MD *type, ENGINE *e, EVP_PKEY *pkey); + int EVP_DigestSignFinal(EVP_MD_CTX *ctx, char *sig, size_t *siglen); + + int EVP_DigestVerifyInit(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx, const EVP_MD *type, ENGINE *e, EVP_PKEY *pkey); + int EVP_DigestVerifyFinal(EVP_MD_CTX *ctx, const char *sig, size_t siglen); + + int EVP_PKEY_CTX_ctrl(EVP_PKEY_CTX *ctx, int keytype, int optype, int cmd, int p1, void *p2); + """) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_openssl/_libcrypto_ctypes.py b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_openssl/_libcrypto_ctypes.py new file mode 100644 index 00000000..f7836633 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_openssl/_libcrypto_ctypes.py @@ -0,0 +1,692 @@ +# coding: utf-8 +from __future__ import unicode_literals, division, absolute_import, print_function + +import re + +from ctypes import CDLL, c_void_p, c_char_p, c_int, c_ulong, c_uint, c_long, c_size_t, POINTER + +from .. import _backend_config +from .._errors import pretty_message +from .._ffi import FFIEngineError, get_library +from ..errors import LibraryNotFoundError + + +__all__ = [ + 'is_libressl', + 'libcrypto', + 'libressl_version', + 'libressl_version_info', + 'version', + 'version_info', +] + + +libcrypto_path = _backend_config().get('libcrypto_path') +if libcrypto_path is None: + libcrypto_path = get_library('crypto', 'libcrypto.dylib', '42') +if not libcrypto_path: + raise LibraryNotFoundError('The library libcrypto could not be found') + +libcrypto = CDLL(libcrypto_path, use_errno=True) + +try: + libcrypto.SSLeay_version.argtypes = [c_int] + libcrypto.SSLeay_version.restype = c_char_p + version_string = libcrypto.SSLeay_version(0).decode('utf-8') +except (AttributeError): + libcrypto.OpenSSL_version.argtypes = [c_int] + libcrypto.OpenSSL_version.restype = c_char_p + version_string = libcrypto.OpenSSL_version(0).decode('utf-8') + +is_libressl = 'LibreSSL' in version_string + +version_match = re.search('\\b(\\d\\.\\d\\.\\d[a-z]*)\\b', version_string) +if not version_match: + version_match = re.search('(?<=LibreSSL )(\\d\\.\\d(\\.\\d)?)\\b', version_string) +if not version_match: + raise LibraryNotFoundError('Error detecting the version of libcrypto') +version = version_match.group(1) +version_parts = re.sub('(\\d)([a-z]+)', '\\1.\\2', version).split('.') +version_info = tuple(int(part) if part.isdigit() else part for part in version_parts) + +# LibreSSL is compatible with libcrypto from OpenSSL 1.0.1 +libressl_version = '' +libressl_version_info = tuple() +if is_libressl: + libressl_version = version + libressl_version_info = version_info + version = '1.0.1' + version_info = (1, 0, 1) + +if version_info < (0, 9, 8): + raise LibraryNotFoundError(pretty_message( + ''' + OpenSSL versions older than 0.9.8 are not supported - found version %s + ''', + version + )) + +P_EVP_CIPHER_CTX = c_void_p +P_EVP_CIPHER = c_void_p + +P_EVP_MD_CTX = c_void_p +P_EVP_MD = c_void_p + +P_ENGINE = c_void_p + +P_EVP_PKEY = c_void_p +EVP_PKEY_CTX = c_void_p +P_EVP_PKEY_CTX = POINTER(c_void_p) +P_X509 = POINTER(c_void_p) +P_DH = c_void_p +P_RSA = c_void_p +P_DSA = c_void_p +P_EC_KEY = c_void_p +P_BN_GENCB = c_void_p +BIGNUM = c_void_p +P_BIGNUM = POINTER(BIGNUM) + +p_int = POINTER(c_int) +p_uint = POINTER(c_uint) + +try: + if version_info < (1, 1): + libcrypto.ERR_load_crypto_strings.argtypes = [] + libcrypto.ERR_load_crypto_strings.restype = None + + libcrypto.ERR_free_strings.argtypes = [] + libcrypto.ERR_free_strings.restype = None + + libcrypto.ERR_get_error.argtypes = [] + libcrypto.ERR_get_error.restype = c_ulong + + libcrypto.ERR_peek_error.argtypes = [] + libcrypto.ERR_peek_error.restype = c_ulong + + libcrypto.ERR_error_string.argtypes = [ + c_ulong, + c_char_p + ] + libcrypto.ERR_error_string.restype = c_char_p + + libcrypto.OPENSSL_config.argtypes = [ + c_char_p + ] + libcrypto.OPENSSL_config.restype = None + + # This allocates the memory and inits + libcrypto.EVP_CIPHER_CTX_new.argtype = [] + libcrypto.EVP_CIPHER_CTX_new.restype = P_EVP_CIPHER_CTX + + libcrypto.EVP_CIPHER_CTX_set_key_length.argtypes = [ + P_EVP_CIPHER_CTX, + c_int + ] + libcrypto.EVP_CIPHER_CTX_set_key_length.restype = c_int + + libcrypto.EVP_CIPHER_CTX_set_padding.argtypes = [ + P_EVP_CIPHER_CTX, + c_int + ] + libcrypto.EVP_CIPHER_CTX_set_padding.restype = c_int + + libcrypto.EVP_CIPHER_CTX_ctrl.argtypes = [ + P_EVP_CIPHER_CTX, + c_int, + c_int, + c_void_p + ] + libcrypto.EVP_CIPHER_CTX_ctrl.restype = c_int + + # This cleans up and frees + libcrypto.EVP_CIPHER_CTX_free.argtypes = [ + P_EVP_CIPHER_CTX + ] + libcrypto.EVP_CIPHER_CTX_free.restype = None + + libcrypto.EVP_aes_128_cbc.argtypes = [] + libcrypto.EVP_aes_128_cbc.restype = P_EVP_CIPHER + + libcrypto.EVP_aes_192_cbc.argtypes = [] + libcrypto.EVP_aes_192_cbc.restype = P_EVP_CIPHER + + libcrypto.EVP_aes_256_cbc.argtypes = [] + libcrypto.EVP_aes_256_cbc.restype = P_EVP_CIPHER + + libcrypto.EVP_des_cbc.argtypes = [] + libcrypto.EVP_des_cbc.restype = P_EVP_CIPHER + + libcrypto.EVP_des_ede_cbc.argtypes = [] + libcrypto.EVP_des_ede_cbc.restype = P_EVP_CIPHER + + libcrypto.EVP_des_ede3_cbc.argtypes = [] + libcrypto.EVP_des_ede3_cbc.restype = P_EVP_CIPHER + + libcrypto.EVP_rc4.argtypes = [] + libcrypto.EVP_rc4.restype = P_EVP_CIPHER + + libcrypto.EVP_rc2_cbc.argtypes = [] + libcrypto.EVP_rc2_cbc.restype = P_EVP_CIPHER + + libcrypto.EVP_EncryptInit_ex.argtypes = [ + P_EVP_CIPHER_CTX, + P_EVP_CIPHER, + P_ENGINE, + c_char_p, + c_char_p + ] + libcrypto.EVP_EncryptInit_ex.restype = c_int + + libcrypto.EVP_EncryptUpdate.argtypes = [ + P_EVP_CIPHER_CTX, + c_char_p, + p_int, + c_char_p, + c_int + ] + libcrypto.EVP_EncryptUpdate.restype = c_int + + libcrypto.EVP_EncryptFinal_ex.argtypes = [ + P_EVP_CIPHER_CTX, + c_char_p, + p_int + ] + libcrypto.EVP_EncryptFinal_ex.restype = c_int + + libcrypto.EVP_DecryptInit_ex.argtypes = [ + P_EVP_CIPHER_CTX, + P_EVP_CIPHER, + P_ENGINE, + c_char_p, + c_char_p + ] + libcrypto.EVP_DecryptInit_ex.restype = c_int + + libcrypto.EVP_DecryptUpdate.argtypes = [ + P_EVP_CIPHER_CTX, + c_char_p, + p_int, + c_char_p, + c_int + ] + libcrypto.EVP_DecryptUpdate.restype = c_int + + libcrypto.EVP_DecryptFinal_ex.argtypes = [ + P_EVP_CIPHER_CTX, + c_char_p, + p_int + ] + libcrypto.EVP_DecryptFinal_ex.restype = c_int + + libcrypto.d2i_AutoPrivateKey.argtypes = [ + POINTER(P_EVP_PKEY), + POINTER(c_char_p), + c_int + ] + libcrypto.d2i_AutoPrivateKey.restype = P_EVP_PKEY + + libcrypto.d2i_PUBKEY.argtypes = [ + POINTER(P_EVP_PKEY), + POINTER(c_char_p), + c_int + ] + libcrypto.d2i_PUBKEY.restype = P_EVP_PKEY + + libcrypto.i2d_PUBKEY.argtypes = [ + P_EVP_PKEY, + POINTER(c_char_p) + ] + libcrypto.i2d_PUBKEY.restype = c_int + + libcrypto.d2i_X509.argtypes = [ + POINTER(P_X509), + POINTER(c_char_p), + c_int + ] + libcrypto.d2i_X509.restype = P_X509 + + libcrypto.i2d_X509.argtypes = [ + P_X509, + POINTER(c_char_p) + ] + libcrypto.i2d_X509.restype = c_int + + libcrypto.X509_get_pubkey.argtypes = [ + P_X509 + ] + libcrypto.X509_get_pubkey.restype = P_EVP_PKEY + + libcrypto.X509_free.argtypes = [ + P_X509 + ] + libcrypto.X509_free.restype = None + + libcrypto.EVP_PKEY_free.argtypes = [ + P_EVP_PKEY + ] + libcrypto.EVP_PKEY_free.restype = None + + if version_info < (1, 1): + libcrypto.EVP_MD_CTX_create.argtypes = [] + libcrypto.EVP_MD_CTX_create.restype = P_EVP_MD_CTX + + libcrypto.EVP_MD_CTX_destroy.argtypes = [ + P_EVP_MD_CTX + ] + libcrypto.EVP_MD_CTX_destroy.restype = None + else: + libcrypto.EVP_MD_CTX_new.argtypes = [] + libcrypto.EVP_MD_CTX_new.restype = P_EVP_MD_CTX + + libcrypto.EVP_MD_CTX_free.argtypes = [ + P_EVP_MD_CTX + ] + libcrypto.EVP_MD_CTX_free.restype = None + + libcrypto.EVP_md5.argtypes = [] + libcrypto.EVP_md5.restype = P_EVP_MD + + libcrypto.EVP_sha1.argtypes = [] + libcrypto.EVP_sha1.restype = P_EVP_MD + + libcrypto.EVP_sha224.argtypes = [] + libcrypto.EVP_sha224.restype = P_EVP_MD + + libcrypto.EVP_sha256.argtypes = [] + libcrypto.EVP_sha256.restype = P_EVP_MD + + libcrypto.EVP_sha384.argtypes = [] + libcrypto.EVP_sha384.restype = P_EVP_MD + + libcrypto.EVP_sha512.argtypes = [] + libcrypto.EVP_sha512.restype = P_EVP_MD + + libcrypto.EVP_PKEY_size.argtypes = [ + P_EVP_PKEY + ] + libcrypto.EVP_PKEY_size.restype = c_int + + libcrypto.EVP_PKEY_get1_RSA.argtypes = [ + P_EVP_PKEY + ] + libcrypto.EVP_PKEY_get1_RSA.restype = P_RSA + + libcrypto.RSA_free.argtypes = [ + P_RSA + ] + libcrypto.RSA_free.restype = None + + libcrypto.RSA_public_encrypt.argtypes = [ + c_int, + c_char_p, + c_char_p, + P_RSA, + c_int + ] + libcrypto.RSA_public_encrypt.restype = c_int + + libcrypto.RSA_private_encrypt.argtypes = [ + c_int, + c_char_p, + c_char_p, + P_RSA, + c_int + ] + libcrypto.RSA_private_encrypt.restype = c_int + + libcrypto.RSA_public_decrypt.argtypes = [ + c_int, + c_char_p, + c_char_p, + P_RSA, + c_int + ] + libcrypto.RSA_public_decrypt.restype = c_int + + libcrypto.RSA_private_decrypt.argtypes = [ + c_int, + c_char_p, + c_char_p, + P_RSA, + c_int + ] + libcrypto.RSA_private_decrypt.restype = c_int + + libcrypto.EVP_DigestUpdate.argtypes = [ + P_EVP_MD_CTX, + c_char_p, + c_uint + ] + libcrypto.EVP_DigestUpdate.restype = c_int + + libcrypto.PKCS12_key_gen_uni.argtypes = [ + c_char_p, + c_int, + c_char_p, + c_int, + c_int, + c_int, + c_int, + c_char_p, + c_void_p + ] + libcrypto.PKCS12_key_gen_uni.restype = c_int + + libcrypto.BN_free.argtypes = [ + P_BIGNUM + ] + libcrypto.BN_free.restype = None + + libcrypto.BN_dec2bn.argtypes = [ + POINTER(P_BIGNUM), + c_char_p + ] + libcrypto.BN_dec2bn.restype = c_int + + libcrypto.DH_new.argtypes = [] + libcrypto.DH_new.restype = P_DH + + libcrypto.DH_generate_parameters_ex.argtypes = [ + P_DH, + c_int, + c_int, + P_BN_GENCB + ] + libcrypto.DH_generate_parameters_ex.restype = c_int + + libcrypto.i2d_DHparams.argtypes = [ + P_DH, + POINTER(c_char_p) + ] + libcrypto.i2d_DHparams.restype = c_int + + libcrypto.DH_free.argtypes = [ + P_DH + ] + libcrypto.DH_free.restype = None + + libcrypto.RSA_new.argtypes = [] + libcrypto.RSA_new.restype = P_RSA + + libcrypto.RSA_generate_key_ex.argtypes = [ + P_RSA, + c_int, + P_BIGNUM, + P_BN_GENCB + ] + libcrypto.RSA_generate_key_ex.restype = c_int + + libcrypto.i2d_RSAPublicKey.argtypes = [ + P_RSA, + POINTER(c_char_p) + ] + libcrypto.i2d_RSAPublicKey.restype = c_int + + libcrypto.i2d_RSAPrivateKey.argtypes = [ + P_RSA, + POINTER(c_char_p) + ] + libcrypto.i2d_RSAPrivateKey.restype = c_int + + libcrypto.RSA_free.argtypes = [ + P_RSA + ] + libcrypto.RSA_free.restype = None + + libcrypto.DSA_new.argtypes = [] + libcrypto.DSA_new.restype = P_DSA + + libcrypto.DSA_generate_parameters_ex.argtypes = [ + P_DSA, + c_int, + c_char_p, + c_int, + POINTER(c_int), + POINTER(c_ulong), + P_BN_GENCB + ] + libcrypto.DSA_generate_parameters_ex.restype = c_int + + libcrypto.DSA_generate_key.argtypes = [ + P_DSA + ] + libcrypto.DSA_generate_key.restype = c_int + + libcrypto.i2d_DSA_PUBKEY.argtypes = [ + P_DSA, + POINTER(c_char_p) + ] + libcrypto.i2d_DSA_PUBKEY.restype = c_int + + libcrypto.i2d_DSAPrivateKey.argtypes = [ + P_DSA, + POINTER(c_char_p) + ] + libcrypto.i2d_DSAPrivateKey.restype = c_int + + libcrypto.DSA_free.argtypes = [ + P_DSA + ] + libcrypto.DSA_free.restype = None + + libcrypto.EC_KEY_new_by_curve_name.argtypes = [ + c_int + ] + libcrypto.EC_KEY_new_by_curve_name.restype = P_EC_KEY + + libcrypto.EC_KEY_generate_key.argtypes = [ + P_EC_KEY + ] + libcrypto.EC_KEY_generate_key.restype = c_int + + libcrypto.EC_KEY_set_asn1_flag.argtypes = [ + P_EC_KEY, + c_int + ] + libcrypto.EC_KEY_set_asn1_flag.restype = None + + libcrypto.i2d_ECPrivateKey.argtypes = [ + P_EC_KEY, + POINTER(c_char_p) + ] + libcrypto.i2d_ECPrivateKey.restype = c_int + + libcrypto.i2o_ECPublicKey.argtypes = [ + P_EC_KEY, + POINTER(c_char_p) + ] + libcrypto.i2o_ECPublicKey.restype = c_int + + libcrypto.EC_KEY_free.argtypes = [ + P_EC_KEY + ] + libcrypto.EC_KEY_free.restype = None + + if version_info < (1,): + P_DSA_SIG = c_void_p + P_ECDSA_SIG = c_void_p + + libcrypto.DSA_do_sign.argtypes = [ + c_char_p, + c_int, + P_DSA + ] + libcrypto.DSA_do_sign.restype = P_DSA_SIG + + libcrypto.ECDSA_do_sign.argtypes = [ + c_char_p, + c_int, + P_EC_KEY + ] + libcrypto.ECDSA_do_sign.restype = P_ECDSA_SIG + + libcrypto.d2i_DSA_SIG.argtypes = [ + POINTER(P_DSA_SIG), + POINTER(c_char_p), + c_long + ] + libcrypto.d2i_DSA_SIG.restype = P_DSA_SIG + + libcrypto.d2i_ECDSA_SIG.argtypes = [ + POINTER(P_ECDSA_SIG), + POINTER(c_char_p), + c_long + ] + libcrypto.d2i_ECDSA_SIG.restype = P_ECDSA_SIG + + libcrypto.i2d_DSA_SIG.argtypes = [ + P_DSA_SIG, + POINTER(c_char_p) + ] + libcrypto.i2d_DSA_SIG.restype = c_int + + libcrypto.i2d_ECDSA_SIG.argtypes = [ + P_ECDSA_SIG, + POINTER(c_char_p) + ] + libcrypto.i2d_ECDSA_SIG.restype = c_int + + libcrypto.DSA_do_verify.argtypes = [ + c_char_p, + c_int, + P_DSA_SIG, + P_DSA + ] + libcrypto.DSA_do_verify.restype = c_int + + libcrypto.ECDSA_do_verify.argtypes = [ + c_char_p, + c_int, + P_ECDSA_SIG, + P_EC_KEY + ] + libcrypto.ECDSA_do_verify.restype = c_int + + libcrypto.DSA_SIG_free.argtypes = [ + P_DSA_SIG + ] + libcrypto.DSA_SIG_free.restype = None + + libcrypto.ECDSA_SIG_free.argtypes = [ + P_ECDSA_SIG + ] + libcrypto.ECDSA_SIG_free.restype = None + + libcrypto.EVP_PKEY_get1_DSA.argtypes = [ + P_EVP_PKEY + ] + libcrypto.EVP_PKEY_get1_DSA.restype = P_DSA + + libcrypto.EVP_PKEY_get1_EC_KEY.argtypes = [ + P_EVP_PKEY + ] + libcrypto.EVP_PKEY_get1_EC_KEY.restype = P_EC_KEY + + libcrypto.RSA_verify_PKCS1_PSS.argtypes = [ + P_RSA, + c_char_p, + P_EVP_MD, + c_char_p, + c_int + ] + libcrypto.RSA_verify_PKCS1_PSS.restype = c_int + + libcrypto.RSA_padding_add_PKCS1_PSS.argtypes = [ + P_RSA, + c_char_p, + c_char_p, + P_EVP_MD, + c_int + ] + libcrypto.RSA_padding_add_PKCS1_PSS.restype = c_int + + libcrypto.EVP_DigestInit_ex.argtypes = [ + P_EVP_MD_CTX, + P_EVP_MD, + P_ENGINE + ] + libcrypto.EVP_DigestInit_ex.restype = c_int + + libcrypto.EVP_SignFinal.argtypes = [ + P_EVP_MD_CTX, + c_char_p, + p_uint, + P_EVP_PKEY + ] + libcrypto.EVP_SignFinal.restype = c_int + + libcrypto.EVP_VerifyFinal.argtypes = [ + P_EVP_MD_CTX, + c_char_p, + c_uint, + P_EVP_PKEY + ] + libcrypto.EVP_VerifyFinal.restype = c_int + + libcrypto.EVP_MD_CTX_set_flags.argtypes = [ + P_EVP_MD_CTX, + c_int + ] + libcrypto.EVP_MD_CTX_set_flags.restype = None + + else: + libcrypto.PKCS5_PBKDF2_HMAC.argtypes = [ + c_char_p, + c_int, + c_char_p, + c_int, + c_int, + P_EVP_MD, + c_int, + c_char_p + ] + libcrypto.PKCS5_PBKDF2_HMAC.restype = c_int + + libcrypto.EVP_DigestSignInit.argtypes = [ + P_EVP_MD_CTX, + POINTER(P_EVP_PKEY_CTX), + P_EVP_MD, + P_ENGINE, + P_EVP_PKEY + ] + libcrypto.EVP_DigestSignInit.restype = c_int + + libcrypto.EVP_DigestSignFinal.argtypes = [ + P_EVP_MD_CTX, + c_char_p, + POINTER(c_size_t) + ] + libcrypto.EVP_DigestSignFinal.restype = c_int + + libcrypto.EVP_DigestVerifyInit.argtypes = [ + P_EVP_MD_CTX, + POINTER(P_EVP_PKEY_CTX), + P_EVP_MD, + P_ENGINE, + P_EVP_PKEY + ] + libcrypto.EVP_DigestVerifyInit.restype = c_int + + libcrypto.EVP_DigestVerifyFinal.argtypes = [ + P_EVP_MD_CTX, + c_char_p, + c_size_t + ] + libcrypto.EVP_DigestVerifyFinal.restype = c_int + + libcrypto.EVP_PKEY_CTX_ctrl.argtypes = [ + P_EVP_PKEY_CTX, + c_int, + c_int, + c_int, + c_int, + c_void_p + ] + libcrypto.EVP_PKEY_CTX_ctrl.restype = c_int + +except (AttributeError): + raise FFIEngineError('Error initializing ctypes') + + +setattr(libcrypto, 'EVP_PKEY_CTX', EVP_PKEY_CTX) +setattr(libcrypto, 'BIGNUM', BIGNUM) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_openssl/_libssl.py b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_openssl/_libssl.py new file mode 100644 index 00000000..2fa2bce7 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_openssl/_libssl.py @@ -0,0 +1,89 @@ +# coding: utf-8 +from __future__ import unicode_literals, division, absolute_import, print_function + +from .. import ffi + +# Initialize OpenSSL +from ._libcrypto import libcrypto_version_info + +if ffi() == 'cffi': + from ._libssl_cffi import libssl +else: + from ._libssl_ctypes import libssl + + +__all__ = [ + 'libssl', + 'LibsslConst', +] + + +if libcrypto_version_info < (1, 1): + libssl.SSL_library_init() +# Enables SHA2 algorithms on 0.9.8n and older +if libcrypto_version_info < (1, 0): + libssl.OPENSSL_add_all_algorithms_noconf() + + +class LibsslConst(): + ERR_LIB_ASN1 = 13 + ERR_LIB_SSL = 20 + + SSL_CTRL_OPTIONS = 32 + SSL_CTRL_SET_SESS_CACHE_MODE = 44 + + SSL_VERIFY_NONE = 0 + SSL_VERIFY_PEER = 1 + + SSL_ST_OK = 3 + + SSL_ERROR_WANT_READ = 2 + SSL_ERROR_WANT_WRITE = 3 + SSL_ERROR_ZERO_RETURN = 6 + + SSL_OP_NO_SSLv2 = 0x01000000 + SSL_OP_NO_SSLv3 = 0x02000000 + SSL_OP_NO_TLSv1 = 0x04000000 + SSL_OP_NO_TLSv1_2 = 0x08000000 + SSL_OP_NO_TLSv1_1 = 0x10000000 + + SSL_SESS_CACHE_CLIENT = 0x0001 + + SSL_R_NO_SHARED_CIPHER = 193 + + SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM = 130 + SSL_F_SSL3_GET_KEY_EXCHANGE = 141 + SSL_F_SSL3_GET_SERVER_CERTIFICATE = 144 + SSL_R_BAD_DH_P_LENGTH = 110 + SSL_R_CERTIFICATE_VERIFY_FAILED = 134 + SSL_R_UNKNOWN_PROTOCOL = 252 + SSL_R_DH_KEY_TOO_SMALL = 372 + + # OpenSSL 1.1.0 + SSL_F_TLS_PROCESS_SKE_DHE = 419 + SSL_F_SSL3_GET_RECORD = 143 + SSL_R_WRONG_VERSION_NUMBER = 267 + SSL_F_TLS_PROCESS_SERVER_CERTIFICATE = 367 + + # OpenSSL < 1.1.0 + SSL_F_SSL23_GET_SERVER_HELLO = 119 + SSL_F_SSL3_READ_BYTES = 148 + SSL_R_SSLV3_ALERT_HANDSHAKE_FAILURE = 1040 + SSL_R_TLSV1_ALERT_PROTOCOL_VERSION = 1070 + + SSL_CTRL_SET_TLSEXT_HOSTNAME = 55 + TLSEXT_NAMETYPE_host_name = 0 + + X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY = 20 + X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN = 19 + X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT = 18 + + X509_V_ERR_CERT_NOT_YET_VALID = 9 + X509_V_ERR_CERT_HAS_EXPIRED = 10 + + ASN1_F_ASN1_ITEM_VERIFY = 197 + ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM = 161 + + +if libcrypto_version_info >= (1, 1, 0): + LibsslConst.SSL_R_DH_KEY_TOO_SMALL = 394 diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_openssl/_libssl_cffi.py b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_openssl/_libssl_cffi.py new file mode 100644 index 00000000..611f50cd --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_openssl/_libssl_cffi.py @@ -0,0 +1,99 @@ +# coding: utf-8 +from __future__ import unicode_literals, division, absolute_import, print_function + +from .. import _backend_config +from .._ffi import get_library, register_ffi +from ..errors import LibraryNotFoundError +from ._libcrypto import libcrypto_version_info + +from cffi import FFI + + +__all__ = [ + 'libssl', +] + + +ffi = FFI() + +libssl_path = _backend_config().get('libssl_path') +if libssl_path is None: + libssl_path = get_library('ssl', 'libssl', '44') +if not libssl_path: + raise LibraryNotFoundError('The library libssl could not be found') + +libssl = ffi.dlopen(libssl_path) +register_ffi(libssl, ffi) + +ffi.cdef(""" + typedef ... SSL_METHOD; + typedef uintptr_t SSL_CTX; + typedef ... SSL_SESSION; + typedef uintptr_t SSL; + typedef ... BIO_METHOD; + typedef uintptr_t BIO; + typedef uintptr_t X509; + typedef ... X509_STORE; + typedef ... X509_STORE_CTX; + typedef uintptr_t _STACK; + + BIO_METHOD *BIO_s_mem(void); + BIO *BIO_new(BIO_METHOD *type); + int BIO_free(BIO *a); + int BIO_read(BIO *b, void *buf, int len); + int BIO_write(BIO *b, const void *buf, int len); + size_t BIO_ctrl_pending(BIO *b); + + SSL_CTX *SSL_CTX_new(const SSL_METHOD *method); + long SSL_CTX_set_timeout(SSL_CTX *ctx, long t); + void SSL_CTX_set_verify(SSL_CTX *ctx, int mode, + int (*verify_callback)(int, X509_STORE_CTX *)); + int SSL_CTX_set_default_verify_paths(SSL_CTX *ctx); + int SSL_CTX_load_verify_locations(SSL_CTX *ctx, const char *CAfile, + const char *CApath); + long SSL_get_verify_result(const SSL *ssl); + X509_STORE *SSL_CTX_get_cert_store(const SSL_CTX *ctx); + int X509_STORE_add_cert(X509_STORE *ctx, X509 *x); + int SSL_CTX_set_cipher_list(SSL_CTX *ctx, const char *str); + long SSL_CTX_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg); + void SSL_CTX_free(SSL_CTX *a); + + SSL *SSL_new(SSL_CTX *ctx); + void SSL_free(SSL *ssl); + void SSL_set_bio(SSL *ssl, BIO *rbio, BIO *wbio); + long SSL_ctrl(SSL *ssl, int cmd, long larg, void *parg); + _STACK *SSL_get_peer_cert_chain(const SSL *s); + + SSL_SESSION *SSL_get1_session(const SSL *ssl); + int SSL_set_session(SSL *ssl, SSL_SESSION *session); + void SSL_SESSION_free(SSL_SESSION *session); + + void SSL_set_connect_state(SSL *ssl); + int SSL_do_handshake(SSL *ssl); + int SSL_get_error(const SSL *ssl, int ret); + const char *SSL_get_version(const SSL *ssl); + + int SSL_read(SSL *ssl, void *buf, int num); + int SSL_write(SSL *ssl, const void *buf, int num); + int SSL_pending(const SSL *ssl); + + int SSL_shutdown(SSL *ssl); +""") + +if libcrypto_version_info < (1, 1): + ffi.cdef(""" + int sk_num(const _STACK *); + X509 *sk_value(const _STACK *, int); + + int SSL_library_init(void); + void OPENSSL_add_all_algorithms_noconf(void); + + SSL_METHOD *SSLv23_method(void); + """) +else: + ffi.cdef(""" + int OPENSSL_sk_num(const _STACK *); + X509 *OPENSSL_sk_value(const _STACK *, int); + + SSL_METHOD *TLS_method(void); + """) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_openssl/_libssl_ctypes.py b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_openssl/_libssl_ctypes.py new file mode 100644 index 00000000..a0ffbc09 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_openssl/_libssl_ctypes.py @@ -0,0 +1,260 @@ +# coding: utf-8 +from __future__ import unicode_literals, division, absolute_import, print_function + +from ctypes import CDLL, CFUNCTYPE, POINTER, c_void_p, c_char_p, c_int, c_size_t, c_long + +from .. import _backend_config +from .._ffi import FFIEngineError, get_library +from ..errors import LibraryNotFoundError +from ._libcrypto import libcrypto_version_info + + +__all__ = [ + 'libssl', +] + + +libssl_path = _backend_config().get('libssl_path') +if libssl_path is None: + libssl_path = get_library('ssl', 'libssl', '44') +if not libssl_path: + raise LibraryNotFoundError('The library libssl could not be found') + +libssl = CDLL(libssl_path, use_errno=True) + +P_SSL_METHOD = POINTER(c_void_p) +P_SSL_CTX = POINTER(c_void_p) +P_SSL_SESSION = POINTER(c_void_p) +P_SSL = POINTER(c_void_p) +P_BIO_METHOD = POINTER(c_void_p) +P_BIO = POINTER(c_void_p) +X509 = c_void_p +P_X509 = POINTER(X509) +P_X509_STORE = POINTER(c_void_p) +P_X509_STORE_CTX = POINTER(c_void_p) +_STACK = c_void_p +P_STACK = POINTER(_STACK) + +try: + if libcrypto_version_info < (1, 1): + libssl.sk_num.argtypes = [P_STACK] + libssl.sk_num.restype = c_int + + libssl.sk_value.argtypes = [P_STACK, c_int] + libssl.sk_value.restype = P_X509 + + libssl.SSL_library_init.argtypes = [] + libssl.SSL_library_init.restype = c_int + + libssl.OPENSSL_add_all_algorithms_noconf.argtypes = [] + libssl.OPENSSL_add_all_algorithms_noconf.restype = None + + libssl.SSLv23_method.argtypes = [] + libssl.SSLv23_method.restype = P_SSL_METHOD + + else: + libssl.OPENSSL_sk_num.argtypes = [P_STACK] + libssl.OPENSSL_sk_num.restype = c_int + + libssl.OPENSSL_sk_value.argtypes = [P_STACK, c_int] + libssl.OPENSSL_sk_value.restype = P_X509 + + libssl.TLS_method.argtypes = [] + libssl.TLS_method.restype = P_SSL_METHOD + + libssl.BIO_s_mem.argtypes = [] + libssl.BIO_s_mem.restype = P_BIO_METHOD + + libssl.BIO_new.argtypes = [ + P_BIO_METHOD + ] + libssl.BIO_new.restype = P_BIO + + libssl.BIO_free.argtypes = [ + P_BIO + ] + libssl.BIO_free.restype = c_int + + libssl.BIO_read.argtypes = [ + P_BIO, + c_char_p, + c_int + ] + libssl.BIO_read.restype = c_int + + libssl.BIO_write.argtypes = [ + P_BIO, + c_char_p, + c_int + ] + libssl.BIO_write.restype = c_int + + libssl.BIO_ctrl_pending.argtypes = [ + P_BIO + ] + libssl.BIO_ctrl_pending.restype = c_size_t + + libssl.SSL_CTX_new.argtypes = [ + P_SSL_METHOD + ] + libssl.SSL_CTX_new.restype = P_SSL_CTX + + libssl.SSL_CTX_set_timeout.argtypes = [ + P_SSL_CTX, + c_long + ] + libssl.SSL_CTX_set_timeout.restype = c_long + + verify_callback = CFUNCTYPE(c_int, c_int, P_X509_STORE_CTX) + setattr(libssl, 'verify_callback', verify_callback) + + libssl.SSL_CTX_set_verify.argtypes = [ + P_SSL_CTX, + c_int, + POINTER(verify_callback) + ] + libssl.SSL_CTX_set_verify.restype = None + + libssl.SSL_CTX_set_default_verify_paths.argtypes = [ + P_SSL_CTX + ] + libssl.SSL_CTX_set_default_verify_paths.restype = c_int + + libssl.SSL_CTX_load_verify_locations.argtypes = [ + P_SSL_CTX, + c_char_p, + c_char_p + ] + libssl.SSL_CTX_load_verify_locations.restype = c_int + + libssl.SSL_get_verify_result.argtypes = [ + P_SSL + ] + libssl.SSL_get_verify_result.restype = c_long + + libssl.SSL_CTX_get_cert_store.argtypes = [ + P_SSL_CTX + ] + libssl.SSL_CTX_get_cert_store.restype = P_X509_STORE + + libssl.X509_STORE_add_cert.argtypes = [ + P_X509_STORE, + P_X509 + ] + libssl.X509_STORE_add_cert.restype = c_int + + libssl.SSL_CTX_set_cipher_list.argtypes = [ + P_SSL_CTX, + c_char_p + ] + libssl.SSL_CTX_set_cipher_list.restype = c_int + + libssl.SSL_CTX_ctrl.arg_types = [ + P_SSL_CTX, + c_int, + c_long, + c_void_p + ] + libssl.SSL_CTX_ctrl.restype = c_long + + libssl.SSL_CTX_free.argtypes = [ + P_SSL_CTX + ] + libssl.SSL_CTX_free.restype = None + + libssl.SSL_new.argtypes = [ + P_SSL_CTX + ] + libssl.SSL_new.restype = P_SSL + + libssl.SSL_free.argtypes = [ + P_SSL + ] + libssl.SSL_free.restype = None + + libssl.SSL_set_bio.argtypes = [ + P_SSL, + P_BIO, + P_BIO + ] + libssl.SSL_set_bio.restype = None + + libssl.SSL_ctrl.arg_types = [ + P_SSL, + c_int, + c_long, + c_void_p + ] + libssl.SSL_ctrl.restype = c_long + + libssl.SSL_get_peer_cert_chain.argtypes = [ + P_SSL + ] + libssl.SSL_get_peer_cert_chain.restype = P_STACK + + libssl.SSL_get1_session.argtypes = [ + P_SSL + ] + libssl.SSL_get1_session.restype = P_SSL_SESSION + + libssl.SSL_set_session.argtypes = [ + P_SSL, + P_SSL_SESSION + ] + libssl.SSL_set_session.restype = c_int + + libssl.SSL_SESSION_free.argtypes = [ + P_SSL_SESSION + ] + libssl.SSL_SESSION_free.restype = None + + libssl.SSL_set_connect_state.argtypes = [ + P_SSL + ] + libssl.SSL_set_connect_state.restype = None + + libssl.SSL_do_handshake.argtypes = [ + P_SSL + ] + libssl.SSL_do_handshake.restype = c_int + + libssl.SSL_get_error.argtypes = [ + P_SSL, + c_int + ] + libssl.SSL_get_error.restype = c_int + + libssl.SSL_get_version.argtypes = [ + P_SSL + ] + libssl.SSL_get_version.restype = c_char_p + + libssl.SSL_read.argtypes = [ + P_SSL, + c_char_p, + c_int + ] + libssl.SSL_read.restype = c_int + + libssl.SSL_write.argtypes = [ + P_SSL, + c_char_p, + c_int + ] + libssl.SSL_write.restype = c_int + + libssl.SSL_pending.argtypes = [ + P_SSL + ] + libssl.SSL_pending.restype = c_int + + libssl.SSL_shutdown.argtypes = [ + P_SSL + ] + libssl.SSL_shutdown.restype = c_int + +except (AttributeError): + raise FFIEngineError('Error initializing ctypes') + +setattr(libssl, '_STACK', _STACK) +setattr(libssl, 'X509', X509) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_openssl/asymmetric.py b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_openssl/asymmetric.py new file mode 100644 index 00000000..880bf4dd --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_openssl/asymmetric.py @@ -0,0 +1,1872 @@ +# coding: utf-8 +from __future__ import unicode_literals, division, absolute_import, print_function + +import hashlib + +from .._asn1 import ( + Certificate as Asn1Certificate, + DHParameters, + ECDomainParameters, + PrivateKeyInfo, + PublicKeyAlgorithm, + PublicKeyInfo, +) +from .._asymmetric import ( + _CertificateBase, + _fingerprint, + _parse_pkcs12, + _PrivateKeyBase, + _PublicKeyBase, + _unwrap_private_key_info, + parse_certificate, + parse_private, + parse_public, +) +from .._errors import pretty_message +from .._ffi import ( + buffer_from_bytes, + buffer_pointer, + bytes_from_buffer, + deref, + is_null, + new, + null, + unwrap, +) +from ._libcrypto import libcrypto, LibcryptoConst, libcrypto_version_info, handle_openssl_error +from ..errors import AsymmetricKeyError, IncompleteAsymmetricKeyError, SignatureError +from .._types import type_name, str_cls, byte_cls, int_types +from ..util import constant_compare + + +__all__ = [ + 'Certificate', + 'dsa_sign', + 'dsa_verify', + 'ecdsa_sign', + 'ecdsa_verify', + 'generate_pair', + 'load_certificate', + 'load_pkcs12', + 'load_private_key', + 'load_public_key', + 'parse_pkcs12', + 'PrivateKey', + 'PublicKey', + 'rsa_oaep_decrypt', + 'rsa_oaep_encrypt', + 'rsa_pkcs1v15_decrypt', + 'rsa_pkcs1v15_encrypt', + 'rsa_pkcs1v15_sign', + 'rsa_pkcs1v15_verify', + 'rsa_pss_sign', + 'rsa_pss_verify', +] + + +class PrivateKey(_PrivateKeyBase): + """ + Container for the OpenSSL representation of a private key + """ + + evp_pkey = None + _public_key = None + + # A reference to the library used in the destructor to make sure it hasn't + # been garbage collected by the time this object is garbage collected + _lib = None + + def __init__(self, evp_pkey, asn1): + """ + :param evp_pkey: + An OpenSSL EVP_PKEY value from loading/importing the key + + :param asn1: + An asn1crypto.keys.PrivateKeyInfo object + """ + + self.evp_pkey = evp_pkey + self.asn1 = asn1 + self._lib = libcrypto + + @property + def public_key(self): + """ + :return: + A PublicKey object corresponding to this private key. + """ + + if self._public_key is None: + buffer_size = libcrypto.i2d_PUBKEY(self.evp_pkey, null()) + pubkey_buffer = buffer_from_bytes(buffer_size) + pubkey_pointer = buffer_pointer(pubkey_buffer) + pubkey_length = libcrypto.i2d_PUBKEY(self.evp_pkey, pubkey_pointer) + handle_openssl_error(pubkey_length) + pubkey_data = bytes_from_buffer(pubkey_buffer, pubkey_length) + + asn1 = PublicKeyInfo.load(pubkey_data) + pub_evp_pkey = libcrypto.d2i_PUBKEY(null(), buffer_pointer(pubkey_buffer), pubkey_length) + if is_null(pub_evp_pkey): + handle_openssl_error(0) + + self._public_key = PublicKey(pub_evp_pkey, asn1) + + return self._public_key + + @property + def fingerprint(self): + """ + Creates a fingerprint that can be compared with a public key to see if + the two form a pair. + + This fingerprint is not compatible with fingerprints generated by any + other software. + + :return: + A byte string that is a sha256 hash of selected components (based + on the key type) + """ + + if self._fingerprint is None: + self._fingerprint = _fingerprint(self.asn1, load_private_key) + return self._fingerprint + + def __del__(self): + if self.evp_pkey: + self._lib.EVP_PKEY_free(self.evp_pkey) + self._lib = None + self.evp_pkey = None + + +class PublicKey(_PublicKeyBase): + """ + Container for the OpenSSL representation of a public key + """ + + evp_pkey = None + + # A reference to the library used in the destructor to make sure it hasn't + # been garbage collected by the time this object is garbage collected + _lib = None + + def __init__(self, evp_pkey, asn1): + """ + :param evp_pkey: + An OpenSSL EVP_PKEY value from loading/importing the key + + :param asn1: + An asn1crypto.keys.PublicKeyInfo object + """ + + self.evp_pkey = evp_pkey + self.asn1 = asn1 + self._lib = libcrypto + + def __del__(self): + if self.evp_pkey: + self._lib.EVP_PKEY_free(self.evp_pkey) + self._lib = None + self.evp_pkey = None + + +class Certificate(_CertificateBase): + """ + Container for the OpenSSL representation of a certificate + """ + + x509 = None + _public_key = None + _self_signed = None + + # A reference to the library used in the destructor to make sure it hasn't + # been garbage collected by the time this object is garbage collected + _lib = None + + def __init__(self, x509, asn1): + """ + :param x509: + An OpenSSL X509 value from loading/importing the certificate + + :param asn1: + An asn1crypto.x509.Certificate object + """ + + self.x509 = x509 + self.asn1 = asn1 + self._lib = libcrypto + + @property + def evp_pkey(self): + """ + :return: + The EVP_PKEY of the public key this certificate contains + """ + + return self.public_key.evp_pkey + + @property + def public_key(self): + """ + :return: + The PublicKey object for the public key this certificate contains + """ + + if not self._public_key and self.x509: + evp_pkey = libcrypto.X509_get_pubkey(self.x509) + self._public_key = PublicKey(evp_pkey, self.asn1['tbs_certificate']['subject_public_key_info']) + + return self._public_key + + @property + def self_signed(self): + """ + :return: + A boolean - if the certificate is self-signed + """ + + if self._self_signed is None: + self._self_signed = False + if self.asn1.self_signed in set(['yes', 'maybe']): + + signature_algo = self.asn1['signature_algorithm'].signature_algo + hash_algo = self.asn1['signature_algorithm'].hash_algo + + if signature_algo == 'rsassa_pkcs1v15': + verify_func = rsa_pkcs1v15_verify + elif signature_algo == 'dsa': + verify_func = dsa_verify + elif signature_algo == 'ecdsa': + verify_func = ecdsa_verify + else: + raise OSError(pretty_message( + ''' + Unable to verify the signature of the certificate since + it uses the unsupported algorithm %s + ''', + signature_algo + )) + + try: + verify_func( + self.public_key, + self.asn1['signature_value'].native, + self.asn1['tbs_certificate'].dump(), + hash_algo + ) + self._self_signed = True + except (SignatureError): + pass + + return self._self_signed + + def __del__(self): + if self._public_key: + self._public_key.__del__() + self._public_key = None + + if self.x509: + self._lib.X509_free(self.x509) + self._lib = None + self.x509 = None + + +def generate_pair(algorithm, bit_size=None, curve=None): + """ + Generates a public/private key pair + + :param algorithm: + The key algorithm - "rsa", "dsa" or "ec" + + :param bit_size: + An integer - used for "rsa" and "dsa". For "rsa" the value maye be 1024, + 2048, 3072 or 4096. For "dsa" the value may be 1024, plus 2048 or 3072 + if OpenSSL 1.0.0 or newer is available. + + :param curve: + A unicode string - used for "ec" keys. Valid values include "secp256r1", + "secp384r1" and "secp521r1". + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + + :return: + A 2-element tuple of (PublicKey, PrivateKey). The contents of each key + may be saved by calling .asn1.dump(). + """ + + if algorithm not in set(['rsa', 'dsa', 'ec']): + raise ValueError(pretty_message( + ''' + algorithm must be one of "rsa", "dsa", "ec", not %s + ''', + repr(algorithm) + )) + + if algorithm == 'rsa': + if bit_size not in set([1024, 2048, 3072, 4096]): + raise ValueError(pretty_message( + ''' + bit_size must be one of 1024, 2048, 3072, 4096, not %s + ''', + repr(bit_size) + )) + + elif algorithm == 'dsa': + if libcrypto_version_info < (1,): + if bit_size != 1024: + raise ValueError(pretty_message( + ''' + bit_size must be 1024, not %s + ''', + repr(bit_size) + )) + else: + if bit_size not in set([1024, 2048, 3072]): + raise ValueError(pretty_message( + ''' + bit_size must be one of 1024, 2048, 3072, not %s + ''', + repr(bit_size) + )) + + elif algorithm == 'ec': + if curve not in set(['secp256r1', 'secp384r1', 'secp521r1']): + raise ValueError(pretty_message( + ''' + curve must be one of "secp256r1", "secp384r1", "secp521r1", + not %s + ''', + repr(curve) + )) + + if algorithm == 'rsa': + rsa = None + exponent = None + + try: + rsa = libcrypto.RSA_new() + if is_null(rsa): + handle_openssl_error(0) + + exponent_pointer = new(libcrypto, 'BIGNUM **') + result = libcrypto.BN_dec2bn(exponent_pointer, b'65537') + handle_openssl_error(result) + exponent = unwrap(exponent_pointer) + + result = libcrypto.RSA_generate_key_ex(rsa, bit_size, exponent, null()) + handle_openssl_error(result) + + buffer_length = libcrypto.i2d_RSAPublicKey(rsa, null()) + if buffer_length < 0: + handle_openssl_error(buffer_length) + buffer = buffer_from_bytes(buffer_length) + result = libcrypto.i2d_RSAPublicKey(rsa, buffer_pointer(buffer)) + if result < 0: + handle_openssl_error(result) + public_key_bytes = bytes_from_buffer(buffer, buffer_length) + + buffer_length = libcrypto.i2d_RSAPrivateKey(rsa, null()) + if buffer_length < 0: + handle_openssl_error(buffer_length) + buffer = buffer_from_bytes(buffer_length) + result = libcrypto.i2d_RSAPrivateKey(rsa, buffer_pointer(buffer)) + if result < 0: + handle_openssl_error(result) + private_key_bytes = bytes_from_buffer(buffer, buffer_length) + + finally: + if rsa: + libcrypto.RSA_free(rsa) + if exponent: + libcrypto.BN_free(exponent) + + elif algorithm == 'dsa': + dsa = None + + try: + dsa = libcrypto.DSA_new() + if is_null(dsa): + handle_openssl_error(0) + + result = libcrypto.DSA_generate_parameters_ex(dsa, bit_size, null(), 0, null(), null(), null()) + handle_openssl_error(result) + + result = libcrypto.DSA_generate_key(dsa) + handle_openssl_error(result) + + buffer_length = libcrypto.i2d_DSA_PUBKEY(dsa, null()) + if buffer_length < 0: + handle_openssl_error(buffer_length) + buffer = buffer_from_bytes(buffer_length) + result = libcrypto.i2d_DSA_PUBKEY(dsa, buffer_pointer(buffer)) + if result < 0: + handle_openssl_error(result) + public_key_bytes = bytes_from_buffer(buffer, buffer_length) + + buffer_length = libcrypto.i2d_DSAPrivateKey(dsa, null()) + if buffer_length < 0: + handle_openssl_error(buffer_length) + buffer = buffer_from_bytes(buffer_length) + result = libcrypto.i2d_DSAPrivateKey(dsa, buffer_pointer(buffer)) + if result < 0: + handle_openssl_error(result) + private_key_bytes = bytes_from_buffer(buffer, buffer_length) + + finally: + if dsa: + libcrypto.DSA_free(dsa) + + elif algorithm == 'ec': + ec_key = None + + try: + curve_id = { + 'secp256r1': LibcryptoConst.NID_X9_62_prime256v1, + 'secp384r1': LibcryptoConst.NID_secp384r1, + 'secp521r1': LibcryptoConst.NID_secp521r1, + }[curve] + + ec_key = libcrypto.EC_KEY_new_by_curve_name(curve_id) + if is_null(ec_key): + handle_openssl_error(0) + + result = libcrypto.EC_KEY_generate_key(ec_key) + handle_openssl_error(result) + + libcrypto.EC_KEY_set_asn1_flag(ec_key, LibcryptoConst.OPENSSL_EC_NAMED_CURVE) + + buffer_length = libcrypto.i2o_ECPublicKey(ec_key, null()) + if buffer_length < 0: + handle_openssl_error(buffer_length) + buffer = buffer_from_bytes(buffer_length) + result = libcrypto.i2o_ECPublicKey(ec_key, buffer_pointer(buffer)) + if result < 0: + handle_openssl_error(result) + public_key_point_bytes = bytes_from_buffer(buffer, buffer_length) + + # i2o_ECPublicKey only returns the ECPoint bytes, so we have to + # manually wrap it in a PublicKeyInfo structure to get it to parse + public_key = PublicKeyInfo({ + 'algorithm': PublicKeyAlgorithm({ + 'algorithm': 'ec', + 'parameters': ECDomainParameters( + name='named', + value=curve + ) + }), + 'public_key': public_key_point_bytes + }) + public_key_bytes = public_key.dump() + + buffer_length = libcrypto.i2d_ECPrivateKey(ec_key, null()) + if buffer_length < 0: + handle_openssl_error(buffer_length) + buffer = buffer_from_bytes(buffer_length) + result = libcrypto.i2d_ECPrivateKey(ec_key, buffer_pointer(buffer)) + if result < 0: + handle_openssl_error(result) + private_key_bytes = bytes_from_buffer(buffer, buffer_length) + + finally: + if ec_key: + libcrypto.EC_KEY_free(ec_key) + + return (load_public_key(public_key_bytes), load_private_key(private_key_bytes)) + + +def generate_dh_parameters(bit_size): + """ + Generates DH parameters for use with Diffie-Hellman key exchange. Returns + a structure in the format of DHParameter defined in PKCS#3, which is also + used by the OpenSSL dhparam tool. + + THIS CAN BE VERY TIME CONSUMING! + + :param bit_size: + The integer bit size of the parameters to generate. Must be between 512 + and 4096, and divisible by 64. Recommended secure value as of early 2016 + is 2048, with an absolute minimum of 1024. + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + + :return: + An asn1crypto.algos.DHParameters object. Use + oscrypto.asymmetric.dump_dh_parameters() to save to disk for usage with + web servers. + """ + + if not isinstance(bit_size, int_types): + raise TypeError(pretty_message( + ''' + bit_size must be an integer, not %s + ''', + type_name(bit_size) + )) + + if bit_size < 512: + raise ValueError('bit_size must be greater than or equal to 512') + + if bit_size > 4096: + raise ValueError('bit_size must be less than or equal to 4096') + + if bit_size % 64 != 0: + raise ValueError('bit_size must be a multiple of 64') + + dh = None + + try: + dh = libcrypto.DH_new() + if is_null(dh): + handle_openssl_error(0) + + result = libcrypto.DH_generate_parameters_ex(dh, bit_size, LibcryptoConst.DH_GENERATOR_2, null()) + handle_openssl_error(result) + + buffer_length = libcrypto.i2d_DHparams(dh, null()) + if buffer_length < 0: + handle_openssl_error(buffer_length) + buffer = buffer_from_bytes(buffer_length) + result = libcrypto.i2d_DHparams(dh, buffer_pointer(buffer)) + if result < 0: + handle_openssl_error(result) + dh_params_bytes = bytes_from_buffer(buffer, buffer_length) + + return DHParameters.load(dh_params_bytes) + + finally: + if dh: + libcrypto.DH_free(dh) + + +def load_certificate(source): + """ + Loads an x509 certificate into a Certificate object + + :param source: + A byte string of file contents, a unicode string filename or an + asn1crypto.x509.Certificate object + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + + :return: + A Certificate object + """ + + if isinstance(source, Asn1Certificate): + certificate = source + + elif isinstance(source, byte_cls): + certificate = parse_certificate(source) + + elif isinstance(source, str_cls): + with open(source, 'rb') as f: + certificate = parse_certificate(f.read()) + + else: + raise TypeError(pretty_message( + ''' + source must be a byte string, unicode string or + asn1crypto.x509.Certificate object, not %s + ''', + type_name(source) + )) + + return _load_x509(certificate) + + +def _load_x509(certificate): + """ + Loads an ASN.1 object of an x509 certificate into a Certificate object + + :param certificate: + An asn1crypto.x509.Certificate object + + :return: + A Certificate object + """ + + source = certificate.dump() + + buffer = buffer_from_bytes(source) + evp_pkey = libcrypto.d2i_X509(null(), buffer_pointer(buffer), len(source)) + if is_null(evp_pkey): + handle_openssl_error(0) + return Certificate(evp_pkey, certificate) + + +def load_private_key(source, password=None): + """ + Loads a private key into a PrivateKey object + + :param source: + A byte string of file contents, a unicode string filename or an + asn1crypto.keys.PrivateKeyInfo object + + :param password: + A byte or unicode string to decrypt the private key file. Unicode + strings will be encoded using UTF-8. Not used is the source is a + PrivateKeyInfo object. + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + oscrypto.errors.AsymmetricKeyError - when the private key is incompatible with the OS crypto library + OSError - when an error is returned by the OS crypto library + + :return: + A PrivateKey object + """ + + if isinstance(source, PrivateKeyInfo): + private_object = source + + else: + if password is not None: + if isinstance(password, str_cls): + password = password.encode('utf-8') + if not isinstance(password, byte_cls): + raise TypeError(pretty_message( + ''' + password must be a byte string, not %s + ''', + type_name(password) + )) + + if isinstance(source, str_cls): + with open(source, 'rb') as f: + source = f.read() + + elif not isinstance(source, byte_cls): + raise TypeError(pretty_message( + ''' + source must be a byte string, unicode string or + asn1crypto.keys.PrivateKeyInfo object, not %s + ''', + type_name(source) + )) + + private_object = parse_private(source, password) + + return _load_key(private_object) + + +def load_public_key(source): + """ + Loads a public key into a PublicKey object + + :param source: + A byte string of file contents, a unicode string filename or an + asn1crypto.keys.PublicKeyInfo object + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + oscrypto.errors.AsymmetricKeyError - when the public key is incompatible with the OS crypto library + OSError - when an error is returned by the OS crypto library + + :return: + A PublicKey object + """ + + if isinstance(source, PublicKeyInfo): + public_key = source + + elif isinstance(source, byte_cls): + public_key = parse_public(source) + + elif isinstance(source, str_cls): + with open(source, 'rb') as f: + public_key = parse_public(f.read()) + + else: + raise TypeError(pretty_message( + ''' + source must be a byte string, unicode string or + asn1crypto.keys.PublicKeyInfo object, not %s + ''', + type_name(public_key) + )) + + if public_key.algorithm == 'dsa': + if libcrypto_version_info < (1,) and public_key.hash_algo == 'sha2': + raise AsymmetricKeyError(pretty_message( + ''' + OpenSSL 0.9.8 only supports DSA keys based on SHA1 (2048 bits or + less) - this key is based on SHA2 and is %s bits + ''', + public_key.bit_size + )) + elif public_key.hash_algo is None: + raise IncompleteAsymmetricKeyError(pretty_message( + ''' + The DSA key does not contain the necessary p, q and g + parameters and can not be used + ''' + )) + + data = public_key.dump() + buffer = buffer_from_bytes(data) + evp_pkey = libcrypto.d2i_PUBKEY(null(), buffer_pointer(buffer), len(data)) + if is_null(evp_pkey): + handle_openssl_error(0) + return PublicKey(evp_pkey, public_key) + + +def _load_key(private_object): + """ + Loads a private key into a PrivateKey object + + :param private_object: + An asn1crypto.keys.PrivateKeyInfo object + + :return: + A PrivateKey object + """ + + if libcrypto_version_info < (1,) and private_object.algorithm == 'dsa' and private_object.hash_algo == 'sha2': + raise AsymmetricKeyError(pretty_message( + ''' + OpenSSL 0.9.8 only supports DSA keys based on SHA1 (2048 bits or + less) - this key is based on SHA2 and is %s bits + ''', + private_object.bit_size + )) + + source = _unwrap_private_key_info(private_object).dump() + + buffer = buffer_from_bytes(source) + evp_pkey = libcrypto.d2i_AutoPrivateKey(null(), buffer_pointer(buffer), len(source)) + if is_null(evp_pkey): + handle_openssl_error(0) + return PrivateKey(evp_pkey, private_object) + + +def parse_pkcs12(data, password=None): + """ + Parses a PKCS#12 ANS.1 DER-encoded structure and extracts certs and keys + + :param data: + A byte string of a DER-encoded PKCS#12 file + + :param password: + A byte string of the password to any encrypted data + + :raises: + ValueError - when any of the parameters are of the wrong type or value + OSError - when an error is returned by one of the OS decryption functions + + :return: + A three-element tuple of: + 1. An asn1crypto.keys.PrivateKeyInfo object + 2. An asn1crypto.x509.Certificate object + 3. A list of zero or more asn1crypto.x509.Certificate objects that are + "extra" certificates, possibly intermediates from the cert chain + """ + + return _parse_pkcs12(data, password, load_private_key) + + +def load_pkcs12(source, password=None): + """ + Loads a .p12 or .pfx file into a PrivateKey object and one or more + Certificates objects + + :param source: + A byte string of file contents or a unicode string filename + + :param password: + A byte or unicode string to decrypt the PKCS12 file. Unicode strings + will be encoded using UTF-8. + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + oscrypto.errors.AsymmetricKeyError - when a contained key is incompatible with the OS crypto library + OSError - when an error is returned by the OS crypto library + + :return: + A three-element tuple containing (PrivateKey, Certificate, [Certificate, ...]) + """ + + if password is not None: + if isinstance(password, str_cls): + password = password.encode('utf-8') + if not isinstance(password, byte_cls): + raise TypeError(pretty_message( + ''' + password must be a byte string, not %s + ''', + type_name(password) + )) + + if isinstance(source, str_cls): + with open(source, 'rb') as f: + source = f.read() + + elif not isinstance(source, byte_cls): + raise TypeError(pretty_message( + ''' + source must be a byte string or a unicode string, not %s + ''', + type_name(source) + )) + + key_info, cert_info, extra_certs_info = parse_pkcs12(source, password) + + key = None + cert = None + + if key_info: + key = _load_key(key_info) + + if cert_info: + cert = _load_x509(cert_info) + + extra_certs = [_load_x509(info) for info in extra_certs_info] + + return (key, cert, extra_certs) + + +def rsa_pkcs1v15_encrypt(certificate_or_public_key, data): + """ + Encrypts a byte string using an RSA public key or certificate. Uses PKCS#1 + v1.5 padding. + + :param certificate_or_public_key: + A PublicKey or Certificate object + + :param data: + A byte string, with a maximum length 11 bytes less than the key length + (in bytes) + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + + :return: + A byte string of the encrypted data + """ + + return _encrypt(certificate_or_public_key, data, LibcryptoConst.RSA_PKCS1_PADDING) + + +def rsa_pkcs1v15_decrypt(private_key, ciphertext): + """ + Decrypts a byte string using an RSA private key. Uses PKCS#1 v1.5 padding. + + :param private_key: + A PrivateKey object + + :param ciphertext: + A byte string of the encrypted data + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + + :return: + A byte string of the original plaintext + """ + + return _decrypt(private_key, ciphertext, LibcryptoConst.RSA_PKCS1_PADDING) + + +def rsa_oaep_encrypt(certificate_or_public_key, data): + """ + Encrypts a byte string using an RSA public key or certificate. Uses PKCS#1 + OAEP padding with SHA1. + + :param certificate_or_public_key: + A PublicKey or Certificate object + + :param data: + A byte string, with a maximum length 41 bytes (or more) less than the + key length (in bytes) + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + + :return: + A byte string of the encrypted data + """ + + return _encrypt(certificate_or_public_key, data, LibcryptoConst.RSA_PKCS1_OAEP_PADDING) + + +def rsa_oaep_decrypt(private_key, ciphertext): + """ + Decrypts a byte string using an RSA private key. Uses PKCS#1 OAEP padding + with SHA1. + + :param private_key: + A PrivateKey object + + :param ciphertext: + A byte string of the encrypted data + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + + :return: + A byte string of the original plaintext + """ + + return _decrypt(private_key, ciphertext, LibcryptoConst.RSA_PKCS1_OAEP_PADDING) + + +def _encrypt(certificate_or_public_key, data, padding): + """ + Encrypts plaintext using an RSA public key or certificate + + :param certificate_or_public_key: + A PublicKey, Certificate or PrivateKey object + + :param data: + The byte string to encrypt + + :param padding: + The padding mode to use + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + + :return: + A byte string of the encrypted data + """ + + if not isinstance(certificate_or_public_key, (Certificate, PublicKey)): + raise TypeError(pretty_message( + ''' + certificate_or_public_key must be an instance of the Certificate or + PublicKey class, not %s + ''', + type_name(certificate_or_public_key) + )) + + if not isinstance(data, byte_cls): + raise TypeError(pretty_message( + ''' + data must be a byte string, not %s + ''', + type_name(data) + )) + + rsa = None + + try: + buffer_size = libcrypto.EVP_PKEY_size(certificate_or_public_key.evp_pkey) + buffer = buffer_from_bytes(buffer_size) + + rsa = libcrypto.EVP_PKEY_get1_RSA(certificate_or_public_key.evp_pkey) + res = libcrypto.RSA_public_encrypt(len(data), data, buffer, rsa, padding) + handle_openssl_error(res) + + return bytes_from_buffer(buffer, res) + + finally: + if rsa: + libcrypto.RSA_free(rsa) + + +def _decrypt(private_key, ciphertext, padding): + """ + Decrypts RSA ciphertext using a private key + + :param private_key: + A PrivateKey object + + :param ciphertext: + The ciphertext - a byte string + + :param padding: + The padding mode to use + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + + :return: + A byte string of the plaintext + """ + + if not isinstance(private_key, PrivateKey): + raise TypeError(pretty_message( + ''' + private_key must be an instance of the PrivateKey class, not %s + ''', + type_name(private_key) + )) + + if not isinstance(ciphertext, byte_cls): + raise TypeError(pretty_message( + ''' + ciphertext must be a byte string, not %s + ''', + type_name(ciphertext) + )) + + rsa = None + + try: + buffer_size = libcrypto.EVP_PKEY_size(private_key.evp_pkey) + buffer = buffer_from_bytes(buffer_size) + + rsa = libcrypto.EVP_PKEY_get1_RSA(private_key.evp_pkey) + res = libcrypto.RSA_private_decrypt(len(ciphertext), ciphertext, buffer, rsa, padding) + handle_openssl_error(res) + + return bytes_from_buffer(buffer, res) + + finally: + if rsa: + libcrypto.RSA_free(rsa) + + +def rsa_pkcs1v15_verify(certificate_or_public_key, signature, data, hash_algorithm): + """ + Verifies an RSASSA-PKCS-v1.5 signature. + + When the hash_algorithm is "raw", the operation is identical to RSA + public key decryption. That is: the data is not hashed and no ASN.1 + structure with an algorithm identifier of the hash algorithm is placed in + the encrypted byte string. + + :param certificate_or_public_key: + A Certificate or PublicKey instance to verify the signature with + + :param signature: + A byte string of the signature to verify + + :param data: + A byte string of the data the signature is for + + :param hash_algorithm: + A unicode string of "md5", "sha1", "sha224", "sha256", "sha384", + "sha512" or "raw" + + :raises: + oscrypto.errors.SignatureError - when the signature is determined to be invalid + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + """ + + if certificate_or_public_key.algorithm != 'rsa': + raise ValueError(pretty_message( + ''' + The key specified is not an RSA public key, but %s + ''', + certificate_or_public_key.algorithm.upper() + )) + + return _verify(certificate_or_public_key, signature, data, hash_algorithm) + + +def rsa_pss_verify(certificate_or_public_key, signature, data, hash_algorithm): + """ + Verifies an RSASSA-PSS signature. For the PSS padding the mask gen algorithm + will be mgf1 using the same hash algorithm as the signature. The salt length + with be the length of the hash algorithm, and the trailer field with be the + standard 0xBC byte. + + :param certificate_or_public_key: + A Certificate or PublicKey instance to verify the signature with + + :param signature: + A byte string of the signature to verify + + :param data: + A byte string of the data the signature is for + + :param hash_algorithm: + A unicode string of "md5", "sha1", "sha224", "sha256", "sha384" or "sha512" + + :raises: + oscrypto.errors.SignatureError - when the signature is determined to be invalid + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + """ + + if certificate_or_public_key.algorithm != 'rsa': + raise ValueError(pretty_message( + ''' + The key specified is not an RSA public key, but %s + ''', + certificate_or_public_key.algorithm.upper() + )) + + return _verify(certificate_or_public_key, signature, data, hash_algorithm, rsa_pss_padding=True) + + +def dsa_verify(certificate_or_public_key, signature, data, hash_algorithm): + """ + Verifies a DSA signature + + :param certificate_or_public_key: + A Certificate or PublicKey instance to verify the signature with + + :param signature: + A byte string of the signature to verify + + :param data: + A byte string of the data the signature is for + + :param hash_algorithm: + A unicode string of "md5", "sha1", "sha224", "sha256", "sha384" or "sha512" + + :raises: + oscrypto.errors.SignatureError - when the signature is determined to be invalid + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + """ + + if certificate_or_public_key.algorithm != 'dsa': + raise ValueError(pretty_message( + ''' + The key specified is not a DSA public key, but %s + ''', + certificate_or_public_key.algorithm.upper() + )) + + return _verify(certificate_or_public_key, signature, data, hash_algorithm) + + +def ecdsa_verify(certificate_or_public_key, signature, data, hash_algorithm): + """ + Verifies an ECDSA signature + + :param certificate_or_public_key: + A Certificate or PublicKey instance to verify the signature with + + :param signature: + A byte string of the signature to verify + + :param data: + A byte string of the data the signature is for + + :param hash_algorithm: + A unicode string of "md5", "sha1", "sha224", "sha256", "sha384" or "sha512" + + :raises: + oscrypto.errors.SignatureError - when the signature is determined to be invalid + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + """ + + if certificate_or_public_key.algorithm != 'ec': + raise ValueError(pretty_message( + ''' + The key specified is not an EC public key, but %s + ''', + certificate_or_public_key.algorithm.upper() + )) + + return _verify(certificate_or_public_key, signature, data, hash_algorithm) + + +def _verify(certificate_or_public_key, signature, data, hash_algorithm, rsa_pss_padding=False): + """ + Verifies an RSA, DSA or ECDSA signature + + :param certificate_or_public_key: + A Certificate or PublicKey instance to verify the signature with + + :param signature: + A byte string of the signature to verify + + :param data: + A byte string of the data the signature is for + + :param hash_algorithm: + A unicode string of "md5", "sha1", "sha224", "sha256", "sha384" or "sha512" + + :param rsa_pss_padding: + If the certificate_or_public_key is an RSA key, this enables PSS padding + + :raises: + oscrypto.errors.SignatureError - when the signature is determined to be invalid + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + """ + + if not isinstance(certificate_or_public_key, (Certificate, PublicKey)): + raise TypeError(pretty_message( + ''' + certificate_or_public_key must be an instance of the Certificate or + PublicKey class, not %s + ''', + type_name(certificate_or_public_key) + )) + + if not isinstance(signature, byte_cls): + raise TypeError(pretty_message( + ''' + signature must be a byte string, not %s + ''', + type_name(signature) + )) + + if not isinstance(data, byte_cls): + raise TypeError(pretty_message( + ''' + data must be a byte string, not %s + ''', + type_name(data) + )) + + valid_hash_algorithms = set(['md5', 'sha1', 'sha224', 'sha256', 'sha384', 'sha512']) + if certificate_or_public_key.algorithm == 'rsa' and not rsa_pss_padding: + valid_hash_algorithms |= set(['raw']) + + if hash_algorithm not in valid_hash_algorithms: + valid_hash_algorithms_error = '"md5", "sha1", "sha224", "sha256", "sha384", "sha512"' + if certificate_or_public_key.algorithm == 'rsa' and not rsa_pss_padding: + valid_hash_algorithms_error += ', "raw"' + raise ValueError(pretty_message( + ''' + hash_algorithm must be one of %s, not %s + ''', + valid_hash_algorithms_error, + repr(hash_algorithm) + )) + + if certificate_or_public_key.algorithm != 'rsa' and rsa_pss_padding: + raise ValueError(pretty_message( + ''' + PSS padding can only be used with RSA keys - the key provided is a + %s key + ''', + certificate_or_public_key.algorithm.upper() + )) + + if certificate_or_public_key.algorithm == 'rsa' and hash_algorithm == 'raw': + if len(data) > certificate_or_public_key.byte_size - 11: + raise ValueError(pretty_message( + ''' + data must be 11 bytes shorter than the key size when + hash_algorithm is "raw" - key size is %s bytes, but data is + %s bytes long + ''', + certificate_or_public_key.byte_size, + len(data) + )) + + rsa = None + + try: + rsa = libcrypto.EVP_PKEY_get1_RSA(certificate_or_public_key.evp_pkey) + if is_null(rsa): + handle_openssl_error(0) + + buffer_size = libcrypto.EVP_PKEY_size(certificate_or_public_key.evp_pkey) + decrypted_buffer = buffer_from_bytes(buffer_size) + decrypted_length = libcrypto.RSA_public_decrypt( + len(signature), + signature, + decrypted_buffer, + rsa, + LibcryptoConst.RSA_PKCS1_PADDING + ) + handle_openssl_error(decrypted_length) + + decrypted_bytes = bytes_from_buffer(decrypted_buffer, decrypted_length) + + if not constant_compare(data, decrypted_bytes): + raise SignatureError('Signature is invalid') + return + + finally: + if rsa: + libcrypto.RSA_free(rsa) + + evp_md_ctx = None + rsa = None + dsa = None + dsa_sig = None + ec_key = None + ecdsa_sig = None + + try: + if libcrypto_version_info < (1, 1): + evp_md_ctx = libcrypto.EVP_MD_CTX_create() + else: + evp_md_ctx = libcrypto.EVP_MD_CTX_new() + + evp_md = { + 'md5': libcrypto.EVP_md5, + 'sha1': libcrypto.EVP_sha1, + 'sha224': libcrypto.EVP_sha224, + 'sha256': libcrypto.EVP_sha256, + 'sha384': libcrypto.EVP_sha384, + 'sha512': libcrypto.EVP_sha512 + }[hash_algorithm]() + + if libcrypto_version_info < (1,): + if certificate_or_public_key.algorithm == 'rsa' and rsa_pss_padding: + digest = getattr(hashlib, hash_algorithm)(data).digest() + + rsa = libcrypto.EVP_PKEY_get1_RSA(certificate_or_public_key.evp_pkey) + if is_null(rsa): + handle_openssl_error(0) + + buffer_size = libcrypto.EVP_PKEY_size(certificate_or_public_key.evp_pkey) + decoded_buffer = buffer_from_bytes(buffer_size) + decoded_length = libcrypto.RSA_public_decrypt( + len(signature), + signature, + decoded_buffer, + rsa, + LibcryptoConst.RSA_NO_PADDING + ) + handle_openssl_error(decoded_length) + + res = libcrypto.RSA_verify_PKCS1_PSS( + rsa, + digest, + evp_md, + decoded_buffer, + LibcryptoConst.EVP_MD_CTX_FLAG_PSS_MDLEN + ) + + elif certificate_or_public_key.algorithm == 'rsa': + res = libcrypto.EVP_DigestInit_ex(evp_md_ctx, evp_md, null()) + handle_openssl_error(res) + + res = libcrypto.EVP_DigestUpdate(evp_md_ctx, data, len(data)) + handle_openssl_error(res) + + res = libcrypto.EVP_VerifyFinal( + evp_md_ctx, + signature, + len(signature), + certificate_or_public_key.evp_pkey + ) + + elif certificate_or_public_key.algorithm == 'dsa': + digest = getattr(hashlib, hash_algorithm)(data).digest() + + signature_buffer = buffer_from_bytes(signature) + signature_pointer = buffer_pointer(signature_buffer) + dsa_sig = libcrypto.d2i_DSA_SIG(null(), signature_pointer, len(signature)) + if is_null(dsa_sig): + raise SignatureError('Signature is invalid') + + dsa = libcrypto.EVP_PKEY_get1_DSA(certificate_or_public_key.evp_pkey) + if is_null(dsa): + handle_openssl_error(0) + + res = libcrypto.DSA_do_verify(digest, len(digest), dsa_sig, dsa) + + elif certificate_or_public_key.algorithm == 'ec': + digest = getattr(hashlib, hash_algorithm)(data).digest() + + signature_buffer = buffer_from_bytes(signature) + signature_pointer = buffer_pointer(signature_buffer) + ecdsa_sig = libcrypto.d2i_ECDSA_SIG(null(), signature_pointer, len(signature)) + if is_null(ecdsa_sig): + raise SignatureError('Signature is invalid') + + ec_key = libcrypto.EVP_PKEY_get1_EC_KEY(certificate_or_public_key.evp_pkey) + if is_null(ec_key): + handle_openssl_error(0) + + res = libcrypto.ECDSA_do_verify(digest, len(digest), ecdsa_sig, ec_key) + + else: + evp_pkey_ctx_pointer_pointer = new(libcrypto, 'EVP_PKEY_CTX **') + res = libcrypto.EVP_DigestVerifyInit( + evp_md_ctx, + evp_pkey_ctx_pointer_pointer, + evp_md, + null(), + certificate_or_public_key.evp_pkey + ) + handle_openssl_error(res) + evp_pkey_ctx_pointer = unwrap(evp_pkey_ctx_pointer_pointer) + + if rsa_pss_padding: + # Enable PSS padding + res = libcrypto.EVP_PKEY_CTX_ctrl( + evp_pkey_ctx_pointer, + LibcryptoConst.EVP_PKEY_RSA, + -1, # All operations + LibcryptoConst.EVP_PKEY_CTRL_RSA_PADDING, + LibcryptoConst.RSA_PKCS1_PSS_PADDING, + null() + ) + handle_openssl_error(res) + + # Use the hash algorithm output length as the salt length + res = libcrypto.EVP_PKEY_CTX_ctrl( + evp_pkey_ctx_pointer, + LibcryptoConst.EVP_PKEY_RSA, + LibcryptoConst.EVP_PKEY_OP_SIGN | LibcryptoConst.EVP_PKEY_OP_VERIFY, + LibcryptoConst.EVP_PKEY_CTRL_RSA_PSS_SALTLEN, + -1, + null() + ) + handle_openssl_error(res) + + res = libcrypto.EVP_DigestUpdate(evp_md_ctx, data, len(data)) + handle_openssl_error(res) + + res = libcrypto.EVP_DigestVerifyFinal(evp_md_ctx, signature, len(signature)) + + if res < 1: + raise SignatureError('Signature is invalid') + handle_openssl_error(res) + + finally: + if evp_md_ctx: + if libcrypto_version_info < (1, 1): + libcrypto.EVP_MD_CTX_destroy(evp_md_ctx) + else: + libcrypto.EVP_MD_CTX_free(evp_md_ctx) + if rsa: + libcrypto.RSA_free(rsa) + if dsa: + libcrypto.DSA_free(dsa) + if dsa_sig: + libcrypto.DSA_SIG_free(dsa_sig) + if ec_key: + libcrypto.EC_KEY_free(ec_key) + if ecdsa_sig: + libcrypto.ECDSA_SIG_free(ecdsa_sig) + + +def rsa_pkcs1v15_sign(private_key, data, hash_algorithm): + """ + Generates an RSASSA-PKCS-v1.5 signature. + + When the hash_algorithm is "raw", the operation is identical to RSA + private key encryption. That is: the data is not hashed and no ASN.1 + structure with an algorithm identifier of the hash algorithm is placed in + the encrypted byte string. + + :param private_key: + The PrivateKey to generate the signature with + + :param data: + A byte string of the data the signature is for + + :param hash_algorithm: + A unicode string of "md5", "sha1", "sha224", "sha256", "sha384", + "sha512" or "raw" + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + + :return: + A byte string of the signature + """ + + if private_key.algorithm != 'rsa': + raise ValueError(pretty_message( + ''' + The key specified is not an RSA private key, but %s + ''', + private_key.algorithm.upper() + )) + + return _sign(private_key, data, hash_algorithm) + + +def rsa_pss_sign(private_key, data, hash_algorithm): + """ + Generates an RSASSA-PSS signature. For the PSS padding the mask gen + algorithm will be mgf1 using the same hash algorithm as the signature. The + salt length with be the length of the hash algorithm, and the trailer field + with be the standard 0xBC byte. + + :param private_key: + The PrivateKey to generate the signature with + + :param data: + A byte string of the data the signature is for + + :param hash_algorithm: + A unicode string of "md5", "sha1", "sha224", "sha256", "sha384" or "sha512" + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + + :return: + A byte string of the signature + """ + + if private_key.algorithm != 'rsa': + raise ValueError(pretty_message( + ''' + The key specified is not an RSA private key, but %s + ''', + private_key.algorithm.upper() + )) + + return _sign(private_key, data, hash_algorithm, rsa_pss_padding=True) + + +def dsa_sign(private_key, data, hash_algorithm): + """ + Generates a DSA signature + + :param private_key: + The PrivateKey to generate the signature with + + :param data: + A byte string of the data the signature is for + + :param hash_algorithm: + A unicode string of "md5", "sha1", "sha224", "sha256", "sha384" or "sha512" + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + + :return: + A byte string of the signature + """ + + if private_key.algorithm != 'dsa': + raise ValueError(pretty_message( + ''' + The key specified is not a DSA private key, but %s + ''', + private_key.algorithm.upper() + )) + + return _sign(private_key, data, hash_algorithm) + + +def ecdsa_sign(private_key, data, hash_algorithm): + """ + Generates an ECDSA signature + + :param private_key: + The PrivateKey to generate the signature with + + :param data: + A byte string of the data the signature is for + + :param hash_algorithm: + A unicode string of "md5", "sha1", "sha224", "sha256", "sha384" or "sha512" + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + + :return: + A byte string of the signature + """ + + if private_key.algorithm != 'ec': + raise ValueError(pretty_message( + ''' + The key specified is not an EC private key, but %s + ''', + private_key.algorithm.upper() + )) + + return _sign(private_key, data, hash_algorithm) + + +def _sign(private_key, data, hash_algorithm, rsa_pss_padding=False): + """ + Generates an RSA, DSA or ECDSA signature + + :param private_key: + The PrivateKey to generate the signature with + + :param data: + A byte string of the data the signature is for + + :param hash_algorithm: + A unicode string of "md5", "sha1", "sha224", "sha256", "sha384" or "sha512" + + :param rsa_pss_padding: + If the private_key is an RSA key, this enables PSS padding + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + + :return: + A byte string of the signature + """ + + if not isinstance(private_key, PrivateKey): + raise TypeError(pretty_message( + ''' + private_key must be an instance of PrivateKey, not %s + ''', + type_name(private_key) + )) + + if not isinstance(data, byte_cls): + raise TypeError(pretty_message( + ''' + data must be a byte string, not %s + ''', + type_name(data) + )) + + valid_hash_algorithms = set(['md5', 'sha1', 'sha224', 'sha256', 'sha384', 'sha512']) + if private_key.algorithm == 'rsa' and not rsa_pss_padding: + valid_hash_algorithms |= set(['raw']) + + if hash_algorithm not in valid_hash_algorithms: + valid_hash_algorithms_error = '"md5", "sha1", "sha224", "sha256", "sha384", "sha512"' + if private_key.algorithm == 'rsa' and not rsa_pss_padding: + valid_hash_algorithms_error += ', "raw"' + raise ValueError(pretty_message( + ''' + hash_algorithm must be one of %s, not %s + ''', + valid_hash_algorithms_error, + repr(hash_algorithm) + )) + + if private_key.algorithm != 'rsa' and rsa_pss_padding: + raise ValueError(pretty_message( + ''' + PSS padding can only be used with RSA keys - the key provided is a + %s key + ''', + private_key.algorithm.upper() + )) + + if private_key.algorithm == 'rsa' and hash_algorithm == 'raw': + if len(data) > private_key.byte_size - 11: + raise ValueError(pretty_message( + ''' + data must be 11 bytes shorter than the key size when + hash_algorithm is "raw" - key size is %s bytes, but data is + %s bytes long + ''', + private_key.byte_size, + len(data) + )) + + rsa = None + + try: + rsa = libcrypto.EVP_PKEY_get1_RSA(private_key.evp_pkey) + if is_null(rsa): + handle_openssl_error(0) + + buffer_size = libcrypto.EVP_PKEY_size(private_key.evp_pkey) + + signature_buffer = buffer_from_bytes(buffer_size) + signature_length = libcrypto.RSA_private_encrypt( + len(data), + data, + signature_buffer, + rsa, + LibcryptoConst.RSA_PKCS1_PADDING + ) + handle_openssl_error(signature_length) + + return bytes_from_buffer(signature_buffer, signature_length) + + finally: + if rsa: + libcrypto.RSA_free(rsa) + + evp_md_ctx = None + rsa = None + dsa = None + dsa_sig = None + ec_key = None + ecdsa_sig = None + + try: + if libcrypto_version_info < (1, 1): + evp_md_ctx = libcrypto.EVP_MD_CTX_create() + else: + evp_md_ctx = libcrypto.EVP_MD_CTX_new() + + evp_md = { + 'md5': libcrypto.EVP_md5, + 'sha1': libcrypto.EVP_sha1, + 'sha224': libcrypto.EVP_sha224, + 'sha256': libcrypto.EVP_sha256, + 'sha384': libcrypto.EVP_sha384, + 'sha512': libcrypto.EVP_sha512 + }[hash_algorithm]() + + if libcrypto_version_info < (1,): + if private_key.algorithm == 'rsa' and rsa_pss_padding: + digest = getattr(hashlib, hash_algorithm)(data).digest() + + rsa = libcrypto.EVP_PKEY_get1_RSA(private_key.evp_pkey) + if is_null(rsa): + handle_openssl_error(0) + + buffer_size = libcrypto.EVP_PKEY_size(private_key.evp_pkey) + em_buffer = buffer_from_bytes(buffer_size) + res = libcrypto.RSA_padding_add_PKCS1_PSS( + rsa, + em_buffer, + digest, + evp_md, + LibcryptoConst.EVP_MD_CTX_FLAG_PSS_MDLEN + ) + handle_openssl_error(res) + + signature_buffer = buffer_from_bytes(buffer_size) + signature_length = libcrypto.RSA_private_encrypt( + buffer_size, + em_buffer, + signature_buffer, + rsa, + LibcryptoConst.RSA_NO_PADDING + ) + handle_openssl_error(signature_length) + + elif private_key.algorithm == 'rsa': + buffer_size = libcrypto.EVP_PKEY_size(private_key.evp_pkey) + signature_buffer = buffer_from_bytes(buffer_size) + signature_length = new(libcrypto, 'unsigned int *') + + res = libcrypto.EVP_DigestInit_ex(evp_md_ctx, evp_md, null()) + handle_openssl_error(res) + + res = libcrypto.EVP_DigestUpdate(evp_md_ctx, data, len(data)) + handle_openssl_error(res) + + res = libcrypto.EVP_SignFinal( + evp_md_ctx, + signature_buffer, + signature_length, + private_key.evp_pkey + ) + handle_openssl_error(res) + + signature_length = deref(signature_length) + + elif private_key.algorithm == 'dsa': + digest = getattr(hashlib, hash_algorithm)(data).digest() + + dsa = libcrypto.EVP_PKEY_get1_DSA(private_key.evp_pkey) + if is_null(dsa): + handle_openssl_error(0) + + dsa_sig = libcrypto.DSA_do_sign(digest, len(digest), dsa) + if is_null(dsa_sig): + handle_openssl_error(0) + + buffer_size = libcrypto.i2d_DSA_SIG(dsa_sig, null()) + signature_buffer = buffer_from_bytes(buffer_size) + signature_pointer = buffer_pointer(signature_buffer) + signature_length = libcrypto.i2d_DSA_SIG(dsa_sig, signature_pointer) + handle_openssl_error(signature_length) + + elif private_key.algorithm == 'ec': + digest = getattr(hashlib, hash_algorithm)(data).digest() + + ec_key = libcrypto.EVP_PKEY_get1_EC_KEY(private_key.evp_pkey) + if is_null(ec_key): + handle_openssl_error(0) + + ecdsa_sig = libcrypto.ECDSA_do_sign(digest, len(digest), ec_key) + if is_null(ecdsa_sig): + handle_openssl_error(0) + + buffer_size = libcrypto.i2d_ECDSA_SIG(ecdsa_sig, null()) + signature_buffer = buffer_from_bytes(buffer_size) + signature_pointer = buffer_pointer(signature_buffer) + signature_length = libcrypto.i2d_ECDSA_SIG(ecdsa_sig, signature_pointer) + handle_openssl_error(signature_length) + + else: + buffer_size = libcrypto.EVP_PKEY_size(private_key.evp_pkey) + signature_buffer = buffer_from_bytes(buffer_size) + signature_length = new(libcrypto, 'size_t *', buffer_size) + + evp_pkey_ctx_pointer_pointer = new(libcrypto, 'EVP_PKEY_CTX **') + res = libcrypto.EVP_DigestSignInit( + evp_md_ctx, + evp_pkey_ctx_pointer_pointer, + evp_md, + null(), + private_key.evp_pkey + ) + handle_openssl_error(res) + evp_pkey_ctx_pointer = unwrap(evp_pkey_ctx_pointer_pointer) + + if rsa_pss_padding: + # Enable PSS padding + res = libcrypto.EVP_PKEY_CTX_ctrl( + evp_pkey_ctx_pointer, + LibcryptoConst.EVP_PKEY_RSA, + -1, # All operations + LibcryptoConst.EVP_PKEY_CTRL_RSA_PADDING, + LibcryptoConst.RSA_PKCS1_PSS_PADDING, + null() + ) + handle_openssl_error(res) + + # Use the hash algorithm output length as the salt length + res = libcrypto.EVP_PKEY_CTX_ctrl( + evp_pkey_ctx_pointer, + LibcryptoConst.EVP_PKEY_RSA, + LibcryptoConst.EVP_PKEY_OP_SIGN | LibcryptoConst.EVP_PKEY_OP_VERIFY, + LibcryptoConst.EVP_PKEY_CTRL_RSA_PSS_SALTLEN, + -1, + null() + ) + handle_openssl_error(res) + + res = libcrypto.EVP_DigestUpdate(evp_md_ctx, data, len(data)) + handle_openssl_error(res) + + res = libcrypto.EVP_DigestSignFinal(evp_md_ctx, signature_buffer, signature_length) + handle_openssl_error(res) + + signature_length = deref(signature_length) + + return bytes_from_buffer(signature_buffer, signature_length) + + finally: + if evp_md_ctx: + if libcrypto_version_info < (1, 1): + libcrypto.EVP_MD_CTX_destroy(evp_md_ctx) + else: + libcrypto.EVP_MD_CTX_free(evp_md_ctx) + if rsa: + libcrypto.RSA_free(rsa) + if dsa: + libcrypto.DSA_free(dsa) + if dsa_sig: + libcrypto.DSA_SIG_free(dsa_sig) + if ec_key: + libcrypto.EC_KEY_free(ec_key) + if ecdsa_sig: + libcrypto.ECDSA_SIG_free(ecdsa_sig) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_openssl/symmetric.py b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_openssl/symmetric.py new file mode 100644 index 00000000..f41bca58 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_openssl/symmetric.py @@ -0,0 +1,841 @@ +# coding: utf-8 +from __future__ import unicode_literals, division, absolute_import, print_function + +import math + +from .._errors import pretty_message +from .._ffi import new, null, is_null, buffer_from_bytes, bytes_from_buffer, deref +from ._libcrypto import libcrypto, LibcryptoConst, handle_openssl_error +from ..util import rand_bytes +from .._types import type_name, byte_cls + + +__all__ = [ + 'aes_cbc_no_padding_decrypt', + 'aes_cbc_no_padding_encrypt', + 'aes_cbc_pkcs7_decrypt', + 'aes_cbc_pkcs7_encrypt', + 'des_cbc_pkcs5_decrypt', + 'des_cbc_pkcs5_encrypt', + 'rc2_cbc_pkcs5_decrypt', + 'rc2_cbc_pkcs5_encrypt', + 'rc4_decrypt', + 'rc4_encrypt', + 'tripledes_cbc_pkcs5_decrypt', + 'tripledes_cbc_pkcs5_encrypt', +] + + +def aes_cbc_no_padding_encrypt(key, data, iv): + """ + Encrypts plaintext using AES in CBC mode with a 128, 192 or 256 bit key and + no padding. This means the ciphertext must be an exact multiple of 16 bytes + long. + + :param key: + The encryption key - a byte string either 16, 24 or 32 bytes long + + :param data: + The plaintext - a byte string + + :param iv: + The initialization vector - either a byte string 16-bytes long or None + to generate an IV + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by OpenSSL + + :return: + A tuple of two byte strings (iv, ciphertext) + """ + + cipher = _calculate_aes_cipher(key) + + if not iv: + iv = rand_bytes(16) + elif len(iv) != 16: + raise ValueError(pretty_message( + ''' + iv must be 16 bytes long - is %s + ''', + len(iv) + )) + + if len(data) % 16 != 0: + raise ValueError(pretty_message( + ''' + data must be a multiple of 16 bytes long - is %s + ''', + len(data) + )) + + return (iv, _encrypt(cipher, key, data, iv, False)) + + +def aes_cbc_no_padding_decrypt(key, data, iv): + """ + Decrypts AES ciphertext in CBC mode using a 128, 192 or 256 bit key and no + padding. + + :param key: + The encryption key - a byte string either 16, 24 or 32 bytes long + + :param data: + The ciphertext - a byte string + + :param iv: + The initialization vector - a byte string 16-bytes long + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by OpenSSL + + :return: + A byte string of the plaintext + """ + + cipher = _calculate_aes_cipher(key) + + if len(iv) != 16: + raise ValueError(pretty_message( + ''' + iv must be 16 bytes long - is %s + ''', + len(iv) + )) + + return _decrypt(cipher, key, data, iv, False) + + +def aes_cbc_pkcs7_encrypt(key, data, iv): + """ + Encrypts plaintext using AES in CBC mode with a 128, 192 or 256 bit key and + PKCS#7 padding. + + :param key: + The encryption key - a byte string either 16, 24 or 32 bytes long + + :param data: + The plaintext - a byte string + + :param iv: + The initialization vector - either a byte string 16-bytes long or None + to generate an IV + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by OpenSSL + + :return: + A tuple of two byte strings (iv, ciphertext) + """ + + cipher = _calculate_aes_cipher(key) + + if not iv: + iv = rand_bytes(16) + elif len(iv) != 16: + raise ValueError(pretty_message( + ''' + iv must be 16 bytes long - is %s + ''', + len(iv) + )) + + return (iv, _encrypt(cipher, key, data, iv, True)) + + +def aes_cbc_pkcs7_decrypt(key, data, iv): + """ + Decrypts AES ciphertext in CBC mode using a 128, 192 or 256 bit key + + :param key: + The encryption key - a byte string either 16, 24 or 32 bytes long + + :param data: + The ciphertext - a byte string + + :param iv: + The initialization vector - a byte string 16-bytes long + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by OpenSSL + + :return: + A byte string of the plaintext + """ + + cipher = _calculate_aes_cipher(key) + + if len(iv) != 16: + raise ValueError(pretty_message( + ''' + iv must be 16 bytes long - is %s + ''', + len(iv) + )) + + return _decrypt(cipher, key, data, iv, True) + + +def _calculate_aes_cipher(key): + """ + Determines if the key is a valid AES 128, 192 or 256 key + + :param key: + A byte string of the key to use + + :raises: + ValueError - when an invalid key is provided + + :return: + A unicode string of the AES variation - "aes128", "aes192" or "aes256" + """ + + if len(key) not in [16, 24, 32]: + raise ValueError(pretty_message( + ''' + key must be either 16, 24 or 32 bytes (128, 192 or 256 bits) + long - is %s + ''', + len(key) + )) + + if len(key) == 16: + cipher = 'aes128' + elif len(key) == 24: + cipher = 'aes192' + elif len(key) == 32: + cipher = 'aes256' + + return cipher + + +def rc4_encrypt(key, data): + """ + Encrypts plaintext using RC4 with a 40-128 bit key + + :param key: + The encryption key - a byte string 5-16 bytes long + + :param data: + The plaintext - a byte string + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by OpenSSL + + :return: + A byte string of the ciphertext + """ + + if len(key) < 5 or len(key) > 16: + raise ValueError(pretty_message( + ''' + key must be 5 to 16 bytes (40 to 128 bits) long - is %s + ''', + len(key) + )) + + return _encrypt('rc4', key, data, None, None) + + +def rc4_decrypt(key, data): + """ + Decrypts RC4 ciphertext using a 40-128 bit key + + :param key: + The encryption key - a byte string 5-16 bytes long + + :param data: + The ciphertext - a byte string + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by OpenSSL + + :return: + A byte string of the plaintext + """ + + if len(key) < 5 or len(key) > 16: + raise ValueError(pretty_message( + ''' + key must be 5 to 16 bytes (40 to 128 bits) long - is %s + ''', + len(key) + )) + + return _decrypt('rc4', key, data, None, None) + + +def rc2_cbc_pkcs5_encrypt(key, data, iv): + """ + Encrypts plaintext using RC2 in CBC mode with a 40-128 bit key and PKCS#5 + padding. + + :param key: + The encryption key - a byte string 8 bytes long + + :param data: + The plaintext - a byte string + + :param iv: + The initialization vector - a byte string 8-bytes long or None + to generate an IV + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by OpenSSL + + :return: + A tuple of two byte strings (iv, ciphertext) + """ + + if len(key) < 5 or len(key) > 16: + raise ValueError(pretty_message( + ''' + key must be 5 to 16 bytes (40 to 128 bits) long - is %s + ''', + len(key) + )) + + if not iv: + iv = rand_bytes(8) + elif len(iv) != 8: + raise ValueError(pretty_message( + ''' + iv must be 8 bytes long - is %s + ''', + len(iv) + )) + + return (iv, _encrypt('rc2', key, data, iv, True)) + + +def rc2_cbc_pkcs5_decrypt(key, data, iv): + """ + Decrypts RC2 ciphertext ib CBC mode using a 40-128 bit key and PKCS#5 + padding. + + :param key: + The encryption key - a byte string 8 bytes long + + :param data: + The ciphertext - a byte string + + :param iv: + The initialization vector - a byte string 8 bytes long + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by OpenSSL + + :return: + A byte string of the plaintext + """ + + if len(key) < 5 or len(key) > 16: + raise ValueError(pretty_message( + ''' + key must be 5 to 16 bytes (40 to 128 bits) long - is %s + ''', + len(key) + )) + + if len(iv) != 8: + raise ValueError(pretty_message( + ''' + iv must be 8 bytes long - is %s + ''', + len(iv) + )) + + return _decrypt('rc2', key, data, iv, True) + + +def tripledes_cbc_pkcs5_encrypt(key, data, iv): + """ + Encrypts plaintext using 3DES in CBC mode using either the 2 or 3 key + variant (16 or 24 byte long key) and PKCS#5 padding. + + :param key: + The encryption key - a byte string 16 or 24 bytes long (2 or 3 key mode) + + :param data: + The plaintext - a byte string + + :param iv: + The initialization vector - a byte string 8-bytes long or None + to generate an IV + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by OpenSSL + + :return: + A tuple of two byte strings (iv, ciphertext) + """ + + if len(key) != 16 and len(key) != 24: + raise ValueError(pretty_message( + ''' + key must be 16 bytes (2 key) or 24 bytes (3 key) long - %s + ''', + len(key) + )) + + if not iv: + iv = rand_bytes(8) + elif len(iv) != 8: + raise ValueError(pretty_message( + ''' + iv must be 8 bytes long - %s + ''', + len(iv) + )) + + cipher = 'tripledes_3key' + # Expand 2-key to actual 24 byte byte string used by cipher + if len(key) == 16: + key = key + key[0:8] + cipher = 'tripledes_2key' + + return (iv, _encrypt(cipher, key, data, iv, True)) + + +def tripledes_cbc_pkcs5_decrypt(key, data, iv): + """ + Decrypts 3DES ciphertext in CBC mode using either the 2 or 3 key variant + (16 or 24 byte long key) and PKCS#5 padding. + + :param key: + The encryption key - a byte string 16 or 24 bytes long (2 or 3 key mode) + + :param data: + The ciphertext - a byte string + + :param iv: + The initialization vector - a byte string 8-bytes long + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by OpenSSL + + :return: + A byte string of the plaintext + """ + + if len(key) != 16 and len(key) != 24: + raise ValueError(pretty_message( + ''' + key must be 16 bytes (2 key) or 24 bytes (3 key) long - is %s + ''', + len(key) + )) + + if len(iv) != 8: + raise ValueError(pretty_message( + ''' + iv must be 8 bytes long - is %s + ''', + len(iv) + )) + + cipher = 'tripledes_3key' + # Expand 2-key to actual 24 byte byte string used by cipher + if len(key) == 16: + key = key + key[0:8] + cipher = 'tripledes_2key' + + return _decrypt(cipher, key, data, iv, True) + + +def des_cbc_pkcs5_encrypt(key, data, iv): + """ + Encrypts plaintext using DES in CBC mode with a 56 bit key and PKCS#5 + padding. + + :param key: + The encryption key - a byte string 8 bytes long (includes error correction bits) + + :param data: + The plaintext - a byte string + + :param iv: + The initialization vector - a byte string 8-bytes long or None + to generate an IV + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by OpenSSL + + :return: + A tuple of two byte strings (iv, ciphertext) + """ + + if len(key) != 8: + raise ValueError(pretty_message( + ''' + key must be 8 bytes (56 bits + 8 parity bits) long - is %s + ''', + len(key) + )) + + if not iv: + iv = rand_bytes(8) + elif len(iv) != 8: + raise ValueError(pretty_message( + ''' + iv must be 8 bytes long - is %s + ''', + len(iv) + )) + + return (iv, _encrypt('des', key, data, iv, True)) + + +def des_cbc_pkcs5_decrypt(key, data, iv): + """ + Decrypts DES ciphertext in CBC mode using a 56 bit key and PKCS#5 padding. + + :param key: + The encryption key - a byte string 8 bytes long (includes error correction bits) + + :param data: + The ciphertext - a byte string + + :param iv: + The initialization vector - a byte string 8-bytes long + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by OpenSSL + + :return: + A byte string of the plaintext + """ + + if len(key) != 8: + raise ValueError(pretty_message( + ''' + key must be 8 bytes (56 bits + 8 parity bits) long - is %s + ''', + len(key) + )) + + if len(iv) != 8: + raise ValueError(pretty_message( + ''' + iv must be 8 bytes long - is %s + ''', + len(iv) + )) + + return _decrypt('des', key, data, iv, True) + + +def _encrypt(cipher, key, data, iv, padding): + """ + Encrypts plaintext + + :param cipher: + A unicode string of "aes128", "aes192", "aes256", "des", + "tripledes_2key", "tripledes_3key", "rc2", "rc4" + + :param key: + The encryption key - a byte string 5-32 bytes long + + :param data: + The plaintext - a byte string + + :param iv: + The initialization vector - a byte string - unused for RC4 + + :param padding: + Boolean, if padding should be used - unused for RC4 + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by OpenSSL + + :return: + A byte string of the ciphertext + """ + + if not isinstance(key, byte_cls): + raise TypeError(pretty_message( + ''' + key must be a byte string, not %s + ''', + type_name(key) + )) + + if not isinstance(data, byte_cls): + raise TypeError(pretty_message( + ''' + data must be a byte string, not %s + ''', + type_name(data) + )) + + if cipher != 'rc4' and not isinstance(iv, byte_cls): + raise TypeError(pretty_message( + ''' + iv must be a byte string, not %s + ''', + type_name(iv) + )) + + if cipher != 'rc4' and not padding: + # AES in CBC mode can be allowed with no padding if + # the data is an exact multiple of the key size + aes128_no_padding = ( + cipher == 'aes128' and + padding is False and + len(data) % 16 == 0 + ) + aes192_no_padding = ( + cipher == 'aes192' and + padding is False and + len(data) % 24 == 0 + ) + aes256_no_padding = ( + cipher == 'aes256' and + padding is False and + len(data) % 32 == 0 + ) + if aes128_no_padding is False and aes192_no_padding is False and aes256_no_padding is False: + raise ValueError('padding must be specified') + + evp_cipher_ctx = None + + try: + evp_cipher_ctx = libcrypto.EVP_CIPHER_CTX_new() + if is_null(evp_cipher_ctx): + handle_openssl_error(0) + + evp_cipher, buffer_size = _setup_evp_encrypt_decrypt(cipher, data) + + if iv is None: + iv = null() + + if cipher in set(['rc2', 'rc4']): + res = libcrypto.EVP_EncryptInit_ex(evp_cipher_ctx, evp_cipher, null(), null(), null()) + handle_openssl_error(res) + res = libcrypto.EVP_CIPHER_CTX_set_key_length(evp_cipher_ctx, len(key)) + handle_openssl_error(res) + if cipher == 'rc2': + res = libcrypto.EVP_CIPHER_CTX_ctrl( + evp_cipher_ctx, + LibcryptoConst.EVP_CTRL_SET_RC2_KEY_BITS, + len(key) * 8, + null() + ) + handle_openssl_error(res) + evp_cipher = null() + + res = libcrypto.EVP_EncryptInit_ex(evp_cipher_ctx, evp_cipher, null(), key, iv) + handle_openssl_error(res) + + if padding is not None: + res = libcrypto.EVP_CIPHER_CTX_set_padding(evp_cipher_ctx, int(padding)) + handle_openssl_error(res) + + buffer = buffer_from_bytes(buffer_size) + output_length = new(libcrypto, 'int *') + + res = libcrypto.EVP_EncryptUpdate(evp_cipher_ctx, buffer, output_length, data, len(data)) + handle_openssl_error(res) + + output = bytes_from_buffer(buffer, deref(output_length)) + + res = libcrypto.EVP_EncryptFinal_ex(evp_cipher_ctx, buffer, output_length) + handle_openssl_error(res) + + output += bytes_from_buffer(buffer, deref(output_length)) + + return output + + finally: + if evp_cipher_ctx: + libcrypto.EVP_CIPHER_CTX_free(evp_cipher_ctx) + + +def _decrypt(cipher, key, data, iv, padding): + """ + Decrypts AES/RC4/RC2/3DES/DES ciphertext + + :param cipher: + A unicode string of "aes128", "aes192", "aes256", "des", + "tripledes_2key", "tripledes_3key", "rc2", "rc4" + + :param key: + The encryption key - a byte string 5-32 bytes long + + :param data: + The ciphertext - a byte string + + :param iv: + The initialization vector - a byte string - unused for RC4 + + :param padding: + Boolean, if padding should be used - unused for RC4 + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by OpenSSL + + :return: + A byte string of the plaintext + """ + + if not isinstance(key, byte_cls): + raise TypeError(pretty_message( + ''' + key must be a byte string, not %s + ''', + type_name(key) + )) + + if not isinstance(data, byte_cls): + raise TypeError(pretty_message( + ''' + data must be a byte string, not %s + ''', + type_name(data) + )) + + if cipher != 'rc4' and not isinstance(iv, byte_cls): + raise TypeError(pretty_message( + ''' + iv must be a byte string, not %s + ''', + type_name(iv) + )) + + if cipher != 'rc4' and padding is None: + raise ValueError('padding must be specified') + + evp_cipher_ctx = None + + try: + evp_cipher_ctx = libcrypto.EVP_CIPHER_CTX_new() + if is_null(evp_cipher_ctx): + handle_openssl_error(0) + + evp_cipher, buffer_size = _setup_evp_encrypt_decrypt(cipher, data) + + if iv is None: + iv = null() + + if cipher in set(['rc2', 'rc4']): + res = libcrypto.EVP_DecryptInit_ex(evp_cipher_ctx, evp_cipher, null(), null(), null()) + handle_openssl_error(res) + res = libcrypto.EVP_CIPHER_CTX_set_key_length(evp_cipher_ctx, len(key)) + handle_openssl_error(res) + if cipher == 'rc2': + res = libcrypto.EVP_CIPHER_CTX_ctrl( + evp_cipher_ctx, + LibcryptoConst.EVP_CTRL_SET_RC2_KEY_BITS, + len(key) * 8, + null() + ) + handle_openssl_error(res) + evp_cipher = null() + + res = libcrypto.EVP_DecryptInit_ex(evp_cipher_ctx, evp_cipher, null(), key, iv) + handle_openssl_error(res) + + if padding is not None: + res = libcrypto.EVP_CIPHER_CTX_set_padding(evp_cipher_ctx, int(padding)) + handle_openssl_error(res) + + buffer = buffer_from_bytes(buffer_size) + output_length = new(libcrypto, 'int *') + + res = libcrypto.EVP_DecryptUpdate(evp_cipher_ctx, buffer, output_length, data, len(data)) + handle_openssl_error(res) + + output = bytes_from_buffer(buffer, deref(output_length)) + + res = libcrypto.EVP_DecryptFinal_ex(evp_cipher_ctx, buffer, output_length) + handle_openssl_error(res) + + output += bytes_from_buffer(buffer, deref(output_length)) + + return output + + finally: + if evp_cipher_ctx: + libcrypto.EVP_CIPHER_CTX_free(evp_cipher_ctx) + + +def _setup_evp_encrypt_decrypt(cipher, data): + """ + Creates an EVP_CIPHER pointer object and determines the buffer size + necessary for the parameter specified. + + :param evp_cipher_ctx: + An EVP_CIPHER_CTX pointer + + :param cipher: + A unicode string of "aes128", "aes192", "aes256", "des", + "tripledes_2key", "tripledes_3key", "rc2", "rc4" + + :param key: + The key byte string + + :param data: + The plaintext or ciphertext as a byte string + + :param padding: + If padding is to be used + + :return: + A 2-element tuple with the first element being an EVP_CIPHER pointer + and the second being an integer that is the required buffer size + """ + + evp_cipher = { + 'aes128': libcrypto.EVP_aes_128_cbc, + 'aes192': libcrypto.EVP_aes_192_cbc, + 'aes256': libcrypto.EVP_aes_256_cbc, + 'rc2': libcrypto.EVP_rc2_cbc, + 'rc4': libcrypto.EVP_rc4, + 'des': libcrypto.EVP_des_cbc, + 'tripledes_2key': libcrypto.EVP_des_ede_cbc, + 'tripledes_3key': libcrypto.EVP_des_ede3_cbc, + }[cipher]() + + if cipher == 'rc4': + buffer_size = len(data) + else: + block_size = { + 'aes128': 16, + 'aes192': 16, + 'aes256': 16, + 'rc2': 8, + 'des': 8, + 'tripledes_2key': 8, + 'tripledes_3key': 8, + }[cipher] + buffer_size = block_size * int(math.ceil(len(data) / block_size)) + + return (evp_cipher, buffer_size) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_openssl/tls.py b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_openssl/tls.py new file mode 100644 index 00000000..8d645801 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_openssl/tls.py @@ -0,0 +1,1251 @@ +# coding: utf-8 +from __future__ import unicode_literals, division, absolute_import, print_function + +import sys +import re +import socket as socket_ +import select +import numbers + +from ._libssl import libssl, LibsslConst +from ._libcrypto import libcrypto, libcrypto_version_info, handle_openssl_error, peek_openssl_error +from .. import _backend_config +from .._asn1 import Certificate as Asn1Certificate +from .._errors import pretty_message +from .._ffi import null, bytes_from_buffer, buffer_from_bytes, is_null, buffer_pointer +from .._types import type_name, str_cls, byte_cls, int_types +from ..errors import TLSError, TLSDisconnectError, TLSGracefulDisconnectError +from .._tls import ( + detect_client_auth_request, + extract_chain, + get_dh_params_length, + parse_session_info, + raise_client_auth, + raise_dh_params, + raise_disconnection, + raise_expired_not_yet_valid, + raise_handshake, + raise_hostname, + raise_no_issuer, + raise_protocol_error, + raise_protocol_version, + raise_self_signed, + raise_verification, + raise_weak_signature, + parse_tls_records, + parse_handshake_messages, +) +from .asymmetric import load_certificate, Certificate +from ..keys import parse_certificate +from ..trust_list import get_path + +if sys.version_info < (3,): + range = xrange # noqa + +if sys.version_info < (3, 7): + Pattern = re._pattern_type +else: + Pattern = re.Pattern + + +__all__ = [ + 'TLSSession', + 'TLSSocket', +] + + +_trust_list_path = _backend_config().get('trust_list_path') +_line_regex = re.compile(b'(\r\n|\r|\n)') +_PROTOCOL_MAP = { + 'SSLv2': LibsslConst.SSL_OP_NO_SSLv2, + 'SSLv3': LibsslConst.SSL_OP_NO_SSLv3, + 'TLSv1': LibsslConst.SSL_OP_NO_TLSv1, + 'TLSv1.1': LibsslConst.SSL_OP_NO_TLSv1_1, + 'TLSv1.2': LibsslConst.SSL_OP_NO_TLSv1_2, +} + + +class TLSSession(object): + """ + A TLS session object that multiple TLSSocket objects can share for the + sake of session reuse + """ + + _protocols = None + _ciphers = None + _manual_validation = None + _extra_trust_roots = None + _ssl_ctx = None + _ssl_session = None + + def __init__(self, protocol=None, manual_validation=False, extra_trust_roots=None): + """ + :param protocol: + A unicode string or set of unicode strings representing allowable + protocols to negotiate with the server: + + - "TLSv1.2" + - "TLSv1.1" + - "TLSv1" + - "SSLv3" + + Default is: {"TLSv1", "TLSv1.1", "TLSv1.2"} + + :param manual_validation: + If certificate and certificate path validation should be skipped + and left to the developer to implement + + :param extra_trust_roots: + A list containing one or more certificates to be treated as trust + roots, in one of the following formats: + - A byte string of the DER encoded certificate + - A unicode string of the certificate filename + - An asn1crypto.x509.Certificate object + - An oscrypto.asymmetric.Certificate object + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + """ + + if not isinstance(manual_validation, bool): + raise TypeError(pretty_message( + ''' + manual_validation must be a boolean, not %s + ''', + type_name(manual_validation) + )) + + self._manual_validation = manual_validation + + if protocol is None: + protocol = set(['TLSv1', 'TLSv1.1', 'TLSv1.2']) + + if isinstance(protocol, str_cls): + protocol = set([protocol]) + elif not isinstance(protocol, set): + raise TypeError(pretty_message( + ''' + protocol must be a unicode string or set of unicode strings, + not %s + ''', + type_name(protocol) + )) + + valid_protocols = set(['SSLv3', 'TLSv1', 'TLSv1.1', 'TLSv1.2']) + unsupported_protocols = protocol - valid_protocols + if unsupported_protocols: + raise ValueError(pretty_message( + ''' + protocol must contain only the unicode strings "SSLv3", "TLSv1", + "TLSv1.1", "TLSv1.2", not %s + ''', + repr(unsupported_protocols) + )) + + self._protocols = protocol + + self._extra_trust_roots = [] + if extra_trust_roots: + for extra_trust_root in extra_trust_roots: + if isinstance(extra_trust_root, Certificate): + extra_trust_root = extra_trust_root.asn1 + elif isinstance(extra_trust_root, byte_cls): + extra_trust_root = parse_certificate(extra_trust_root) + elif isinstance(extra_trust_root, str_cls): + with open(extra_trust_root, 'rb') as f: + extra_trust_root = parse_certificate(f.read()) + elif not isinstance(extra_trust_root, Asn1Certificate): + raise TypeError(pretty_message( + ''' + extra_trust_roots must be a list of byte strings, unicode + strings, asn1crypto.x509.Certificate objects or + oscrypto.asymmetric.Certificate objects, not %s + ''', + type_name(extra_trust_root) + )) + self._extra_trust_roots.append(extra_trust_root) + + ssl_ctx = None + try: + if libcrypto_version_info < (1, 1): + method = libssl.SSLv23_method() + else: + method = libssl.TLS_method() + ssl_ctx = libssl.SSL_CTX_new(method) + if is_null(ssl_ctx): + handle_openssl_error(0) + self._ssl_ctx = ssl_ctx + + libssl.SSL_CTX_set_timeout(ssl_ctx, 600) + + # Allow caching SSL sessions + libssl.SSL_CTX_ctrl( + ssl_ctx, + LibsslConst.SSL_CTRL_SET_SESS_CACHE_MODE, + LibsslConst.SSL_SESS_CACHE_CLIENT, + null() + ) + + if sys.platform in set(['win32', 'darwin']): + trust_list_path = _trust_list_path + if trust_list_path is None: + trust_list_path = get_path() + + if sys.platform == 'win32': + path_encoding = 'mbcs' + else: + path_encoding = 'utf-8' + result = libssl.SSL_CTX_load_verify_locations( + ssl_ctx, + trust_list_path.encode(path_encoding), + null() + ) + + else: + result = libssl.SSL_CTX_set_default_verify_paths(ssl_ctx) + handle_openssl_error(result) + + verify_mode = LibsslConst.SSL_VERIFY_NONE if manual_validation else LibsslConst.SSL_VERIFY_PEER + libssl.SSL_CTX_set_verify(ssl_ctx, verify_mode, null()) + + # Modern cipher suite list from https://wiki.mozilla.org/Security/Server_Side_TLS late August 2015 + result = libssl.SSL_CTX_set_cipher_list( + ssl_ctx, + ( + b'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:' + b'ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:' + b'DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:' + b'kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:' + b'ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:' + b'ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:' + b'DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:' + b'DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:' + b'AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:' + b'AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:' + b'!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:' + b'!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA' + ) + ) + handle_openssl_error(result) + + disabled_protocols = set(['SSLv2']) + disabled_protocols |= (valid_protocols - self._protocols) + for disabled_protocol in disabled_protocols: + libssl.SSL_CTX_ctrl( + ssl_ctx, + LibsslConst.SSL_CTRL_OPTIONS, + _PROTOCOL_MAP[disabled_protocol], + null() + ) + + if self._extra_trust_roots: + x509_store = libssl.SSL_CTX_get_cert_store(ssl_ctx) + for cert in self._extra_trust_roots: + oscrypto_cert = load_certificate(cert) + result = libssl.X509_STORE_add_cert( + x509_store, + oscrypto_cert.x509 + ) + handle_openssl_error(result) + + except (Exception): + if ssl_ctx: + libssl.SSL_CTX_free(ssl_ctx) + self._ssl_ctx = None + raise + + def __del__(self): + if self._ssl_ctx: + libssl.SSL_CTX_free(self._ssl_ctx) + self._ssl_ctx = None + + if self._ssl_session: + libssl.SSL_SESSION_free(self._ssl_session) + self._ssl_session = None + + +class TLSSocket(object): + """ + A wrapper around a socket.socket that adds TLS + """ + + _socket = None + + # An oscrypto.tls.TLSSession object + _session = None + + # An OpenSSL SSL struct pointer + _ssl = None + + # OpenSSL memory bios used for reading/writing data to and + # from the socket + _rbio = None + _wbio = None + + # Size of _bio_write_buffer and _read_buffer + _buffer_size = 8192 + + # A buffer used to pull bytes out of the _wbio memory bio to + # be written to the socket + _bio_write_buffer = None + + # A buffer used to push bytes into the _rbio memory bio to + # be decrypted by OpenSSL + _read_buffer = None + + # Raw ciphertext from the socker that hasn't need fed to OpenSSL yet + _raw_bytes = None + + # Plaintext that has been decrypted, but not asked for yet + _decrypted_bytes = None + + _hostname = None + + _certificate = None + _intermediates = None + + _protocol = None + _cipher_suite = None + _compression = None + _session_id = None + _session_ticket = None + + # If we explicitly asked for the connection to be closed + _local_closed = False + + _gracefully_closed = False + + @classmethod + def wrap(cls, socket, hostname, session=None): + """ + Takes an existing socket and adds TLS + + :param socket: + A socket.socket object to wrap with TLS + + :param hostname: + A unicode string of the hostname or IP the socket is connected to + + :param session: + An existing TLSSession object to allow for session reuse, specific + protocol or manual certificate validation + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + """ + + if not isinstance(socket, socket_.socket): + raise TypeError(pretty_message( + ''' + socket must be an instance of socket.socket, not %s + ''', + type_name(socket) + )) + + if not isinstance(hostname, str_cls): + raise TypeError(pretty_message( + ''' + hostname must be a unicode string, not %s + ''', + type_name(hostname) + )) + + if session is not None and not isinstance(session, TLSSession): + raise TypeError(pretty_message( + ''' + session must be an instance of oscrypto.tls.TLSSession, not %s + ''', + type_name(session) + )) + + new_socket = cls(None, None, session=session) + new_socket._socket = socket + new_socket._hostname = hostname + new_socket._handshake() + + return new_socket + + def __init__(self, address, port, timeout=10, session=None): + """ + :param address: + A unicode string of the domain name or IP address to conenct to + + :param port: + An integer of the port number to connect to + + :param timeout: + An integer timeout to use for the socket + + :param session: + An oscrypto.tls.TLSSession object to allow for session reuse and + controlling the protocols and validation performed + """ + + self._raw_bytes = b'' + self._decrypted_bytes = b'' + + if address is None and port is None: + self._socket = None + + else: + if not isinstance(address, str_cls): + raise TypeError(pretty_message( + ''' + address must be a unicode string, not %s + ''', + type_name(address) + )) + + if not isinstance(port, int_types): + raise TypeError(pretty_message( + ''' + port must be an integer, not %s + ''', + type_name(port) + )) + + if timeout is not None and not isinstance(timeout, numbers.Number): + raise TypeError(pretty_message( + ''' + timeout must be a number, not %s + ''', + type_name(timeout) + )) + + self._socket = socket_.create_connection((address, port), timeout) + self._socket.settimeout(timeout) + + if session is None: + session = TLSSession() + + elif not isinstance(session, TLSSession): + raise TypeError(pretty_message( + ''' + session must be an instance of oscrypto.tls.TLSSession, not %s + ''', + type_name(session) + )) + + self._session = session + + if self._socket: + self._hostname = address + self._handshake() + + def _handshake(self): + """ + Perform an initial TLS handshake + """ + + self._ssl = None + self._rbio = None + self._wbio = None + + try: + self._ssl = libssl.SSL_new(self._session._ssl_ctx) + if is_null(self._ssl): + self._ssl = None + handle_openssl_error(0) + + mem_bio = libssl.BIO_s_mem() + + self._rbio = libssl.BIO_new(mem_bio) + if is_null(self._rbio): + handle_openssl_error(0) + + self._wbio = libssl.BIO_new(mem_bio) + if is_null(self._wbio): + handle_openssl_error(0) + + libssl.SSL_set_bio(self._ssl, self._rbio, self._wbio) + + utf8_domain = self._hostname.encode('utf-8') + libssl.SSL_ctrl( + self._ssl, + LibsslConst.SSL_CTRL_SET_TLSEXT_HOSTNAME, + LibsslConst.TLSEXT_NAMETYPE_host_name, + utf8_domain + ) + + libssl.SSL_set_connect_state(self._ssl) + + if self._session._ssl_session: + libssl.SSL_set_session(self._ssl, self._session._ssl_session) + + self._bio_write_buffer = buffer_from_bytes(self._buffer_size) + self._read_buffer = buffer_from_bytes(self._buffer_size) + + handshake_server_bytes = b'' + handshake_client_bytes = b'' + + while True: + result = libssl.SSL_do_handshake(self._ssl) + handshake_client_bytes += self._raw_write() + + if result == 1: + break + + error = libssl.SSL_get_error(self._ssl, result) + if error == LibsslConst.SSL_ERROR_WANT_READ: + chunk = self._raw_read() + if chunk == b'': + if handshake_server_bytes == b'': + raise_disconnection() + if detect_client_auth_request(handshake_server_bytes): + raise_client_auth() + raise_protocol_error(handshake_server_bytes) + handshake_server_bytes += chunk + + elif error == LibsslConst.SSL_ERROR_WANT_WRITE: + handshake_client_bytes += self._raw_write() + + elif error == LibsslConst.SSL_ERROR_ZERO_RETURN: + self._gracefully_closed = True + self._shutdown(False) + self._raise_closed() + + else: + info = peek_openssl_error() + + dh_key_info_1 = ( + LibsslConst.ERR_LIB_SSL, + LibsslConst.SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM, + LibsslConst.SSL_R_DH_KEY_TOO_SMALL + ) + dh_key_info_2 = ( + LibsslConst.ERR_LIB_SSL, + LibsslConst.SSL_F_TLS_PROCESS_SKE_DHE, + LibsslConst.SSL_R_DH_KEY_TOO_SMALL + ) + dh_key_info_3 = ( + LibsslConst.ERR_LIB_SSL, + LibsslConst.SSL_F_SSL3_GET_KEY_EXCHANGE, + LibsslConst.SSL_R_BAD_DH_P_LENGTH + ) + if info == dh_key_info_1 or info == dh_key_info_2 or info == dh_key_info_3: + raise_dh_params() + + if libcrypto_version_info < (1, 1): + unknown_protocol_info = ( + LibsslConst.ERR_LIB_SSL, + LibsslConst.SSL_F_SSL23_GET_SERVER_HELLO, + LibsslConst.SSL_R_UNKNOWN_PROTOCOL + ) + else: + unknown_protocol_info = ( + LibsslConst.ERR_LIB_SSL, + LibsslConst.SSL_F_SSL3_GET_RECORD, + LibsslConst.SSL_R_WRONG_VERSION_NUMBER + ) + if info == unknown_protocol_info: + raise_protocol_error(handshake_server_bytes) + + tls_version_info_error = ( + LibsslConst.ERR_LIB_SSL, + LibsslConst.SSL_F_SSL23_GET_SERVER_HELLO, + LibsslConst.SSL_R_TLSV1_ALERT_PROTOCOL_VERSION + ) + if info == tls_version_info_error: + raise_protocol_version() + + handshake_error_info = ( + LibsslConst.ERR_LIB_SSL, + LibsslConst.SSL_F_SSL23_GET_SERVER_HELLO, + LibsslConst.SSL_R_SSLV3_ALERT_HANDSHAKE_FAILURE + ) + if info == handshake_error_info: + raise_handshake() + + handshake_failure_info = ( + LibsslConst.ERR_LIB_SSL, + LibsslConst.SSL_F_SSL3_READ_BYTES, + LibsslConst.SSL_R_SSLV3_ALERT_HANDSHAKE_FAILURE + ) + if info == handshake_failure_info: + saw_client_auth = False + for record_type, _, record_data in parse_tls_records(handshake_server_bytes): + if record_type != b'\x16': + continue + for message_type, message_data in parse_handshake_messages(record_data): + if message_type == b'\x0d': + saw_client_auth = True + break + if saw_client_auth: + raise_client_auth() + raise_handshake() + + if libcrypto_version_info < (1, 1): + cert_verify_failed_info = ( + LibsslConst.ERR_LIB_SSL, + LibsslConst.SSL_F_SSL3_GET_SERVER_CERTIFICATE, + LibsslConst.SSL_R_CERTIFICATE_VERIFY_FAILED + ) + else: + cert_verify_failed_info = ( + LibsslConst.ERR_LIB_SSL, + LibsslConst.SSL_F_TLS_PROCESS_SERVER_CERTIFICATE, + LibsslConst.SSL_R_CERTIFICATE_VERIFY_FAILED + ) + + # It would appear that some versions of OpenSSL (such as on Fedora 30) + # don't even have the MD5 digest algorithm included any longer? To + # give a more useful error message we handle this specifically. + unknown_hash_algo_info = ( + LibsslConst.ERR_LIB_ASN1, + LibsslConst.ASN1_F_ASN1_ITEM_VERIFY, + LibsslConst.ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM + ) + + if info == unknown_hash_algo_info: + chain = extract_chain(handshake_server_bytes) + if chain: + cert = chain[0] + oscrypto_cert = load_certificate(cert) + if oscrypto_cert.asn1.hash_algo in set(['md5', 'md2']): + raise_weak_signature(oscrypto_cert) + + if info == cert_verify_failed_info: + verify_result = libssl.SSL_get_verify_result(self._ssl) + chain = extract_chain(handshake_server_bytes) + + self_signed = False + time_invalid = False + no_issuer = False + cert = None + oscrypto_cert = None + + if chain: + cert = chain[0] + oscrypto_cert = load_certificate(cert) + self_signed = oscrypto_cert.self_signed + + issuer_error_codes = set([ + LibsslConst.X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT, + LibsslConst.X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN, + LibsslConst.X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY + ]) + if verify_result in issuer_error_codes: + no_issuer = not self_signed + + time_error_codes = set([ + LibsslConst.X509_V_ERR_CERT_HAS_EXPIRED, + LibsslConst.X509_V_ERR_CERT_NOT_YET_VALID + ]) + time_invalid = verify_result in time_error_codes + + if time_invalid: + raise_expired_not_yet_valid(cert) + if no_issuer: + raise_no_issuer(cert) + if self_signed: + raise_self_signed(cert) + if oscrypto_cert and oscrypto_cert.asn1.hash_algo in set(['md5', 'md2']): + raise_weak_signature(oscrypto_cert) + raise_verification(cert) + + handle_openssl_error(0, TLSError) + + session_info = parse_session_info( + handshake_server_bytes, + handshake_client_bytes + ) + self._protocol = session_info['protocol'] + self._cipher_suite = session_info['cipher_suite'] + self._compression = session_info['compression'] + self._session_id = session_info['session_id'] + self._session_ticket = session_info['session_ticket'] + + if self._cipher_suite.find('_DHE_') != -1: + dh_params_length = get_dh_params_length(handshake_server_bytes) + if dh_params_length < 1024: + self.close() + raise_dh_params() + + # When saving the session for future requests, we use + # SSL_get1_session() variant to increase the reference count. This + # prevents the session from being freed when one connection closes + # before another is opened. However, since we increase the ref + # count, we also have to explicitly free any previous session. + if self._session_id == 'new' or self._session_ticket == 'new': + if self._session._ssl_session: + libssl.SSL_SESSION_free(self._session._ssl_session) + self._session._ssl_session = libssl.SSL_get1_session(self._ssl) + + if not self._session._manual_validation: + if self.certificate.hash_algo in set(['md5', 'md2']): + raise_weak_signature(self.certificate) + + # OpenSSL does not do hostname or IP address checking in the end + # entity certificate, so we must perform that check + if not self.certificate.is_valid_domain_ip(self._hostname): + raise_hostname(self.certificate, self._hostname) + + except (OSError, socket_.error): + if self._ssl: + libssl.SSL_free(self._ssl) + self._ssl = None + self._rbio = None + self._wbio = None + # The BIOs are freed by SSL_free(), so we only need to free + # them if for some reason SSL_free() was not called + else: + if self._rbio: + libssl.BIO_free(self._rbio) + self._rbio = None + if self._wbio: + libssl.BIO_free(self._wbio) + self._wbio = None + self.close() + + raise + + def _raw_read(self): + """ + Reads data from the socket and writes it to the memory bio + used by libssl to decrypt the data. Returns the unencrypted + data for the purpose of debugging handshakes. + + :return: + A byte string of ciphertext from the socket. Used for + debugging the handshake only. + """ + + data = self._raw_bytes + try: + data += self._socket.recv(8192) + except (socket_.error): + pass + output = data + written = libssl.BIO_write(self._rbio, data, len(data)) + self._raw_bytes = data[written:] + return output + + def _raw_write(self): + """ + Takes ciphertext from the memory bio and writes it to the + socket. + + :return: + A byte string of ciphertext going to the socket. Used + for debugging the handshake only. + """ + + data_available = libssl.BIO_ctrl_pending(self._wbio) + if data_available == 0: + return b'' + to_read = min(self._buffer_size, data_available) + read = libssl.BIO_read(self._wbio, self._bio_write_buffer, to_read) + to_write = bytes_from_buffer(self._bio_write_buffer, read) + output = to_write + while len(to_write): + raise_disconnect = False + try: + sent = self._socket.send(to_write) + except (socket_.error) as e: + # Handle ECONNRESET and EPIPE + if e.errno == 104 or e.errno == 32: + raise_disconnect = True + # Handle EPROTOTYPE. Newer versions of macOS will return this + # if we try to call send() while the socket is being torn down + elif sys.platform == 'darwin' and e.errno == 41: + raise_disconnect = True + else: + raise + + if raise_disconnect: + raise_disconnection() + to_write = to_write[sent:] + if len(to_write): + self.select_write() + return output + + def read(self, max_length): + """ + Reads data from the TLS-wrapped socket + + :param max_length: + The number of bytes to read - output may be less than this + + :raises: + socket.socket - when a non-TLS socket error occurs + oscrypto.errors.TLSError - when a TLS-related error occurs + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + + :return: + A byte string of the data read + """ + + if not isinstance(max_length, int_types): + raise TypeError(pretty_message( + ''' + max_length must be an integer, not %s + ''', + type_name(max_length) + )) + + buffered_length = len(self._decrypted_bytes) + + # If we already have enough buffered data, just use that + if buffered_length >= max_length: + output = self._decrypted_bytes[0:max_length] + self._decrypted_bytes = self._decrypted_bytes[max_length:] + return output + + if self._ssl is None: + self._raise_closed() + + # Don't block if we have buffered data available, since it is ok to + # return less than the max_length + if buffered_length > 0 and not self.select_read(0): + output = self._decrypted_bytes + self._decrypted_bytes = b'' + return output + + # Only read enough to get the requested amount when + # combined with buffered data + to_read = min(self._buffer_size, max_length - buffered_length) + + output = self._decrypted_bytes + + # The SSL_read() loop handles renegotiations, so we need to handle + # requests for both reads and writes + again = True + while again: + again = False + result = libssl.SSL_read(self._ssl, self._read_buffer, to_read) + self._raw_write() + if result <= 0: + + error = libssl.SSL_get_error(self._ssl, result) + if error == LibsslConst.SSL_ERROR_WANT_READ: + if self._raw_read() != b'': + again = True + continue + raise_disconnection() + + elif error == LibsslConst.SSL_ERROR_WANT_WRITE: + self._raw_write() + again = True + continue + + elif error == LibsslConst.SSL_ERROR_ZERO_RETURN: + self._gracefully_closed = True + self._shutdown(False) + break + + else: + handle_openssl_error(0, TLSError) + + output += bytes_from_buffer(self._read_buffer, result) + + if self._gracefully_closed and len(output) == 0: + self._raise_closed() + + self._decrypted_bytes = output[max_length:] + return output[0:max_length] + + def select_read(self, timeout=None): + """ + Blocks until the socket is ready to be read from, or the timeout is hit + + :param timeout: + A float - the period of time to wait for data to be read. None for + no time limit. + + :return: + A boolean - if data is ready to be read. Will only be False if + timeout is not None. + """ + + # If we have buffered data, we consider a read possible + if len(self._decrypted_bytes) > 0: + return True + + read_ready, _, _ = select.select([self._socket], [], [], timeout) + return len(read_ready) > 0 + + def read_until(self, marker): + """ + Reads data from the socket until a marker is found. Data read includes + the marker. + + :param marker: + A byte string or regex object from re.compile(). Used to determine + when to stop reading. Regex objects are more inefficient since + they must scan the entire byte string of read data each time data + is read off the socket. + + :return: + A byte string of the data read, including the marker + """ + + if not isinstance(marker, byte_cls) and not isinstance(marker, Pattern): + raise TypeError(pretty_message( + ''' + marker must be a byte string or compiled regex object, not %s + ''', + type_name(marker) + )) + + output = b'' + + is_regex = isinstance(marker, Pattern) + + while True: + if len(self._decrypted_bytes) > 0: + chunk = self._decrypted_bytes + self._decrypted_bytes = b'' + else: + if self._ssl is None: + self._raise_closed() + to_read = libssl.SSL_pending(self._ssl) or 8192 + chunk = self.read(to_read) + + offset = len(output) + output += chunk + + if is_regex: + match = marker.search(output) + if match is not None: + end = match.end() + break + else: + # If the marker was not found last time, we have to start + # at a position where the marker would have its final char + # in the newly read chunk + start = max(0, offset - len(marker) - 1) + match = output.find(marker, start) + if match != -1: + end = match + len(marker) + break + + self._decrypted_bytes = output[end:] + self._decrypted_bytes + return output[0:end] + + def read_line(self): + r""" + Reads a line from the socket, including the line ending of "\r\n", "\r", + or "\n" + + :return: + A byte string of the next line from the socket + """ + + return self.read_until(_line_regex) + + def read_exactly(self, num_bytes): + """ + Reads exactly the specified number of bytes from the socket + + :param num_bytes: + An integer - the exact number of bytes to read + + :return: + A byte string of the data that was read + """ + + output = b'' + remaining = num_bytes + while remaining > 0: + output += self.read(remaining) + remaining = num_bytes - len(output) + + return output + + def write(self, data): + """ + Writes data to the TLS-wrapped socket + + :param data: + A byte string to write to the socket + + :raises: + socket.socket - when a non-TLS socket error occurs + oscrypto.errors.TLSError - when a TLS-related error occurs + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + """ + + data_len = len(data) + while data_len: + if self._ssl is None: + self._raise_closed() + result = libssl.SSL_write(self._ssl, data, data_len) + self._raw_write() + if result <= 0: + + error = libssl.SSL_get_error(self._ssl, result) + if error == LibsslConst.SSL_ERROR_WANT_READ: + if self._raw_read() != b'': + continue + raise_disconnection() + + elif error == LibsslConst.SSL_ERROR_WANT_WRITE: + self._raw_write() + continue + + elif error == LibsslConst.SSL_ERROR_ZERO_RETURN: + self._gracefully_closed = True + self._shutdown(False) + self._raise_closed() + + else: + handle_openssl_error(0, TLSError) + + data = data[result:] + data_len = len(data) + + def select_write(self, timeout=None): + """ + Blocks until the socket is ready to be written to, or the timeout is hit + + :param timeout: + A float - the period of time to wait for the socket to be ready to + written to. None for no time limit. + + :return: + A boolean - if the socket is ready for writing. Will only be False + if timeout is not None. + """ + + _, write_ready, _ = select.select([], [self._socket], [], timeout) + return len(write_ready) > 0 + + def _shutdown(self, manual): + """ + Shuts down the TLS session and then shuts down the underlying socket + + :param manual: + A boolean if the connection was manually shutdown + """ + + if self._ssl is None: + return + + while True: + result = libssl.SSL_shutdown(self._ssl) + + # Don't be noisy if the socket is already closed + try: + self._raw_write() + except (TLSDisconnectError): + pass + + if result >= 0: + break + if result < 0: + error = libssl.SSL_get_error(self._ssl, result) + if error == LibsslConst.SSL_ERROR_WANT_READ: + if self._raw_read() != b'': + continue + else: + break + + elif error == LibsslConst.SSL_ERROR_WANT_WRITE: + self._raw_write() + continue + + else: + handle_openssl_error(0, TLSError) + + if manual: + self._local_closed = True + + libssl.SSL_free(self._ssl) + self._ssl = None + # BIOs are freed by SSL_free() + self._rbio = None + self._wbio = None + + try: + self._socket.shutdown(socket_.SHUT_RDWR) + except (socket_.error): + pass + + def shutdown(self): + """ + Shuts down the TLS session and then shuts down the underlying socket + """ + + self._shutdown(True) + + def close(self): + """ + Shuts down the TLS session and socket and forcibly closes it + """ + + try: + self.shutdown() + + finally: + if self._socket: + try: + self._socket.close() + except (socket_.error): + pass + self._socket = None + + def _read_certificates(self): + """ + Reads end-entity and intermediate certificate information from the + TLS session + """ + + stack_pointer = libssl.SSL_get_peer_cert_chain(self._ssl) + if is_null(stack_pointer): + handle_openssl_error(0, TLSError) + + if libcrypto_version_info < (1, 1): + number_certs = libssl.sk_num(stack_pointer) + else: + number_certs = libssl.OPENSSL_sk_num(stack_pointer) + + self._intermediates = [] + + for index in range(0, number_certs): + if libcrypto_version_info < (1, 1): + x509_ = libssl.sk_value(stack_pointer, index) + else: + x509_ = libssl.OPENSSL_sk_value(stack_pointer, index) + buffer_size = libcrypto.i2d_X509(x509_, null()) + cert_buffer = buffer_from_bytes(buffer_size) + cert_pointer = buffer_pointer(cert_buffer) + cert_length = libcrypto.i2d_X509(x509_, cert_pointer) + handle_openssl_error(cert_length) + cert_data = bytes_from_buffer(cert_buffer, cert_length) + + cert = Asn1Certificate.load(cert_data) + + if index == 0: + self._certificate = cert + else: + self._intermediates.append(cert) + + def _raise_closed(self): + """ + Raises an exception describing if the local or remote end closed the + connection + """ + + if self._local_closed: + raise TLSDisconnectError('The connection was already closed') + elif self._gracefully_closed: + raise TLSGracefulDisconnectError('The remote end closed the connection') + else: + raise TLSDisconnectError('The connection was closed') + + @property + def certificate(self): + """ + An asn1crypto.x509.Certificate object of the end-entity certificate + presented by the server + """ + + if self._ssl is None: + self._raise_closed() + + if self._certificate is None: + self._read_certificates() + + return self._certificate + + @property + def intermediates(self): + """ + A list of asn1crypto.x509.Certificate objects that were presented as + intermediates by the server + """ + + if self._ssl is None: + self._raise_closed() + + if self._certificate is None: + self._read_certificates() + + return self._intermediates + + @property + def cipher_suite(self): + """ + A unicode string of the IANA cipher suite name of the negotiated + cipher suite + """ + + return self._cipher_suite + + @property + def protocol(self): + """ + A unicode string of: "TLSv1.2", "TLSv1.1", "TLSv1", "SSLv3" + """ + + return self._protocol + + @property + def compression(self): + """ + A boolean if compression is enabled + """ + + return self._compression + + @property + def session_id(self): + """ + A unicode string of "new" or "reused" or None for no ticket + """ + + return self._session_id + + @property + def session_ticket(self): + """ + A unicode string of "new" or "reused" or None for no ticket + """ + + return self._session_ticket + + @property + def session(self): + """ + The oscrypto.tls.TLSSession object used for this connection + """ + + return self._session + + @property + def hostname(self): + """ + A unicode string of the TLS server domain name or IP address + """ + + return self._hostname + + @property + def port(self): + """ + An integer of the port number the socket is connected to + """ + + return self.socket.getpeername()[1] + + @property + def socket(self): + """ + The underlying socket.socket connection + """ + + if self._ssl is None: + self._raise_closed() + + return self._socket + + def __del__(self): + self.close() diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_openssl/util.py b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_openssl/util.py new file mode 100644 index 00000000..fa9bea8c --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_openssl/util.py @@ -0,0 +1,243 @@ +# coding: utf-8 +from __future__ import unicode_literals, division, absolute_import, print_function + +from .._errors import pretty_message +from .._ffi import buffer_from_bytes, bytes_from_buffer +from ._libcrypto import libcrypto, libcrypto_version_info, handle_openssl_error +from .._rand import rand_bytes +from .._types import type_name, byte_cls, int_types + + +__all__ = [ + 'pbkdf2', + 'pkcs12_kdf', + 'rand_bytes', +] + + +# OpenSSL 0.9.8 does not include PBKDF2 +if libcrypto_version_info < (1,): + from .._pkcs5 import pbkdf2 + +else: + def pbkdf2(hash_algorithm, password, salt, iterations, key_length): + """ + PBKDF2 from PKCS#5 + + :param hash_algorithm: + The string name of the hash algorithm to use: "sha1", "sha224", "sha256", "sha384", "sha512" + + :param password: + A byte string of the password to use an input to the KDF + + :param salt: + A cryptographic random byte string + + :param iterations: + The numbers of iterations to use when deriving the key + + :param key_length: + The length of the desired key in bytes + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + + :return: + The derived key as a byte string + """ + + if not isinstance(password, byte_cls): + raise TypeError(pretty_message( + ''' + password must be a byte string, not %s + ''', + type_name(password) + )) + + if not isinstance(salt, byte_cls): + raise TypeError(pretty_message( + ''' + salt must be a byte string, not %s + ''', + type_name(salt) + )) + + if not isinstance(iterations, int_types): + raise TypeError(pretty_message( + ''' + iterations must be an integer, not %s + ''', + type_name(iterations) + )) + + if iterations < 1: + raise ValueError('iterations must be greater than 0') + + if not isinstance(key_length, int_types): + raise TypeError(pretty_message( + ''' + key_length must be an integer, not %s + ''', + type_name(key_length) + )) + + if key_length < 1: + raise ValueError('key_length must be greater than 0') + + if hash_algorithm not in set(['sha1', 'sha224', 'sha256', 'sha384', 'sha512']): + raise ValueError(pretty_message( + ''' + hash_algorithm must be one of "sha1", "sha224", "sha256", "sha384", + "sha512", not %s + ''', + repr(hash_algorithm) + )) + + evp_md = { + 'sha1': libcrypto.EVP_sha1, + 'sha224': libcrypto.EVP_sha224, + 'sha256': libcrypto.EVP_sha256, + 'sha384': libcrypto.EVP_sha384, + 'sha512': libcrypto.EVP_sha512 + }[hash_algorithm]() + + output_buffer = buffer_from_bytes(key_length) + result = libcrypto.PKCS5_PBKDF2_HMAC( + password, + len(password), + salt, + len(salt), + iterations, + evp_md, + key_length, + output_buffer + ) + handle_openssl_error(result) + + return bytes_from_buffer(output_buffer) + + pbkdf2.pure_python = False + + +def pkcs12_kdf(hash_algorithm, password, salt, iterations, key_length, id_): + """ + KDF from RFC7292 appendix B.2 - https://tools.ietf.org/html/rfc7292#page-19 + + :param hash_algorithm: + The string name of the hash algorithm to use: "md5", "sha1", "sha224", "sha256", "sha384", "sha512" + + :param password: + A byte string of the password to use an input to the KDF + + :param salt: + A cryptographic random byte string + + :param iterations: + The numbers of iterations to use when deriving the key + + :param key_length: + The length of the desired key in bytes + + :param id_: + The ID of the usage - 1 for key, 2 for iv, 3 for mac + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + + :return: + The derived key as a byte string + """ + + if not isinstance(password, byte_cls): + raise TypeError(pretty_message( + ''' + password must be a byte string, not %s + ''', + type_name(password) + )) + + if not isinstance(salt, byte_cls): + raise TypeError(pretty_message( + ''' + salt must be a byte string, not %s + ''', + type_name(salt) + )) + + if not isinstance(iterations, int_types): + raise TypeError(pretty_message( + ''' + iterations must be an integer, not %s + ''', + type_name(iterations) + )) + + if iterations < 1: + raise ValueError(pretty_message( + ''' + iterations must be greater than 0 - is %s + ''', + repr(iterations) + )) + + if not isinstance(key_length, int_types): + raise TypeError(pretty_message( + ''' + key_length must be an integer, not %s + ''', + type_name(key_length) + )) + + if key_length < 1: + raise ValueError(pretty_message( + ''' + key_length must be greater than 0 - is %s + ''', + repr(key_length) + )) + + if hash_algorithm not in set(['md5', 'sha1', 'sha224', 'sha256', 'sha384', 'sha512']): + raise ValueError(pretty_message( + ''' + hash_algorithm must be one of "md5", "sha1", "sha224", "sha256", + "sha384", "sha512", not %s + ''', + repr(hash_algorithm) + )) + + if id_ not in set([1, 2, 3]): + raise ValueError(pretty_message( + ''' + id_ must be one of 1, 2, 3, not %s + ''', + repr(id_) + )) + + utf16_password = password.decode('utf-8').encode('utf-16be') + b'\x00\x00' + + digest_type = { + 'md5': libcrypto.EVP_md5, + 'sha1': libcrypto.EVP_sha1, + 'sha224': libcrypto.EVP_sha224, + 'sha256': libcrypto.EVP_sha256, + 'sha384': libcrypto.EVP_sha384, + 'sha512': libcrypto.EVP_sha512, + }[hash_algorithm]() + + output_buffer = buffer_from_bytes(key_length) + result = libcrypto.PKCS12_key_gen_uni( + utf16_password, + len(utf16_password), + salt, + len(salt), + id_, + iterations, + key_length, + output_buffer, + digest_type + ) + handle_openssl_error(result) + + return bytes_from_buffer(output_buffer) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_pkcs1.py b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_pkcs1.py new file mode 100644 index 00000000..2044b84c --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_pkcs1.py @@ -0,0 +1,740 @@ +# coding: utf-8 +from __future__ import unicode_literals, division, absolute_import, print_function + +import sys +import hashlib +import math +import platform +import struct +import os + +from . import backend +from .util import constant_compare, rand_bytes +from ._asn1 import ( + Certificate, + int_from_bytes, + int_to_bytes, + PrivateKeyInfo, + PublicKeyInfo, +) +from ._errors import pretty_message +from ._int import fill_width +from ._types import type_name, byte_cls, int_types + +if sys.version_info < (3,): + chr_cls = chr + range = xrange # noqa + +else: + def chr_cls(num): + return bytes([num]) + + +_backend = backend() + + +__all__ = [ + 'add_pss_padding', + 'add_pkcs1v15_signature_padding', + 'raw_rsa_private_crypt', + 'raw_rsa_public_crypt', + 'remove_pkcs1v15_encryption_padding', + 'remove_pkcs1v15_signature_padding', + 'verify_pss_padding', +] + + +def _is_osx_107(): + """ + :return: + A bool if the current machine is running OS X 10.7 + """ + + if sys.platform != 'darwin': + return False + version = platform.mac_ver()[0] + return tuple(map(int, version.split('.')))[0:2] == (10, 7) + + +def add_pss_padding(hash_algorithm, salt_length, key_length, message): + """ + Pads a byte string using the EMSA-PSS-Encode operation described in PKCS#1 + v2.2. + + :param hash_algorithm: + The string name of the hash algorithm to use: "sha1", "sha224", + "sha256", "sha384", "sha512" + + :param salt_length: + The length of the salt as an integer - typically the same as the length + of the output from the hash_algorithm + + :param key_length: + The length of the RSA key, in bits + + :param message: + A byte string of the message to pad + + :return: + The encoded (passed) message + """ + + if _backend != 'winlegacy' and sys.platform != 'darwin': + raise SystemError(pretty_message( + ''' + Pure-python RSA PSS signature padding addition code is only for + Windows XP/2003 and OS X + ''' + )) + + if not isinstance(message, byte_cls): + raise TypeError(pretty_message( + ''' + message must be a byte string, not %s + ''', + type_name(message) + )) + + if not isinstance(salt_length, int_types): + raise TypeError(pretty_message( + ''' + salt_length must be an integer, not %s + ''', + type_name(salt_length) + )) + + if salt_length < 0: + raise ValueError(pretty_message( + ''' + salt_length must be 0 or more - is %s + ''', + repr(salt_length) + )) + + if not isinstance(key_length, int_types): + raise TypeError(pretty_message( + ''' + key_length must be an integer, not %s + ''', + type_name(key_length) + )) + + if key_length < 512: + raise ValueError(pretty_message( + ''' + key_length must be 512 or more - is %s + ''', + repr(key_length) + )) + + if hash_algorithm not in set(['sha1', 'sha224', 'sha256', 'sha384', 'sha512']): + raise ValueError(pretty_message( + ''' + hash_algorithm must be one of "sha1", "sha224", "sha256", "sha384", + "sha512", not %s + ''', + repr(hash_algorithm) + )) + + hash_func = getattr(hashlib, hash_algorithm) + + # The maximal bit size of a non-negative integer is one less than the bit + # size of the key since the first bit is used to store sign + em_bits = key_length - 1 + em_len = int(math.ceil(em_bits / 8)) + + message_digest = hash_func(message).digest() + hash_length = len(message_digest) + + if em_len < hash_length + salt_length + 2: + raise ValueError(pretty_message( + ''' + Key is not long enough to use with specified hash_algorithm and + salt_length + ''' + )) + + if salt_length > 0: + salt = os.urandom(salt_length) + else: + salt = b'' + + m_prime = (b'\x00' * 8) + message_digest + salt + + m_prime_digest = hash_func(m_prime).digest() + + padding = b'\x00' * (em_len - salt_length - hash_length - 2) + + db = padding + b'\x01' + salt + + db_mask = _mgf1(hash_algorithm, m_prime_digest, em_len - hash_length - 1) + + masked_db = int_to_bytes(int_from_bytes(db) ^ int_from_bytes(db_mask)) + masked_db = fill_width(masked_db, len(db_mask)) + + zero_bits = (8 * em_len) - em_bits + left_bit_mask = ('0' * zero_bits) + ('1' * (8 - zero_bits)) + left_int_mask = int(left_bit_mask, 2) + + if left_int_mask != 255: + masked_db = chr_cls(left_int_mask & ord(masked_db[0:1])) + masked_db[1:] + + return masked_db + m_prime_digest + b'\xBC' + + +def verify_pss_padding(hash_algorithm, salt_length, key_length, message, signature): + """ + Verifies the PSS padding on an encoded message + + :param hash_algorithm: + The string name of the hash algorithm to use: "sha1", "sha224", + "sha256", "sha384", "sha512" + + :param salt_length: + The length of the salt as an integer - typically the same as the length + of the output from the hash_algorithm + + :param key_length: + The length of the RSA key, in bits + + :param message: + A byte string of the message to pad + + :param signature: + The signature to verify + + :return: + A boolean indicating if the signature is invalid + """ + + if _backend != 'winlegacy' and sys.platform != 'darwin': + raise SystemError(pretty_message( + ''' + Pure-python RSA PSS signature padding verification code is only for + Windows XP/2003 and OS X + ''' + )) + + if not isinstance(message, byte_cls): + raise TypeError(pretty_message( + ''' + message must be a byte string, not %s + ''', + type_name(message) + )) + + if not isinstance(signature, byte_cls): + raise TypeError(pretty_message( + ''' + signature must be a byte string, not %s + ''', + type_name(signature) + )) + + if not isinstance(salt_length, int_types): + raise TypeError(pretty_message( + ''' + salt_length must be an integer, not %s + ''', + type_name(salt_length) + )) + + if salt_length < 0: + raise ValueError(pretty_message( + ''' + salt_length must be 0 or more - is %s + ''', + repr(salt_length) + )) + + if hash_algorithm not in set(['sha1', 'sha224', 'sha256', 'sha384', 'sha512']): + raise ValueError(pretty_message( + ''' + hash_algorithm must be one of "sha1", "sha224", "sha256", "sha384", + "sha512", not %s + ''', + repr(hash_algorithm) + )) + + hash_func = getattr(hashlib, hash_algorithm) + + em_bits = key_length - 1 + em_len = int(math.ceil(em_bits / 8)) + + message_digest = hash_func(message).digest() + hash_length = len(message_digest) + + if em_len < hash_length + salt_length + 2: + return False + + if signature[-1:] != b'\xBC': + return False + + zero_bits = (8 * em_len) - em_bits + + masked_db_length = em_len - hash_length - 1 + masked_db = signature[0:masked_db_length] + + first_byte = ord(masked_db[0:1]) + bits_that_should_be_zero = first_byte >> (8 - zero_bits) + if bits_that_should_be_zero != 0: + return False + + m_prime_digest = signature[masked_db_length:masked_db_length + hash_length] + + db_mask = _mgf1(hash_algorithm, m_prime_digest, em_len - hash_length - 1) + + left_bit_mask = ('0' * zero_bits) + ('1' * (8 - zero_bits)) + left_int_mask = int(left_bit_mask, 2) + + if left_int_mask != 255: + db_mask = chr_cls(left_int_mask & ord(db_mask[0:1])) + db_mask[1:] + + db = int_to_bytes(int_from_bytes(masked_db) ^ int_from_bytes(db_mask)) + if len(db) < len(masked_db): + db = (b'\x00' * (len(masked_db) - len(db))) + db + + zero_length = em_len - hash_length - salt_length - 2 + zero_string = b'\x00' * zero_length + if not constant_compare(db[0:zero_length], zero_string): + return False + + if db[zero_length:zero_length + 1] != b'\x01': + return False + + salt = db[0 - salt_length:] + + m_prime = (b'\x00' * 8) + message_digest + salt + + h_prime = hash_func(m_prime).digest() + + return constant_compare(m_prime_digest, h_prime) + + +def _mgf1(hash_algorithm, seed, mask_length): + """ + The PKCS#1 MGF1 mask generation algorithm + + :param hash_algorithm: + The string name of the hash algorithm to use: "sha1", "sha224", + "sha256", "sha384", "sha512" + + :param seed: + A byte string to use as the seed for the mask + + :param mask_length: + The desired mask length, as an integer + + :return: + A byte string of the mask + """ + + if not isinstance(seed, byte_cls): + raise TypeError(pretty_message( + ''' + seed must be a byte string, not %s + ''', + type_name(seed) + )) + + if not isinstance(mask_length, int_types): + raise TypeError(pretty_message( + ''' + mask_length must be an integer, not %s + ''', + type_name(mask_length) + )) + + if mask_length < 1: + raise ValueError(pretty_message( + ''' + mask_length must be greater than 0 - is %s + ''', + repr(mask_length) + )) + + if hash_algorithm not in set(['sha1', 'sha224', 'sha256', 'sha384', 'sha512']): + raise ValueError(pretty_message( + ''' + hash_algorithm must be one of "sha1", "sha224", "sha256", "sha384", + "sha512", not %s + ''', + repr(hash_algorithm) + )) + + output = b'' + + hash_length = { + 'sha1': 20, + 'sha224': 28, + 'sha256': 32, + 'sha384': 48, + 'sha512': 64 + }[hash_algorithm] + + iterations = int(math.ceil(mask_length / hash_length)) + + pack = struct.Struct(b'>I').pack + hash_func = getattr(hashlib, hash_algorithm) + + for counter in range(0, iterations): + b = pack(counter) + output += hash_func(seed + b).digest() + + return output[0:mask_length] + + +def add_pkcs1v15_signature_padding(key_length, data): + """ + Adds PKCS#1 v1.5 padding to a message to be signed + + :param key_length: + An integer of the number of bytes in the key + + :param data: + A byte string to pad + + :return: + The padded data as a byte string + """ + + if _backend != 'winlegacy': + raise SystemError(pretty_message( + ''' + Pure-python RSA PKCSv1.5 signature padding addition code is only + for Windows XP/2003 + ''' + )) + + return _add_pkcs1v15_padding(key_length, data, 'signing') + + +def remove_pkcs1v15_signature_padding(key_length, data): + """ + Removes PKCS#1 v1.5 padding from a signed message using constant time + operations + + :param key_length: + An integer of the number of bytes in the key + + :param data: + A byte string to unpad + + :return: + The unpadded data as a byte string + """ + + if _backend != 'winlegacy': + raise SystemError(pretty_message( + ''' + Pure-python RSA PKCSv1.5 signature padding removal code is only for + Windows XP/2003 + ''' + )) + + return _remove_pkcs1v15_padding(key_length, data, 'verifying') + + +def remove_pkcs1v15_encryption_padding(key_length, data): + """ + Removes PKCS#1 v1.5 padding from a decrypted message using constant time + operations + + :param key_length: + An integer of the number of bytes in the key + + :param data: + A byte string to unpad + + :return: + The unpadded data as a byte string + """ + + if not _is_osx_107(): + raise SystemError(pretty_message( + ''' + Pure-python RSA PKCSv1.5 encryption padding removal code is only + for OS X 10.7 + ''' + )) + + return _remove_pkcs1v15_padding(key_length, data, 'decrypting') + + +def _add_pkcs1v15_padding(key_length, data, operation): + """ + Adds PKCS#1 v1.5 padding to a message + + :param key_length: + An integer of the number of bytes in the key + + :param data: + A byte string to unpad + + :param operation: + A unicode string of "encrypting" or "signing" + + :return: + The padded data as a byte string + """ + + if operation == 'encrypting': + second_byte = b'\x02' + else: + second_byte = b'\x01' + + if not isinstance(data, byte_cls): + raise TypeError(pretty_message( + ''' + data must be a byte string, not %s + ''', + type_name(data) + )) + + if not isinstance(key_length, int_types): + raise TypeError(pretty_message( + ''' + key_length must be an integer, not %s + ''', + type_name(key_length) + )) + + if key_length < 64: + raise ValueError(pretty_message( + ''' + key_length must be 64 or more - is %s + ''', + repr(key_length) + )) + + if len(data) > key_length - 11: + raise ValueError(pretty_message( + ''' + data must be between 1 and %s bytes long - is %s + ''', + key_length - 11, + len(data) + )) + + required_bytes = key_length - 3 - len(data) + padding = b'' + while required_bytes > 0: + temp_padding = rand_bytes(required_bytes) + # Remove null bytes since they are markers in PKCS#1 v1.5 + temp_padding = b''.join(temp_padding.split(b'\x00')) + padding += temp_padding + required_bytes -= len(temp_padding) + + return b'\x00' + second_byte + padding + b'\x00' + data + + +def _remove_pkcs1v15_padding(key_length, data, operation): + """ + Removes PKCS#1 v1.5 padding from a message using constant time operations + + :param key_length: + An integer of the number of bytes in the key + + :param data: + A byte string to unpad + + :param operation: + A unicode string of "decrypting" or "verifying" + + :return: + The unpadded data as a byte string + """ + + if operation == 'decrypting': + second_byte = 2 + else: + second_byte = 1 + + if not isinstance(data, byte_cls): + raise TypeError(pretty_message( + ''' + data must be a byte string, not %s + ''', + type_name(data) + )) + + if not isinstance(key_length, int_types): + raise TypeError(pretty_message( + ''' + key_length must be an integer, not %s + ''', + type_name(key_length) + )) + + if key_length < 64: + raise ValueError(pretty_message( + ''' + key_length must be 64 or more - is %s + ''', + repr(key_length) + )) + + if len(data) != key_length: + raise ValueError('Error %s' % operation) + + error = 0 + trash = 0 + padding_end = 0 + + # Uses bitwise operations on an error variable and another trash variable + # to perform constant time error checking/token scanning on the data + for i in range(0, len(data)): + byte = data[i:i + 1] + byte_num = ord(byte) + + # First byte should be \x00 + if i == 0: + error |= byte_num + + # Second byte should be \x02 for decryption, \x01 for verification + elif i == 1: + error |= int((byte_num | second_byte) != second_byte) + + # Bytes 3-10 should not be \x00 + elif i < 10: + error |= int((byte_num ^ 0) == 0) + + # Byte 11 or after that is zero is end of padding + else: + non_zero = byte_num | 0 + if padding_end == 0: + if non_zero: + trash |= i + else: + padding_end |= i + else: + if non_zero: + trash |= i + else: + trash |= i + + if error != 0: + raise ValueError('Error %s' % operation) + + return data[padding_end + 1:] + + +def raw_rsa_private_crypt(private_key, data): + """ + Performs a raw RSA algorithm in a byte string using a private key. + This is a low-level primitive and is prone to disastrous results if used + incorrectly. + + :param private_key: + An oscrypto.asymmetric.PrivateKey object + + :param data: + A byte string of the plaintext to be signed or ciphertext to be + decrypted. Must be less than or equal to the length of the private key. + In the case of signing, padding must already be applied. In the case of + decryption, padding must be removed afterward. + + :return: + A byte string of the transformed data + """ + + if _backend != 'winlegacy': + raise SystemError('Pure-python RSA crypt is only for Windows XP/2003') + + if not hasattr(private_key, 'asn1') or not isinstance(private_key.asn1, PrivateKeyInfo): + raise TypeError(pretty_message( + ''' + private_key must be an instance of the + oscrypto.asymmetric.PrivateKey class, not %s + ''', + type_name(private_key) + )) + + algo = private_key.asn1['private_key_algorithm']['algorithm'].native + if algo != 'rsa': + raise ValueError(pretty_message( + ''' + private_key must be an RSA key, not %s + ''', + algo.upper() + )) + + if not isinstance(data, byte_cls): + raise TypeError(pretty_message( + ''' + data must be a byte string, not %s + ''', + type_name(data) + )) + + rsa_private_key = private_key.asn1['private_key'].parsed + transformed_int = pow( + int_from_bytes(data), + rsa_private_key['private_exponent'].native, + rsa_private_key['modulus'].native + ) + return int_to_bytes(transformed_int, width=private_key.asn1.byte_size) + + +def raw_rsa_public_crypt(certificate_or_public_key, data): + """ + Performs a raw RSA algorithm in a byte string using a certificate or + public key. This is a low-level primitive and is prone to disastrous results + if used incorrectly. + + :param certificate_or_public_key: + An oscrypto.asymmetric.PublicKey or oscrypto.asymmetric.Certificate + object + + :param data: + A byte string of the signature when verifying, or padded plaintext when + encrypting. Must be less than or equal to the length of the public key. + When verifying, padding will need to be removed afterwards. When + encrypting, padding must be applied before. + + :return: + A byte string of the transformed data + """ + + if _backend != 'winlegacy': + raise SystemError('Pure-python RSA crypt is only for Windows XP/2003') + + has_asn1 = hasattr(certificate_or_public_key, 'asn1') + valid_types = (PublicKeyInfo, Certificate) + if not has_asn1 or not isinstance(certificate_or_public_key.asn1, valid_types): + raise TypeError(pretty_message( + ''' + certificate_or_public_key must be an instance of the + oscrypto.asymmetric.PublicKey or oscrypto.asymmetric.Certificate + classes, not %s + ''', + type_name(certificate_or_public_key) + )) + + algo = certificate_or_public_key.asn1['algorithm']['algorithm'].native + if algo != 'rsa': + raise ValueError(pretty_message( + ''' + certificate_or_public_key must be an RSA key, not %s + ''', + algo.upper() + )) + + if not isinstance(data, byte_cls): + raise TypeError(pretty_message( + ''' + data must be a byte string, not %s + ''', + type_name(data) + )) + + rsa_public_key = certificate_or_public_key.asn1['public_key'].parsed + transformed_int = pow( + int_from_bytes(data), + rsa_public_key['public_exponent'].native, + rsa_public_key['modulus'].native + ) + return int_to_bytes( + transformed_int, + width=certificate_or_public_key.asn1.byte_size + ) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_pkcs12.py b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_pkcs12.py new file mode 100644 index 00000000..b8f584ce --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_pkcs12.py @@ -0,0 +1,198 @@ +# coding: utf-8 +from __future__ import unicode_literals, division, absolute_import, print_function + +import sys +import hashlib +import math + +from ._asn1 import int_from_bytes, int_to_bytes +from ._errors import pretty_message +from ._types import type_name, byte_cls, int_types + + +if sys.version_info < (3,): + chr_cls = chr + +else: + def chr_cls(num): + return bytes([num]) + + +__all__ = [ + 'pkcs12_kdf', +] + + +def pkcs12_kdf(hash_algorithm, password, salt, iterations, key_length, id_): + """ + KDF from RFC7292 appendix b.2 - https://tools.ietf.org/html/rfc7292#page-19 + + :param hash_algorithm: + The string name of the hash algorithm to use: "md5", "sha1", "sha224", + "sha256", "sha384", "sha512" + + :param password: + A byte string of the password to use an input to the KDF + + :param salt: + A cryptographic random byte string + + :param iterations: + The numbers of iterations to use when deriving the key + + :param key_length: + The length of the desired key in bytes + + :param id_: + The ID of the usage - 1 for key, 2 for iv, 3 for mac + + :return: + The derived key as a byte string + """ + + if not isinstance(password, byte_cls): + raise TypeError(pretty_message( + ''' + password must be a byte string, not %s + ''', + type_name(password) + )) + + if not isinstance(salt, byte_cls): + raise TypeError(pretty_message( + ''' + salt must be a byte string, not %s + ''', + type_name(salt) + )) + + if not isinstance(iterations, int_types): + raise TypeError(pretty_message( + ''' + iterations must be an integer, not %s + ''', + type_name(iterations) + )) + + if iterations < 1: + raise ValueError(pretty_message( + ''' + iterations must be greater than 0 - is %s + ''', + repr(iterations) + )) + + if not isinstance(key_length, int_types): + raise TypeError(pretty_message( + ''' + key_length must be an integer, not %s + ''', + type_name(key_length) + )) + + if key_length < 1: + raise ValueError(pretty_message( + ''' + key_length must be greater than 0 - is %s + ''', + repr(key_length) + )) + + if hash_algorithm not in set(['md5', 'sha1', 'sha224', 'sha256', 'sha384', 'sha512']): + raise ValueError(pretty_message( + ''' + hash_algorithm must be one of "md5", "sha1", "sha224", "sha256", + "sha384", "sha512", not %s + ''', + repr(hash_algorithm) + )) + + if id_ not in set([1, 2, 3]): + raise ValueError(pretty_message( + ''' + id_ must be one of 1, 2, 3, not %s + ''', + repr(id_) + )) + + utf16_password = password.decode('utf-8').encode('utf-16be') + b'\x00\x00' + + algo = getattr(hashlib, hash_algorithm) + + # u and v values are bytes (not bits as in the RFC) + u = { + 'md5': 16, + 'sha1': 20, + 'sha224': 28, + 'sha256': 32, + 'sha384': 48, + 'sha512': 64 + }[hash_algorithm] + + if hash_algorithm in ['sha384', 'sha512']: + v = 128 + else: + v = 64 + + # Step 1 + d = chr_cls(id_) * v + + # Step 2 + s = b'' + if salt != b'': + s_len = v * int(math.ceil(float(len(salt)) / v)) + while len(s) < s_len: + s += salt + s = s[0:s_len] + + # Step 3 + p = b'' + if utf16_password != b'': + p_len = v * int(math.ceil(float(len(utf16_password)) / v)) + while len(p) < p_len: + p += utf16_password + p = p[0:p_len] + + # Step 4 + i = s + p + + # Step 5 + c = int(math.ceil(float(key_length) / u)) + + a = b'\x00' * (c * u) + + for num in range(1, c + 1): + # Step 6A + a2 = algo(d + i).digest() + for _ in range(2, iterations + 1): + a2 = algo(a2).digest() + + if num < c: + # Step 6B + b = b'' + while len(b) < v: + b += a2 + + b = int_from_bytes(b[0:v]) + 1 + + # Step 6C + for num2 in range(0, len(i) // v): + start = num2 * v + end = (num2 + 1) * v + i_num2 = i[start:end] + + i_num2 = int_to_bytes(int_from_bytes(i_num2) + b) + + # Ensure the new slice is the right size + i_num2_l = len(i_num2) + if i_num2_l > v: + i_num2 = i_num2[i_num2_l - v:] + + i = i[0:start] + i_num2 + i[end:] + + # Step 7 (one peice at a time) + begin = (num - 1) * u + to_copy = min(key_length, u) + a = a[0:begin] + a2[0:to_copy] + a[begin + to_copy:] + + return a[0:key_length] diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_pkcs5.py b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_pkcs5.py new file mode 100644 index 00000000..405d4191 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_pkcs5.py @@ -0,0 +1,142 @@ +# coding: utf-8 +from __future__ import unicode_literals, division, absolute_import, print_function + +import sys +import hashlib +import hmac +import struct + +from ._asn1 import int_from_bytes, int_to_bytes +from ._errors import pretty_message +from ._types import type_name, byte_cls, int_types + +if sys.version_info < (3,): + chr_cls = chr + +else: + def chr_cls(num): + return bytes([num]) + + +__all__ = [ + 'pbkdf2', +] + + +def pbkdf2(hash_algorithm, password, salt, iterations, key_length): + """ + Implements PBKDF2 from PKCS#5 v2.2 in pure Python + + :param hash_algorithm: + The string name of the hash algorithm to use: "md5", "sha1", "sha224", + "sha256", "sha384", "sha512" + + :param password: + A byte string of the password to use an input to the KDF + + :param salt: + A cryptographic random byte string + + :param iterations: + The numbers of iterations to use when deriving the key + + :param key_length: + The length of the desired key in bytes + + :return: + The derived key as a byte string + """ + + if not isinstance(password, byte_cls): + raise TypeError(pretty_message( + ''' + password must be a byte string, not %s + ''', + type_name(password) + )) + + if not isinstance(salt, byte_cls): + raise TypeError(pretty_message( + ''' + salt must be a byte string, not %s + ''', + type_name(salt) + )) + + if not isinstance(iterations, int_types): + raise TypeError(pretty_message( + ''' + iterations must be an integer, not %s + ''', + type_name(iterations) + )) + + if iterations < 1: + raise ValueError(pretty_message( + ''' + iterations must be greater than 0 - is %s + ''', + repr(iterations) + )) + + if not isinstance(key_length, int_types): + raise TypeError(pretty_message( + ''' + key_length must be an integer, not %s + ''', + type_name(key_length) + )) + + if key_length < 1: + raise ValueError(pretty_message( + ''' + key_length must be greater than 0 - is %s + ''', + repr(key_length) + )) + + if hash_algorithm not in set(['md5', 'sha1', 'sha224', 'sha256', 'sha384', 'sha512']): + raise ValueError(pretty_message( + ''' + hash_algorithm must be one of "md5", "sha1", "sha224", "sha256", + "sha384", "sha512", not %s + ''', + repr(hash_algorithm) + )) + + algo = getattr(hashlib, hash_algorithm) + + hash_length = { + 'md5': 16, + 'sha1': 20, + 'sha224': 28, + 'sha256': 32, + 'sha384': 48, + 'sha512': 64 + }[hash_algorithm] + + original_hmac = hmac.new(password, None, algo) + + block = 1 + output = b'' + + while len(output) < key_length: + prf = original_hmac.copy() + prf.update(salt + struct.pack(b'>I', block)) + last = prf.digest() + + u = int_from_bytes(last) + + for _ in range(iterations-1): + prf = original_hmac.copy() + prf.update(last) + last = prf.digest() + u ^= int_from_bytes(last) + + output += int_to_bytes(u, width=hash_length) + block += 1 + + return output[0:key_length] + + +pbkdf2.pure_python = True diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_rand.py b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_rand.py new file mode 100644 index 00000000..805e2cd4 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_rand.py @@ -0,0 +1,45 @@ +# coding: utf-8 +from __future__ import unicode_literals, division, absolute_import, print_function + +import os + +from ._errors import pretty_message +from ._types import type_name, int_types + + +__all__ = [ + 'rand_bytes', +] + + +def rand_bytes(length): + """ + Returns a number of random bytes suitable for cryptographic purposes + + :param length: + The desired number of bytes + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by OpenSSL + + :return: + A byte string + """ + + if not isinstance(length, int_types): + raise TypeError(pretty_message( + ''' + length must be an integer, not %s + ''', + type_name(length) + )) + + if length < 1: + raise ValueError('length must be greater than 0') + + if length > 1024: + raise ValueError('length must not be greater than 1024') + + return os.urandom(length) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_tls.py b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_tls.py new file mode 100644 index 00000000..181d82b2 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_tls.py @@ -0,0 +1,588 @@ +# coding: utf-8 +from __future__ import unicode_literals, division, absolute_import, print_function + +import re +from datetime import datetime + +from ._asn1 import Certificate, int_from_bytes, timezone +from ._cipher_suites import CIPHER_SUITE_MAP +from .errors import TLSVerificationError, TLSDisconnectError, TLSError + + +__all__ = [ + 'detect_client_auth_request', + 'extract_chain', + 'get_dh_params_length', + 'parse_alert', + 'parse_handshake_messages', + 'parse_session_info', + 'parse_tls_records', + 'raise_client_auth', + 'raise_dh_params', + 'raise_disconnection', + 'raise_expired_not_yet_valid', + 'raise_handshake', + 'raise_hostname', + 'raise_no_issuer', + 'raise_protocol_error', + 'raise_revoked', + 'raise_self_signed', + 'raise_verification', + 'raise_weak_signature', +] + + +def extract_chain(server_handshake_bytes): + """ + Extracts the X.509 certificates from the server handshake bytes for use + when debugging + + :param server_handshake_bytes: + A byte string of the handshake data received from the server + + :return: + A list of asn1crypto.x509.Certificate objects + """ + + output = [] + + chain_bytes = None + + for record_type, _, record_data in parse_tls_records(server_handshake_bytes): + if record_type != b'\x16': + continue + for message_type, message_data in parse_handshake_messages(record_data): + if message_type == b'\x0b': + chain_bytes = message_data + break + if chain_bytes: + break + + if chain_bytes: + # The first 3 bytes are the cert chain length + pointer = 3 + while pointer < len(chain_bytes): + cert_length = int_from_bytes(chain_bytes[pointer:pointer + 3]) + cert_start = pointer + 3 + cert_end = cert_start + cert_length + pointer = cert_end + cert_bytes = chain_bytes[cert_start:cert_end] + output.append(Certificate.load(cert_bytes)) + + return output + + +def detect_client_auth_request(server_handshake_bytes): + """ + Determines if a CertificateRequest message is sent from the server asking + the client for a certificate + + :param server_handshake_bytes: + A byte string of the handshake data received from the server + + :return: + A boolean - if a client certificate request was found + """ + + for record_type, _, record_data in parse_tls_records(server_handshake_bytes): + if record_type != b'\x16': + continue + for message_type, message_data in parse_handshake_messages(record_data): + if message_type == b'\x0d': + return True + return False + + +def get_dh_params_length(server_handshake_bytes): + """ + Determines the length of the DH params from the ServerKeyExchange + + :param server_handshake_bytes: + A byte string of the handshake data received from the server + + :return: + None or an integer of the bit size of the DH parameters + """ + + output = None + + dh_params_bytes = None + + for record_type, _, record_data in parse_tls_records(server_handshake_bytes): + if record_type != b'\x16': + continue + for message_type, message_data in parse_handshake_messages(record_data): + if message_type == b'\x0c': + dh_params_bytes = message_data + break + if dh_params_bytes: + break + + if dh_params_bytes: + output = int_from_bytes(dh_params_bytes[0:2]) * 8 + + return output + + +def parse_alert(server_handshake_bytes): + """ + Parses the handshake for protocol alerts + + :param server_handshake_bytes: + A byte string of the handshake data received from the server + + :return: + None or an 2-element tuple of integers: + 0: 1 (warning) or 2 (fatal) + 1: The alert description (see https://tools.ietf.org/html/rfc5246#section-7.2) + """ + + for record_type, _, record_data in parse_tls_records(server_handshake_bytes): + if record_type != b'\x15': + continue + if len(record_data) != 2: + return None + return (int_from_bytes(record_data[0:1]), int_from_bytes(record_data[1:2])) + return None + + +def parse_session_info(server_handshake_bytes, client_handshake_bytes): + """ + Parse the TLS handshake from the client to the server to extract information + including the cipher suite selected, if compression is enabled, the + session id and if a new or reused session ticket exists. + + :param server_handshake_bytes: + A byte string of the handshake data received from the server + + :param client_handshake_bytes: + A byte string of the handshake data sent to the server + + :return: + A dict with the following keys: + - "protocol": unicode string + - "cipher_suite": unicode string + - "compression": boolean + - "session_id": "new", "reused" or None + - "session_ticket: "new", "reused" or None + """ + + protocol = None + cipher_suite = None + compression = False + session_id = None + session_ticket = None + + server_session_id = None + client_session_id = None + + for record_type, _, record_data in parse_tls_records(server_handshake_bytes): + if record_type != b'\x16': + continue + for message_type, message_data in parse_handshake_messages(record_data): + # Ensure we are working with a ServerHello message + if message_type != b'\x02': + continue + protocol = { + b'\x03\x00': "SSLv3", + b'\x03\x01': "TLSv1", + b'\x03\x02': "TLSv1.1", + b'\x03\x03': "TLSv1.2", + b'\x03\x04': "TLSv1.3", + }[message_data[0:2]] + + session_id_length = int_from_bytes(message_data[34:35]) + if session_id_length > 0: + server_session_id = message_data[35:35 + session_id_length] + + cipher_suite_start = 35 + session_id_length + cipher_suite_bytes = message_data[cipher_suite_start:cipher_suite_start + 2] + cipher_suite = CIPHER_SUITE_MAP[cipher_suite_bytes] + + compression_start = cipher_suite_start + 2 + compression = message_data[compression_start:compression_start + 1] != b'\x00' + + extensions_length_start = compression_start + 1 + extensions_data = message_data[extensions_length_start:] + for extension_type, extension_data in _parse_hello_extensions(extensions_data): + if extension_type == 35: + session_ticket = "new" + break + break + + for record_type, _, record_data in parse_tls_records(client_handshake_bytes): + if record_type != b'\x16': + continue + for message_type, message_data in parse_handshake_messages(record_data): + # Ensure we are working with a ClientHello message + if message_type != b'\x01': + continue + + session_id_length = int_from_bytes(message_data[34:35]) + if session_id_length > 0: + client_session_id = message_data[35:35 + session_id_length] + + cipher_suite_start = 35 + session_id_length + cipher_suite_length = int_from_bytes(message_data[cipher_suite_start:cipher_suite_start + 2]) + + compression_start = cipher_suite_start + 2 + cipher_suite_length + compression_length = int_from_bytes(message_data[compression_start:compression_start + 1]) + + # On subsequent requests, the session ticket will only be seen + # in the ClientHello message + if server_session_id is None and session_ticket is None: + extensions_length_start = compression_start + 1 + compression_length + extensions_data = message_data[extensions_length_start:] + for extension_type, extension_data in _parse_hello_extensions(extensions_data): + if extension_type == 35: + session_ticket = "reused" + break + break + + if server_session_id is not None: + if client_session_id is None: + session_id = "new" + else: + if client_session_id != server_session_id: + session_id = "new" + else: + session_id = "reused" + + return { + "protocol": protocol, + "cipher_suite": cipher_suite, + "compression": compression, + "session_id": session_id, + "session_ticket": session_ticket, + } + + +def parse_tls_records(data): + """ + Creates a generator returning tuples of information about each record + in a byte string of data from a TLS client or server. Stops as soon as it + find a ChangeCipherSpec message since all data from then on is encrypted. + + :param data: + A byte string of TLS records + + :return: + A generator that yields 3-element tuples: + [0] Byte string of record type + [1] Byte string of protocol version + [2] Byte string of record data + """ + + pointer = 0 + data_len = len(data) + while pointer < data_len: + # Don't try to parse any more once the ChangeCipherSpec is found + if data[pointer:pointer + 1] == b'\x14': + break + length = int_from_bytes(data[pointer + 3:pointer + 5]) + yield ( + data[pointer:pointer + 1], + data[pointer + 1:pointer + 3], + data[pointer + 5:pointer + 5 + length] + ) + pointer += 5 + length + + +def parse_handshake_messages(data): + """ + Creates a generator returning tuples of information about each message in + a byte string of data from a TLS handshake record + + :param data: + A byte string of a TLS handshake record data + + :return: + A generator that yields 2-element tuples: + [0] Byte string of message type + [1] Byte string of message data + """ + + pointer = 0 + data_len = len(data) + while pointer < data_len: + length = int_from_bytes(data[pointer + 1:pointer + 4]) + yield ( + data[pointer:pointer + 1], + data[pointer + 4:pointer + 4 + length] + ) + pointer += 4 + length + + +def _parse_hello_extensions(data): + """ + Creates a generator returning tuples of information about each extension + from a byte string of extension data contained in a ServerHello ores + ClientHello message + + :param data: + A byte string of a extension data from a TLS ServerHello or ClientHello + message + + :return: + A generator that yields 2-element tuples: + [0] Byte string of extension type + [1] Byte string of extension data + """ + + if data == b'': + return + + extentions_length = int_from_bytes(data[0:2]) + extensions_start = 2 + extensions_end = 2 + extentions_length + + pointer = extensions_start + while pointer < extensions_end: + extension_type = int_from_bytes(data[pointer:pointer + 2]) + extension_length = int_from_bytes(data[pointer + 2:pointer + 4]) + yield ( + extension_type, + data[pointer + 4:pointer + 4 + extension_length] + ) + pointer += 4 + extension_length + + +def raise_hostname(certificate, hostname): + """ + Raises a TLSVerificationError due to a hostname mismatch + + :param certificate: + An asn1crypto.x509.Certificate object + + :raises: + TLSVerificationError + """ + + is_ip = re.match('^\\d+\\.\\d+\\.\\d+\\.\\d+$', hostname) or hostname.find(':') != -1 + if is_ip: + hostname_type = 'IP address %s' % hostname + else: + hostname_type = 'domain name %s' % hostname + message = 'Server certificate verification failed - %s does not match' % hostname_type + valid_ips = ', '.join(certificate.valid_ips) + valid_domains = ', '.join(certificate.valid_domains) + if valid_domains: + message += ' valid domains: %s' % valid_domains + if valid_domains and valid_ips: + message += ' or' + if valid_ips: + message += ' valid IP addresses: %s' % valid_ips + raise TLSVerificationError(message, certificate) + + +def raise_verification(certificate): + """ + Raises a generic TLSVerificationError + + :param certificate: + An asn1crypto.x509.Certificate object + + :raises: + TLSVerificationError + """ + + message = 'Server certificate verification failed' + raise TLSVerificationError(message, certificate) + + +def raise_weak_signature(certificate): + """ + Raises a TLSVerificationError when a certificate uses a weak signature + algorithm + + :param certificate: + An asn1crypto.x509.Certificate object + + :raises: + TLSVerificationError + """ + + message = 'Server certificate verification failed - weak certificate signature algorithm' + raise TLSVerificationError(message, certificate) + + +def raise_client_auth(): + """ + Raises a TLSError indicating client authentication is required + + :raises: + TLSError + """ + + message = 'TLS handshake failed - client authentication required' + raise TLSError(message) + + +def raise_revoked(certificate): + """ + Raises a TLSVerificationError due to the certificate being revoked + + :param certificate: + An asn1crypto.x509.Certificate object + + :raises: + TLSVerificationError + """ + + message = 'Server certificate verification failed - certificate has been revoked' + raise TLSVerificationError(message, certificate) + + +def raise_no_issuer(certificate): + """ + Raises a TLSVerificationError due to no issuer certificate found in trust + roots + + :param certificate: + An asn1crypto.x509.Certificate object + + :raises: + TLSVerificationError + """ + + message = 'Server certificate verification failed - certificate issuer not found in trusted root certificate store' + raise TLSVerificationError(message, certificate) + + +def raise_self_signed(certificate): + """ + Raises a TLSVerificationError due to a self-signed certificate + roots + + :param certificate: + An asn1crypto.x509.Certificate object + + :raises: + TLSVerificationError + """ + + message = 'Server certificate verification failed - certificate is self-signed' + raise TLSVerificationError(message, certificate) + + +def raise_expired_not_yet_valid(certificate): + """ + Raises a TLSVerificationError due to certificate being expired, or not yet + being valid + + :param certificate: + An asn1crypto.x509.Certificate object + + :raises: + TLSVerificationError + """ + + validity = certificate['tbs_certificate']['validity'] + not_after = validity['not_after'].native + not_before = validity['not_before'].native + + now = datetime.now(timezone.utc) + + if not_before > now: + formatted_before = not_before.strftime('%Y-%m-%d %H:%M:%SZ') + message = 'Server certificate verification failed - certificate not valid until %s' % formatted_before + elif not_after < now: + formatted_after = not_after.strftime('%Y-%m-%d %H:%M:%SZ') + message = 'Server certificate verification failed - certificate expired %s' % formatted_after + + raise TLSVerificationError(message, certificate) + + +def raise_disconnection(): + """ + Raises a TLSDisconnectError due to a disconnection + + :raises: + TLSDisconnectError + """ + + raise TLSDisconnectError('The remote end closed the connection') + + +def raise_protocol_error(server_handshake_bytes): + """ + Raises a TLSError due to a protocol error + + :param server_handshake_bytes: + A byte string of the handshake data received from the server + + :raises: + TLSError + """ + + other_protocol = detect_other_protocol(server_handshake_bytes) + + if other_protocol: + raise TLSError('TLS protocol error - server responded using %s' % other_protocol) + + raise TLSError('TLS protocol error - server responded using a different protocol') + + +def raise_handshake(): + """ + Raises a TLSError due to a handshake error + + :raises: + TLSError + """ + + raise TLSError('TLS handshake failed') + + +def raise_protocol_version(): + """ + Raises a TLSError due to a TLS version incompatibility + + :raises: + TLSError + """ + + raise TLSError('TLS handshake failed - protocol version error') + + +def raise_dh_params(): + """ + Raises a TLSError due to weak DH params + + :raises: + TLSError + """ + + raise TLSError('TLS handshake failed - weak DH parameters') + + +def detect_other_protocol(server_handshake_bytes): + """ + Looks at the server handshake bytes to try and detect a different protocol + + :param server_handshake_bytes: + A byte string of the handshake data received from the server + + :return: + None, or a unicode string of "ftp", "http", "imap", "pop3", "smtp" + """ + + if server_handshake_bytes[0:5] == b'HTTP/': + return 'HTTP' + + if server_handshake_bytes[0:4] == b'220 ': + if re.match(b'^[^\r\n]*ftp', server_handshake_bytes, re.I): + return 'FTP' + else: + return 'SMTP' + + if server_handshake_bytes[0:4] == b'220-': + return 'FTP' + + if server_handshake_bytes[0:4] == b'+OK ': + return 'POP3' + + if server_handshake_bytes[0:4] == b'* OK' or server_handshake_bytes[0:9] == b'* PREAUTH': + return 'IMAP' + + return None diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_types.py b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_types.py new file mode 100644 index 00000000..d28dd0ff --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_types.py @@ -0,0 +1,41 @@ +# coding: utf-8 +from __future__ import unicode_literals, division, absolute_import, print_function + +import sys +import inspect + + +if sys.version_info < (3,): + str_cls = unicode # noqa + byte_cls = str + int_types = (int, long) # noqa + + def bytes_to_list(byte_string): + return [ord(b) for b in byte_string] + +else: + str_cls = str + byte_cls = bytes + int_types = (int,) + + bytes_to_list = list + + +def type_name(value): + """ + Returns a user-readable name for the type of an object + + :param value: + A value to get the type name of + + :return: + A unicode string of the object's type name + """ + + if inspect.isclass(value): + cls = value + else: + cls = value.__class__ + if cls.__module__ in set(['builtins', '__builtin__']): + return cls.__name__ + return '%s.%s' % (cls.__module__, cls.__name__) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_win/__init__.py b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_win/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_win/_advapi32.py b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_win/_advapi32.py new file mode 100644 index 00000000..5066e11d --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_win/_advapi32.py @@ -0,0 +1,165 @@ +# coding: utf-8 +from __future__ import unicode_literals, division, absolute_import, print_function + +import sys + +from .. import ffi +from ._decode import _try_decode +from ..errors import SignatureError +from .._ffi import new, unwrap, null +from .._types import str_cls + +if ffi() == 'cffi': + from ._advapi32_cffi import advapi32, get_error +else: + from ._advapi32_ctypes import advapi32, get_error + + +__all__ = [ + 'advapi32', + 'Advapi32Const', + 'handle_error', +] + + +_gwv = sys.getwindowsversion() +_win_version_info = (_gwv[0], _gwv[1]) + + +def open_context_handle(provider, verify_only=True): + if provider == Advapi32Const.MS_ENH_RSA_AES_PROV: + provider_type = Advapi32Const.PROV_RSA_AES + elif provider == Advapi32Const.MS_ENH_DSS_DH_PROV: + provider_type = Advapi32Const.PROV_DSS_DH + else: + raise ValueError('Invalid provider specified: %s' % provider) + + # Ths DSS provider needs a container to allow importing and exporting + # private keys, but all of the RSA stuff works fine with CRYPT_VERIFYCONTEXT + if verify_only or provider != Advapi32Const.MS_ENH_DSS_DH_PROV: + container_name = null() + flags = Advapi32Const.CRYPT_VERIFYCONTEXT + else: + container_name = Advapi32Const.CONTAINER_NAME + flags = Advapi32Const.CRYPT_NEWKEYSET + + context_handle_pointer = new(advapi32, 'HCRYPTPROV *') + res = advapi32.CryptAcquireContextW( + context_handle_pointer, + container_name, + provider, + provider_type, + flags + ) + # If using the DSS provider and the container exists, just open it + if not res and get_error()[0] == Advapi32Const.NTE_EXISTS: + res = advapi32.CryptAcquireContextW( + context_handle_pointer, + container_name, + provider, + provider_type, + 0 + ) + handle_error(res) + + return unwrap(context_handle_pointer) + + +def close_context_handle(handle): + res = advapi32.CryptReleaseContext(handle, 0) + handle_error(res) + + +def handle_error(result): + """ + Extracts the last Windows error message into a python unicode string + + :param result: + A function result, 0 or None indicates failure + + :return: + A unicode string error message + """ + + if result: + return + + code, error_string = get_error() + + if code == Advapi32Const.NTE_BAD_SIGNATURE: + raise SignatureError('Signature is invalid') + + if not isinstance(error_string, str_cls): + error_string = _try_decode(error_string) + + raise OSError(error_string) + + +class Advapi32Const(): + # Name we give to a container used to make DSA private key import/export work + CONTAINER_NAME = 'oscrypto temporary DSS keyset' + + PROV_RSA_AES = 24 + PROV_DSS_DH = 13 + + X509_PUBLIC_KEY_INFO = 8 + PKCS_PRIVATE_KEY_INFO = 44 + X509_DSS_SIGNATURE = 40 + CRYPT_NO_SALT = 0x00000010 + + MS_ENH_DSS_DH_PROV = "Microsoft Enhanced DSS and Diffie-Hellman Cryptographic Provider" + # This is the name for Windows Server 2003 and newer and Windows Vista and newer + MS_ENH_RSA_AES_PROV = "Microsoft Enhanced RSA and AES Cryptographic Provider" + + CRYPT_EXPORTABLE = 1 + CRYPT_NEWKEYSET = 0x00000008 + CRYPT_VERIFYCONTEXT = 0xF0000000 + + CALG_MD5 = 0x00008003 + CALG_SHA1 = 0x00008004 + CALG_SHA_256 = 0x0000800c + CALG_SHA_384 = 0x0000800d + CALG_SHA_512 = 0x0000800e + + CALG_RC2 = 0x00006602 + CALG_RC4 = 0x00006801 + CALG_DES = 0x00006601 + CALG_3DES_112 = 0x00006609 + CALG_3DES = 0x00006603 + CALG_AES_128 = 0x0000660e + CALG_AES_192 = 0x0000660f + CALG_AES_256 = 0x00006610 + + CALG_DSS_SIGN = 0x00002200 + CALG_RSA_SIGN = 0x00002400 + CALG_RSA_KEYX = 0x0000a400 + + CRYPT_MODE_CBC = 1 + + PKCS5_PADDING = 1 + + CUR_BLOB_VERSION = 2 + PUBLICKEYBLOB = 6 + PRIVATEKEYBLOB = 7 + PLAINTEXTKEYBLOB = 8 + + KP_IV = 1 + KP_PADDING = 3 + KP_MODE = 4 + KP_EFFECTIVE_KEYLEN = 19 + + CRYPT_OAEP = 0x00000040 + + NTE_BAD_SIGNATURE = -2146893818 # 0x80090006 + NTE_EXISTS = -2146893809 # 0x8009000F + AT_SIGNATURE = 2 + + RSA1 = 0x31415352 + RSA2 = 0x32415352 + DSS1 = 0x31535344 + DSS2 = 0x32535344 + + +if _win_version_info == (5, 1): + # This is the Windows XP name for the provider + Advapi32Const.MS_ENH_RSA_AES_PROV = "Microsoft Enhanced RSA and AES Cryptographic Provider (Prototype)" diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_win/_advapi32_cffi.py b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_win/_advapi32_cffi.py new file mode 100644 index 00000000..49932ffb --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_win/_advapi32_cffi.py @@ -0,0 +1,145 @@ +# coding: utf-8 +from __future__ import unicode_literals, division, absolute_import, print_function + +from .._ffi import register_ffi +from .._types import str_cls +from ..errors import LibraryNotFoundError + +import cffi + + +__all__ = [ + 'advapi32', + 'get_error', +] + + +ffi = cffi.FFI() +if cffi.__version_info__ >= (0, 9): + ffi.set_unicode(True) +ffi.cdef(""" + typedef HANDLE HCRYPTPROV; + typedef HANDLE HCRYPTKEY; + typedef HANDLE HCRYPTHASH; + typedef unsigned int ALG_ID; + + typedef struct _CRYPTOAPI_BLOB { + DWORD cbData; + BYTE *pbData; + } CRYPT_INTEGER_BLOB, CRYPT_OBJID_BLOB, CRYPT_DER_BLOB, CRYPT_ATTR_BLOB; + + typedef struct _CRYPT_ALGORITHM_IDENTIFIER { + LPSTR pszObjId; + CRYPT_OBJID_BLOB Parameters; + } CRYPT_ALGORITHM_IDENTIFIER; + + typedef struct _CRYPT_BIT_BLOB { + DWORD cbData; + BYTE *pbData; + DWORD cUnusedBits; + } CRYPT_BIT_BLOB; + + typedef struct _CERT_PUBLIC_KEY_INFO { + CRYPT_ALGORITHM_IDENTIFIER Algorithm; + CRYPT_BIT_BLOB PublicKey; + } CERT_PUBLIC_KEY_INFO; + + typedef struct _CRYPT_ATTRIBUTE { + LPSTR pszObjId; + DWORD cValue; + CRYPT_ATTR_BLOB *rgValue; + } CRYPT_ATTRIBUTE; + + typedef struct _CRYPT_ATTRIBUTES { + DWORD cAttr; + CRYPT_ATTRIBUTE *rgAttr; + } CRYPT_ATTRIBUTES; + + typedef struct _CRYPT_PRIVATE_KEY_INFO { + DWORD Version; + CRYPT_ALGORITHM_IDENTIFIER Algorithm; + CRYPT_DER_BLOB PrivateKey; + CRYPT_ATTRIBUTES *pAttributes; + } CRYPT_PRIVATE_KEY_INFO; + + typedef struct _PUBLICKEYSTRUC { + BYTE bType; + BYTE bVersion; + WORD reserved; + ALG_ID aiKeyAlg; + } BLOBHEADER, PUBLICKEYSTRUC; + + typedef struct _DSSPUBKEY { + DWORD magic; + DWORD bitlen; + } DSSPUBKEY; + + typedef struct _DSSBLOBHEADER { + PUBLICKEYSTRUC publickeystruc; + DSSPUBKEY dsspubkey; + } DSSBLOBHEADER; + + typedef struct _RSAPUBKEY { + DWORD magic; + DWORD bitlen; + DWORD pubexp; + } RSAPUBKEY; + + typedef struct _RSABLOBHEADER { + PUBLICKEYSTRUC publickeystruc; + RSAPUBKEY rsapubkey; + } RSABLOBHEADER; + + typedef struct _PLAINTEXTKEYBLOB { + BLOBHEADER hdr; + DWORD dwKeySize; + // rgbKeyData omitted since it is a flexible array member + } PLAINTEXTKEYBLOB; + + typedef struct _DSSSEED { + DWORD counter; + BYTE seed[20]; + } DSSSEED; + + BOOL CryptAcquireContextW(HCRYPTPROV *phProv, LPCWSTR pszContainer, LPCWSTR pszProvider, + DWORD dwProvType, DWORD dwFlags); + BOOL CryptReleaseContext(HCRYPTPROV hProv, DWORD dwFlags); + + BOOL CryptImportKey(HCRYPTPROV hProv, BYTE *pbData, DWORD dwDataLen, + HCRYPTKEY hPubKey, DWORD dwFlags, HCRYPTKEY *phKey); + BOOL CryptGenKey(HCRYPTPROV hProv, ALG_ID Algid, DWORD dwFlags, HCRYPTKEY *phKey); + BOOL CryptGetKeyParam(HCRYPTKEY hKey, DWORD dwParam, BYTE *pbData, DWORD *pdwDataLen, DWORD dwFlags); + BOOL CryptSetKeyParam(HCRYPTKEY hKey, DWORD dwParam, void *pbData, DWORD dwFlags); + BOOL CryptExportKey(HCRYPTKEY hKey, HCRYPTKEY hExpKey, DWORD dwBlobType, + DWORD dwFlags, BYTE *pbData, DWORD *pdwDataLen); + BOOL CryptDestroyKey(HCRYPTKEY hKey); + + BOOL CryptCreateHash(HCRYPTPROV hProv, ALG_ID Algid, HCRYPTKEY hKey, + DWORD dwFlags, HCRYPTHASH *phHash); + BOOL CryptHashData(HCRYPTHASH hHash, BYTE *pbData, DWORD dwDataLen, DWORD dwFlags); + BOOL CryptSetHashParam(HCRYPTHASH hHash, DWORD dwParam, BYTE *pbData, DWORD dwFlags); + BOOL CryptSignHashW(HCRYPTHASH hHash, DWORD dwKeySpec, LPCWSTR sDescription, + DWORD dwFlags, BYTE *pbSignature, DWORD *pdwSigLen); + BOOL CryptVerifySignatureW(HCRYPTHASH hHash, BYTE *pbSignature, DWORD dwSigLen, + HCRYPTKEY hPubKey, LPCWSTR sDescription, DWORD dwFlags); + BOOL CryptDestroyHash(HCRYPTHASH hHash); + + BOOL CryptEncrypt(HCRYPTKEY hKey, HCRYPTHASH hHash, BOOL Final, DWORD dwFlags, + BYTE *pbData, DWORD *pdwDataLen, DWORD dwBufLen); + BOOL CryptDecrypt(HCRYPTKEY hKey, HCRYPTHASH hHash, BOOL Final, DWORD dwFlags, + BYTE *pbData, DWORD *pdwDataLen); +""") + + +try: + advapi32 = ffi.dlopen('advapi32.dll') + register_ffi(advapi32, ffi) + +except (OSError) as e: + if str_cls(e).find('cannot load library') != -1: + raise LibraryNotFoundError('advapi32.dll could not be found') + raise + + +def get_error(): + return ffi.getwinerror() diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_win/_advapi32_ctypes.py b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_win/_advapi32_ctypes.py new file mode 100644 index 00000000..ba5ee10c --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_win/_advapi32_ctypes.py @@ -0,0 +1,295 @@ +# coding: utf-8 +from __future__ import unicode_literals, division, absolute_import, print_function + +import ctypes +from ctypes import windll, wintypes, POINTER, Structure, c_void_p, c_char_p, c_uint +from ctypes.wintypes import BOOL, DWORD + +from .._ffi import FFIEngineError +from .._types import str_cls +from ..errors import LibraryNotFoundError + + +__all__ = [ + 'advapi32', + 'get_error', +] + + +try: + advapi32 = windll.advapi32 +except (OSError) as e: + if str_cls(e).find('The specified module could not be found') != -1: + raise LibraryNotFoundError('advapi32.dll could not be found') + raise + +HCRYPTPROV = wintypes.HANDLE +HCRYPTKEY = wintypes.HANDLE +HCRYPTHASH = wintypes.HANDLE +PBYTE = c_char_p +ALG_ID = c_uint + +try: + class CRYPTOAPI_BLOB(Structure): # noqa + _fields_ = [ + ("cbData", DWORD), + ("pbData", POINTER(ctypes.c_byte)), + ] + CRYPT_INTEGER_BLOB = CRYPTOAPI_BLOB + CRYPT_OBJID_BLOB = CRYPTOAPI_BLOB + CRYPT_DER_BLOB = CRYPTOAPI_BLOB + CRYPT_ATTR_BLOB = CRYPTOAPI_BLOB + + class CRYPT_ALGORITHM_IDENTIFIER(Structure): + _fields = [ + ('pszObjId', wintypes.LPSTR), + ('Parameters', CRYPT_OBJID_BLOB), + ] + + class CRYPT_BIT_BLOB(Structure): + _fields_ = [ + ('cbData', DWORD), + ('pbData', PBYTE), + ('cUnusedBits', DWORD), + ] + + class CERT_PUBLIC_KEY_INFO(Structure): + _fields_ = [ + ('Algorithm', CRYPT_ALGORITHM_IDENTIFIER), + ('PublicKey', CRYPT_BIT_BLOB), + ] + + class CRYPT_ATTRIBUTE(Structure): + _fields_ = [ + ('pszObjId', wintypes.LPSTR), + ('cValue', DWORD), + ('rgValue', POINTER(CRYPT_ATTR_BLOB)), + ] + + class CRYPT_ATTRIBUTES(Structure): + _fields_ = [ + ('cAttr', DWORD), + ('rgAttr', POINTER(CRYPT_ATTRIBUTE)), + ] + + class CRYPT_PRIVATE_KEY_INFO(Structure): + _fields_ = [ + ('Version', DWORD), + ('Algorithm', CRYPT_ALGORITHM_IDENTIFIER), + ('PrivateKey', CRYPT_DER_BLOB), + ('pAttributes', POINTER(CRYPT_ATTRIBUTES)), + ] + + class PUBLICKEYSTRUC(Structure): + _fields_ = [ + ('bType', wintypes.BYTE), + ('bVersion', wintypes.BYTE), + ('reserved', wintypes.WORD), + ('aiKeyAlg', ALG_ID), + ] + BLOBHEADER = PUBLICKEYSTRUC + + class DSSPUBKEY(Structure): + _fields_ = [ + ('magic', DWORD), + ('bitlen', DWORD), + ] + + class DSSBLOBHEADER(Structure): + _fields_ = [ + ('publickeystruc', PUBLICKEYSTRUC), + ('dsspubkey', DSSPUBKEY), + ] + + class RSAPUBKEY(Structure): + _fields_ = [ + ('magic', DWORD), + ('bitlen', DWORD), + ('pubexp', DWORD), + ] + + class RSABLOBHEADER(Structure): + _fields_ = [ + ('publickeystruc', PUBLICKEYSTRUC), + ('rsapubkey', RSAPUBKEY), + ] + + class PLAINTEXTKEYBLOB(Structure): + _fields_ = [ + ('hdr', BLOBHEADER), + ('dwKeySize', DWORD), + # rgbKeyData omitted since it is a flexible array member + ] + + class DSSSEED(Structure): + _fields_ = [ + ('counter', DWORD), + ('seed', wintypes.BYTE * 20), + ] + + advapi32.CryptAcquireContextW.argtypes = [ + POINTER(HCRYPTPROV), + wintypes.LPCWSTR, + wintypes.LPCWSTR, + DWORD, + DWORD + ] + advapi32.CryptAcquireContextW.restype = wintypes.BOOL + + advapi32.CryptReleaseContext.argtypes = [ + HCRYPTPROV, + DWORD + ] + advapi32.CryptReleaseContext.restype = wintypes.BOOL + + advapi32.CryptImportKey.argtypes = [ + HCRYPTPROV, + PBYTE, + DWORD, + HCRYPTKEY, + DWORD, + POINTER(HCRYPTKEY) + ] + advapi32.CryptImportKey.restype = BOOL + + advapi32.CryptGenKey.argtypes = [ + HCRYPTPROV, + ALG_ID, + DWORD, + POINTER(HCRYPTKEY) + ] + advapi32.CryptGenKey.restype = wintypes.BOOL + + advapi32.CryptGetKeyParam.argtypes = [ + HCRYPTKEY, + DWORD, + PBYTE, + POINTER(DWORD), + DWORD + ] + advapi32.CryptGetKeyParam.restype = wintypes.BOOL + + advapi32.CryptSetKeyParam.argtypes = [ + HCRYPTKEY, + DWORD, + c_void_p, + DWORD + ] + advapi32.CryptSetKeyParam.restype = wintypes.BOOL + + advapi32.CryptExportKey.argtypes = [ + HCRYPTKEY, + HCRYPTKEY, + DWORD, + DWORD, + PBYTE, + POINTER(DWORD) + ] + advapi32.CryptExportKey.restype = BOOL + + advapi32.CryptDestroyKey.argtypes = [ + HCRYPTKEY + ] + advapi32.CryptDestroyKey.restype = wintypes.BOOL + + advapi32.CryptCreateHash.argtypes = [ + HCRYPTPROV, + ALG_ID, + HCRYPTKEY, + DWORD, + POINTER(HCRYPTHASH) + ] + advapi32.CryptCreateHash.restype = BOOL + + advapi32.CryptHashData.argtypes = [ + HCRYPTHASH, + PBYTE, + DWORD, + DWORD + ] + advapi32.CryptHashData.restype = BOOL + + advapi32.CryptSetHashParam.argtypes = [ + HCRYPTHASH, + DWORD, + PBYTE, + DWORD + ] + advapi32.CryptSetHashParam.restype = BOOL + + advapi32.CryptSignHashW.argtypes = [ + HCRYPTHASH, + DWORD, + wintypes.LPCWSTR, + DWORD, + PBYTE, + POINTER(DWORD) + ] + advapi32.CryptSignHashW.restype = BOOL + + advapi32.CryptVerifySignatureW.argtypes = [ + HCRYPTHASH, + PBYTE, + DWORD, + HCRYPTKEY, + wintypes.LPCWSTR, + DWORD + ] + advapi32.CryptVerifySignatureW.restype = BOOL + + advapi32.CryptDestroyHash.argtypes = [ + HCRYPTHASH + ] + advapi32.CryptDestroyHash.restype = wintypes.BOOL + + advapi32.CryptEncrypt.argtypes = [ + HCRYPTKEY, + HCRYPTHASH, + BOOL, + DWORD, + PBYTE, + POINTER(DWORD), + DWORD + ] + advapi32.CryptEncrypt.restype = BOOL + + advapi32.CryptDecrypt.argtypes = [ + HCRYPTKEY, + HCRYPTHASH, + BOOL, + DWORD, + PBYTE, + POINTER(DWORD) + ] + advapi32.CryptDecrypt.restype = BOOL + +except (AttributeError): + raise FFIEngineError('Error initializing ctypes') + + +setattr(advapi32, 'HCRYPTPROV', HCRYPTPROV) +setattr(advapi32, 'HCRYPTKEY', HCRYPTKEY) +setattr(advapi32, 'HCRYPTHASH', HCRYPTHASH) +setattr(advapi32, 'CRYPT_INTEGER_BLOB', CRYPT_INTEGER_BLOB) +setattr(advapi32, 'CRYPT_OBJID_BLOB', CRYPT_OBJID_BLOB) +setattr(advapi32, 'CRYPT_DER_BLOB', CRYPT_DER_BLOB) +setattr(advapi32, 'CRYPT_ATTR_BLOB', CRYPT_ATTR_BLOB) +setattr(advapi32, 'CRYPT_ALGORITHM_IDENTIFIER', CRYPT_ALGORITHM_IDENTIFIER) +setattr(advapi32, 'CRYPT_BIT_BLOB', CRYPT_BIT_BLOB) +setattr(advapi32, 'CERT_PUBLIC_KEY_INFO', CERT_PUBLIC_KEY_INFO) +setattr(advapi32, 'CRYPT_PRIVATE_KEY_INFO', CRYPT_PRIVATE_KEY_INFO) +setattr(advapi32, 'CRYPT_ATTRIBUTE', CRYPT_ATTRIBUTE) +setattr(advapi32, 'CRYPT_ATTRIBUTES', CRYPT_ATTRIBUTES) +setattr(advapi32, 'PUBLICKEYSTRUC', PUBLICKEYSTRUC) +setattr(advapi32, 'DSSPUBKEY', DSSPUBKEY) +setattr(advapi32, 'DSSBLOBHEADER', DSSBLOBHEADER) +setattr(advapi32, 'RSAPUBKEY', RSAPUBKEY) +setattr(advapi32, 'RSABLOBHEADER', RSABLOBHEADER) +setattr(advapi32, 'BLOBHEADER', BLOBHEADER) +setattr(advapi32, 'PLAINTEXTKEYBLOB', PLAINTEXTKEYBLOB) +setattr(advapi32, 'DSSSEED', DSSSEED) + + +def get_error(): + error = ctypes.GetLastError() + return (error, ctypes.FormatError(error)) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_win/_cng.py b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_win/_cng.py new file mode 100644 index 00000000..0eb02d74 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_win/_cng.py @@ -0,0 +1,148 @@ +# coding: utf-8 +from __future__ import unicode_literals, division, absolute_import, print_function + +from .. import ffi +from .._ffi import new, null, unwrap + +if ffi() == 'cffi': + from ._cng_cffi import bcrypt +else: + from ._cng_ctypes import bcrypt + + +__all__ = [ + 'bcrypt', + 'BcryptConst', + 'close_alg_handle', + 'handle_error', + 'open_alg_handle', +] + + +def open_alg_handle(constant, flags=0): + handle_pointer = new(bcrypt, 'BCRYPT_ALG_HANDLE *') + res = bcrypt.BCryptOpenAlgorithmProvider(handle_pointer, constant, null(), flags) + handle_error(res) + + return unwrap(handle_pointer) + + +def close_alg_handle(handle): + res = bcrypt.BCryptCloseAlgorithmProvider(handle, 0) + handle_error(res) + + +def handle_error(error_num): + """ + Extracts the last Windows error message into a python unicode string + + :param error_num: + The number to get the error string for + + :return: + A unicode string error message + """ + + if error_num == 0: + return + + messages = { + BcryptConst.STATUS_NOT_FOUND: 'The object was not found', + BcryptConst.STATUS_INVALID_PARAMETER: 'An invalid parameter was passed to a service or function', + BcryptConst.STATUS_NO_MEMORY: ( + 'Not enough virtual memory or paging file quota is available to complete the specified operation' + ), + BcryptConst.STATUS_INVALID_HANDLE: 'An invalid HANDLE was specified', + BcryptConst.STATUS_INVALID_SIGNATURE: 'The cryptographic signature is invalid', + BcryptConst.STATUS_NOT_SUPPORTED: 'The request is not supported', + BcryptConst.STATUS_BUFFER_TOO_SMALL: 'The buffer is too small to contain the entry', + BcryptConst.STATUS_INVALID_BUFFER_SIZE: 'The size of the buffer is invalid for the specified operation', + } + + output = 'NTSTATUS error 0x%0.2X' % error_num + + if error_num is not None and error_num in messages: + output += ': ' + messages[error_num] + + raise OSError(output) + + +class BcryptConst(): + BCRYPT_RNG_ALGORITHM = 'RNG' + + BCRYPT_KEY_LENGTH = 'KeyLength' + BCRYPT_EFFECTIVE_KEY_LENGTH = 'EffectiveKeyLength' + + BCRYPT_RSAPRIVATE_BLOB = 'RSAPRIVATEBLOB' + BCRYPT_RSAFULLPRIVATE_BLOB = 'RSAFULLPRIVATEBLOB' + BCRYPT_RSAPUBLIC_BLOB = 'RSAPUBLICBLOB' + BCRYPT_DSA_PRIVATE_BLOB = 'DSAPRIVATEBLOB' + BCRYPT_DSA_PUBLIC_BLOB = 'DSAPUBLICBLOB' + BCRYPT_ECCPRIVATE_BLOB = 'ECCPRIVATEBLOB' + BCRYPT_ECCPUBLIC_BLOB = 'ECCPUBLICBLOB' + + BCRYPT_RSAPUBLIC_MAGIC = 0x31415352 + BCRYPT_RSAPRIVATE_MAGIC = 0x32415352 + BCRYPT_RSAFULLPRIVATE_MAGIC = 0x33415352 + + BCRYPT_DSA_PUBLIC_MAGIC = 0x42505344 + BCRYPT_DSA_PRIVATE_MAGIC = 0x56505344 + BCRYPT_DSA_PUBLIC_MAGIC_V2 = 0x32425044 + BCRYPT_DSA_PRIVATE_MAGIC_V2 = 0x32565044 + + DSA_HASH_ALGORITHM_SHA1 = 0 + DSA_HASH_ALGORITHM_SHA256 = 1 + DSA_HASH_ALGORITHM_SHA512 = 2 + + DSA_FIPS186_2 = 0 + DSA_FIPS186_3 = 1 + + BCRYPT_NO_KEY_VALIDATION = 8 + + BCRYPT_ECDSA_PUBLIC_P256_MAGIC = 0x31534345 + BCRYPT_ECDSA_PRIVATE_P256_MAGIC = 0x32534345 + BCRYPT_ECDSA_PUBLIC_P384_MAGIC = 0x33534345 + BCRYPT_ECDSA_PRIVATE_P384_MAGIC = 0x34534345 + BCRYPT_ECDSA_PUBLIC_P521_MAGIC = 0x35534345 + BCRYPT_ECDSA_PRIVATE_P521_MAGIC = 0x36534345 + + STATUS_SUCCESS = 0x00000000 + STATUS_NOT_FOUND = 0xC0000225 + STATUS_INVALID_PARAMETER = 0xC000000D + STATUS_NO_MEMORY = 0xC0000017 + STATUS_INVALID_HANDLE = 0xC0000008 + STATUS_INVALID_SIGNATURE = 0xC000A000 + STATUS_NOT_SUPPORTED = 0xC00000BB + STATUS_BUFFER_TOO_SMALL = 0xC0000023 + STATUS_INVALID_BUFFER_SIZE = 0xC0000206 + + BCRYPT_KEY_DATA_BLOB_MAGIC = 0x4d42444b + BCRYPT_KEY_DATA_BLOB_VERSION1 = 0x00000001 + BCRYPT_KEY_DATA_BLOB = 'KeyDataBlob' + + BCRYPT_PAD_PKCS1 = 0x00000002 + BCRYPT_PAD_OAEP = 0x00000004 + BCRYPT_PAD_PSS = 0x00000008 + + BCRYPT_3DES_ALGORITHM = '3DES' + BCRYPT_3DES_112_ALGORITHM = '3DES_112' + BCRYPT_AES_ALGORITHM = 'AES' + BCRYPT_DES_ALGORITHM = 'DES' + BCRYPT_RC2_ALGORITHM = 'RC2' + BCRYPT_RC4_ALGORITHM = 'RC4' + + BCRYPT_DSA_ALGORITHM = 'DSA' + BCRYPT_ECDSA_P256_ALGORITHM = 'ECDSA_P256' + BCRYPT_ECDSA_P384_ALGORITHM = 'ECDSA_P384' + BCRYPT_ECDSA_P521_ALGORITHM = 'ECDSA_P521' + BCRYPT_RSA_ALGORITHM = 'RSA' + + BCRYPT_MD5_ALGORITHM = 'MD5' + BCRYPT_SHA1_ALGORITHM = 'SHA1' + BCRYPT_SHA256_ALGORITHM = 'SHA256' + BCRYPT_SHA384_ALGORITHM = 'SHA384' + BCRYPT_SHA512_ALGORITHM = 'SHA512' + + BCRYPT_ALG_HANDLE_HMAC_FLAG = 0x00000008 + + BCRYPT_BLOCK_PADDING = 0x00000001 diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_win/_cng_cffi.py b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_win/_cng_cffi.py new file mode 100644 index 00000000..3e9d5cec --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_win/_cng_cffi.py @@ -0,0 +1,120 @@ +# coding: utf-8 +from __future__ import unicode_literals, division, absolute_import, print_function + +from .._ffi import register_ffi +from .._types import str_cls +from ..errors import LibraryNotFoundError + +from cffi import FFI + + +__all__ = [ + 'bcrypt', +] + + +ffi = FFI() +ffi.cdef(""" + typedef HANDLE BCRYPT_ALG_HANDLE; + typedef HANDLE BCRYPT_KEY_HANDLE; + typedef ULONG NTSTATUS; + typedef unsigned char *PUCHAR; + typedef unsigned char *PBYTE; + + + typedef struct _BCRYPT_RSAKEY_BLOB { + ULONG Magic; + ULONG BitLength; + ULONG cbPublicExp; + ULONG cbModulus; + ULONG cbPrime1; + ULONG cbPrime2; + } BCRYPT_RSAKEY_BLOB; + + typedef struct _BCRYPT_DSA_KEY_BLOB { + ULONG dwMagic; + ULONG cbKey; + UCHAR Count[4]; + UCHAR Seed[20]; + UCHAR q[20]; + } BCRYPT_DSA_KEY_BLOB; + + typedef struct _BCRYPT_DSA_KEY_BLOB_V2 { + ULONG dwMagic; + ULONG cbKey; + INT hashAlgorithm; + INT standardVersion; + ULONG cbSeedLength; + ULONG cbGroupSize; + UCHAR Count[4]; + } BCRYPT_DSA_KEY_BLOB_V2; + + typedef struct _BCRYPT_ECCKEY_BLOB { + ULONG dwMagic; + ULONG cbKey; + } BCRYPT_ECCKEY_BLOB; + + typedef struct _BCRYPT_PKCS1_PADDING_INFO { + LPCWSTR pszAlgId; + } BCRYPT_PKCS1_PADDING_INFO; + + typedef struct _BCRYPT_PSS_PADDING_INFO { + LPCWSTR pszAlgId; + ULONG cbSalt; + } BCRYPT_PSS_PADDING_INFO; + + typedef struct _BCRYPT_OAEP_PADDING_INFO { + LPCWSTR pszAlgId; + PUCHAR pbLabel; + ULONG cbLabel; + } BCRYPT_OAEP_PADDING_INFO; + + typedef struct _BCRYPT_KEY_DATA_BLOB_HEADER { + ULONG dwMagic; + ULONG dwVersion; + ULONG cbKeyData; + } BCRYPT_KEY_DATA_BLOB_HEADER; + + NTSTATUS BCryptOpenAlgorithmProvider(BCRYPT_ALG_HANDLE *phAlgorithm, LPCWSTR pszAlgId, LPCWSTR pszImplementation, + DWORD dwFlags); + NTSTATUS BCryptCloseAlgorithmProvider(BCRYPT_ALG_HANDLE hAlgorithm, DWORD dwFlags); + NTSTATUS BCryptSetProperty(HANDLE hObject, LPCWSTR pszProperty, ULONG *pbInput, ULONG cbInput, ULONG dwFlags); + + NTSTATUS BCryptImportKeyPair(BCRYPT_ALG_HANDLE hAlgorithm, BCRYPT_KEY_HANDLE hImportKey, LPCWSTR pszBlobType, + BCRYPT_KEY_HANDLE *phKey, PUCHAR pbInput, ULONG cbInput, ULONG dwFlags); + NTSTATUS BCryptImportKey(BCRYPT_ALG_HANDLE hAlgorithm, BCRYPT_KEY_HANDLE hImportKey, LPCWSTR pszBlobType, + BCRYPT_KEY_HANDLE *phKey, PUCHAR pbKeyObject, ULONG cbKeyObject, PUCHAR pbInput, ULONG cbInput, + ULONG dwFlags); + NTSTATUS BCryptDestroyKey(BCRYPT_KEY_HANDLE hKey); + + NTSTATUS BCryptVerifySignature(BCRYPT_KEY_HANDLE hKey, void *pPaddingInfo, PUCHAR pbHash, ULONG cbHash, + PUCHAR pbSignature, ULONG cbSignature, ULONG dwFlags); + NTSTATUS BCryptSignHash(BCRYPT_KEY_HANDLE hKey, void * pPaddingInfo, PBYTE pbInput, DWORD cbInput, PBYTE pbOutput, + DWORD cbOutput, DWORD *pcbResult, ULONG dwFlags); + + NTSTATUS BCryptEncrypt(BCRYPT_KEY_HANDLE hKey, PUCHAR pbInput, ULONG cbInput, void *pPaddingInfo, PUCHAR pbIV, + ULONG cbIV, PUCHAR pbOutput, ULONG cbOutput, ULONG *pcbResult, ULONG dwFlags); + NTSTATUS BCryptDecrypt(BCRYPT_KEY_HANDLE hKey, PUCHAR pbInput, ULONG cbInput, void *pPaddingInfo, PUCHAR pbIV, + ULONG cbIV, PUCHAR pbOutput, ULONG cbOutput, ULONG *pcbResult, ULONG dwFlags); + + NTSTATUS BCryptDeriveKeyPBKDF2(BCRYPT_ALG_HANDLE hPrf, PUCHAR pbPassword, ULONG cbPassword, PUCHAR pbSalt, + ULONG cbSalt, ULONGLONG cIterations, PUCHAR pbDerivedKey, ULONG cbDerivedKey, ULONG dwFlags); + + NTSTATUS BCryptGenRandom(BCRYPT_ALG_HANDLE hAlgorithm, PUCHAR pbBuffer, ULONG cbBuffer, ULONG dwFlags); + + NTSTATUS BCryptGenerateKeyPair(BCRYPT_ALG_HANDLE hAlgorithm, BCRYPT_KEY_HANDLE *phKey, ULONG dwLength, + ULONG dwFlags); + NTSTATUS BCryptFinalizeKeyPair(BCRYPT_KEY_HANDLE hKey, ULONG dwFlags); + NTSTATUS BCryptExportKey(BCRYPT_KEY_HANDLE hKey, BCRYPT_KEY_HANDLE hExportKey, LPCWSTR pszBlobType, + PUCHAR pbOutput, ULONG cbOutput, ULONG *pcbResult, ULONG dwFlags); +""") + + +try: + bcrypt = ffi.dlopen('bcrypt.dll') + register_ffi(bcrypt, ffi) + +except (OSError) as e: + if str_cls(e).find('cannot load library') != -1: + raise LibraryNotFoundError('bcrypt.dll could not be found - Windows XP and Server 2003 are not supported') + raise diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_win/_cng_ctypes.py b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_win/_cng_ctypes.py new file mode 100644 index 00000000..fcfae6b9 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_win/_cng_ctypes.py @@ -0,0 +1,263 @@ +# coding: utf-8 +from __future__ import unicode_literals, division, absolute_import, print_function + +from ctypes import windll, wintypes, POINTER, Structure, c_void_p, c_ulonglong, c_char_p, c_byte +from ctypes.wintypes import ULONG, DWORD, LPCWSTR + +from .._ffi import FFIEngineError +from .._types import str_cls +from ..errors import LibraryNotFoundError + + +__all__ = [ + 'bcrypt', +] + + +try: + bcrypt = windll.bcrypt +except (OSError) as e: + if str_cls(e).find('The specified module could not be found') != -1: + raise LibraryNotFoundError('bcrypt.dll could not be found - Windows XP and Server 2003 are not supported') + raise + +BCRYPT_ALG_HANDLE = wintypes.HANDLE +BCRYPT_KEY_HANDLE = wintypes.HANDLE +NTSTATUS = wintypes.ULONG +PUCHAR = c_char_p +PBYTE = c_char_p + +try: + bcrypt.BCryptOpenAlgorithmProvider.argtypes = [ + POINTER(BCRYPT_ALG_HANDLE), + LPCWSTR, + LPCWSTR, + DWORD + ] + bcrypt.BCryptOpenAlgorithmProvider.restype = NTSTATUS + + bcrypt.BCryptCloseAlgorithmProvider.argtypes = [ + BCRYPT_ALG_HANDLE, + ULONG + ] + bcrypt.BCryptCloseAlgorithmProvider.restype = NTSTATUS + + bcrypt.BCryptImportKeyPair.argtypes = [ + BCRYPT_ALG_HANDLE, + BCRYPT_KEY_HANDLE, + LPCWSTR, + POINTER(BCRYPT_KEY_HANDLE), + PUCHAR, + ULONG, + ULONG + ] + bcrypt.BCryptImportKeyPair.restype = NTSTATUS + + bcrypt.BCryptImportKey.argtypes = [ + BCRYPT_ALG_HANDLE, + BCRYPT_KEY_HANDLE, + LPCWSTR, + POINTER(BCRYPT_KEY_HANDLE), + PUCHAR, + ULONG, + PUCHAR, + ULONG, + ULONG + ] + bcrypt.BCryptImportKey.restype = NTSTATUS + + bcrypt.BCryptDestroyKey.argtypes = [ + BCRYPT_KEY_HANDLE + ] + bcrypt.BCryptDestroyKey.restype = NTSTATUS + + bcrypt.BCryptVerifySignature.argtypes = [ + BCRYPT_KEY_HANDLE, + c_void_p, + PUCHAR, + ULONG, + PUCHAR, + ULONG, + ULONG + ] + bcrypt.BCryptVerifySignature.restype = NTSTATUS + + bcrypt.BCryptSignHash.argtypes = [ + BCRYPT_KEY_HANDLE, + c_void_p, + PBYTE, + DWORD, + PBYTE, + DWORD, + POINTER(DWORD), + ULONG + ] + bcrypt.BCryptSignHash.restype = NTSTATUS + + bcrypt.BCryptSetProperty.argtypes = [ + BCRYPT_KEY_HANDLE, + LPCWSTR, + c_void_p, + ULONG, + ULONG + ] + bcrypt.BCryptSetProperty.restype = NTSTATUS + + bcrypt.BCryptEncrypt.argtypes = [ + BCRYPT_KEY_HANDLE, + PUCHAR, + ULONG, + c_void_p, + PUCHAR, + ULONG, + PUCHAR, + ULONG, + POINTER(ULONG), + ULONG + ] + bcrypt.BCryptEncrypt.restype = NTSTATUS + + bcrypt.BCryptDecrypt.argtypes = [ + BCRYPT_KEY_HANDLE, + PUCHAR, + ULONG, + c_void_p, + PUCHAR, + ULONG, + PUCHAR, + ULONG, + POINTER(ULONG), + ULONG + ] + bcrypt.BCryptDecrypt.restype = NTSTATUS + + bcrypt.BCryptDeriveKeyPBKDF2.argtypes = [ + BCRYPT_ALG_HANDLE, + PUCHAR, + ULONG, + PUCHAR, + ULONG, + c_ulonglong, + PUCHAR, + ULONG, + ULONG + ] + bcrypt.BCryptDeriveKeyPBKDF2.restype = NTSTATUS + + bcrypt.BCryptGenRandom.argtypes = [ + BCRYPT_ALG_HANDLE, + PUCHAR, + ULONG, + ULONG + ] + bcrypt.BCryptGenRandom.restype = NTSTATUS + + bcrypt.BCryptGenerateKeyPair.argtypes = [ + BCRYPT_ALG_HANDLE, + POINTER(BCRYPT_KEY_HANDLE), + ULONG, + ULONG + ] + bcrypt.BCryptGenerateKeyPair.restype = NTSTATUS + + bcrypt.BCryptFinalizeKeyPair.argtypes = [ + BCRYPT_KEY_HANDLE, + ULONG + ] + bcrypt.BCryptFinalizeKeyPair.restype = NTSTATUS + + bcrypt.BCryptExportKey.argtypes = [ + BCRYPT_KEY_HANDLE, + BCRYPT_KEY_HANDLE, + LPCWSTR, + PUCHAR, + ULONG, + POINTER(ULONG), + ULONG + ] + bcrypt.BCryptExportKey.restype = NTSTATUS + +except (AttributeError): + raise FFIEngineError('Error initializing ctypes') + + +class BCRYPT_RSAKEY_BLOB(Structure): # noqa + _fields_ = [ + ('Magic', ULONG), + ('BitLength', ULONG), + ('cbPublicExp', ULONG), + ('cbModulus', ULONG), + ('cbPrime1', ULONG), + ('cbPrime2', ULONG), + ] + + +class BCRYPT_DSA_KEY_BLOB(Structure): # noqa + _fields_ = [ + ('dwMagic', ULONG), + ('cbKey', ULONG), + ('Count', c_byte * 4), + ('Seed', c_byte * 20), + ('q', c_byte * 20), + ] + + +class BCRYPT_DSA_KEY_BLOB_V2(Structure): # noqa + _fields_ = [ + ('dwMagic', ULONG), + ('cbKey', ULONG), + ('hashAlgorithm', wintypes.INT), + ('standardVersion', wintypes.INT), + ('cbSeedLength', ULONG), + ('cbGroupSize', ULONG), + ('Count', c_byte * 4), + ] + + +class BCRYPT_ECCKEY_BLOB(Structure): # noqa + _fields_ = [ + ('dwMagic', ULONG), + ('cbKey', ULONG), + ] + + +class BCRYPT_PKCS1_PADDING_INFO(Structure): # noqa + _fields_ = [ + ('pszAlgId', LPCWSTR), + ] + + +class BCRYPT_PSS_PADDING_INFO(Structure): # noqa + _fields_ = [ + ('pszAlgId', LPCWSTR), + ('cbSalt', ULONG), + ] + + +class BCRYPT_OAEP_PADDING_INFO(Structure): # noqa + _fields_ = [ + ('pszAlgId', LPCWSTR), + ('pbLabel', PUCHAR), + ('cbLabel', ULONG), + ] + + +class BCRYPT_KEY_DATA_BLOB_HEADER(Structure): # noqa + _fields_ = [ + ('dwMagic', ULONG), + ('dwVersion', ULONG), + ('cbKeyData', ULONG), + ] + + +setattr(bcrypt, 'BCRYPT_ALG_HANDLE', BCRYPT_ALG_HANDLE) +setattr(bcrypt, 'BCRYPT_KEY_HANDLE', BCRYPT_KEY_HANDLE) + +setattr(bcrypt, 'BCRYPT_RSAKEY_BLOB', BCRYPT_RSAKEY_BLOB) +setattr(bcrypt, 'BCRYPT_DSA_KEY_BLOB', BCRYPT_DSA_KEY_BLOB) +setattr(bcrypt, 'BCRYPT_DSA_KEY_BLOB_V2', BCRYPT_DSA_KEY_BLOB_V2) +setattr(bcrypt, 'BCRYPT_ECCKEY_BLOB', BCRYPT_ECCKEY_BLOB) +setattr(bcrypt, 'BCRYPT_PKCS1_PADDING_INFO', BCRYPT_PKCS1_PADDING_INFO) +setattr(bcrypt, 'BCRYPT_PSS_PADDING_INFO', BCRYPT_PSS_PADDING_INFO) +setattr(bcrypt, 'BCRYPT_OAEP_PADDING_INFO', BCRYPT_OAEP_PADDING_INFO) +setattr(bcrypt, 'BCRYPT_KEY_DATA_BLOB_HEADER', BCRYPT_KEY_DATA_BLOB_HEADER) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_win/_crypt32.py b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_win/_crypt32.py new file mode 100644 index 00000000..bc6e8559 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_win/_crypt32.py @@ -0,0 +1,73 @@ +# coding: utf-8 +from __future__ import unicode_literals, division, absolute_import, print_function + +from .. import ffi +from ._decode import _try_decode +from .._ffi import buffer_from_bytes +from .._types import str_cls + +if ffi() == 'cffi': + from ._crypt32_cffi import crypt32, get_error +else: + from ._crypt32_ctypes import crypt32, get_error + + +__all__ = [ + 'crypt32', + 'Crypt32Const', + 'handle_error', +] + + +def handle_error(result): + """ + Extracts the last Windows error message into a python unicode string + + :param result: + A function result, 0 or None indicates failure + + :return: + A unicode string error message + """ + + if result: + return + + _, error_string = get_error() + + if not isinstance(error_string, str_cls): + error_string = _try_decode(error_string) + + raise OSError(error_string) + + +class Crypt32Const(): + X509_ASN_ENCODING = 1 + + ERROR_INSUFFICIENT_BUFFER = 122 + CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG = 0x4 + CRYPT_E_NOT_FOUND = -2146885628 + + CERT_STORE_PROV_MEMORY = b'Memory' + CERT_STORE_CREATE_NEW_FLAG = 0x00002000 + CERT_STORE_ADD_USE_EXISTING = 2 + USAGE_MATCH_TYPE_OR = 1 + CERT_CHAIN_POLICY_SSL = 4 + AUTHTYPE_SERVER = 2 + CERT_CHAIN_POLICY_ALLOW_UNKNOWN_CA_FLAG = 0x00000010 + CERT_CHAIN_POLICY_IGNORE_ALL_REV_UNKNOWN_FLAGS = 0x00000F00 + CERT_CHAIN_CACHE_END_CERT = 1 + CERT_CHAIN_REVOCATION_CHECK_CACHE_ONLY = 0x80000000 + + TRUST_E_CERT_SIGNATURE = 0x80096004 + + CERT_E_EXPIRED = 0x800B0101 + CERT_E_ROLE = 0x800B0103 + CERT_E_PURPOSE = 0x800B0106 + CERT_E_UNTRUSTEDROOT = 0x800B0109 + CERT_E_CN_NO_MATCH = 0x800B010F + CRYPT_E_REVOKED = 0x80092010 + + PKIX_KP_SERVER_AUTH = buffer_from_bytes(b"1.3.6.1.5.5.7.3.1\x00") + SERVER_GATED_CRYPTO = buffer_from_bytes(b"1.3.6.1.4.1.311.10.3.3\x00") + SGC_NETSCAPE = buffer_from_bytes(b"2.16.840.1.113730.4.1\x00") diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_win/_crypt32_cffi.py b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_win/_crypt32_cffi.py new file mode 100644 index 00000000..3952682a --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_win/_crypt32_cffi.py @@ -0,0 +1,188 @@ +# coding: utf-8 +from __future__ import unicode_literals, division, absolute_import, print_function + +import sys + +from .._ffi import register_ffi +from .._types import str_cls +from ..errors import LibraryNotFoundError + +import cffi + + +__all__ = [ + 'crypt32', + 'get_error', +] + + +ffi = cffi.FFI() +if cffi.__version_info__ >= (0, 9): + ffi.set_unicode(True) +if sys.maxsize > 2 ** 32: + ffi.cdef("typedef uint64_t ULONG_PTR;") +else: + ffi.cdef("typedef unsigned long ULONG_PTR;") +ffi.cdef(""" + typedef HANDLE HCERTSTORE; + typedef unsigned char *PBYTE; + + + typedef struct _CRYPTOAPI_BLOB { + DWORD cbData; + PBYTE pbData; + } CRYPTOAPI_BLOB; + typedef CRYPTOAPI_BLOB CRYPT_INTEGER_BLOB; + typedef CRYPTOAPI_BLOB CERT_NAME_BLOB; + typedef CRYPTOAPI_BLOB CRYPT_BIT_BLOB; + typedef CRYPTOAPI_BLOB CRYPT_OBJID_BLOB; + + typedef struct _CRYPT_ALGORITHM_IDENTIFIER { + LPSTR pszObjId; + CRYPT_OBJID_BLOB Parameters; + } CRYPT_ALGORITHM_IDENTIFIER; + + typedef struct _FILETIME { + DWORD dwLowDateTime; + DWORD dwHighDateTime; + } FILETIME; + + typedef struct _CERT_PUBLIC_KEY_INFO { + CRYPT_ALGORITHM_IDENTIFIER Algorithm; + CRYPT_BIT_BLOB PublicKey; + } CERT_PUBLIC_KEY_INFO; + + typedef struct _CERT_EXTENSION { + LPSTR pszObjId; + BOOL fCritical; + CRYPT_OBJID_BLOB Value; + } CERT_EXTENSION, *PCERT_EXTENSION; + + typedef struct _CERT_INFO { + DWORD dwVersion; + CRYPT_INTEGER_BLOB SerialNumber; + CRYPT_ALGORITHM_IDENTIFIER SignatureAlgorithm; + CERT_NAME_BLOB Issuer; + FILETIME NotBefore; + FILETIME NotAfter; + CERT_NAME_BLOB Subject; + CERT_PUBLIC_KEY_INFO SubjectPublicKeyInfo; + CRYPT_BIT_BLOB IssuerUniqueId; + CRYPT_BIT_BLOB SubjectUniqueId; + DWORD cExtension; + PCERT_EXTENSION *rgExtension; + } CERT_INFO, *PCERT_INFO; + + typedef struct _CERT_CONTEXT { + DWORD dwCertEncodingType; + PBYTE pbCertEncoded; + DWORD cbCertEncoded; + PCERT_INFO pCertInfo; + HCERTSTORE hCertStore; + } CERT_CONTEXT, *PCERT_CONTEXT; + + typedef struct _CERT_TRUST_STATUS { + DWORD dwErrorStatus; + DWORD dwInfoStatus; + } CERT_TRUST_STATUS, *PCERT_TRUST_STATUS; + + typedef struct _CERT_ENHKEY_USAGE { + DWORD cUsageIdentifier; + LPSTR *rgpszUsageIdentifier; + } CERT_ENHKEY_USAGE, *PCERT_ENHKEY_USAGE; + + typedef struct _CERT_CHAIN_ELEMENT { + DWORD cbSize; + PCERT_CONTEXT pCertContext; + CERT_TRUST_STATUS TrustStatus; + void *pRevocationInfo; + PCERT_ENHKEY_USAGE pIssuanceUsage; + PCERT_ENHKEY_USAGE pApplicationUsage; + LPCWSTR pwszExtendedErrorInfo; + } CERT_CHAIN_ELEMENT, *PCERT_CHAIN_ELEMENT; + + typedef struct _CERT_SIMPLE_CHAIN { + DWORD cbSize; + CERT_TRUST_STATUS TrustStatus; + DWORD cElement; + PCERT_CHAIN_ELEMENT *rgpElement; + void *pTrustListInfo; + BOOL fHasRevocationFreshnessTime; + DWORD dwRevocationFreshnessTime; + } CERT_SIMPLE_CHAIN, *PCERT_SIMPLE_CHAIN; + + typedef struct _CERT_CHAIN_CONTEXT { + DWORD cbSize; + CERT_TRUST_STATUS TrustStatus; + DWORD cChain; + PCERT_SIMPLE_CHAIN *rgpChain; + DWORD cLowerQualityChainContext; + void *rgpLowerQualityChainContext; + BOOL fHasRevocationFreshnessTime; + DWORD dwRevocationFreshnessTime; + } CERT_CHAIN_CONTEXT, *PCERT_CHAIN_CONTEXT; + + typedef struct _CERT_USAGE_MATCH { + DWORD dwType; + CERT_ENHKEY_USAGE Usage; + } CERT_USAGE_MATCH; + + typedef struct _CERT_CHAIN_PARA { + DWORD cbSize; + CERT_USAGE_MATCH RequestedUsage; + } CERT_CHAIN_PARA; + + typedef struct _CERT_CHAIN_POLICY_PARA { + DWORD cbSize; + DWORD dwFlags; + void *pvExtraPolicyPara; + } CERT_CHAIN_POLICY_PARA; + + typedef struct _HTTPSPolicyCallbackData { + DWORD cbSize; + DWORD dwAuthType; + DWORD fdwChecks; + WCHAR *pwszServerName; + } SSL_EXTRA_CERT_CHAIN_POLICY_PARA; + + typedef struct _CERT_CHAIN_POLICY_STATUS { + DWORD cbSize; + DWORD dwError; + LONG lChainIndex; + LONG lElementIndex; + void *pvExtraPolicyStatus; + } CERT_CHAIN_POLICY_STATUS; + + typedef HANDLE HCERTCHAINENGINE; + typedef HANDLE HCRYPTPROV; + + HCERTSTORE CertOpenStore(LPCSTR lpszStoreProvider, DWORD dwMsgAndCertEncodingType, HCRYPTPROV hCryptProv, + DWORD dwFlags, void *pvPara); + BOOL CertAddEncodedCertificateToStore(HCERTSTORE hCertStore, DWORD dwCertEncodingType, BYTE *pbCertEncoded, + DWORD cbCertEncoded, DWORD dwAddDisposition, PCERT_CONTEXT *ppCertContext); + BOOL CertGetCertificateChain(HCERTCHAINENGINE hChainEngine, CERT_CONTEXT *pCertContext, FILETIME *pTime, + HCERTSTORE hAdditionalStore, CERT_CHAIN_PARA *pChainPara, DWORD dwFlags, void *pvReserved, + PCERT_CHAIN_CONTEXT *ppChainContext); + BOOL CertVerifyCertificateChainPolicy(ULONG_PTR pszPolicyOID, PCERT_CHAIN_CONTEXT pChainContext, + CERT_CHAIN_POLICY_PARA *pPolicyPara, CERT_CHAIN_POLICY_STATUS *pPolicyStatus); + void CertFreeCertificateChain(PCERT_CHAIN_CONTEXT pChainContext); + + HCERTSTORE CertOpenSystemStoreW(HANDLE hprov, LPCWSTR szSubsystemProtocol); + PCERT_CONTEXT CertEnumCertificatesInStore(HCERTSTORE hCertStore, CERT_CONTEXT *pPrevCertContext); + BOOL CertCloseStore(HCERTSTORE hCertStore, DWORD dwFlags); + BOOL CertGetEnhancedKeyUsage(CERT_CONTEXT *pCertContext, DWORD dwFlags, CERT_ENHKEY_USAGE *pUsage, DWORD *pcbUsage); +""") + + +try: + crypt32 = ffi.dlopen('crypt32.dll') + register_ffi(crypt32, ffi) + +except (OSError) as e: + if str_cls(e).find('cannot load library') != -1: + raise LibraryNotFoundError('crypt32.dll could not be found') + raise + + +def get_error(): + return ffi.getwinerror() diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_win/_crypt32_ctypes.py b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_win/_crypt32_ctypes.py new file mode 100644 index 00000000..b9818569 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_win/_crypt32_ctypes.py @@ -0,0 +1,276 @@ +# coding: utf-8 +from __future__ import unicode_literals, division, absolute_import, print_function + +import sys + +import ctypes +from ctypes import windll, wintypes, POINTER, Structure, c_void_p, c_char_p +from ctypes.wintypes import DWORD + +from .._ffi import FFIEngineError +from .._types import str_cls +from ..errors import LibraryNotFoundError +from ._kernel32 import kernel32 + + +__all__ = [ + 'crypt32', + 'get_error', +] + + +try: + crypt32 = windll.crypt32 +except (OSError) as e: + if str_cls(e).find('The specified module could not be found') != -1: + raise LibraryNotFoundError('crypt32.dll could not be found') + raise + +HCERTSTORE = wintypes.HANDLE +HCERTCHAINENGINE = wintypes.HANDLE +HCRYPTPROV = wintypes.HANDLE +HCRYPTKEY = wintypes.HANDLE +PBYTE = c_char_p +if sys.maxsize > 2 ** 32: + ULONG_PTR = ctypes.c_uint64 +else: + ULONG_PTR = ctypes.c_ulong + +try: + class CRYPTOAPI_BLOB(Structure): # noqa + _fields_ = [ + ("cbData", DWORD), + ("pbData", c_void_p), + ] + CRYPT_INTEGER_BLOB = CRYPTOAPI_BLOB + CERT_NAME_BLOB = CRYPTOAPI_BLOB + CRYPT_BIT_BLOB = CRYPTOAPI_BLOB + CRYPT_OBJID_BLOB = CRYPTOAPI_BLOB + + class CRYPT_ALGORITHM_IDENTIFIER(Structure): # noqa + _fields_ = [ + ("pszObjId", wintypes.LPSTR), + ("Parameters", CRYPT_OBJID_BLOB), + ] + + class CERT_PUBLIC_KEY_INFO(Structure): # noqa + _fields_ = [ + ("Algorithm", CRYPT_ALGORITHM_IDENTIFIER), + ("PublicKey", CRYPT_BIT_BLOB), + ] + + class CERT_EXTENSION(Structure): # noqa + _fields_ = [ + ("pszObjId", wintypes.LPSTR), + ("fCritical", wintypes.BOOL), + ("Value", CRYPT_OBJID_BLOB), + ] + PCERT_EXTENSION = POINTER(CERT_EXTENSION) + + class CERT_INFO(Structure): # noqa + _fields_ = [ + ("dwVersion", DWORD), + ("SerialNumber", CRYPT_INTEGER_BLOB), + ("SignatureAlgorithm", CRYPT_ALGORITHM_IDENTIFIER), + ("Issuer", CERT_NAME_BLOB), + ("NotBefore", kernel32.FILETIME), + ("NotAfter", kernel32.FILETIME), + ("Subject", CERT_NAME_BLOB), + ("SubjectPublicKeyInfo", CERT_PUBLIC_KEY_INFO), + ("IssuerUniqueId", CRYPT_BIT_BLOB), + ("SubjectUniqueId", CRYPT_BIT_BLOB), + ("cExtension", DWORD), + ("rgExtension", POINTER(PCERT_EXTENSION)), + ] + PCERT_INFO = POINTER(CERT_INFO) + + class CERT_CONTEXT(Structure): # noqa + _fields_ = [ + ("dwCertEncodingType", DWORD), + ("pbCertEncoded", c_void_p), + ("cbCertEncoded", DWORD), + ("pCertInfo", PCERT_INFO), + ("hCertStore", HCERTSTORE) + ] + + PCERT_CONTEXT = POINTER(CERT_CONTEXT) + + class CERT_ENHKEY_USAGE(Structure): # noqa + _fields_ = [ + ('cUsageIdentifier', DWORD), + ('rgpszUsageIdentifier', POINTER(POINTER(wintypes.BYTE))), + ] + + PCERT_ENHKEY_USAGE = POINTER(CERT_ENHKEY_USAGE) + + class CERT_TRUST_STATUS(Structure): # noqa + _fields_ = [ + ('dwErrorStatus', DWORD), + ('dwInfoStatus', DWORD), + ] + + class CERT_CHAIN_ELEMENT(Structure): # noqa + _fields_ = [ + ('cbSize', DWORD), + ('pCertContext', PCERT_CONTEXT), + ('TrustStatus', CERT_TRUST_STATUS), + ('pRevocationInfo', c_void_p), + ('pIssuanceUsage', PCERT_ENHKEY_USAGE), + ('pApplicationUsage', PCERT_ENHKEY_USAGE), + ('pwszExtendedErrorInfo', wintypes.LPCWSTR), + ] + + PCERT_CHAIN_ELEMENT = POINTER(CERT_CHAIN_ELEMENT) + + class CERT_SIMPLE_CHAIN(Structure): # noqa + _fields_ = [ + ('cbSize', DWORD), + ('TrustStatus', CERT_TRUST_STATUS), + ('cElement', DWORD), + ('rgpElement', POINTER(PCERT_CHAIN_ELEMENT)), + ('pTrustListInfo', c_void_p), + ('fHasRevocationFreshnessTime', wintypes.BOOL), + ('dwRevocationFreshnessTime', DWORD), + ] + + PCERT_SIMPLE_CHAIN = POINTER(CERT_SIMPLE_CHAIN) + + class CERT_CHAIN_CONTEXT(Structure): # noqa + _fields_ = [ + ('cbSize', DWORD), + ('TrustStatus', CERT_TRUST_STATUS), + ('cChain', DWORD), + ('rgpChain', POINTER(PCERT_SIMPLE_CHAIN)), + ('cLowerQualityChainContext', DWORD), + ('rgpLowerQualityChainContext', c_void_p), + ('fHasRevocationFreshnessTime', wintypes.BOOL), + ('dwRevocationFreshnessTime', DWORD), + ] + + PCERT_CHAIN_CONTEXT = POINTER(CERT_CHAIN_CONTEXT) + + class CERT_USAGE_MATCH(Structure): # noqa + _fields_ = [ + ('dwType', DWORD), + ('Usage', CERT_ENHKEY_USAGE), + ] + + class CERT_CHAIN_PARA(Structure): # noqa + _fields_ = [ + ('cbSize', DWORD), + ('RequestedUsage', CERT_USAGE_MATCH), + ] + + class CERT_CHAIN_POLICY_PARA(Structure): # noqa + _fields_ = [ + ('cbSize', DWORD), + ('dwFlags', DWORD), + ('pvExtraPolicyPara', c_void_p), + ] + + class SSL_EXTRA_CERT_CHAIN_POLICY_PARA(Structure): # noqa + _fields_ = [ + ('cbSize', DWORD), + ('dwAuthType', DWORD), + ('fdwChecks', DWORD), + ('pwszServerName', wintypes.LPCWSTR), + ] + + class CERT_CHAIN_POLICY_STATUS(Structure): # noqa + _fields_ = [ + ('cbSize', DWORD), + ('dwError', DWORD), + ('lChainIndex', wintypes.LONG), + ('lElementIndex', wintypes.LONG), + ('pvExtraPolicyStatus', c_void_p), + ] + + crypt32.CertOpenStore.argtypes = [ + wintypes.LPCSTR, + DWORD, + HCRYPTPROV, + DWORD, + c_void_p + ] + crypt32.CertOpenStore.restype = HCERTSTORE + + crypt32.CertAddEncodedCertificateToStore.argtypes = [ + HCERTSTORE, + DWORD, + PBYTE, + DWORD, + DWORD, + POINTER(PCERT_CONTEXT) + ] + crypt32.CertAddEncodedCertificateToStore.restype = wintypes.BOOL + + crypt32.CertGetCertificateChain.argtypes = [ + HCERTCHAINENGINE, + PCERT_CONTEXT, + POINTER(kernel32.FILETIME), + HCERTSTORE, + POINTER(CERT_CHAIN_PARA), + DWORD, + c_void_p, + POINTER(PCERT_CHAIN_CONTEXT) + ] + crypt32.CertGetCertificateChain.restype = wintypes.BOOL + + crypt32.CertVerifyCertificateChainPolicy.argtypes = [ + ULONG_PTR, + PCERT_CHAIN_CONTEXT, + POINTER(CERT_CHAIN_POLICY_PARA), + POINTER(CERT_CHAIN_POLICY_STATUS) + ] + crypt32.CertVerifyCertificateChainPolicy.restype = wintypes.BOOL + + crypt32.CertFreeCertificateChain.argtypes = [ + PCERT_CHAIN_CONTEXT + ] + crypt32.CertFreeCertificateChain.restype = None + + crypt32.CertOpenSystemStoreW.argtypes = [ + wintypes.HANDLE, + wintypes.LPCWSTR + ] + crypt32.CertOpenSystemStoreW.restype = HCERTSTORE + + crypt32.CertEnumCertificatesInStore.argtypes = [ + HCERTSTORE, + PCERT_CONTEXT + ] + crypt32.CertEnumCertificatesInStore.restype = PCERT_CONTEXT + + crypt32.CertCloseStore.argtypes = [ + HCERTSTORE, + DWORD + ] + crypt32.CertCloseStore.restype = wintypes.BOOL + + crypt32.CertGetEnhancedKeyUsage.argtypes = [ + PCERT_CONTEXT, + DWORD, + c_void_p, + POINTER(DWORD) + ] + crypt32.CertGetEnhancedKeyUsage.restype = wintypes.BOOL + +except (AttributeError): + raise FFIEngineError('Error initializing ctypes') + + +setattr(crypt32, 'FILETIME', kernel32.FILETIME) +setattr(crypt32, 'CERT_ENHKEY_USAGE', CERT_ENHKEY_USAGE) +setattr(crypt32, 'CERT_CONTEXT', CERT_CONTEXT) +setattr(crypt32, 'PCERT_CONTEXT', PCERT_CONTEXT) +setattr(crypt32, 'CERT_USAGE_MATCH', CERT_USAGE_MATCH) +setattr(crypt32, 'CERT_CHAIN_PARA', CERT_CHAIN_PARA) +setattr(crypt32, 'CERT_CHAIN_POLICY_PARA', CERT_CHAIN_POLICY_PARA) +setattr(crypt32, 'SSL_EXTRA_CERT_CHAIN_POLICY_PARA', SSL_EXTRA_CERT_CHAIN_POLICY_PARA) +setattr(crypt32, 'CERT_CHAIN_POLICY_STATUS', CERT_CHAIN_POLICY_STATUS) +setattr(crypt32, 'PCERT_CHAIN_CONTEXT', PCERT_CHAIN_CONTEXT) + + +def get_error(): + error = ctypes.GetLastError() + return (error, ctypes.FormatError(error)) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_win/_decode.py b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_win/_decode.py new file mode 100644 index 00000000..0bf8901c --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_win/_decode.py @@ -0,0 +1,36 @@ +# coding: utf-8 +from __future__ import unicode_literals, division, absolute_import, print_function + +import locale + +from .._types import str_cls + + +_encoding = locale.getpreferredencoding() +_fallback_encodings = ['utf-8', 'cp1252'] + + +def _try_decode(byte_string): + """ + Tries decoding a byte string from the OS into a unicode string + + :param byte_string: + A byte string + + :return: + A unicode string + """ + + try: + return str_cls(byte_string, _encoding) + + # If the "correct" encoding did not work, try some defaults, and then just + # obliterate characters that we can't seen to decode properly + except (UnicodeDecodeError): + for encoding in _fallback_encodings: + try: + return str_cls(byte_string, encoding, errors='strict') + except (UnicodeDecodeError): + pass + + return str_cls(byte_string, errors='replace') diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_win/_kernel32.py b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_win/_kernel32.py new file mode 100644 index 00000000..94b560fd --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_win/_kernel32.py @@ -0,0 +1,39 @@ +# coding: utf-8 +from __future__ import unicode_literals, division, absolute_import, print_function + +from .. import ffi +from ._decode import _try_decode +from .._types import str_cls + +if ffi() == 'cffi': + from ._kernel32_cffi import kernel32, get_error +else: + from ._kernel32_ctypes import kernel32, get_error + + +__all__ = [ + 'handle_error', + 'kernel32', +] + + +def handle_error(result): + """ + Extracts the last Windows error message into a python unicode string + + :param result: + A function result, 0 or None indicates failure + + :return: + A unicode string error message + """ + + if result: + return + + _, error_string = get_error() + + if not isinstance(error_string, str_cls): + error_string = _try_decode(error_string) + + raise OSError(error_string) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_win/_kernel32_cffi.py b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_win/_kernel32_cffi.py new file mode 100644 index 00000000..1ddbae59 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_win/_kernel32_cffi.py @@ -0,0 +1,44 @@ +# coding: utf-8 +from __future__ import unicode_literals, division, absolute_import, print_function + +from .._ffi import register_ffi +from .._types import str_cls +from ..errors import LibraryNotFoundError + +import cffi + + +__all__ = [ + 'get_error', + 'kernel32', +] + + +ffi = cffi.FFI() +if cffi.__version_info__ >= (0, 9): + ffi.set_unicode(True) +ffi.cdef(""" + typedef long long LARGE_INTEGER; + BOOL QueryPerformanceCounter(LARGE_INTEGER *lpPerformanceCount); + + typedef struct _FILETIME { + DWORD dwLowDateTime; + DWORD dwHighDateTime; + } FILETIME; + + void GetSystemTimeAsFileTime(FILETIME *lpSystemTimeAsFileTime); +""") + + +try: + kernel32 = ffi.dlopen('kernel32.dll') + register_ffi(kernel32, ffi) + +except (OSError) as e: + if str_cls(e).find('cannot load library') != -1: + raise LibraryNotFoundError('kernel32.dll could not be found') + raise + + +def get_error(): + return ffi.getwinerror() diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_win/_kernel32_ctypes.py b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_win/_kernel32_ctypes.py new file mode 100644 index 00000000..67c965c4 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_win/_kernel32_ctypes.py @@ -0,0 +1,50 @@ +# coding: utf-8 +from __future__ import unicode_literals, division, absolute_import, print_function + +import ctypes +from ctypes import windll, wintypes, POINTER, c_longlong, Structure + +from .._ffi import FFIEngineError +from .._types import str_cls +from ..errors import LibraryNotFoundError + + +__all__ = [ + 'get_error', + 'kernel32', +] + + +try: + kernel32 = windll.kernel32 +except (OSError) as e: + if str_cls(e).find('The specified module could not be found') != -1: + raise LibraryNotFoundError('kernel32.dll could not be found') + raise + +LARGE_INTEGER = c_longlong + +try: + kernel32.QueryPerformanceCounter.argtypes = [POINTER(LARGE_INTEGER)] + kernel32.QueryPerformanceCounter.restype = wintypes.BOOL + + class FILETIME(Structure): + _fields_ = [ + ("dwLowDateTime", wintypes.DWORD), + ("dwHighDateTime", wintypes.DWORD), + ] + + kernel32.GetSystemTimeAsFileTime.argtypes = [POINTER(FILETIME)] + kernel32.GetSystemTimeAsFileTime.restype = None + +except (AttributeError): + raise FFIEngineError('Error initializing ctypes') + + +setattr(kernel32, 'LARGE_INTEGER', LARGE_INTEGER) +setattr(kernel32, 'FILETIME', FILETIME) + + +def get_error(): + error = ctypes.GetLastError() + return (error, ctypes.FormatError(error)) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_win/_secur32.py b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_win/_secur32.py new file mode 100644 index 00000000..c9560781 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_win/_secur32.py @@ -0,0 +1,145 @@ +# coding: utf-8 +from __future__ import unicode_literals, division, absolute_import, print_function + +from .. import ffi +from ._decode import _try_decode +from ..errors import TLSError +from .._types import str_cls + +if ffi() == 'cffi': + from ._secur32_cffi import secur32, get_error +else: + from ._secur32_ctypes import secur32, get_error + + +__all__ = [ + 'handle_error', + 'secur32', + 'Secur32Const', +] + + +def handle_error(result, exception_class=None): + """ + Extracts the last Windows error message into a python unicode string + + :param result: + A function result, 0 or None indicates failure + + :param exception_class: + The exception class to use for the exception if an error occurred + + :return: + A unicode string error message + """ + + if result == 0: + return + + if result == Secur32Const.SEC_E_OUT_OF_SEQUENCE: + raise TLSError('A packet was received out of order') + + if result == Secur32Const.SEC_E_MESSAGE_ALTERED: + raise TLSError('A packet was received altered') + + if result == Secur32Const.SEC_E_CONTEXT_EXPIRED: + raise TLSError('The TLS session expired') + + _, error_string = get_error() + + if not isinstance(error_string, str_cls): + error_string = _try_decode(error_string) + + if exception_class is None: + exception_class = OSError + + raise exception_class(('SECURITY_STATUS error 0x%0.2X: ' % result) + error_string) + + +class Secur32Const(): + SCHANNEL_CRED_VERSION = 4 + + SECPKG_CRED_OUTBOUND = 0x00000002 + UNISP_NAME = "Microsoft Unified Security Protocol Provider" + + SCH_CRED_MANUAL_CRED_VALIDATION = 0x00000008 + SCH_CRED_AUTO_CRED_VALIDATION = 0x00000020 + SCH_USE_STRONG_CRYPTO = 0x00400000 + SCH_CRED_NO_DEFAULT_CREDS = 0x00000010 + + SECBUFFER_VERSION = 0 + + SEC_E_OK = 0x00000000 + SEC_I_CONTINUE_NEEDED = 0x00090312 + SEC_I_CONTEXT_EXPIRED = 0x00090317 + SEC_I_RENEGOTIATE = 0x00090321 + SEC_E_INCOMPLETE_MESSAGE = 0x80090318 + SEC_E_INVALID_TOKEN = 0x80090308 + SEC_E_OUT_OF_SEQUENCE = 0x8009031 + SEC_E_MESSAGE_ALTERED = 0x8009030F + SEC_E_CONTEXT_EXPIRED = 0x80090317 + SEC_E_INVALID_PARAMETER = 0x8009035D + + SEC_E_WRONG_PRINCIPAL = 0x80090322 # Domain name mismatch + SEC_E_UNTRUSTED_ROOT = 0x80090325 + SEC_E_CERT_EXPIRED = 0x80090328 + SEC_E_ILLEGAL_MESSAGE = 0x80090326 # Handshake error + SEC_E_INTERNAL_ERROR = 0x80090304 # Occurs when DH params are too small + SEC_E_BUFFER_TOO_SMALL = 0x80090321 + SEC_I_INCOMPLETE_CREDENTIALS = 0x00090320 + + ISC_REQ_REPLAY_DETECT = 4 + ISC_REQ_SEQUENCE_DETECT = 8 + ISC_REQ_CONFIDENTIALITY = 16 + ISC_REQ_ALLOCATE_MEMORY = 256 + ISC_REQ_INTEGRITY = 65536 + ISC_REQ_STREAM = 0x00008000 + ISC_REQ_USE_SUPPLIED_CREDS = 0x00000080 + + ISC_RET_REPLAY_DETECT = 4 + ISC_RET_SEQUENCE_DETECT = 8 + ISC_RET_CONFIDENTIALITY = 16 + ISC_RET_ALLOCATED_MEMORY = 256 + ISC_RET_INTEGRITY = 65536 + ISC_RET_STREAM = 0x00008000 + + SECBUFFER_ALERT = 17 + SECBUFFER_STREAM_HEADER = 7 + SECBUFFER_STREAM_TRAILER = 6 + SECBUFFER_EXTRA = 5 + SECBUFFER_TOKEN = 2 + SECBUFFER_DATA = 1 + SECBUFFER_EMPTY = 0 + + SECPKG_ATTR_STREAM_SIZES = 0x04 + SECPKG_ATTR_CONNECTION_INFO = 0x5A + SECPKG_ATTR_REMOTE_CERT_CONTEXT = 0x53 + + SP_PROT_TLS1_2_CLIENT = 0x800 + SP_PROT_TLS1_1_CLIENT = 0x200 + SP_PROT_TLS1_CLIENT = 0x80 + SP_PROT_SSL3_CLIENT = 0x20 + SP_PROT_SSL2_CLIENT = 0x8 + + CALG_AES_256 = 0x00006610 + CALG_AES_128 = 0x0000660E + CALG_3DES = 0x00006603 + CALG_RC4 = 0x00006801 + CALG_RC2 = 0x00006602 + CALG_DES = 0x00006601 + + CALG_MD5 = 0x00008003 + CALG_SHA1 = 0x00008004 + CALG_SHA256 = 0x0000800C + CALG_SHA384 = 0x0000800D + CALG_SHA512 = 0x0000800E + + CALG_DH_SF = 0x0000AA01 + CALG_DH_EPHEM = 0x0000AA02 + CALG_ECDH = 0x0000AA05 + CALG_ECDHE = 0x0000AE06 + CALG_RSA_KEYX = 0x0000A400 + + CALG_RSA_SIGN = 0x00002400 + CALG_ECDSA = 0x00002203 + CALG_DSS_SIGN = 0x00002200 diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_win/_secur32_cffi.py b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_win/_secur32_cffi.py new file mode 100644 index 00000000..2d80e2b7 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_win/_secur32_cffi.py @@ -0,0 +1,129 @@ +# coding: utf-8 +from __future__ import unicode_literals, division, absolute_import, print_function + +import sys + +from .._ffi import register_ffi +from .._types import str_cls +from ..errors import LibraryNotFoundError + +import cffi + + +__all__ = [ + 'get_error', + 'secur32', +] + + +ffi = cffi.FFI() +if cffi.__version_info__ >= (0, 9): + ffi.set_unicode(True) +if sys.maxsize > 2 ** 32: + ffi.cdef("typedef uint64_t ULONG_PTR;") +else: + ffi.cdef("typedef unsigned long ULONG_PTR;") +ffi.cdef(""" + typedef HANDLE HCERTSTORE; + typedef unsigned int ALG_ID; + typedef WCHAR SEC_WCHAR; + typedef unsigned long SECURITY_STATUS; + typedef void *LUID; + typedef void *SEC_GET_KEY_FN; + + typedef struct _SecHandle { + ULONG_PTR dwLower; + ULONG_PTR dwUpper; + } SecHandle; + typedef SecHandle CredHandle; + typedef SecHandle CtxtHandle; + + typedef struct _SCHANNEL_CRED { + DWORD dwVersion; + DWORD cCreds; + void *paCred; + HCERTSTORE hRootStore; + DWORD cMappers; + void **aphMappers; + DWORD cSupportedAlgs; + ALG_ID *palgSupportedAlgs; + DWORD grbitEnabledProtocols; + DWORD dwMinimumCipherStrength; + DWORD dwMaximumCipherStrength; + DWORD dwSessionLifespan; + DWORD dwFlags; + DWORD dwCredFormat; + } SCHANNEL_CRED; + + typedef struct _TimeStamp { + DWORD dwLowDateTime; + DWORD dwHighDateTime; + } TimeStamp; + + typedef struct _SecBuffer { + ULONG cbBuffer; + ULONG BufferType; + BYTE *pvBuffer; + } SecBuffer; + + typedef struct _SecBufferDesc { + ULONG ulVersion; + ULONG cBuffers; + SecBuffer *pBuffers; + } SecBufferDesc; + + typedef struct _SecPkgContext_StreamSizes { + ULONG cbHeader; + ULONG cbTrailer; + ULONG cbMaximumMessage; + ULONG cBuffers; + ULONG cbBlockSize; + } SecPkgContext_StreamSizes; + + typedef struct _CERT_CONTEXT { + DWORD dwCertEncodingType; + BYTE *pbCertEncoded; + DWORD cbCertEncoded; + void *pCertInfo; + HCERTSTORE hCertStore; + } CERT_CONTEXT; + + typedef struct _SecPkgContext_ConnectionInfo { + DWORD dwProtocol; + ALG_ID aiCipher; + DWORD dwCipherStrength; + ALG_ID aiHash; + DWORD dwHashStrength; + ALG_ID aiExch; + DWORD dwExchStrength; + } SecPkgContext_ConnectionInfo; + + SECURITY_STATUS AcquireCredentialsHandleW(SEC_WCHAR *pszPrincipal, SEC_WCHAR *pszPackage, ULONG fCredentialUse, + LUID *pvLogonID, void *pAuthData, SEC_GET_KEY_FN pGetKeyFn, void *pvGetKeyArgument, + CredHandle *phCredential, TimeStamp *ptsExpiry); + SECURITY_STATUS FreeCredentialsHandle(CredHandle *phCredential); + SECURITY_STATUS InitializeSecurityContextW(CredHandle *phCredential, CtxtHandle *phContext, + SEC_WCHAR *pszTargetName, ULONG fContextReq, ULONG Reserved1, ULONG TargetDataRep, + SecBufferDesc *pInput, ULONG Reserved2, CtxtHandle *phNewContext, SecBufferDesc *pOutput, + ULONG *pfContextAttr, TimeStamp *ptsExpiry); + SECURITY_STATUS FreeContextBuffer(void *pvContextBuffer); + SECURITY_STATUS ApplyControlToken(CtxtHandle *phContext, SecBufferDesc *pInput); + SECURITY_STATUS DeleteSecurityContext(CtxtHandle *phContext); + SECURITY_STATUS QueryContextAttributesW(CtxtHandle *phContext, ULONG ulAttribute, void *pBuffer); + SECURITY_STATUS EncryptMessage(CtxtHandle *phContext, ULONG fQOP, SecBufferDesc *pMessage, ULONG MessageSeqNo); + SECURITY_STATUS DecryptMessage(CtxtHandle *phContext, SecBufferDesc *pMessage, ULONG MessageSeqNo, ULONG *pfQOP); +""") + + +try: + secur32 = ffi.dlopen('secur32.dll') + register_ffi(secur32, ffi) + +except (OSError) as e: + if str_cls(e).find('cannot load library') != -1: + raise LibraryNotFoundError('secur32.dll could not be found') + raise + + +def get_error(): + return ffi.getwinerror() diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_win/_secur32_ctypes.py b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_win/_secur32_ctypes.py new file mode 100644 index 00000000..fb3415d0 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_win/_secur32_ctypes.py @@ -0,0 +1,198 @@ +# coding: utf-8 +from __future__ import unicode_literals, division, absolute_import, print_function + +import sys + +import ctypes +from ctypes import windll, wintypes, POINTER, c_void_p, c_uint, Structure +from ctypes.wintypes import DWORD, ULONG + +from .._ffi import FFIEngineError +from .._types import str_cls +from ..errors import LibraryNotFoundError + + +__all__ = [ + 'get_error', + 'secur32', +] + + +try: + secur32 = windll.secur32 +except (OSError) as e: + if str_cls(e).find('The specified module could not be found') != -1: + raise LibraryNotFoundError('secur32.dll could not be found') + raise + +HCERTSTORE = wintypes.HANDLE +ALG_ID = c_uint +if sys.maxsize > 2 ** 32: + ULONG_PTR = ctypes.c_uint64 +else: + ULONG_PTR = ctypes.c_ulong +SEC_GET_KEY_FN = c_void_p +LUID = c_void_p +SECURITY_STATUS = ctypes.c_ulong +SEC_WCHAR = wintypes.WCHAR + +try: + class SecHandle(Structure): + _fields_ = [ + ('dwLower', ULONG_PTR), + ('dwUpper', ULONG_PTR), + ] + + CredHandle = SecHandle + CtxtHandle = SecHandle + + class SCHANNEL_CRED(Structure): # noqa + _fields_ = [ + ('dwVersion', DWORD), + ('cCreds', DWORD), + ('paCred', c_void_p), + ('hRootStore', HCERTSTORE), + ('cMappers', DWORD), + ('aphMappers', POINTER(c_void_p)), + ('cSupportedAlgs', DWORD), + ('palgSupportedAlgs', POINTER(ALG_ID)), + ('grbitEnabledProtocols', DWORD), + ('dwMinimumCipherStrength', DWORD), + ('dwMaximumCipherStrength', DWORD), + ('dwSessionLifespan', DWORD), + ('dwFlags', DWORD), + ('dwCredFormat', DWORD), + ] + + class TimeStamp(Structure): + _fields_ = [ + ('dwLowDateTime', DWORD), + ('dwHighDateTime', DWORD), + ] + + class SecBuffer(Structure): + _fields_ = [ + ('cbBuffer', ULONG), + ('BufferType', ULONG), + ('pvBuffer', POINTER(ctypes.c_byte)), + ] + + PSecBuffer = POINTER(SecBuffer) + + class SecBufferDesc(Structure): + _fields_ = [ + ('ulVersion', ULONG), + ('cBuffers', ULONG), + ('pBuffers', PSecBuffer), + ] + + class SecPkgContext_StreamSizes(Structure): # noqa + _fields_ = [ + ('cbHeader', ULONG), + ('cbTrailer', ULONG), + ('cbMaximumMessage', ULONG), + ('cBuffers', ULONG), + ('cbBlockSize', ULONG), + ] + + class SecPkgContext_ConnectionInfo(Structure): # noqa + _fields_ = [ + ('dwProtocol', DWORD), + ('aiCipher', ALG_ID), + ('dwCipherStrength', DWORD), + ('aiHash', ALG_ID), + ('dwHashStrength', DWORD), + ('aiExch', ALG_ID), + ('dwExchStrength', DWORD), + ] + + secur32.AcquireCredentialsHandleW.argtypes = [ + POINTER(SEC_WCHAR), + POINTER(SEC_WCHAR), + ULONG, + POINTER(LUID), + c_void_p, + SEC_GET_KEY_FN, + c_void_p, + POINTER(CredHandle), + POINTER(TimeStamp) + ] + secur32.AcquireCredentialsHandleW.restype = SECURITY_STATUS + + secur32.FreeCredentialsHandle.argtypes = [ + POINTER(CredHandle) + ] + secur32.FreeCredentialsHandle.restype = SECURITY_STATUS + + secur32.InitializeSecurityContextW.argtypes = [ + POINTER(CredHandle), + POINTER(CtxtHandle), + POINTER(SEC_WCHAR), + ULONG, + ULONG, + ULONG, + POINTER(SecBufferDesc), + ULONG, + POINTER(CtxtHandle), + POINTER(SecBufferDesc), + POINTER(ULONG), + POINTER(TimeStamp) + ] + secur32.InitializeSecurityContextW.restype = SECURITY_STATUS + + secur32.FreeContextBuffer.argtypes = [ + c_void_p + ] + secur32.FreeContextBuffer.restype = SECURITY_STATUS + + secur32.ApplyControlToken.argtypes = [ + POINTER(CtxtHandle), + POINTER(SecBufferDesc) + ] + secur32.ApplyControlToken.restype = SECURITY_STATUS + + secur32.DeleteSecurityContext.argtypes = [ + POINTER(CtxtHandle) + ] + secur32.DeleteSecurityContext.restype = SECURITY_STATUS + + secur32.QueryContextAttributesW.argtypes = [ + POINTER(CtxtHandle), + ULONG, + c_void_p + ] + secur32.QueryContextAttributesW.restype = SECURITY_STATUS + + secur32.EncryptMessage.argtypes = [ + POINTER(CtxtHandle), + ULONG, + POINTER(SecBufferDesc), + ULONG + ] + secur32.EncryptMessage.restype = SECURITY_STATUS + + secur32.DecryptMessage.argtypes = [ + POINTER(CtxtHandle), + POINTER(SecBufferDesc), + ULONG, + POINTER(ULONG) + ] + secur32.DecryptMessage.restype = SECURITY_STATUS + +except (AttributeError): + raise FFIEngineError('Error initializing ctypes') + + +setattr(secur32, 'ALG_ID', ALG_ID) +setattr(secur32, 'CredHandle', CredHandle) +setattr(secur32, 'CtxtHandle', CtxtHandle) +setattr(secur32, 'SecBuffer', SecBuffer) +setattr(secur32, 'SecBufferDesc', SecBufferDesc) +setattr(secur32, 'SecPkgContext_StreamSizes', SecPkgContext_StreamSizes) +setattr(secur32, 'SecPkgContext_ConnectionInfo', SecPkgContext_ConnectionInfo) +setattr(secur32, 'SCHANNEL_CRED', SCHANNEL_CRED) + + +def get_error(): + error = ctypes.GetLastError() + return (error, ctypes.FormatError(error)) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_win/asymmetric.py b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_win/asymmetric.py new file mode 100644 index 00000000..9e6eb466 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_win/asymmetric.py @@ -0,0 +1,3520 @@ +# coding: utf-8 +from __future__ import unicode_literals, division, absolute_import, print_function + +import os +import sys +import hashlib +import random + +from .._asn1 import ( + Certificate as Asn1Certificate, + DHParameters, + DSAParams, + DSASignature, + ECDomainParameters, + ECPrivateKey, + Integer, + int_from_bytes, + int_to_bytes, + PrivateKeyAlgorithm, + PrivateKeyInfo, + PublicKeyAlgorithm, + PublicKeyInfo, + RSAPrivateKey, + RSAPublicKey, +) +from .._asymmetric import ( + _CertificateBase, + _fingerprint, + _parse_pkcs12, + _PrivateKeyBase, + _PublicKeyBase, + _unwrap_private_key_info, + parse_certificate, + parse_private, + parse_public, +) +from .._errors import pretty_message +from .._ffi import ( + buffer_from_bytes, + buffer_from_unicode, + byte_array, + bytes_from_buffer, + cast, + deref, + native, + new, + null, + pointer_set, + sizeof, + struct, + struct_bytes, + struct_from_buffer, + unwrap, + write_to_buffer, +) +from .. import backend +from .._int import fill_width +from ..errors import AsymmetricKeyError, IncompleteAsymmetricKeyError, SignatureError +from .._types import type_name, str_cls, byte_cls, int_types +from .._pkcs1 import ( + add_pkcs1v15_signature_padding, + add_pss_padding, + raw_rsa_private_crypt, + raw_rsa_public_crypt, + remove_pkcs1v15_signature_padding, + verify_pss_padding, +) +from ..util import constant_compare + +_gwv = sys.getwindowsversion() +_win_version_info = (_gwv[0], _gwv[1]) +_backend = backend() + +if _backend == 'winlegacy': + from ._advapi32 import advapi32, Advapi32Const, handle_error, open_context_handle, close_context_handle + from .._ecdsa import ( + ec_generate_pair as _pure_python_ec_generate_pair, + ec_compute_public_key_point as _pure_python_ec_compute_public_key_point, + ec_public_key_info, + ecdsa_sign as _pure_python_ecdsa_sign, + ecdsa_verify as _pure_python_ecdsa_verify, + ) +else: + from ._cng import bcrypt, BcryptConst, handle_error, open_alg_handle, close_alg_handle + + +__all__ = [ + 'Certificate', + 'dsa_sign', + 'dsa_verify', + 'ecdsa_sign', + 'ecdsa_verify', + 'generate_pair', + 'load_certificate', + 'load_pkcs12', + 'load_private_key', + 'load_public_key', + 'parse_pkcs12', + 'PrivateKey', + 'PublicKey', + 'rsa_oaep_decrypt', + 'rsa_oaep_encrypt', + 'rsa_pkcs1v15_decrypt', + 'rsa_pkcs1v15_encrypt', + 'rsa_pkcs1v15_sign', + 'rsa_pkcs1v15_verify', + 'rsa_pss_sign', + 'rsa_pss_verify', +] + + +# A list of primes from OpenSSL's bn_prime.h to use when testing primality of a +# large integer +_SMALL_PRIMES = [ + 2, 3, 5, 7, 11, 13, 17, 19, + 23, 29, 31, 37, 41, 43, 47, 53, + 59, 61, 67, 71, 73, 79, 83, 89, + 97, 101, 103, 107, 109, 113, 127, 131, + 137, 139, 149, 151, 157, 163, 167, 173, + 179, 181, 191, 193, 197, 199, 211, 223, + 227, 229, 233, 239, 241, 251, 257, 263, + 269, 271, 277, 281, 283, 293, 307, 311, + 313, 317, 331, 337, 347, 349, 353, 359, + 367, 373, 379, 383, 389, 397, 401, 409, + 419, 421, 431, 433, 439, 443, 449, 457, + 461, 463, 467, 479, 487, 491, 499, 503, + 509, 521, 523, 541, 547, 557, 563, 569, + 571, 577, 587, 593, 599, 601, 607, 613, + 617, 619, 631, 641, 643, 647, 653, 659, + 661, 673, 677, 683, 691, 701, 709, 719, + 727, 733, 739, 743, 751, 757, 761, 769, + 773, 787, 797, 809, 811, 821, 823, 827, + 829, 839, 853, 857, 859, 863, 877, 881, + 883, 887, 907, 911, 919, 929, 937, 941, + 947, 953, 967, 971, 977, 983, 991, 997, + 1009, 1013, 1019, 1021, 1031, 1033, 1039, 1049, + 1051, 1061, 1063, 1069, 1087, 1091, 1093, 1097, + 1103, 1109, 1117, 1123, 1129, 1151, 1153, 1163, + 1171, 1181, 1187, 1193, 1201, 1213, 1217, 1223, + 1229, 1231, 1237, 1249, 1259, 1277, 1279, 1283, + 1289, 1291, 1297, 1301, 1303, 1307, 1319, 1321, + 1327, 1361, 1367, 1373, 1381, 1399, 1409, 1423, + 1427, 1429, 1433, 1439, 1447, 1451, 1453, 1459, + 1471, 1481, 1483, 1487, 1489, 1493, 1499, 1511, + 1523, 1531, 1543, 1549, 1553, 1559, 1567, 1571, + 1579, 1583, 1597, 1601, 1607, 1609, 1613, 1619, + 1621, 1627, 1637, 1657, 1663, 1667, 1669, 1693, + 1697, 1699, 1709, 1721, 1723, 1733, 1741, 1747, + 1753, 1759, 1777, 1783, 1787, 1789, 1801, 1811, + 1823, 1831, 1847, 1861, 1867, 1871, 1873, 1877, + 1879, 1889, 1901, 1907, 1913, 1931, 1933, 1949, + 1951, 1973, 1979, 1987, 1993, 1997, 1999, 2003, + 2011, 2017, 2027, 2029, 2039, 2053, 2063, 2069, + 2081, 2083, 2087, 2089, 2099, 2111, 2113, 2129, + 2131, 2137, 2141, 2143, 2153, 2161, 2179, 2203, + 2207, 2213, 2221, 2237, 2239, 2243, 2251, 2267, + 2269, 2273, 2281, 2287, 2293, 2297, 2309, 2311, + 2333, 2339, 2341, 2347, 2351, 2357, 2371, 2377, + 2381, 2383, 2389, 2393, 2399, 2411, 2417, 2423, + 2437, 2441, 2447, 2459, 2467, 2473, 2477, 2503, + 2521, 2531, 2539, 2543, 2549, 2551, 2557, 2579, + 2591, 2593, 2609, 2617, 2621, 2633, 2647, 2657, + 2659, 2663, 2671, 2677, 2683, 2687, 2689, 2693, + 2699, 2707, 2711, 2713, 2719, 2729, 2731, 2741, + 2749, 2753, 2767, 2777, 2789, 2791, 2797, 2801, + 2803, 2819, 2833, 2837, 2843, 2851, 2857, 2861, + 2879, 2887, 2897, 2903, 2909, 2917, 2927, 2939, + 2953, 2957, 2963, 2969, 2971, 2999, 3001, 3011, + 3019, 3023, 3037, 3041, 3049, 3061, 3067, 3079, + 3083, 3089, 3109, 3119, 3121, 3137, 3163, 3167, + 3169, 3181, 3187, 3191, 3203, 3209, 3217, 3221, + 3229, 3251, 3253, 3257, 3259, 3271, 3299, 3301, + 3307, 3313, 3319, 3323, 3329, 3331, 3343, 3347, + 3359, 3361, 3371, 3373, 3389, 3391, 3407, 3413, + 3433, 3449, 3457, 3461, 3463, 3467, 3469, 3491, + 3499, 3511, 3517, 3527, 3529, 3533, 3539, 3541, + 3547, 3557, 3559, 3571, 3581, 3583, 3593, 3607, + 3613, 3617, 3623, 3631, 3637, 3643, 3659, 3671, + 3673, 3677, 3691, 3697, 3701, 3709, 3719, 3727, + 3733, 3739, 3761, 3767, 3769, 3779, 3793, 3797, + 3803, 3821, 3823, 3833, 3847, 3851, 3853, 3863, + 3877, 3881, 3889, 3907, 3911, 3917, 3919, 3923, + 3929, 3931, 3943, 3947, 3967, 3989, 4001, 4003, + 4007, 4013, 4019, 4021, 4027, 4049, 4051, 4057, + 4073, 4079, 4091, 4093, 4099, 4111, 4127, 4129, + 4133, 4139, 4153, 4157, 4159, 4177, 4201, 4211, + 4217, 4219, 4229, 4231, 4241, 4243, 4253, 4259, + 4261, 4271, 4273, 4283, 4289, 4297, 4327, 4337, + 4339, 4349, 4357, 4363, 4373, 4391, 4397, 4409, + 4421, 4423, 4441, 4447, 4451, 4457, 4463, 4481, + 4483, 4493, 4507, 4513, 4517, 4519, 4523, 4547, + 4549, 4561, 4567, 4583, 4591, 4597, 4603, 4621, + 4637, 4639, 4643, 4649, 4651, 4657, 4663, 4673, + 4679, 4691, 4703, 4721, 4723, 4729, 4733, 4751, + 4759, 4783, 4787, 4789, 4793, 4799, 4801, 4813, + 4817, 4831, 4861, 4871, 4877, 4889, 4903, 4909, + 4919, 4931, 4933, 4937, 4943, 4951, 4957, 4967, + 4969, 4973, 4987, 4993, 4999, 5003, 5009, 5011, + 5021, 5023, 5039, 5051, 5059, 5077, 5081, 5087, + 5099, 5101, 5107, 5113, 5119, 5147, 5153, 5167, + 5171, 5179, 5189, 5197, 5209, 5227, 5231, 5233, + 5237, 5261, 5273, 5279, 5281, 5297, 5303, 5309, + 5323, 5333, 5347, 5351, 5381, 5387, 5393, 5399, + 5407, 5413, 5417, 5419, 5431, 5437, 5441, 5443, + 5449, 5471, 5477, 5479, 5483, 5501, 5503, 5507, + 5519, 5521, 5527, 5531, 5557, 5563, 5569, 5573, + 5581, 5591, 5623, 5639, 5641, 5647, 5651, 5653, + 5657, 5659, 5669, 5683, 5689, 5693, 5701, 5711, + 5717, 5737, 5741, 5743, 5749, 5779, 5783, 5791, + 5801, 5807, 5813, 5821, 5827, 5839, 5843, 5849, + 5851, 5857, 5861, 5867, 5869, 5879, 5881, 5897, + 5903, 5923, 5927, 5939, 5953, 5981, 5987, 6007, + 6011, 6029, 6037, 6043, 6047, 6053, 6067, 6073, + 6079, 6089, 6091, 6101, 6113, 6121, 6131, 6133, + 6143, 6151, 6163, 6173, 6197, 6199, 6203, 6211, + 6217, 6221, 6229, 6247, 6257, 6263, 6269, 6271, + 6277, 6287, 6299, 6301, 6311, 6317, 6323, 6329, + 6337, 6343, 6353, 6359, 6361, 6367, 6373, 6379, + 6389, 6397, 6421, 6427, 6449, 6451, 6469, 6473, + 6481, 6491, 6521, 6529, 6547, 6551, 6553, 6563, + 6569, 6571, 6577, 6581, 6599, 6607, 6619, 6637, + 6653, 6659, 6661, 6673, 6679, 6689, 6691, 6701, + 6703, 6709, 6719, 6733, 6737, 6761, 6763, 6779, + 6781, 6791, 6793, 6803, 6823, 6827, 6829, 6833, + 6841, 6857, 6863, 6869, 6871, 6883, 6899, 6907, + 6911, 6917, 6947, 6949, 6959, 6961, 6967, 6971, + 6977, 6983, 6991, 6997, 7001, 7013, 7019, 7027, + 7039, 7043, 7057, 7069, 7079, 7103, 7109, 7121, + 7127, 7129, 7151, 7159, 7177, 7187, 7193, 7207, + 7211, 7213, 7219, 7229, 7237, 7243, 7247, 7253, + 7283, 7297, 7307, 7309, 7321, 7331, 7333, 7349, + 7351, 7369, 7393, 7411, 7417, 7433, 7451, 7457, + 7459, 7477, 7481, 7487, 7489, 7499, 7507, 7517, + 7523, 7529, 7537, 7541, 7547, 7549, 7559, 7561, + 7573, 7577, 7583, 7589, 7591, 7603, 7607, 7621, + 7639, 7643, 7649, 7669, 7673, 7681, 7687, 7691, + 7699, 7703, 7717, 7723, 7727, 7741, 7753, 7757, + 7759, 7789, 7793, 7817, 7823, 7829, 7841, 7853, + 7867, 7873, 7877, 7879, 7883, 7901, 7907, 7919, + 7927, 7933, 7937, 7949, 7951, 7963, 7993, 8009, + 8011, 8017, 8039, 8053, 8059, 8069, 8081, 8087, + 8089, 8093, 8101, 8111, 8117, 8123, 8147, 8161, + 8167, 8171, 8179, 8191, 8209, 8219, 8221, 8231, + 8233, 8237, 8243, 8263, 8269, 8273, 8287, 8291, + 8293, 8297, 8311, 8317, 8329, 8353, 8363, 8369, + 8377, 8387, 8389, 8419, 8423, 8429, 8431, 8443, + 8447, 8461, 8467, 8501, 8513, 8521, 8527, 8537, + 8539, 8543, 8563, 8573, 8581, 8597, 8599, 8609, + 8623, 8627, 8629, 8641, 8647, 8663, 8669, 8677, + 8681, 8689, 8693, 8699, 8707, 8713, 8719, 8731, + 8737, 8741, 8747, 8753, 8761, 8779, 8783, 8803, + 8807, 8819, 8821, 8831, 8837, 8839, 8849, 8861, + 8863, 8867, 8887, 8893, 8923, 8929, 8933, 8941, + 8951, 8963, 8969, 8971, 8999, 9001, 9007, 9011, + 9013, 9029, 9041, 9043, 9049, 9059, 9067, 9091, + 9103, 9109, 9127, 9133, 9137, 9151, 9157, 9161, + 9173, 9181, 9187, 9199, 9203, 9209, 9221, 9227, + 9239, 9241, 9257, 9277, 9281, 9283, 9293, 9311, + 9319, 9323, 9337, 9341, 9343, 9349, 9371, 9377, + 9391, 9397, 9403, 9413, 9419, 9421, 9431, 9433, + 9437, 9439, 9461, 9463, 9467, 9473, 9479, 9491, + 9497, 9511, 9521, 9533, 9539, 9547, 9551, 9587, + 9601, 9613, 9619, 9623, 9629, 9631, 9643, 9649, + 9661, 9677, 9679, 9689, 9697, 9719, 9721, 9733, + 9739, 9743, 9749, 9767, 9769, 9781, 9787, 9791, + 9803, 9811, 9817, 9829, 9833, 9839, 9851, 9857, + 9859, 9871, 9883, 9887, 9901, 9907, 9923, 9929, + 9931, 9941, 9949, 9967, 9973, 10007, 10009, 10037, + 10039, 10061, 10067, 10069, 10079, 10091, 10093, 10099, + 10103, 10111, 10133, 10139, 10141, 10151, 10159, 10163, + 10169, 10177, 10181, 10193, 10211, 10223, 10243, 10247, + 10253, 10259, 10267, 10271, 10273, 10289, 10301, 10303, + 10313, 10321, 10331, 10333, 10337, 10343, 10357, 10369, + 10391, 10399, 10427, 10429, 10433, 10453, 10457, 10459, + 10463, 10477, 10487, 10499, 10501, 10513, 10529, 10531, + 10559, 10567, 10589, 10597, 10601, 10607, 10613, 10627, + 10631, 10639, 10651, 10657, 10663, 10667, 10687, 10691, + 10709, 10711, 10723, 10729, 10733, 10739, 10753, 10771, + 10781, 10789, 10799, 10831, 10837, 10847, 10853, 10859, + 10861, 10867, 10883, 10889, 10891, 10903, 10909, 10937, + 10939, 10949, 10957, 10973, 10979, 10987, 10993, 11003, + 11027, 11047, 11057, 11059, 11069, 11071, 11083, 11087, + 11093, 11113, 11117, 11119, 11131, 11149, 11159, 11161, + 11171, 11173, 11177, 11197, 11213, 11239, 11243, 11251, + 11257, 11261, 11273, 11279, 11287, 11299, 11311, 11317, + 11321, 11329, 11351, 11353, 11369, 11383, 11393, 11399, + 11411, 11423, 11437, 11443, 11447, 11467, 11471, 11483, + 11489, 11491, 11497, 11503, 11519, 11527, 11549, 11551, + 11579, 11587, 11593, 11597, 11617, 11621, 11633, 11657, + 11677, 11681, 11689, 11699, 11701, 11717, 11719, 11731, + 11743, 11777, 11779, 11783, 11789, 11801, 11807, 11813, + 11821, 11827, 11831, 11833, 11839, 11863, 11867, 11887, + 11897, 11903, 11909, 11923, 11927, 11933, 11939, 11941, + 11953, 11959, 11969, 11971, 11981, 11987, 12007, 12011, + 12037, 12041, 12043, 12049, 12071, 12073, 12097, 12101, + 12107, 12109, 12113, 12119, 12143, 12149, 12157, 12161, + 12163, 12197, 12203, 12211, 12227, 12239, 12241, 12251, + 12253, 12263, 12269, 12277, 12281, 12289, 12301, 12323, + 12329, 12343, 12347, 12373, 12377, 12379, 12391, 12401, + 12409, 12413, 12421, 12433, 12437, 12451, 12457, 12473, + 12479, 12487, 12491, 12497, 12503, 12511, 12517, 12527, + 12539, 12541, 12547, 12553, 12569, 12577, 12583, 12589, + 12601, 12611, 12613, 12619, 12637, 12641, 12647, 12653, + 12659, 12671, 12689, 12697, 12703, 12713, 12721, 12739, + 12743, 12757, 12763, 12781, 12791, 12799, 12809, 12821, + 12823, 12829, 12841, 12853, 12889, 12893, 12899, 12907, + 12911, 12917, 12919, 12923, 12941, 12953, 12959, 12967, + 12973, 12979, 12983, 13001, 13003, 13007, 13009, 13033, + 13037, 13043, 13049, 13063, 13093, 13099, 13103, 13109, + 13121, 13127, 13147, 13151, 13159, 13163, 13171, 13177, + 13183, 13187, 13217, 13219, 13229, 13241, 13249, 13259, + 13267, 13291, 13297, 13309, 13313, 13327, 13331, 13337, + 13339, 13367, 13381, 13397, 13399, 13411, 13417, 13421, + 13441, 13451, 13457, 13463, 13469, 13477, 13487, 13499, + 13513, 13523, 13537, 13553, 13567, 13577, 13591, 13597, + 13613, 13619, 13627, 13633, 13649, 13669, 13679, 13681, + 13687, 13691, 13693, 13697, 13709, 13711, 13721, 13723, + 13729, 13751, 13757, 13759, 13763, 13781, 13789, 13799, + 13807, 13829, 13831, 13841, 13859, 13873, 13877, 13879, + 13883, 13901, 13903, 13907, 13913, 13921, 13931, 13933, + 13963, 13967, 13997, 13999, 14009, 14011, 14029, 14033, + 14051, 14057, 14071, 14081, 14083, 14087, 14107, 14143, + 14149, 14153, 14159, 14173, 14177, 14197, 14207, 14221, + 14243, 14249, 14251, 14281, 14293, 14303, 14321, 14323, + 14327, 14341, 14347, 14369, 14387, 14389, 14401, 14407, + 14411, 14419, 14423, 14431, 14437, 14447, 14449, 14461, + 14479, 14489, 14503, 14519, 14533, 14537, 14543, 14549, + 14551, 14557, 14561, 14563, 14591, 14593, 14621, 14627, + 14629, 14633, 14639, 14653, 14657, 14669, 14683, 14699, + 14713, 14717, 14723, 14731, 14737, 14741, 14747, 14753, + 14759, 14767, 14771, 14779, 14783, 14797, 14813, 14821, + 14827, 14831, 14843, 14851, 14867, 14869, 14879, 14887, + 14891, 14897, 14923, 14929, 14939, 14947, 14951, 14957, + 14969, 14983, 15013, 15017, 15031, 15053, 15061, 15073, + 15077, 15083, 15091, 15101, 15107, 15121, 15131, 15137, + 15139, 15149, 15161, 15173, 15187, 15193, 15199, 15217, + 15227, 15233, 15241, 15259, 15263, 15269, 15271, 15277, + 15287, 15289, 15299, 15307, 15313, 15319, 15329, 15331, + 15349, 15359, 15361, 15373, 15377, 15383, 15391, 15401, + 15413, 15427, 15439, 15443, 15451, 15461, 15467, 15473, + 15493, 15497, 15511, 15527, 15541, 15551, 15559, 15569, + 15581, 15583, 15601, 15607, 15619, 15629, 15641, 15643, + 15647, 15649, 15661, 15667, 15671, 15679, 15683, 15727, + 15731, 15733, 15737, 15739, 15749, 15761, 15767, 15773, + 15787, 15791, 15797, 15803, 15809, 15817, 15823, 15859, + 15877, 15881, 15887, 15889, 15901, 15907, 15913, 15919, + 15923, 15937, 15959, 15971, 15973, 15991, 16001, 16007, + 16033, 16057, 16061, 16063, 16067, 16069, 16073, 16087, + 16091, 16097, 16103, 16111, 16127, 16139, 16141, 16183, + 16187, 16189, 16193, 16217, 16223, 16229, 16231, 16249, + 16253, 16267, 16273, 16301, 16319, 16333, 16339, 16349, + 16361, 16363, 16369, 16381, 16411, 16417, 16421, 16427, + 16433, 16447, 16451, 16453, 16477, 16481, 16487, 16493, + 16519, 16529, 16547, 16553, 16561, 16567, 16573, 16603, + 16607, 16619, 16631, 16633, 16649, 16651, 16657, 16661, + 16673, 16691, 16693, 16699, 16703, 16729, 16741, 16747, + 16759, 16763, 16787, 16811, 16823, 16829, 16831, 16843, + 16871, 16879, 16883, 16889, 16901, 16903, 16921, 16927, + 16931, 16937, 16943, 16963, 16979, 16981, 16987, 16993, + 17011, 17021, 17027, 17029, 17033, 17041, 17047, 17053, + 17077, 17093, 17099, 17107, 17117, 17123, 17137, 17159, + 17167, 17183, 17189, 17191, 17203, 17207, 17209, 17231, + 17239, 17257, 17291, 17293, 17299, 17317, 17321, 17327, + 17333, 17341, 17351, 17359, 17377, 17383, 17387, 17389, + 17393, 17401, 17417, 17419, 17431, 17443, 17449, 17467, + 17471, 17477, 17483, 17489, 17491, 17497, 17509, 17519, + 17539, 17551, 17569, 17573, 17579, 17581, 17597, 17599, + 17609, 17623, 17627, 17657, 17659, 17669, 17681, 17683, + 17707, 17713, 17729, 17737, 17747, 17749, 17761, 17783, + 17789, 17791, 17807, 17827, 17837, 17839, 17851, 17863, +] + + +class _WinKey(): + + # A CNG BCRYPT_KEY_HANDLE on Vista and newer, an HCRYPTKEY on XP and 2003 + key_handle = None + # On XP and 2003, we have to carry around more info + context_handle = None + ex_key_handle = None + + # A reference to the library used in the destructor to make sure it hasn't + # been garbage collected by the time this object is garbage collected + _lib = None + + def __init__(self, key_handle, asn1): + """ + :param key_handle: + A CNG BCRYPT_KEY_HANDLE value (Vista and newer) or an HCRYPTKEY + (XP and 2003) from loading/importing the key + + :param asn1: + An asn1crypto object for the concrete type + """ + + self.key_handle = key_handle + self.asn1 = asn1 + + if _backend == 'winlegacy': + self._lib = advapi32 + else: + self._lib = bcrypt + + def __del__(self): + if self.key_handle: + if _backend == 'winlegacy': + res = self._lib.CryptDestroyKey(self.key_handle) + else: + res = self._lib.BCryptDestroyKey(self.key_handle) + handle_error(res) + self.key_handle = None + if self.context_handle and _backend == 'winlegacy': + close_context_handle(self.context_handle) + self.context_handle = None + self._lib = None + + +class PrivateKey(_WinKey, _PrivateKeyBase): + """ + Container for the OS crypto library representation of a private key + """ + + _public_key = None + + def __init__(self, key_handle, asn1): + """ + :param key_handle: + A CNG BCRYPT_KEY_HANDLE value (Vista and newer) or an HCRYPTKEY + (XP and 2003) from loading/importing the key + + :param asn1: + An asn1crypto.keys.PrivateKeyInfo object + """ + + _WinKey.__init__(self, key_handle, asn1) + + @property + def public_key(self): + """ + :return: + A PublicKey object corresponding to this private key. + """ + + if _backend == 'winlegacy': + if self.algorithm == 'ec': + pub_point = _pure_python_ec_compute_public_key_point(self.asn1) + self._public_key = PublicKey(None, ec_public_key_info(pub_point, self.curve)) + elif self.algorithm == 'dsa': + # The DSA provider won't allow exporting the private key with + # CryptoImportKey flags set to 0 and won't allow flags to be set + # to CRYPT_EXPORTABLE, so we manually recreated the public key + # ASN.1 + params = self.asn1['private_key_algorithm']['parameters'] + pub_asn1 = PublicKeyInfo({ + 'algorithm': PublicKeyAlgorithm({ + 'algorithm': 'dsa', + 'parameters': params + }), + 'public_key': Integer(pow( + params['g'].native, + self.asn1['private_key'].parsed.native, + params['p'].native + )) + }) + self._public_key = load_public_key(pub_asn1) + else: + # This suffers from similar problems as above, although not + # as insurmountable. This is just a simpler/faster solution + # since the private key has all of the data we need anyway + parsed = self.asn1['private_key'].parsed + pub_asn1 = PublicKeyInfo({ + 'algorithm': PublicKeyAlgorithm({ + 'algorithm': 'rsa' + }), + 'public_key': RSAPublicKey({ + 'modulus': parsed['modulus'], + 'public_exponent': parsed['public_exponent'] + }) + }) + self._public_key = load_public_key(pub_asn1) + else: + pub_asn1, _ = _bcrypt_key_handle_to_asn1(self.algorithm, self.bit_size, self.key_handle) + self._public_key = load_public_key(pub_asn1) + return self._public_key + + @property + def fingerprint(self): + """ + Creates a fingerprint that can be compared with a public key to see if + the two form a pair. + + This fingerprint is not compatible with fingerprints generated by any + other software. + + :return: + A byte string that is a sha256 hash of selected components (based + on the key type) + """ + + if self._fingerprint is None: + self._fingerprint = _fingerprint(self.asn1, load_private_key) + return self._fingerprint + + +class PublicKey(_WinKey, _PublicKeyBase): + """ + Container for the OS crypto library representation of a public key + """ + + def __init__(self, key_handle, asn1): + """ + :param key_handle: + A CNG BCRYPT_KEY_HANDLE value (Vista and newer) or an HCRYPTKEY + (XP and 2003) from loading/importing the key + + :param asn1: + An asn1crypto.keys.PublicKeyInfo object + """ + + _WinKey.__init__(self, key_handle, asn1) + + +class Certificate(_WinKey, _CertificateBase): + """ + Container for the OS crypto library representation of a certificate + """ + + _public_key = None + _self_signed = None + + def __init__(self, key_handle, asn1): + """ + :param key_handle: + A CNG BCRYPT_KEY_HANDLE value (Vista and newer) or an HCRYPTKEY + (XP and 2003) from loading/importing the certificate + + :param asn1: + An asn1crypto.x509.Certificate object + """ + + _WinKey.__init__(self, key_handle, asn1) + + @property + def public_key(self): + """ + :return: + The PublicKey object for the public key this certificate contains + """ + + if self._public_key is None: + self._public_key = load_public_key(self.asn1['tbs_certificate']['subject_public_key_info']) + return self._public_key + + @property + def self_signed(self): + """ + :return: + A boolean - if the certificate is self-signed + """ + + if self._self_signed is None: + self._self_signed = False + if self.asn1.self_signed in set(['yes', 'maybe']): + + signature_algo = self.asn1['signature_algorithm'].signature_algo + hash_algo = self.asn1['signature_algorithm'].hash_algo + + if signature_algo == 'rsassa_pkcs1v15': + verify_func = rsa_pkcs1v15_verify + elif signature_algo == 'dsa': + verify_func = dsa_verify + elif signature_algo == 'ecdsa': + verify_func = ecdsa_verify + else: + raise OSError(pretty_message( + ''' + Unable to verify the signature of the certificate since + it uses the unsupported algorithm %s + ''', + signature_algo + )) + + try: + verify_func( + self, + self.asn1['signature_value'].native, + self.asn1['tbs_certificate'].dump(), + hash_algo + ) + self._self_signed = True + except (SignatureError): + pass + + return self._self_signed + + +def generate_pair(algorithm, bit_size=None, curve=None): + """ + Generates a public/private key pair + + :param algorithm: + The key algorithm - "rsa", "dsa" or "ec" + + :param bit_size: + An integer - used for "rsa" and "dsa". For "rsa" the value maye be 1024, + 2048, 3072 or 4096. For "dsa" the value may be 1024, plus 2048 or 3072 + if on Windows 8 or newer. + + :param curve: + A unicode string - used for "ec" keys. Valid values include "secp256r1", + "secp384r1" and "secp521r1". + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + + :return: + A 2-element tuple of (PublicKey, PrivateKey). The contents of each key + may be saved by calling .asn1.dump(). + """ + + if algorithm not in set(['rsa', 'dsa', 'ec']): + raise ValueError(pretty_message( + ''' + algorithm must be one of "rsa", "dsa", "ec", not %s + ''', + repr(algorithm) + )) + + if algorithm == 'rsa': + if bit_size not in set([1024, 2048, 3072, 4096]): + raise ValueError(pretty_message( + ''' + bit_size must be one of 1024, 2048, 3072, 4096, not %s + ''', + repr(bit_size) + )) + + elif algorithm == 'dsa': + # Windows Vista and 7 only support SHA1-based DSA keys + if _win_version_info < (6, 2) or _backend == 'winlegacy': + if bit_size != 1024: + raise ValueError(pretty_message( + ''' + bit_size must be 1024, not %s + ''', + repr(bit_size) + )) + else: + if bit_size not in set([1024, 2048, 3072]): + raise ValueError(pretty_message( + ''' + bit_size must be one of 1024, 2048, 3072, not %s + ''', + repr(bit_size) + )) + + elif algorithm == 'ec': + if curve not in set(['secp256r1', 'secp384r1', 'secp521r1']): + raise ValueError(pretty_message( + ''' + curve must be one of "secp256r1", "secp384r1", "secp521r1", not %s + ''', + repr(curve) + )) + + if _backend == 'winlegacy': + if algorithm == 'ec': + pub_info, priv_info = _pure_python_ec_generate_pair(curve) + return (PublicKey(None, pub_info), PrivateKey(None, priv_info)) + return _advapi32_generate_pair(algorithm, bit_size) + else: + return _bcrypt_generate_pair(algorithm, bit_size, curve) + + +def _advapi32_key_handle_to_asn1(algorithm, bit_size, key_handle): + """ + Accepts an key handle and exports it to ASN.1 + + :param algorithm: + The key algorithm - "rsa" or "dsa" + + :param bit_size: + An integer - only used when algorithm is "rsa" + + :param key_handle: + The handle to export + + :return: + A 2-element tuple of asn1crypto.keys.PrivateKeyInfo and + asn1crypto.keys.PublicKeyInfo + """ + + if algorithm == 'rsa': + struct_type = 'RSABLOBHEADER' + else: + struct_type = 'DSSBLOBHEADER' + + out_len = new(advapi32, 'DWORD *') + res = advapi32.CryptExportKey( + key_handle, + null(), + Advapi32Const.PRIVATEKEYBLOB, + 0, + null(), + out_len + ) + handle_error(res) + + buffer_length = deref(out_len) + buffer_ = buffer_from_bytes(buffer_length) + res = advapi32.CryptExportKey( + key_handle, + null(), + Advapi32Const.PRIVATEKEYBLOB, + 0, + buffer_, + out_len + ) + handle_error(res) + + blob_struct_pointer = struct_from_buffer(advapi32, struct_type, buffer_) + blob_struct = unwrap(blob_struct_pointer) + struct_size = sizeof(advapi32, blob_struct) + + private_blob = bytes_from_buffer(buffer_, buffer_length)[struct_size:] + + if algorithm == 'rsa': + public_info, private_info = _advapi32_interpret_rsa_key_blob(bit_size, blob_struct, private_blob) + + else: + # The public key for a DSA key is not available in from the private + # key blob, so we have to separately export the public key + public_out_len = new(advapi32, 'DWORD *') + res = advapi32.CryptExportKey( + key_handle, + null(), + Advapi32Const.PUBLICKEYBLOB, + 0, + null(), + public_out_len + ) + handle_error(res) + + public_buffer_length = deref(public_out_len) + public_buffer = buffer_from_bytes(public_buffer_length) + res = advapi32.CryptExportKey( + key_handle, + null(), + Advapi32Const.PUBLICKEYBLOB, + 0, + public_buffer, + public_out_len + ) + handle_error(res) + + public_blob = bytes_from_buffer(public_buffer, public_buffer_length)[struct_size:] + + public_info, private_info = _advapi32_interpret_dsa_key_blob(bit_size, public_blob, private_blob) + + return (public_info, private_info) + + +def _advapi32_generate_pair(algorithm, bit_size=None): + """ + Generates a public/private key pair using CryptoAPI + + :param algorithm: + The key algorithm - "rsa" or "dsa" + + :param bit_size: + An integer - used for "rsa" and "dsa". For "rsa" the value maye be 1024, + 2048, 3072 or 4096. For "dsa" the value may be 1024. + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + + :return: + A 2-element tuple of (PublicKey, PrivateKey). The contents of each key + may be saved by calling .asn1.dump(). + """ + + if algorithm == 'rsa': + provider = Advapi32Const.MS_ENH_RSA_AES_PROV + algorithm_id = Advapi32Const.CALG_RSA_SIGN + else: + provider = Advapi32Const.MS_ENH_DSS_DH_PROV + algorithm_id = Advapi32Const.CALG_DSS_SIGN + + context_handle = None + key_handle = None + + try: + context_handle = open_context_handle(provider, verify_only=False) + + key_handle_pointer = new(advapi32, 'HCRYPTKEY *') + flags = (bit_size << 16) | Advapi32Const.CRYPT_EXPORTABLE + res = advapi32.CryptGenKey(context_handle, algorithm_id, flags, key_handle_pointer) + handle_error(res) + + key_handle = unwrap(key_handle_pointer) + + public_info, private_info = _advapi32_key_handle_to_asn1(algorithm, bit_size, key_handle) + + return (load_public_key(public_info), load_private_key(private_info)) + + finally: + if context_handle: + close_context_handle(context_handle) + if key_handle: + advapi32.CryptDestroyKey(key_handle) + + +def _bcrypt_key_handle_to_asn1(algorithm, bit_size, key_handle): + """ + Accepts an key handle and exports it to ASN.1 + + :param algorithm: + The key algorithm - "rsa", "dsa" or "ec" + + :param bit_size: + An integer - only used when algorithm is "dsa" + + :param key_handle: + The handle to export + + :return: + A 2-element tuple of asn1crypto.keys.PrivateKeyInfo and + asn1crypto.keys.PublicKeyInfo + """ + + if algorithm == 'rsa': + struct_type = 'BCRYPT_RSAKEY_BLOB' + private_blob_type = BcryptConst.BCRYPT_RSAFULLPRIVATE_BLOB + public_blob_type = BcryptConst.BCRYPT_RSAPUBLIC_BLOB + + elif algorithm == 'dsa': + if bit_size > 1024: + struct_type = 'BCRYPT_DSA_KEY_BLOB_V2' + else: + struct_type = 'BCRYPT_DSA_KEY_BLOB' + private_blob_type = BcryptConst.BCRYPT_DSA_PRIVATE_BLOB + public_blob_type = BcryptConst.BCRYPT_DSA_PUBLIC_BLOB + + else: + struct_type = 'BCRYPT_ECCKEY_BLOB' + private_blob_type = BcryptConst.BCRYPT_ECCPRIVATE_BLOB + public_blob_type = BcryptConst.BCRYPT_ECCPUBLIC_BLOB + + private_out_len = new(bcrypt, 'ULONG *') + res = bcrypt.BCryptExportKey(key_handle, null(), private_blob_type, null(), 0, private_out_len, 0) + handle_error(res) + + private_buffer_length = deref(private_out_len) + private_buffer = buffer_from_bytes(private_buffer_length) + res = bcrypt.BCryptExportKey( + key_handle, + null(), + private_blob_type, + private_buffer, + private_buffer_length, + private_out_len, + 0 + ) + handle_error(res) + private_blob_struct_pointer = struct_from_buffer(bcrypt, struct_type, private_buffer) + private_blob_struct = unwrap(private_blob_struct_pointer) + struct_size = sizeof(bcrypt, private_blob_struct) + private_blob = bytes_from_buffer(private_buffer, private_buffer_length)[struct_size:] + + if algorithm == 'rsa': + private_key = _bcrypt_interpret_rsa_key_blob('private', private_blob_struct, private_blob) + elif algorithm == 'dsa': + if bit_size > 1024: + private_key = _bcrypt_interpret_dsa_key_blob('private', 2, private_blob_struct, private_blob) + else: + private_key = _bcrypt_interpret_dsa_key_blob('private', 1, private_blob_struct, private_blob) + else: + private_key = _bcrypt_interpret_ec_key_blob('private', private_blob_struct, private_blob) + + public_out_len = new(bcrypt, 'ULONG *') + res = bcrypt.BCryptExportKey(key_handle, null(), public_blob_type, null(), 0, public_out_len, 0) + handle_error(res) + + public_buffer_length = deref(public_out_len) + public_buffer = buffer_from_bytes(public_buffer_length) + res = bcrypt.BCryptExportKey( + key_handle, + null(), + public_blob_type, + public_buffer, + public_buffer_length, + public_out_len, + 0 + ) + handle_error(res) + public_blob_struct_pointer = struct_from_buffer(bcrypt, struct_type, public_buffer) + public_blob_struct = unwrap(public_blob_struct_pointer) + struct_size = sizeof(bcrypt, public_blob_struct) + public_blob = bytes_from_buffer(public_buffer, public_buffer_length)[struct_size:] + + if algorithm == 'rsa': + public_key = _bcrypt_interpret_rsa_key_blob('public', public_blob_struct, public_blob) + elif algorithm == 'dsa': + if bit_size > 1024: + public_key = _bcrypt_interpret_dsa_key_blob('public', 2, public_blob_struct, public_blob) + else: + public_key = _bcrypt_interpret_dsa_key_blob('public', 1, public_blob_struct, public_blob) + else: + public_key = _bcrypt_interpret_ec_key_blob('public', public_blob_struct, public_blob) + + return (public_key, private_key) + + +def _bcrypt_generate_pair(algorithm, bit_size=None, curve=None): + """ + Generates a public/private key pair using CNG + + :param algorithm: + The key algorithm - "rsa", "dsa" or "ec" + + :param bit_size: + An integer - used for "rsa" and "dsa". For "rsa" the value maye be 1024, + 2048, 3072 or 4096. For "dsa" the value may be 1024, plus 2048 or 3072 + if on Windows 8 or newer. + + :param curve: + A unicode string - used for "ec" keys. Valid values include "secp256r1", + "secp384r1" and "secp521r1". + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + + :return: + A 2-element tuple of (PublicKey, PrivateKey). The contents of each key + may be saved by calling .asn1.dump(). + """ + + if algorithm == 'rsa': + alg_constant = BcryptConst.BCRYPT_RSA_ALGORITHM + + elif algorithm == 'dsa': + alg_constant = BcryptConst.BCRYPT_DSA_ALGORITHM + + else: + alg_constant = { + 'secp256r1': BcryptConst.BCRYPT_ECDSA_P256_ALGORITHM, + 'secp384r1': BcryptConst.BCRYPT_ECDSA_P384_ALGORITHM, + 'secp521r1': BcryptConst.BCRYPT_ECDSA_P521_ALGORITHM, + }[curve] + bit_size = { + 'secp256r1': 256, + 'secp384r1': 384, + 'secp521r1': 521, + }[curve] + + key_handle = None + try: + alg_handle = open_alg_handle(alg_constant) + key_handle_pointer = new(bcrypt, 'BCRYPT_KEY_HANDLE *') + res = bcrypt.BCryptGenerateKeyPair(alg_handle, key_handle_pointer, bit_size, 0) + handle_error(res) + key_handle = unwrap(key_handle_pointer) + + res = bcrypt.BCryptFinalizeKeyPair(key_handle, 0) + handle_error(res) + + public_key, private_key = _bcrypt_key_handle_to_asn1(algorithm, bit_size, key_handle) + + finally: + if key_handle: + bcrypt.BCryptDestroyKey(key_handle) + + return (load_public_key(public_key), load_private_key(private_key)) + + +def generate_dh_parameters(bit_size): + """ + Generates DH parameters for use with Diffie-Hellman key exchange. Returns + a structure in the format of DHParameter defined in PKCS#3, which is also + used by the OpenSSL dhparam tool. + + THIS CAN BE VERY TIME CONSUMING! + + :param bit_size: + The integer bit size of the parameters to generate. Must be between 512 + and 4096, and divisible by 64. Recommended secure value as of early 2016 + is 2048, with an absolute minimum of 1024. + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + + :return: + An asn1crypto.algos.DHParameters object. Use + oscrypto.asymmetric.dump_dh_parameters() to save to disk for usage with + web servers. + """ + + if not isinstance(bit_size, int_types): + raise TypeError(pretty_message( + ''' + bit_size must be an integer, not %s + ''', + type_name(bit_size) + )) + + if bit_size < 512: + raise ValueError('bit_size must be greater than or equal to 512') + + if bit_size > 4096: + raise ValueError('bit_size must be less than or equal to 4096') + + if bit_size % 64 != 0: + raise ValueError('bit_size must be a multiple of 64') + + alg_handle = None + + # The following algorithm has elements taken from OpenSSL. In short, it + # generates random numbers and then ensures that they are valid for the + # hardcoded generator of 2, and then ensures the number is a "safe" prime + # by ensuring p//2 is prime also. + + # OpenSSL allows use of generator 2 or 5, but we hardcode 2 since it is + # the default, and what is used by Security.framework on OS X also. + g = 2 + + try: + byte_size = bit_size // 8 + if _backend == 'win': + alg_handle = open_alg_handle(BcryptConst.BCRYPT_RNG_ALGORITHM) + buffer = buffer_from_bytes(byte_size) + + while True: + if _backend == 'winlegacy': + rb = os.urandom(byte_size) + else: + res = bcrypt.BCryptGenRandom(alg_handle, buffer, byte_size, 0) + handle_error(res) + rb = bytes_from_buffer(buffer) + + p = int_from_bytes(rb) + + # If a number is even, it can't be prime + if p % 2 == 0: + continue + + # Perform the generator checks outlined in OpenSSL's + # dh_builtin_genparams() located in dh_gen.c + if g == 2: + if p % 24 != 11: + continue + elif g == 5: + rem = p % 10 + if rem != 3 and rem != 7: + continue + + divisible = False + for prime in _SMALL_PRIMES: + if p % prime == 0: + divisible = True + break + + # If the number is not divisible by any of the small primes, then + # move on to the full Miller-Rabin test. + if not divisible and _is_prime(bit_size, p): + q = p // 2 + if _is_prime(bit_size, q): + return DHParameters({'p': p, 'g': g}) + + finally: + if alg_handle: + close_alg_handle(alg_handle) + + +def _is_prime(bit_size, n): + """ + An implementation of Miller–Rabin for checking if a number is prime. + + :param bit_size: + An integer of the number of bits in the prime number + + :param n: + An integer, the prime number + + :return: + A boolean + """ + + r = 0 + s = n - 1 + while s % 2 == 0: + r += 1 + s //= 2 + + if bit_size >= 1300: + k = 2 + elif bit_size >= 850: + k = 3 + elif bit_size >= 650: + k = 4 + elif bit_size >= 550: + k = 5 + elif bit_size >= 450: + k = 6 + + for _ in range(k): + a = random.randrange(2, n - 1) + x = pow(a, s, n) + if x == 1 or x == n - 1: + continue + for _ in range(r - 1): + x = pow(x, 2, n) + if x == n - 1: + break + else: + return False + + return True + + +def _advapi32_interpret_rsa_key_blob(bit_size, blob_struct, blob): + """ + Takes a CryptoAPI RSA private key blob and converts it into the ASN.1 + structures for the public and private keys + + :param bit_size: + The integer bit size of the key + + :param blob_struct: + An instance of the advapi32.RSAPUBKEY struct + + :param blob: + A byte string of the binary data after the header + + :return: + A 2-element tuple of (asn1crypto.keys.PublicKeyInfo, + asn1crypto.keys.PrivateKeyInfo) + """ + + len1 = bit_size // 8 + len2 = bit_size // 16 + + prime1_offset = len1 + prime2_offset = prime1_offset + len2 + exponent1_offset = prime2_offset + len2 + exponent2_offset = exponent1_offset + len2 + coefficient_offset = exponent2_offset + len2 + private_exponent_offset = coefficient_offset + len2 + + public_exponent = blob_struct.rsapubkey.pubexp + modulus = int_from_bytes(blob[0:prime1_offset][::-1]) + prime1 = int_from_bytes(blob[prime1_offset:prime2_offset][::-1]) + prime2 = int_from_bytes(blob[prime2_offset:exponent1_offset][::-1]) + exponent1 = int_from_bytes(blob[exponent1_offset:exponent2_offset][::-1]) + exponent2 = int_from_bytes(blob[exponent2_offset:coefficient_offset][::-1]) + coefficient = int_from_bytes(blob[coefficient_offset:private_exponent_offset][::-1]) + private_exponent = int_from_bytes(blob[private_exponent_offset:private_exponent_offset + len1][::-1]) + + public_key_info = PublicKeyInfo({ + 'algorithm': PublicKeyAlgorithm({ + 'algorithm': 'rsa', + }), + 'public_key': RSAPublicKey({ + 'modulus': modulus, + 'public_exponent': public_exponent, + }), + }) + + rsa_private_key = RSAPrivateKey({ + 'version': 'two-prime', + 'modulus': modulus, + 'public_exponent': public_exponent, + 'private_exponent': private_exponent, + 'prime1': prime1, + 'prime2': prime2, + 'exponent1': exponent1, + 'exponent2': exponent2, + 'coefficient': coefficient, + }) + + private_key_info = PrivateKeyInfo({ + 'version': 0, + 'private_key_algorithm': PrivateKeyAlgorithm({ + 'algorithm': 'rsa', + }), + 'private_key': rsa_private_key, + }) + + return (public_key_info, private_key_info) + + +def _advapi32_interpret_dsa_key_blob(bit_size, public_blob, private_blob): + """ + Takes a CryptoAPI DSS private key blob and converts it into the ASN.1 + structures for the public and private keys + + :param bit_size: + The integer bit size of the key + + :param public_blob: + A byte string of the binary data after the public key header + + :param private_blob: + A byte string of the binary data after the private key header + + :return: + A 2-element tuple of (asn1crypto.keys.PublicKeyInfo, + asn1crypto.keys.PrivateKeyInfo) + """ + + len1 = 20 + len2 = bit_size // 8 + + q_offset = len2 + g_offset = q_offset + len1 + x_offset = g_offset + len2 + y_offset = x_offset + + p = int_from_bytes(private_blob[0:q_offset][::-1]) + q = int_from_bytes(private_blob[q_offset:g_offset][::-1]) + g = int_from_bytes(private_blob[g_offset:x_offset][::-1]) + x = int_from_bytes(private_blob[x_offset:x_offset + len1][::-1]) + y = int_from_bytes(public_blob[y_offset:y_offset + len2][::-1]) + + public_key_info = PublicKeyInfo({ + 'algorithm': PublicKeyAlgorithm({ + 'algorithm': 'dsa', + 'parameters': DSAParams({ + 'p': p, + 'q': q, + 'g': g, + }) + }), + 'public_key': Integer(y), + }) + + private_key_info = PrivateKeyInfo({ + 'version': 0, + 'private_key_algorithm': PrivateKeyAlgorithm({ + 'algorithm': 'dsa', + 'parameters': DSAParams({ + 'p': p, + 'q': q, + 'g': g, + }) + }), + 'private_key': Integer(x), + }) + + return (public_key_info, private_key_info) + + +def _bcrypt_interpret_rsa_key_blob(key_type, blob_struct, blob): + """ + Take a CNG BCRYPT_RSAFULLPRIVATE_BLOB and converts it into an ASN.1 + structure + + :param key_type: + A unicode string of "private" or "public" + + :param blob_struct: + An instance of BCRYPT_RSAKEY_BLOB + + :param blob: + A byte string of the binary data contained after the struct + + :return: + An asn1crypto.keys.PrivateKeyInfo or asn1crypto.keys.PublicKeyInfo + object, based on the key_type param + """ + + public_exponent_byte_length = native(int, blob_struct.cbPublicExp) + modulus_byte_length = native(int, blob_struct.cbModulus) + + modulus_offset = public_exponent_byte_length + + public_exponent = int_from_bytes(blob[0:modulus_offset]) + modulus = int_from_bytes(blob[modulus_offset:modulus_offset + modulus_byte_length]) + + if key_type == 'public': + return PublicKeyInfo({ + 'algorithm': PublicKeyAlgorithm({ + 'algorithm': 'rsa', + }), + 'public_key': RSAPublicKey({ + 'modulus': modulus, + 'public_exponent': public_exponent, + }), + }) + + elif key_type == 'private': + prime1_byte_length = native(int, blob_struct.cbPrime1) + prime2_byte_length = native(int, blob_struct.cbPrime2) + + prime1_offset = modulus_offset + modulus_byte_length + prime2_offset = prime1_offset + prime1_byte_length + exponent1_offset = prime2_offset + prime2_byte_length + exponent2_offset = exponent1_offset + prime2_byte_length + coefficient_offset = exponent2_offset + prime2_byte_length + private_exponent_offset = coefficient_offset + prime1_byte_length + + prime1 = int_from_bytes(blob[prime1_offset:prime2_offset]) + prime2 = int_from_bytes(blob[prime2_offset:exponent1_offset]) + exponent1 = int_from_bytes(blob[exponent1_offset:exponent2_offset]) + exponent2 = int_from_bytes(blob[exponent2_offset:coefficient_offset]) + coefficient = int_from_bytes(blob[coefficient_offset:private_exponent_offset]) + private_exponent = int_from_bytes(blob[private_exponent_offset:private_exponent_offset + modulus_byte_length]) + + rsa_private_key = RSAPrivateKey({ + 'version': 'two-prime', + 'modulus': modulus, + 'public_exponent': public_exponent, + 'private_exponent': private_exponent, + 'prime1': prime1, + 'prime2': prime2, + 'exponent1': exponent1, + 'exponent2': exponent2, + 'coefficient': coefficient, + }) + + return PrivateKeyInfo({ + 'version': 0, + 'private_key_algorithm': PrivateKeyAlgorithm({ + 'algorithm': 'rsa', + }), + 'private_key': rsa_private_key, + }) + + else: + raise ValueError(pretty_message( + ''' + key_type must be one of "public", "private", not %s + ''', + repr(key_type) + )) + + +def _bcrypt_interpret_dsa_key_blob(key_type, version, blob_struct, blob): + """ + Take a CNG BCRYPT_DSA_KEY_BLOB or BCRYPT_DSA_KEY_BLOB_V2 and converts it + into an ASN.1 structure + + :param key_type: + A unicode string of "private" or "public" + + :param version: + An integer - 1 or 2, indicating the blob is BCRYPT_DSA_KEY_BLOB or + BCRYPT_DSA_KEY_BLOB_V2 + + :param blob_struct: + An instance of BCRYPT_DSA_KEY_BLOB or BCRYPT_DSA_KEY_BLOB_V2 + + :param blob: + A byte string of the binary data contained after the struct + + :return: + An asn1crypto.keys.PrivateKeyInfo or asn1crypto.keys.PublicKeyInfo + object, based on the key_type param + """ + + key_byte_length = native(int, blob_struct.cbKey) + + if version == 1: + q = int_from_bytes(native(byte_cls, blob_struct.q)) + + g_offset = key_byte_length + public_offset = g_offset + key_byte_length + private_offset = public_offset + key_byte_length + + p = int_from_bytes(blob[0:g_offset]) + g = int_from_bytes(blob[g_offset:public_offset]) + + elif version == 2: + seed_byte_length = native(int, blob_struct.cbSeedLength) + group_byte_length = native(int, blob_struct.cbGroupSize) + + q_offset = seed_byte_length + p_offset = q_offset + group_byte_length + g_offset = p_offset + key_byte_length + public_offset = g_offset + key_byte_length + private_offset = public_offset + key_byte_length + + # The seed is skipped since it is not part of the ASN.1 structure + q = int_from_bytes(blob[q_offset:p_offset]) + p = int_from_bytes(blob[p_offset:g_offset]) + g = int_from_bytes(blob[g_offset:public_offset]) + + else: + raise ValueError('version must be 1 or 2, not %s' % repr(version)) + + if key_type == 'public': + public = int_from_bytes(blob[public_offset:private_offset]) + return PublicKeyInfo({ + 'algorithm': PublicKeyAlgorithm({ + 'algorithm': 'dsa', + 'parameters': DSAParams({ + 'p': p, + 'q': q, + 'g': g, + }) + }), + 'public_key': Integer(public), + }) + + elif key_type == 'private': + private = int_from_bytes(blob[private_offset:private_offset + key_byte_length]) + return PrivateKeyInfo({ + 'version': 0, + 'private_key_algorithm': PrivateKeyAlgorithm({ + 'algorithm': 'dsa', + 'parameters': DSAParams({ + 'p': p, + 'q': q, + 'g': g, + }) + }), + 'private_key': Integer(private), + }) + + else: + raise ValueError(pretty_message( + ''' + key_type must be one of "public", "private", not %s + ''', + repr(key_type) + )) + + +def _bcrypt_interpret_ec_key_blob(key_type, blob_struct, blob): + """ + Take a CNG BCRYPT_ECCKEY_BLOB and converts it into an ASN.1 structure + + :param key_type: + A unicode string of "private" or "public" + + :param blob_struct: + An instance of BCRYPT_ECCKEY_BLOB + + :param blob: + A byte string of the binary data contained after the struct + + :return: + An asn1crypto.keys.PrivateKeyInfo or asn1crypto.keys.PublicKeyInfo + object, based on the key_type param + """ + + magic = native(int, blob_struct.dwMagic) + key_byte_length = native(int, blob_struct.cbKey) + + curve = { + BcryptConst.BCRYPT_ECDSA_PRIVATE_P256_MAGIC: 'secp256r1', + BcryptConst.BCRYPT_ECDSA_PRIVATE_P384_MAGIC: 'secp384r1', + BcryptConst.BCRYPT_ECDSA_PRIVATE_P521_MAGIC: 'secp521r1', + BcryptConst.BCRYPT_ECDSA_PUBLIC_P256_MAGIC: 'secp256r1', + BcryptConst.BCRYPT_ECDSA_PUBLIC_P384_MAGIC: 'secp384r1', + BcryptConst.BCRYPT_ECDSA_PUBLIC_P521_MAGIC: 'secp521r1', + }[magic] + + public = b'\x04' + blob[0:key_byte_length * 2] + + if key_type == 'public': + return PublicKeyInfo({ + 'algorithm': PublicKeyAlgorithm({ + 'algorithm': 'ec', + 'parameters': ECDomainParameters( + name='named', + value=curve + ) + }), + 'public_key': public, + }) + + elif key_type == 'private': + private = int_from_bytes(blob[key_byte_length * 2:key_byte_length * 3]) + return PrivateKeyInfo({ + 'version': 0, + 'private_key_algorithm': PrivateKeyAlgorithm({ + 'algorithm': 'ec', + 'parameters': ECDomainParameters( + name='named', + value=curve + ) + }), + 'private_key': ECPrivateKey({ + 'version': 'ecPrivkeyVer1', + 'private_key': private, + 'public_key': public, + }), + }) + + else: + raise ValueError(pretty_message( + ''' + key_type must be one of "public", "private", not %s + ''', + repr(key_type) + )) + + +def load_certificate(source): + """ + Loads an x509 certificate into a Certificate object + + :param source: + A byte string of file contents or a unicode string filename + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + + :return: + A Certificate object + """ + + if isinstance(source, Asn1Certificate): + certificate = source + + elif isinstance(source, byte_cls): + certificate = parse_certificate(source) + + elif isinstance(source, str_cls): + with open(source, 'rb') as f: + certificate = parse_certificate(f.read()) + + else: + raise TypeError(pretty_message( + ''' + source must be a byte string, unicode string or + asn1crypto.x509.Certificate object, not %s + ''', + type_name(source) + )) + + return _load_key(certificate, Certificate) + + +def _load_key(key_object, container): + """ + Loads a certificate, public key or private key into a Certificate, + PublicKey or PrivateKey object + + :param key_object: + An asn1crypto.x509.Certificate, asn1crypto.keys.PublicKeyInfo or + asn1crypto.keys.PrivateKeyInfo object + + :param container: + The class of the object to hold the key_handle + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + oscrypto.errors.AsymmetricKeyError - when the key is incompatible with the OS crypto library + OSError - when an error is returned by the OS crypto library + + :return: + A PrivateKey, PublicKey or Certificate object, based on container + """ + + key_info = key_object + if isinstance(key_object, Asn1Certificate): + key_info = key_object['tbs_certificate']['subject_public_key_info'] + + algo = key_info.algorithm + curve_name = None + + if algo == 'ec': + curve_type, curve_name = key_info.curve + if curve_type != 'named': + raise AsymmetricKeyError(pretty_message( + ''' + Windows only supports EC keys using named curves + ''' + )) + if curve_name not in set(['secp256r1', 'secp384r1', 'secp521r1']): + raise AsymmetricKeyError(pretty_message( + ''' + Windows only supports EC keys using the named curves + secp256r1, secp384r1 and secp521r1 + ''' + )) + + elif algo == 'dsa': + if key_info.hash_algo is None: + raise IncompleteAsymmetricKeyError(pretty_message( + ''' + The DSA key does not contain the necessary p, q and g + parameters and can not be used + ''' + )) + elif key_info.bit_size > 1024 and (_win_version_info < (6, 2) or _backend == 'winlegacy'): + raise AsymmetricKeyError(pretty_message( + ''' + Windows XP, 2003, Vista, 7 and Server 2008 only support DSA + keys based on SHA1 (1024 bits or less) - this key is based + on %s and is %s bits + ''', + key_info.hash_algo.upper(), + key_info.bit_size + )) + elif key_info.bit_size == 2048 and key_info.hash_algo == 'sha1': + raise AsymmetricKeyError(pretty_message( + ''' + Windows only supports 2048 bit DSA keys based on SHA2 - this + key is 2048 bits and based on SHA1, a non-standard + combination that is usually generated by old versions + of OpenSSL + ''' + )) + + if _backend == 'winlegacy': + if algo == 'ec': + return container(None, key_object) + return _advapi32_load_key(key_object, key_info, container) + return _bcrypt_load_key(key_object, key_info, container, curve_name) + + +def _advapi32_load_key(key_object, key_info, container): + """ + Loads a certificate, public key or private key into a Certificate, + PublicKey or PrivateKey object via CryptoAPI + + :param key_object: + An asn1crypto.x509.Certificate, asn1crypto.keys.PublicKeyInfo or + asn1crypto.keys.PrivateKeyInfo object + + :param key_info: + An asn1crypto.keys.PublicKeyInfo or asn1crypto.keys.PrivateKeyInfo + object + + :param container: + The class of the object to hold the key_handle + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + oscrypto.errors.AsymmetricKeyError - when the key is incompatible with the OS crypto library + OSError - when an error is returned by the OS crypto library + + :return: + A PrivateKey, PublicKey or Certificate object, based on container + """ + + key_type = 'public' if isinstance(key_info, PublicKeyInfo) else 'private' + algo = key_info.algorithm + + if algo == 'rsa': + provider = Advapi32Const.MS_ENH_RSA_AES_PROV + else: + provider = Advapi32Const.MS_ENH_DSS_DH_PROV + + context_handle = None + key_handle = None + + try: + context_handle = open_context_handle(provider, verify_only=key_type == 'public') + + blob = _advapi32_create_blob(key_info, key_type, algo) + buffer_ = buffer_from_bytes(blob) + + key_handle_pointer = new(advapi32, 'HCRYPTKEY *') + res = advapi32.CryptImportKey( + context_handle, + buffer_, + len(blob), + null(), + 0, + key_handle_pointer + ) + handle_error(res) + + key_handle = unwrap(key_handle_pointer) + output = container(key_handle, key_object) + output.context_handle = context_handle + + if algo == 'rsa': + ex_blob = _advapi32_create_blob(key_info, key_type, algo, signing=False) + ex_buffer = buffer_from_bytes(ex_blob) + + ex_key_handle_pointer = new(advapi32, 'HCRYPTKEY *') + res = advapi32.CryptImportKey( + context_handle, + ex_buffer, + len(ex_blob), + null(), + 0, + ex_key_handle_pointer + ) + handle_error(res) + + output.ex_key_handle = unwrap(ex_key_handle_pointer) + + return output + + except (Exception): + if key_handle: + advapi32.CryptDestroyKey(key_handle) + if context_handle: + close_context_handle(context_handle) + raise + + +def _advapi32_create_blob(key_info, key_type, algo, signing=True): + """ + Generates a blob for importing a key to CryptoAPI + + :param key_info: + An asn1crypto.keys.PublicKeyInfo or asn1crypto.keys.PrivateKeyInfo + object + + :param key_type: + A unicode string of "public" or "private" + + :param algo: + A unicode string of "rsa" or "dsa" + + :param signing: + If the key handle is for signing - may only be False for rsa keys + + :return: + A byte string of a blob to pass to advapi32.CryptImportKey() + """ + + if key_type == 'public': + blob_type = Advapi32Const.PUBLICKEYBLOB + else: + blob_type = Advapi32Const.PRIVATEKEYBLOB + + if algo == 'rsa': + struct_type = 'RSABLOBHEADER' + if signing: + algorithm_id = Advapi32Const.CALG_RSA_SIGN + else: + algorithm_id = Advapi32Const.CALG_RSA_KEYX + else: + struct_type = 'DSSBLOBHEADER' + algorithm_id = Advapi32Const.CALG_DSS_SIGN + + blob_header_pointer = struct(advapi32, 'BLOBHEADER') + blob_header = unwrap(blob_header_pointer) + blob_header.bType = blob_type + blob_header.bVersion = Advapi32Const.CUR_BLOB_VERSION + blob_header.reserved = 0 + blob_header.aiKeyAlg = algorithm_id + + blob_struct_pointer = struct(advapi32, struct_type) + blob_struct = unwrap(blob_struct_pointer) + blob_struct.publickeystruc = blob_header + + bit_size = key_info.bit_size + len1 = bit_size // 8 + len2 = bit_size // 16 + + if algo == 'rsa': + pubkey_pointer = struct(advapi32, 'RSAPUBKEY') + pubkey = unwrap(pubkey_pointer) + pubkey.bitlen = bit_size + if key_type == 'public': + parsed_key_info = key_info['public_key'].parsed + pubkey.magic = Advapi32Const.RSA1 + pubkey.pubexp = parsed_key_info['public_exponent'].native + blob_data = int_to_bytes(parsed_key_info['modulus'].native, signed=False, width=len1)[::-1] + else: + parsed_key_info = key_info['private_key'].parsed + pubkey.magic = Advapi32Const.RSA2 + pubkey.pubexp = parsed_key_info['public_exponent'].native + blob_data = int_to_bytes(parsed_key_info['modulus'].native, signed=False, width=len1)[::-1] + blob_data += int_to_bytes(parsed_key_info['prime1'].native, signed=False, width=len2)[::-1] + blob_data += int_to_bytes(parsed_key_info['prime2'].native, signed=False, width=len2)[::-1] + blob_data += int_to_bytes(parsed_key_info['exponent1'].native, signed=False, width=len2)[::-1] + blob_data += int_to_bytes(parsed_key_info['exponent2'].native, signed=False, width=len2)[::-1] + blob_data += int_to_bytes(parsed_key_info['coefficient'].native, signed=False, width=len2)[::-1] + blob_data += int_to_bytes(parsed_key_info['private_exponent'].native, signed=False, width=len1)[::-1] + blob_struct.rsapubkey = pubkey + + else: + pubkey_pointer = struct(advapi32, 'DSSPUBKEY') + pubkey = unwrap(pubkey_pointer) + pubkey.bitlen = bit_size + + if key_type == 'public': + pubkey.magic = Advapi32Const.DSS1 + params = key_info['algorithm']['parameters'].native + key_data = int_to_bytes(key_info['public_key'].parsed.native, signed=False, width=len1)[::-1] + else: + pubkey.magic = Advapi32Const.DSS2 + params = key_info['private_key_algorithm']['parameters'].native + key_data = int_to_bytes(key_info['private_key'].parsed.native, signed=False, width=20)[::-1] + blob_struct.dsspubkey = pubkey + + blob_data = int_to_bytes(params['p'], signed=False, width=len1)[::-1] + blob_data += int_to_bytes(params['q'], signed=False, width=20)[::-1] + blob_data += int_to_bytes(params['g'], signed=False, width=len1)[::-1] + blob_data += key_data + + dssseed_pointer = struct(advapi32, 'DSSSEED') + dssseed = unwrap(dssseed_pointer) + # This indicates no counter or seed info is available + dssseed.counter = 0xffffffff + + blob_data += struct_bytes(dssseed_pointer) + + return struct_bytes(blob_struct_pointer) + blob_data + + +def _bcrypt_load_key(key_object, key_info, container, curve_name): + """ + Loads a certificate, public key or private key into a Certificate, + PublicKey or PrivateKey object via CNG + + :param key_object: + An asn1crypto.x509.Certificate, asn1crypto.keys.PublicKeyInfo or + asn1crypto.keys.PrivateKeyInfo object + + :param key_info: + An asn1crypto.keys.PublicKeyInfo or asn1crypto.keys.PrivateKeyInfo + object + + :param container: + The class of the object to hold the key_handle + + :param curve_name: + None or a unicode string of the curve name for an EC key + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + oscrypto.errors.AsymmetricKeyError - when the key is incompatible with the OS crypto library + OSError - when an error is returned by the OS crypto library + + :return: + A PrivateKey, PublicKey or Certificate object, based on container + """ + + alg_handle = None + key_handle = None + + key_type = 'public' if isinstance(key_info, PublicKeyInfo) else 'private' + algo = key_info.algorithm + + try: + alg_selector = key_info.curve[1] if algo == 'ec' else algo + alg_constant = { + 'rsa': BcryptConst.BCRYPT_RSA_ALGORITHM, + 'dsa': BcryptConst.BCRYPT_DSA_ALGORITHM, + 'secp256r1': BcryptConst.BCRYPT_ECDSA_P256_ALGORITHM, + 'secp384r1': BcryptConst.BCRYPT_ECDSA_P384_ALGORITHM, + 'secp521r1': BcryptConst.BCRYPT_ECDSA_P521_ALGORITHM, + }[alg_selector] + alg_handle = open_alg_handle(alg_constant) + + if algo == 'rsa': + if key_type == 'public': + blob_type = BcryptConst.BCRYPT_RSAPUBLIC_BLOB + magic = BcryptConst.BCRYPT_RSAPUBLIC_MAGIC + parsed_key = key_info['public_key'].parsed + prime1_size = 0 + prime2_size = 0 + else: + blob_type = BcryptConst.BCRYPT_RSAFULLPRIVATE_BLOB + magic = BcryptConst.BCRYPT_RSAFULLPRIVATE_MAGIC + parsed_key = key_info['private_key'].parsed + prime1 = int_to_bytes(parsed_key['prime1'].native) + prime2 = int_to_bytes(parsed_key['prime2'].native) + exponent1 = int_to_bytes(parsed_key['exponent1'].native) + exponent2 = int_to_bytes(parsed_key['exponent2'].native) + coefficient = int_to_bytes(parsed_key['coefficient'].native) + private_exponent = int_to_bytes(parsed_key['private_exponent'].native) + prime1_size = len(prime1) + prime2_size = len(prime2) + + public_exponent = int_to_bytes(parsed_key['public_exponent'].native) + modulus = int_to_bytes(parsed_key['modulus'].native) + + blob_struct_pointer = struct(bcrypt, 'BCRYPT_RSAKEY_BLOB') + blob_struct = unwrap(blob_struct_pointer) + blob_struct.Magic = magic + blob_struct.BitLength = key_info.bit_size + blob_struct.cbPublicExp = len(public_exponent) + blob_struct.cbModulus = len(modulus) + blob_struct.cbPrime1 = prime1_size + blob_struct.cbPrime2 = prime2_size + + blob = struct_bytes(blob_struct_pointer) + public_exponent + modulus + if key_type == 'private': + blob += prime1 + prime2 + blob += fill_width(exponent1, prime1_size) + blob += fill_width(exponent2, prime2_size) + blob += fill_width(coefficient, prime1_size) + blob += fill_width(private_exponent, len(modulus)) + + elif algo == 'dsa': + if key_type == 'public': + blob_type = BcryptConst.BCRYPT_DSA_PUBLIC_BLOB + public_key = key_info['public_key'].parsed.native + params = key_info['algorithm']['parameters'] + else: + blob_type = BcryptConst.BCRYPT_DSA_PRIVATE_BLOB + public_key = _unwrap_private_key_info(key_info)['public_key'].native + private_bytes = int_to_bytes(key_info['private_key'].parsed.native) + params = key_info['private_key_algorithm']['parameters'] + + public_bytes = int_to_bytes(public_key) + p = int_to_bytes(params['p'].native) + g = int_to_bytes(params['g'].native) + q = int_to_bytes(params['q'].native) + + if key_info.bit_size > 1024: + q_len = len(q) + else: + q_len = 20 + + key_width = max(len(public_bytes), len(g), len(p)) + + public_bytes = fill_width(public_bytes, key_width) + p = fill_width(p, key_width) + g = fill_width(g, key_width) + q = fill_width(q, q_len) + # We don't know the count or seed, so we set them to the max value + # since setting them to 0 results in a parameter error + count = b'\xff' * 4 + seed = b'\xff' * q_len + + if key_info.bit_size > 1024: + if key_type == 'public': + magic = BcryptConst.BCRYPT_DSA_PUBLIC_MAGIC_V2 + else: + magic = BcryptConst.BCRYPT_DSA_PRIVATE_MAGIC_V2 + + blob_struct_pointer = struct(bcrypt, 'BCRYPT_DSA_KEY_BLOB_V2') + blob_struct = unwrap(blob_struct_pointer) + blob_struct.dwMagic = magic + blob_struct.cbKey = key_width + # We don't know if SHA256 was used here, but the output is long + # enough for the generation of q for the supported 2048/224, + # 2048/256 and 3072/256 FIPS approved pairs + blob_struct.hashAlgorithm = BcryptConst.DSA_HASH_ALGORITHM_SHA256 + blob_struct.standardVersion = BcryptConst.DSA_FIPS186_3 + blob_struct.cbSeedLength = q_len + blob_struct.cbGroupSize = q_len + blob_struct.Count = byte_array(count) + + blob = struct_bytes(blob_struct_pointer) + blob += seed + q + p + g + public_bytes + if key_type == 'private': + blob += fill_width(private_bytes, q_len) + + else: + if key_type == 'public': + magic = BcryptConst.BCRYPT_DSA_PUBLIC_MAGIC + else: + magic = BcryptConst.BCRYPT_DSA_PRIVATE_MAGIC + + blob_struct_pointer = struct(bcrypt, 'BCRYPT_DSA_KEY_BLOB') + blob_struct = unwrap(blob_struct_pointer) + blob_struct.dwMagic = magic + blob_struct.cbKey = key_width + blob_struct.Count = byte_array(count) + blob_struct.Seed = byte_array(seed) + blob_struct.q = byte_array(q) + + blob = struct_bytes(blob_struct_pointer) + p + g + public_bytes + if key_type == 'private': + blob += fill_width(private_bytes, q_len) + + elif algo == 'ec': + if key_type == 'public': + blob_type = BcryptConst.BCRYPT_ECCPUBLIC_BLOB + x, y = key_info['public_key'].to_coords() + else: + blob_type = BcryptConst.BCRYPT_ECCPRIVATE_BLOB + public_key = key_info['private_key'].parsed['public_key'] + # We aren't guaranteed to get the public key coords with the + # key info structure, but BCrypt doesn't seem to have an issue + # importing the private key with 0 values, which can only be + # presumed that it is generating the x and y points from the + # private key value and base point + if public_key: + x, y = public_key.to_coords() + else: + x = 0 + y = 0 + private_bytes = int_to_bytes(key_info['private_key'].parsed['private_key'].native) + + blob_struct_pointer = struct(bcrypt, 'BCRYPT_ECCKEY_BLOB') + blob_struct = unwrap(blob_struct_pointer) + + magic = { + ('public', 'secp256r1'): BcryptConst.BCRYPT_ECDSA_PUBLIC_P256_MAGIC, + ('public', 'secp384r1'): BcryptConst.BCRYPT_ECDSA_PUBLIC_P384_MAGIC, + ('public', 'secp521r1'): BcryptConst.BCRYPT_ECDSA_PUBLIC_P521_MAGIC, + ('private', 'secp256r1'): BcryptConst.BCRYPT_ECDSA_PRIVATE_P256_MAGIC, + ('private', 'secp384r1'): BcryptConst.BCRYPT_ECDSA_PRIVATE_P384_MAGIC, + ('private', 'secp521r1'): BcryptConst.BCRYPT_ECDSA_PRIVATE_P521_MAGIC, + }[(key_type, curve_name)] + + key_width = { + 'secp256r1': 32, + 'secp384r1': 48, + 'secp521r1': 66 + }[curve_name] + + x_bytes = int_to_bytes(x) + y_bytes = int_to_bytes(y) + + x_bytes = fill_width(x_bytes, key_width) + y_bytes = fill_width(y_bytes, key_width) + + blob_struct.dwMagic = magic + blob_struct.cbKey = key_width + + blob = struct_bytes(blob_struct_pointer) + x_bytes + y_bytes + if key_type == 'private': + blob += fill_width(private_bytes, key_width) + + key_handle_pointer = new(bcrypt, 'BCRYPT_KEY_HANDLE *') + res = bcrypt.BCryptImportKeyPair( + alg_handle, + null(), + blob_type, + key_handle_pointer, + blob, + len(blob), + BcryptConst.BCRYPT_NO_KEY_VALIDATION + ) + handle_error(res) + + key_handle = unwrap(key_handle_pointer) + return container(key_handle, key_object) + + finally: + if alg_handle: + close_alg_handle(alg_handle) + + +def load_private_key(source, password=None): + """ + Loads a private key into a PrivateKey object + + :param source: + A byte string of file contents, a unicode string filename or an + asn1crypto.keys.PrivateKeyInfo object + + :param password: + A byte or unicode string to decrypt the private key file. Unicode + strings will be encoded using UTF-8. Not used is the source is a + PrivateKeyInfo object. + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + oscrypto.errors.AsymmetricKeyError - when the private key is incompatible with the OS crypto library + OSError - when an error is returned by the OS crypto library + + :return: + A PrivateKey object + """ + + if isinstance(source, PrivateKeyInfo): + private_object = source + + else: + if password is not None: + if isinstance(password, str_cls): + password = password.encode('utf-8') + if not isinstance(password, byte_cls): + raise TypeError(pretty_message( + ''' + password must be a byte string, not %s + ''', + type_name(password) + )) + + if isinstance(source, str_cls): + with open(source, 'rb') as f: + source = f.read() + + elif not isinstance(source, byte_cls): + raise TypeError(pretty_message( + ''' + source must be a byte string, unicode string or + asn1crypto.keys.PrivateKeyInfo object, not %s + ''', + type_name(source) + )) + + private_object = parse_private(source, password) + + return _load_key(private_object, PrivateKey) + + +def load_public_key(source): + """ + Loads a public key into a PublicKey object + + :param source: + A byte string of file contents, a unicode string filename or an + asn1crypto.keys.PublicKeyInfo object + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + oscrypto.errors.AsymmetricKeyError - when the public key is incompatible with the OS crypto library + OSError - when an error is returned by the OS crypto library + + :return: + A PublicKey object + """ + + if isinstance(source, PublicKeyInfo): + public_key = source + + elif isinstance(source, byte_cls): + public_key = parse_public(source) + + elif isinstance(source, str_cls): + with open(source, 'rb') as f: + public_key = parse_public(f.read()) + + else: + raise TypeError(pretty_message( + ''' + source must be a byte string, unicode string or + asn1crypto.keys.PublicKeyInfo object, not %s + ''', + type_name(public_key) + )) + + return _load_key(public_key, PublicKey) + + +def parse_pkcs12(data, password=None): + """ + Parses a PKCS#12 ANS.1 DER-encoded structure and extracts certs and keys + + :param data: + A byte string of a DER-encoded PKCS#12 file + + :param password: + A byte string of the password to any encrypted data + + :raises: + ValueError - when any of the parameters are of the wrong type or value + OSError - when an error is returned by one of the OS decryption functions + + :return: + A three-element tuple of: + 1. An asn1crypto.keys.PrivateKeyInfo object + 2. An asn1crypto.x509.Certificate object + 3. A list of zero or more asn1crypto.x509.Certificate objects that are + "extra" certificates, possibly intermediates from the cert chain + """ + + return _parse_pkcs12(data, password, load_private_key) + + +def load_pkcs12(source, password=None): + """ + Loads a .p12 or .pfx file into a PrivateKey object and one or more + Certificates objects + + :param source: + A byte string of file contents or a unicode string filename + + :param password: + A byte or unicode string to decrypt the PKCS12 file. Unicode strings + will be encoded using UTF-8. + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + oscrypto.errors.AsymmetricKeyError - when a contained key is incompatible with the OS crypto library + OSError - when an error is returned by the OS crypto library + + :return: + A three-element tuple containing (PrivateKey, Certificate, [Certificate, ...]) + """ + + if password is not None: + if isinstance(password, str_cls): + password = password.encode('utf-8') + if not isinstance(password, byte_cls): + raise TypeError(pretty_message( + ''' + password must be a byte string, not %s + ''', + type_name(password) + )) + + if isinstance(source, str_cls): + with open(source, 'rb') as f: + source = f.read() + + elif not isinstance(source, byte_cls): + raise TypeError(pretty_message( + ''' + source must be a byte string or a unicode string, not %s + ''', + type_name(source) + )) + + key_info, cert_info, extra_certs_info = parse_pkcs12(source, password) + + key = None + cert = None + + if key_info: + key = _load_key(key_info, PrivateKey) + + if cert_info: + cert = _load_key(cert_info.public_key, Certificate) + + extra_certs = [_load_key(info.public_key, Certificate) for info in extra_certs_info] + + return (key, cert, extra_certs) + + +def rsa_pkcs1v15_verify(certificate_or_public_key, signature, data, hash_algorithm): + """ + Verifies an RSASSA-PKCS-v1.5 signature. + + When the hash_algorithm is "raw", the operation is identical to RSA + public key decryption. That is: the data is not hashed and no ASN.1 + structure with an algorithm identifier of the hash algorithm is placed in + the encrypted byte string. + + :param certificate_or_public_key: + A Certificate or PublicKey instance to verify the signature with + + :param signature: + A byte string of the signature to verify + + :param data: + A byte string of the data the signature is for + + :param hash_algorithm: + A unicode string of "md5", "sha1", "sha256", "sha384", "sha512" or "raw" + + :raises: + oscrypto.errors.SignatureError - when the signature is determined to be invalid + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + """ + + if certificate_or_public_key.algorithm != 'rsa': + raise ValueError('The key specified is not an RSA public key') + + return _verify(certificate_or_public_key, signature, data, hash_algorithm) + + +def rsa_pss_verify(certificate_or_public_key, signature, data, hash_algorithm): + """ + Verifies an RSASSA-PSS signature. For the PSS padding the mask gen algorithm + will be mgf1 using the same hash algorithm as the signature. The salt length + with be the length of the hash algorithm, and the trailer field with be the + standard 0xBC byte. + + :param certificate_or_public_key: + A Certificate or PublicKey instance to verify the signature with + + :param signature: + A byte string of the signature to verify + + :param data: + A byte string of the data the signature is for + + :param hash_algorithm: + A unicode string of "md5", "sha1", "sha256", "sha384" or "sha512" + + :raises: + oscrypto.errors.SignatureError - when the signature is determined to be invalid + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + """ + + if certificate_or_public_key.algorithm != 'rsa': + raise ValueError('The key specified is not an RSA public key') + + return _verify(certificate_or_public_key, signature, data, hash_algorithm, rsa_pss_padding=True) + + +def dsa_verify(certificate_or_public_key, signature, data, hash_algorithm): + """ + Verifies a DSA signature + + :param certificate_or_public_key: + A Certificate or PublicKey instance to verify the signature with + + :param signature: + A byte string of the signature to verify + + :param data: + A byte string of the data the signature is for + + :param hash_algorithm: + A unicode string of "md5", "sha1", "sha256", "sha384" or "sha512" + + :raises: + oscrypto.errors.SignatureError - when the signature is determined to be invalid + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + """ + + if certificate_or_public_key.algorithm != 'dsa': + raise ValueError('The key specified is not a DSA public key') + + return _verify(certificate_or_public_key, signature, data, hash_algorithm) + + +def ecdsa_verify(certificate_or_public_key, signature, data, hash_algorithm): + """ + Verifies an ECDSA signature + + :param certificate_or_public_key: + A Certificate or PublicKey instance to verify the signature with + + :param signature: + A byte string of the signature to verify + + :param data: + A byte string of the data the signature is for + + :param hash_algorithm: + A unicode string of "md5", "sha1", "sha256", "sha384" or "sha512" + + :raises: + oscrypto.errors.SignatureError - when the signature is determined to be invalid + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + """ + + if certificate_or_public_key.algorithm != 'ec': + raise ValueError('The key specified is not an EC public key') + + return _verify(certificate_or_public_key, signature, data, hash_algorithm) + + +def _verify(certificate_or_public_key, signature, data, hash_algorithm, rsa_pss_padding=False): + """ + Verifies an RSA, DSA or ECDSA signature + + :param certificate_or_public_key: + A Certificate or PublicKey instance to verify the signature with + + :param signature: + A byte string of the signature to verify + + :param data: + A byte string of the data the signature is for + + :param hash_algorithm: + A unicode string of "md5", "sha1", "sha256", "sha384", "sha512" or "raw" + + :param rsa_pss_padding: + If PSS padding should be used for RSA keys + + :raises: + oscrypto.errors.SignatureError - when the signature is determined to be invalid + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + """ + + if not isinstance(certificate_or_public_key, (Certificate, PublicKey)): + raise TypeError(pretty_message( + ''' + certificate_or_public_key must be an instance of the Certificate or + PublicKey class, not %s + ''', + type_name(certificate_or_public_key) + )) + + if not isinstance(signature, byte_cls): + raise TypeError(pretty_message( + ''' + signature must be a byte string, not %s + ''', + type_name(signature) + )) + + if not isinstance(data, byte_cls): + raise TypeError(pretty_message( + ''' + data must be a byte string, not %s + ''', + type_name(data) + )) + + valid_hash_algorithms = set(['md5', 'sha1', 'sha256', 'sha384', 'sha512']) + if certificate_or_public_key.algorithm == 'rsa' and not rsa_pss_padding: + valid_hash_algorithms |= set(['raw']) + + if hash_algorithm not in valid_hash_algorithms: + valid_hash_algorithms_error = '"md5", "sha1", "sha256", "sha384", "sha512"' + if certificate_or_public_key.algorithm == 'rsa' and not rsa_pss_padding: + valid_hash_algorithms_error += ', "raw"' + raise ValueError(pretty_message( + ''' + hash_algorithm must be one of %s, not %s + ''', + valid_hash_algorithms_error, + repr(hash_algorithm) + )) + + if certificate_or_public_key.algorithm != 'rsa' and rsa_pss_padding is not False: + raise ValueError(pretty_message( + ''' + PSS padding may only be used with RSA keys - signing via a %s key + was requested + ''', + certificate_or_public_key.algorithm.upper() + )) + + if hash_algorithm == 'raw': + if len(data) > certificate_or_public_key.byte_size - 11: + raise ValueError(pretty_message( + ''' + data must be 11 bytes shorter than the key size when + hash_algorithm is "raw" - key size is %s bytes, but + data is %s bytes long + ''', + certificate_or_public_key.byte_size, + len(data) + )) + + if _backend == 'winlegacy': + if certificate_or_public_key.algorithm == 'ec': + return _pure_python_ecdsa_verify(certificate_or_public_key, signature, data, hash_algorithm) + return _advapi32_verify(certificate_or_public_key, signature, data, hash_algorithm, rsa_pss_padding) + return _bcrypt_verify(certificate_or_public_key, signature, data, hash_algorithm, rsa_pss_padding) + + +def _advapi32_verify(certificate_or_public_key, signature, data, hash_algorithm, rsa_pss_padding=False): + """ + Verifies an RSA, DSA or ECDSA signature via CryptoAPI + + :param certificate_or_public_key: + A Certificate or PublicKey instance to verify the signature with + + :param signature: + A byte string of the signature to verify + + :param data: + A byte string of the data the signature is for + + :param hash_algorithm: + A unicode string of "md5", "sha1", "sha256", "sha384", "sha512" or "raw" + + :param rsa_pss_padding: + If PSS padding should be used for RSA keys + + :raises: + oscrypto.errors.SignatureError - when the signature is determined to be invalid + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + """ + + algo = certificate_or_public_key.algorithm + + if algo == 'rsa' and rsa_pss_padding: + hash_length = { + 'sha1': 20, + 'sha224': 28, + 'sha256': 32, + 'sha384': 48, + 'sha512': 64 + }.get(hash_algorithm, 0) + decrypted_signature = raw_rsa_public_crypt(certificate_or_public_key, signature) + key_size = certificate_or_public_key.bit_size + if not verify_pss_padding(hash_algorithm, hash_length, key_size, data, decrypted_signature): + raise SignatureError('Signature is invalid') + return + + if algo == 'rsa' and hash_algorithm == 'raw': + padded_plaintext = raw_rsa_public_crypt(certificate_or_public_key, signature) + try: + plaintext = remove_pkcs1v15_signature_padding(certificate_or_public_key.byte_size, padded_plaintext) + if not constant_compare(plaintext, data): + raise ValueError() + except (ValueError): + raise SignatureError('Signature is invalid') + return + + hash_handle = None + + try: + alg_id = { + 'md5': Advapi32Const.CALG_MD5, + 'sha1': Advapi32Const.CALG_SHA1, + 'sha256': Advapi32Const.CALG_SHA_256, + 'sha384': Advapi32Const.CALG_SHA_384, + 'sha512': Advapi32Const.CALG_SHA_512, + }[hash_algorithm] + + hash_handle_pointer = new(advapi32, 'HCRYPTHASH *') + res = advapi32.CryptCreateHash( + certificate_or_public_key.context_handle, + alg_id, + null(), + 0, + hash_handle_pointer + ) + handle_error(res) + + hash_handle = unwrap(hash_handle_pointer) + + res = advapi32.CryptHashData(hash_handle, data, len(data), 0) + handle_error(res) + + if algo == 'dsa': + # Windows doesn't use the ASN.1 Sequence for DSA signatures, + # so we have to convert it here for the verification to work + try: + signature = DSASignature.load(signature).to_p1363() + # Switch the two integers so that the reversal later will + # result in the correct order + half_len = len(signature) // 2 + signature = signature[half_len:] + signature[:half_len] + except (ValueError, OverflowError, TypeError): + raise SignatureError('Signature is invalid') + + # The CryptoAPI expects signatures to be in little endian byte order, + # which is the opposite of other systems, so we must reverse it + reversed_signature = signature[::-1] + + res = advapi32.CryptVerifySignatureW( + hash_handle, + reversed_signature, + len(signature), + certificate_or_public_key.key_handle, + null(), + 0 + ) + handle_error(res) + + finally: + if hash_handle: + advapi32.CryptDestroyHash(hash_handle) + + +def _bcrypt_verify(certificate_or_public_key, signature, data, hash_algorithm, rsa_pss_padding=False): + """ + Verifies an RSA, DSA or ECDSA signature via CNG + + :param certificate_or_public_key: + A Certificate or PublicKey instance to verify the signature with + + :param signature: + A byte string of the signature to verify + + :param data: + A byte string of the data the signature is for + + :param hash_algorithm: + A unicode string of "md5", "sha1", "sha256", "sha384", "sha512" or "raw" + + :param rsa_pss_padding: + If PSS padding should be used for RSA keys + + :raises: + oscrypto.errors.SignatureError - when the signature is determined to be invalid + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + """ + + if hash_algorithm == 'raw': + digest = data + else: + hash_constant = { + 'md5': BcryptConst.BCRYPT_MD5_ALGORITHM, + 'sha1': BcryptConst.BCRYPT_SHA1_ALGORITHM, + 'sha256': BcryptConst.BCRYPT_SHA256_ALGORITHM, + 'sha384': BcryptConst.BCRYPT_SHA384_ALGORITHM, + 'sha512': BcryptConst.BCRYPT_SHA512_ALGORITHM + }[hash_algorithm] + digest = getattr(hashlib, hash_algorithm)(data).digest() + + padding_info = null() + flags = 0 + + if certificate_or_public_key.algorithm == 'rsa': + if rsa_pss_padding: + flags = BcryptConst.BCRYPT_PAD_PSS + padding_info_struct_pointer = struct(bcrypt, 'BCRYPT_PSS_PADDING_INFO') + padding_info_struct = unwrap(padding_info_struct_pointer) + # This has to be assigned to a variable to prevent cffi from gc'ing it + hash_buffer = buffer_from_unicode(hash_constant) + padding_info_struct.pszAlgId = cast(bcrypt, 'wchar_t *', hash_buffer) + padding_info_struct.cbSalt = len(digest) + else: + flags = BcryptConst.BCRYPT_PAD_PKCS1 + padding_info_struct_pointer = struct(bcrypt, 'BCRYPT_PKCS1_PADDING_INFO') + padding_info_struct = unwrap(padding_info_struct_pointer) + # This has to be assigned to a variable to prevent cffi from gc'ing it + if hash_algorithm == 'raw': + padding_info_struct.pszAlgId = null() + else: + hash_buffer = buffer_from_unicode(hash_constant) + padding_info_struct.pszAlgId = cast(bcrypt, 'wchar_t *', hash_buffer) + padding_info = cast(bcrypt, 'void *', padding_info_struct_pointer) + else: + # Windows doesn't use the ASN.1 Sequence for DSA/ECDSA signatures, + # so we have to convert it here for the verification to work + try: + signature = DSASignature.load(signature).to_p1363() + except (ValueError, OverflowError, TypeError): + raise SignatureError('Signature is invalid') + + res = bcrypt.BCryptVerifySignature( + certificate_or_public_key.key_handle, + padding_info, + digest, + len(digest), + signature, + len(signature), + flags + ) + failure = res == BcryptConst.STATUS_INVALID_SIGNATURE + failure = failure or res == BcryptConst.STATUS_INVALID_PARAMETER + if failure: + raise SignatureError('Signature is invalid') + + handle_error(res) + + +def rsa_pkcs1v15_sign(private_key, data, hash_algorithm): + """ + Generates an RSASSA-PKCS-v1.5 signature. + + When the hash_algorithm is "raw", the operation is identical to RSA + private key encryption. That is: the data is not hashed and no ASN.1 + structure with an algorithm identifier of the hash algorithm is placed in + the encrypted byte string. + + :param private_key: + The PrivateKey to generate the signature with + + :param data: + A byte string of the data the signature is for + + :param hash_algorithm: + A unicode string of "md5", "sha1", "sha256", "sha384", "sha512" or "raw" + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + + :return: + A byte string of the signature + """ + + if private_key.algorithm != 'rsa': + raise ValueError('The key specified is not an RSA private key') + + return _sign(private_key, data, hash_algorithm) + + +def rsa_pss_sign(private_key, data, hash_algorithm): + """ + Generates an RSASSA-PSS signature. For the PSS padding the mask gen + algorithm will be mgf1 using the same hash algorithm as the signature. The + salt length with be the length of the hash algorithm, and the trailer field + with be the standard 0xBC byte. + + :param private_key: + The PrivateKey to generate the signature with + + :param data: + A byte string of the data the signature is for + + :param hash_algorithm: + A unicode string of "md5", "sha1", "sha256", "sha384" or "sha512" + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + + :return: + A byte string of the signature + """ + + if private_key.algorithm != 'rsa': + raise ValueError('The key specified is not an RSA private key') + + return _sign(private_key, data, hash_algorithm, rsa_pss_padding=True) + + +def dsa_sign(private_key, data, hash_algorithm): + """ + Generates a DSA signature + + :param private_key: + The PrivateKey to generate the signature with + + :param data: + A byte string of the data the signature is for + + :param hash_algorithm: + A unicode string of "md5", "sha1", "sha256", "sha384" or "sha512" + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + + :return: + A byte string of the signature + """ + + if private_key.algorithm != 'dsa': + raise ValueError('The key specified is not a DSA private key') + + return _sign(private_key, data, hash_algorithm) + + +def ecdsa_sign(private_key, data, hash_algorithm): + """ + Generates an ECDSA signature + + :param private_key: + The PrivateKey to generate the signature with + + :param data: + A byte string of the data the signature is for + + :param hash_algorithm: + A unicode string of "md5", "sha1", "sha256", "sha384" or "sha512" + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + + :return: + A byte string of the signature + """ + + if private_key.algorithm != 'ec': + raise ValueError('The key specified is not an EC private key') + + return _sign(private_key, data, hash_algorithm) + + +def _sign(private_key, data, hash_algorithm, rsa_pss_padding=False): + """ + Generates an RSA, DSA or ECDSA signature + + :param private_key: + The PrivateKey to generate the signature with + + :param data: + A byte string of the data the signature is for + + :param hash_algorithm: + A unicode string of "md5", "sha1", "sha256", "sha384", "sha512" or "raw" + + :param rsa_pss_padding: + If PSS padding should be used for RSA keys + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + + :return: + A byte string of the signature + """ + + if not isinstance(private_key, PrivateKey): + raise TypeError(pretty_message( + ''' + private_key must be an instance of PrivateKey, not %s + ''', + type_name(private_key) + )) + + if not isinstance(data, byte_cls): + raise TypeError(pretty_message( + ''' + data must be a byte string, not %s + ''', + type_name(data) + )) + + valid_hash_algorithms = set(['md5', 'sha1', 'sha256', 'sha384', 'sha512']) + if private_key.algorithm == 'rsa' and not rsa_pss_padding: + valid_hash_algorithms |= set(['raw']) + + if hash_algorithm not in valid_hash_algorithms: + valid_hash_algorithms_error = '"md5", "sha1", "sha256", "sha384", "sha512"' + if private_key.algorithm == 'rsa' and not rsa_pss_padding: + valid_hash_algorithms_error += ', "raw"' + raise ValueError(pretty_message( + ''' + hash_algorithm must be one of %s, not %s + ''', + valid_hash_algorithms_error, + repr(hash_algorithm) + )) + + if private_key.algorithm != 'rsa' and rsa_pss_padding is not False: + raise ValueError(pretty_message( + ''' + PSS padding may only be used with RSA keys - signing via a %s key + was requested + ''', + private_key.algorithm.upper() + )) + + if hash_algorithm == 'raw': + if len(data) > private_key.byte_size - 11: + raise ValueError(pretty_message( + ''' + data must be 11 bytes shorter than the key size when + hash_algorithm is "raw" - key size is %s bytes, but data + is %s bytes long + ''', + private_key.byte_size, + len(data) + )) + + if _backend == 'winlegacy': + if private_key.algorithm == 'ec': + return _pure_python_ecdsa_sign(private_key, data, hash_algorithm) + return _advapi32_sign(private_key, data, hash_algorithm, rsa_pss_padding) + return _bcrypt_sign(private_key, data, hash_algorithm, rsa_pss_padding) + + +def _advapi32_sign(private_key, data, hash_algorithm, rsa_pss_padding=False): + """ + Generates an RSA, DSA or ECDSA signature via CryptoAPI + + :param private_key: + The PrivateKey to generate the signature with + + :param data: + A byte string of the data the signature is for + + :param hash_algorithm: + A unicode string of "md5", "sha1", "sha256", "sha384", "sha512" or "raw" + + :param rsa_pss_padding: + If PSS padding should be used for RSA keys + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + + :return: + A byte string of the signature + """ + + algo = private_key.algorithm + + if algo == 'rsa' and hash_algorithm == 'raw': + padded_data = add_pkcs1v15_signature_padding(private_key.byte_size, data) + return raw_rsa_private_crypt(private_key, padded_data) + + if algo == 'rsa' and rsa_pss_padding: + hash_length = { + 'sha1': 20, + 'sha224': 28, + 'sha256': 32, + 'sha384': 48, + 'sha512': 64 + }.get(hash_algorithm, 0) + padded_data = add_pss_padding(hash_algorithm, hash_length, private_key.bit_size, data) + return raw_rsa_private_crypt(private_key, padded_data) + + if private_key.algorithm == 'dsa' and hash_algorithm == 'md5': + raise ValueError(pretty_message( + ''' + Windows does not support md5 signatures with DSA keys + ''' + )) + + hash_handle = None + + try: + alg_id = { + 'md5': Advapi32Const.CALG_MD5, + 'sha1': Advapi32Const.CALG_SHA1, + 'sha256': Advapi32Const.CALG_SHA_256, + 'sha384': Advapi32Const.CALG_SHA_384, + 'sha512': Advapi32Const.CALG_SHA_512, + }[hash_algorithm] + + hash_handle_pointer = new(advapi32, 'HCRYPTHASH *') + res = advapi32.CryptCreateHash( + private_key.context_handle, + alg_id, + null(), + 0, + hash_handle_pointer + ) + handle_error(res) + + hash_handle = unwrap(hash_handle_pointer) + + res = advapi32.CryptHashData(hash_handle, data, len(data), 0) + handle_error(res) + + out_len = new(advapi32, 'DWORD *') + res = advapi32.CryptSignHashW( + hash_handle, + Advapi32Const.AT_SIGNATURE, + null(), + 0, + null(), + out_len + ) + handle_error(res) + + buffer_length = deref(out_len) + buffer_ = buffer_from_bytes(buffer_length) + + res = advapi32.CryptSignHashW( + hash_handle, + Advapi32Const.AT_SIGNATURE, + null(), + 0, + buffer_, + out_len + ) + handle_error(res) + + output = bytes_from_buffer(buffer_, deref(out_len)) + + # CryptoAPI outputs the signature in little endian byte order, so we + # must swap it for compatibility with other systems + output = output[::-1] + + if algo == 'dsa': + # Switch the two integers because the reversal just before switched + # then + half_len = len(output) // 2 + output = output[half_len:] + output[:half_len] + # Windows doesn't use the ASN.1 Sequence for DSA signatures, + # so we have to convert it here for the verification to work + output = DSASignature.from_p1363(output).dump() + + return output + + finally: + if hash_handle: + advapi32.CryptDestroyHash(hash_handle) + + +def _bcrypt_sign(private_key, data, hash_algorithm, rsa_pss_padding=False): + """ + Generates an RSA, DSA or ECDSA signature via CNG + + :param private_key: + The PrivateKey to generate the signature with + + :param data: + A byte string of the data the signature is for + + :param hash_algorithm: + A unicode string of "md5", "sha1", "sha256", "sha384", "sha512" or "raw" + + :param rsa_pss_padding: + If PSS padding should be used for RSA keys + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + + :return: + A byte string of the signature + """ + + if hash_algorithm == 'raw': + digest = data + else: + hash_constant = { + 'md5': BcryptConst.BCRYPT_MD5_ALGORITHM, + 'sha1': BcryptConst.BCRYPT_SHA1_ALGORITHM, + 'sha256': BcryptConst.BCRYPT_SHA256_ALGORITHM, + 'sha384': BcryptConst.BCRYPT_SHA384_ALGORITHM, + 'sha512': BcryptConst.BCRYPT_SHA512_ALGORITHM + }[hash_algorithm] + + digest = getattr(hashlib, hash_algorithm)(data).digest() + + padding_info = null() + flags = 0 + + if private_key.algorithm == 'rsa': + if rsa_pss_padding: + hash_length = { + 'md5': 16, + 'sha1': 20, + 'sha256': 32, + 'sha384': 48, + 'sha512': 64 + }[hash_algorithm] + + flags = BcryptConst.BCRYPT_PAD_PSS + padding_info_struct_pointer = struct(bcrypt, 'BCRYPT_PSS_PADDING_INFO') + padding_info_struct = unwrap(padding_info_struct_pointer) + # This has to be assigned to a variable to prevent cffi from gc'ing it + hash_buffer = buffer_from_unicode(hash_constant) + padding_info_struct.pszAlgId = cast(bcrypt, 'wchar_t *', hash_buffer) + padding_info_struct.cbSalt = hash_length + else: + flags = BcryptConst.BCRYPT_PAD_PKCS1 + padding_info_struct_pointer = struct(bcrypt, 'BCRYPT_PKCS1_PADDING_INFO') + padding_info_struct = unwrap(padding_info_struct_pointer) + # This has to be assigned to a variable to prevent cffi from gc'ing it + if hash_algorithm == 'raw': + padding_info_struct.pszAlgId = null() + else: + hash_buffer = buffer_from_unicode(hash_constant) + padding_info_struct.pszAlgId = cast(bcrypt, 'wchar_t *', hash_buffer) + padding_info = cast(bcrypt, 'void *', padding_info_struct_pointer) + + if private_key.algorithm == 'dsa' and private_key.bit_size > 1024 and hash_algorithm in set(['md5', 'sha1']): + raise ValueError(pretty_message( + ''' + Windows does not support sha1 signatures with DSA keys based on + sha224, sha256 or sha512 + ''' + )) + + out_len = new(bcrypt, 'DWORD *') + res = bcrypt.BCryptSignHash( + private_key.key_handle, + padding_info, + digest, + len(digest), + null(), + 0, + out_len, + flags + ) + handle_error(res) + + buffer_len = deref(out_len) + buffer = buffer_from_bytes(buffer_len) + + if private_key.algorithm == 'rsa': + padding_info = cast(bcrypt, 'void *', padding_info_struct_pointer) + + res = bcrypt.BCryptSignHash( + private_key.key_handle, + padding_info, + digest, + len(digest), + buffer, + buffer_len, + out_len, + flags + ) + handle_error(res) + signature = bytes_from_buffer(buffer, deref(out_len)) + + if private_key.algorithm != 'rsa': + # Windows doesn't use the ASN.1 Sequence for DSA/ECDSA signatures, + # so we have to convert it here for the verification to work + signature = DSASignature.from_p1363(signature).dump() + + return signature + + +def _encrypt(certificate_or_public_key, data, rsa_oaep_padding=False): + """ + Encrypts a value using an RSA public key + + :param certificate_or_public_key: + A Certificate or PublicKey instance to encrypt with + + :param data: + A byte string of the data to encrypt + + :param rsa_oaep_padding: + If OAEP padding should be used instead of PKCS#1 v1.5 + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + + :return: + A byte string of the ciphertext + """ + + if not isinstance(certificate_or_public_key, (Certificate, PublicKey)): + raise TypeError(pretty_message( + ''' + certificate_or_public_key must be an instance of the Certificate or + PublicKey class, not %s + ''', + type_name(certificate_or_public_key) + )) + + if not isinstance(data, byte_cls): + raise TypeError(pretty_message( + ''' + data must be a byte string, not %s + ''', + type_name(data) + )) + + if not isinstance(rsa_oaep_padding, bool): + raise TypeError(pretty_message( + ''' + rsa_oaep_padding must be a bool, not %s + ''', + type_name(rsa_oaep_padding) + )) + + if _backend == 'winlegacy': + return _advapi32_encrypt(certificate_or_public_key, data, rsa_oaep_padding) + return _bcrypt_encrypt(certificate_or_public_key, data, rsa_oaep_padding) + + +def _advapi32_encrypt(certificate_or_public_key, data, rsa_oaep_padding=False): + """ + Encrypts a value using an RSA public key via CryptoAPI + + :param certificate_or_public_key: + A Certificate or PublicKey instance to encrypt with + + :param data: + A byte string of the data to encrypt + + :param rsa_oaep_padding: + If OAEP padding should be used instead of PKCS#1 v1.5 + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + + :return: + A byte string of the ciphertext + """ + + flags = 0 + if rsa_oaep_padding: + flags = Advapi32Const.CRYPT_OAEP + + out_len = new(advapi32, 'DWORD *', len(data)) + res = advapi32.CryptEncrypt( + certificate_or_public_key.ex_key_handle, + null(), + True, + flags, + null(), + out_len, + 0 + ) + handle_error(res) + + buffer_len = deref(out_len) + buffer = buffer_from_bytes(buffer_len) + write_to_buffer(buffer, data) + + pointer_set(out_len, len(data)) + res = advapi32.CryptEncrypt( + certificate_or_public_key.ex_key_handle, + null(), + True, + flags, + buffer, + out_len, + buffer_len + ) + handle_error(res) + + return bytes_from_buffer(buffer, deref(out_len))[::-1] + + +def _bcrypt_encrypt(certificate_or_public_key, data, rsa_oaep_padding=False): + """ + Encrypts a value using an RSA public key via CNG + + :param certificate_or_public_key: + A Certificate or PublicKey instance to encrypt with + + :param data: + A byte string of the data to encrypt + + :param rsa_oaep_padding: + If OAEP padding should be used instead of PKCS#1 v1.5 + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + + :return: + A byte string of the ciphertext + """ + + flags = BcryptConst.BCRYPT_PAD_PKCS1 + if rsa_oaep_padding is True: + flags = BcryptConst.BCRYPT_PAD_OAEP + + padding_info_struct_pointer = struct(bcrypt, 'BCRYPT_OAEP_PADDING_INFO') + padding_info_struct = unwrap(padding_info_struct_pointer) + # This has to be assigned to a variable to prevent cffi from gc'ing it + hash_buffer = buffer_from_unicode(BcryptConst.BCRYPT_SHA1_ALGORITHM) + padding_info_struct.pszAlgId = cast(bcrypt, 'wchar_t *', hash_buffer) + padding_info_struct.pbLabel = null() + padding_info_struct.cbLabel = 0 + padding_info = cast(bcrypt, 'void *', padding_info_struct_pointer) + else: + padding_info = null() + + out_len = new(bcrypt, 'ULONG *') + res = bcrypt.BCryptEncrypt( + certificate_or_public_key.key_handle, + data, + len(data), + padding_info, + null(), + 0, + null(), + 0, + out_len, + flags + ) + handle_error(res) + + buffer_len = deref(out_len) + buffer = buffer_from_bytes(buffer_len) + + res = bcrypt.BCryptEncrypt( + certificate_or_public_key.key_handle, + data, + len(data), + padding_info, + null(), + 0, + buffer, + buffer_len, + out_len, + flags + ) + handle_error(res) + + return bytes_from_buffer(buffer, deref(out_len)) + + +def _decrypt(private_key, ciphertext, rsa_oaep_padding=False): + """ + Encrypts a value using an RSA private key + + :param private_key: + A PrivateKey instance to decrypt with + + :param ciphertext: + A byte string of the data to decrypt + + :param rsa_oaep_padding: + If OAEP padding should be used instead of PKCS#1 v1.5 + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + + :return: + A byte string of the plaintext + """ + + if not isinstance(private_key, PrivateKey): + raise TypeError(pretty_message( + ''' + private_key must be an instance of the PrivateKey class, not %s + ''', + type_name(private_key) + )) + + if not isinstance(ciphertext, byte_cls): + raise TypeError(pretty_message( + ''' + ciphertext must be a byte string, not %s + ''', + type_name(ciphertext) + )) + + if not isinstance(rsa_oaep_padding, bool): + raise TypeError(pretty_message( + ''' + rsa_oaep_padding must be a bool, not %s + ''', + type_name(rsa_oaep_padding) + )) + + if _backend == 'winlegacy': + return _advapi32_decrypt(private_key, ciphertext, rsa_oaep_padding) + return _bcrypt_decrypt(private_key, ciphertext, rsa_oaep_padding) + + +def _advapi32_decrypt(private_key, ciphertext, rsa_oaep_padding=False): + """ + Encrypts a value using an RSA private key via CryptoAPI + + :param private_key: + A PrivateKey instance to decrypt with + + :param ciphertext: + A byte string of the data to decrypt + + :param rsa_oaep_padding: + If OAEP padding should be used instead of PKCS#1 v1.5 + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + + :return: + A byte string of the plaintext + """ + + flags = 0 + if rsa_oaep_padding: + flags = Advapi32Const.CRYPT_OAEP + + ciphertext = ciphertext[::-1] + + buffer = buffer_from_bytes(ciphertext) + out_len = new(advapi32, 'DWORD *', len(ciphertext)) + res = advapi32.CryptDecrypt( + private_key.ex_key_handle, + null(), + True, + flags, + buffer, + out_len + ) + handle_error(res) + + return bytes_from_buffer(buffer, deref(out_len)) + + +def _bcrypt_decrypt(private_key, ciphertext, rsa_oaep_padding=False): + """ + Encrypts a value using an RSA private key via CNG + + :param private_key: + A PrivateKey instance to decrypt with + + :param ciphertext: + A byte string of the data to decrypt + + :param rsa_oaep_padding: + If OAEP padding should be used instead of PKCS#1 v1.5 + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + + :return: + A byte string of the plaintext + """ + + flags = BcryptConst.BCRYPT_PAD_PKCS1 + if rsa_oaep_padding is True: + flags = BcryptConst.BCRYPT_PAD_OAEP + + padding_info_struct_pointer = struct(bcrypt, 'BCRYPT_OAEP_PADDING_INFO') + padding_info_struct = unwrap(padding_info_struct_pointer) + # This has to be assigned to a variable to prevent cffi from gc'ing it + hash_buffer = buffer_from_unicode(BcryptConst.BCRYPT_SHA1_ALGORITHM) + padding_info_struct.pszAlgId = cast(bcrypt, 'wchar_t *', hash_buffer) + padding_info_struct.pbLabel = null() + padding_info_struct.cbLabel = 0 + padding_info = cast(bcrypt, 'void *', padding_info_struct_pointer) + else: + padding_info = null() + + out_len = new(bcrypt, 'ULONG *') + res = bcrypt.BCryptDecrypt( + private_key.key_handle, + ciphertext, + len(ciphertext), + padding_info, + null(), + 0, + null(), + 0, + out_len, + flags + ) + handle_error(res) + + buffer_len = deref(out_len) + buffer = buffer_from_bytes(buffer_len) + + res = bcrypt.BCryptDecrypt( + private_key.key_handle, + ciphertext, + len(ciphertext), + padding_info, + null(), + 0, + buffer, + buffer_len, + out_len, + flags + ) + handle_error(res) + + return bytes_from_buffer(buffer, deref(out_len)) + + +def rsa_pkcs1v15_encrypt(certificate_or_public_key, data): + """ + Encrypts a byte string using an RSA public key or certificate. Uses PKCS#1 + v1.5 padding. + + :param certificate_or_public_key: + A PublicKey or Certificate object + + :param data: + A byte string, with a maximum length 11 bytes less than the key length + (in bytes) + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + + :return: + A byte string of the encrypted data + """ + + return _encrypt(certificate_or_public_key, data) + + +def rsa_pkcs1v15_decrypt(private_key, ciphertext): + """ + Decrypts a byte string using an RSA private key. Uses PKCS#1 v1.5 padding. + + :param private_key: + A PrivateKey object + + :param ciphertext: + A byte string of the encrypted data + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + + :return: + A byte string of the original plaintext + """ + + return _decrypt(private_key, ciphertext) + + +def rsa_oaep_encrypt(certificate_or_public_key, data): + """ + Encrypts a byte string using an RSA public key or certificate. Uses PKCS#1 + OAEP padding with SHA1. + + :param certificate_or_public_key: + A PublicKey or Certificate object + + :param data: + A byte string, with a maximum length 41 bytes (or more) less than the + key length (in bytes) + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + + :return: + A byte string of the encrypted data + """ + + return _encrypt(certificate_or_public_key, data, rsa_oaep_padding=True) + + +def rsa_oaep_decrypt(private_key, ciphertext): + """ + Decrypts a byte string using an RSA private key. Uses PKCS#1 OAEP padding + with SHA1. + + :param private_key: + A PrivateKey object + + :param ciphertext: + A byte string of the encrypted data + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + + :return: + A byte string of the original plaintext + """ + + return _decrypt(private_key, ciphertext, rsa_oaep_padding=True) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_win/symmetric.py b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_win/symmetric.py new file mode 100644 index 00000000..e93cd135 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_win/symmetric.py @@ -0,0 +1,1166 @@ +# coding: utf-8 +from __future__ import unicode_literals, division, absolute_import, print_function + +from .._errors import pretty_message +from .._ffi import ( + buffer_from_bytes, + bytes_from_buffer, + deref, + new, + null, + pointer_set, + struct, + struct_bytes, + unwrap, + write_to_buffer, +) +from .util import rand_bytes +from .. import backend +from .._types import type_name, byte_cls + +_backend = backend() + +if _backend == 'winlegacy': + from ._advapi32 import advapi32, Advapi32Const, handle_error, open_context_handle, close_context_handle +else: + from ._cng import bcrypt, BcryptConst, handle_error, open_alg_handle, close_alg_handle + + +__all__ = [ + 'aes_cbc_no_padding_decrypt', + 'aes_cbc_no_padding_encrypt', + 'aes_cbc_pkcs7_decrypt', + 'aes_cbc_pkcs7_encrypt', + 'des_cbc_pkcs5_decrypt', + 'des_cbc_pkcs5_encrypt', + 'rc2_cbc_pkcs5_decrypt', + 'rc2_cbc_pkcs5_encrypt', + 'rc4_decrypt', + 'rc4_encrypt', + 'tripledes_cbc_pkcs5_decrypt', + 'tripledes_cbc_pkcs5_encrypt', +] + + +def aes_cbc_no_padding_encrypt(key, data, iv): + """ + Encrypts plaintext using AES in CBC mode with a 128, 192 or 256 bit key and + no padding. This means the ciphertext must be an exact multiple of 16 bytes + long. + + :param key: + The encryption key - a byte string either 16, 24 or 32 bytes long + + :param data: + The plaintext - a byte string + + :param iv: + The initialization vector - either a byte string 16-bytes long or None + to generate an IV + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + + :return: + A tuple of two byte strings (iv, ciphertext) + """ + + if len(key) not in [16, 24, 32]: + raise ValueError(pretty_message( + ''' + key must be either 16, 24 or 32 bytes (128, 192 or 256 bits) + long - is %s + ''', + len(key) + )) + + if not iv: + iv = rand_bytes(16) + elif len(iv) != 16: + raise ValueError(pretty_message( + ''' + iv must be 16 bytes long - is %s + ''', + len(iv) + )) + + if len(data) % 16 != 0: + raise ValueError(pretty_message( + ''' + data must be a multiple of 16 bytes long - is %s + ''', + len(data) + )) + + return (iv, _encrypt('aes', key, data, iv, False)) + + +def aes_cbc_no_padding_decrypt(key, data, iv): + """ + Decrypts AES ciphertext in CBC mode using a 128, 192 or 256 bit key and no + padding. + + :param key: + The encryption key - a byte string either 16, 24 or 32 bytes long + + :param data: + The ciphertext - a byte string + + :param iv: + The initialization vector - a byte string 16-bytes long + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + + :return: + A byte string of the plaintext + """ + + if len(key) not in [16, 24, 32]: + raise ValueError(pretty_message( + ''' + key must be either 16, 24 or 32 bytes (128, 192 or 256 bits) + long - is %s + ''', + len(key) + )) + + if len(iv) != 16: + raise ValueError(pretty_message( + ''' + iv must be 16 bytes long - is %s + ''', + len(iv) + )) + + return _decrypt('aes', key, data, iv, False) + + +def aes_cbc_pkcs7_encrypt(key, data, iv): + """ + Encrypts plaintext using AES in CBC mode with a 128, 192 or 256 bit key and + PKCS#7 padding. + + :param key: + The encryption key - a byte string either 16, 24 or 32 bytes long + + :param data: + The plaintext - a byte string + + :param iv: + The initialization vector - either a byte string 16-bytes long or None + to generate an IV + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + + :return: + A tuple of two byte strings (iv, ciphertext) + """ + + if len(key) not in [16, 24, 32]: + raise ValueError(pretty_message( + ''' + key must be either 16, 24 or 32 bytes (128, 192 or 256 bits) + long - is %s + ''', + len(key) + )) + + if not iv: + iv = rand_bytes(16) + elif len(iv) != 16: + raise ValueError(pretty_message( + ''' + iv must be 16 bytes long - is %s + ''', + len(iv) + )) + + return (iv, _encrypt('aes', key, data, iv, True)) + + +def aes_cbc_pkcs7_decrypt(key, data, iv): + """ + Decrypts AES ciphertext in CBC mode using a 128, 192 or 256 bit key + + :param key: + The encryption key - a byte string either 16, 24 or 32 bytes long + + :param data: + The ciphertext - a byte string + + :param iv: + The initialization vector - a byte string 16-bytes long + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + + :return: + A byte string of the plaintext + """ + + if len(key) not in [16, 24, 32]: + raise ValueError(pretty_message( + ''' + key must be either 16, 24 or 32 bytes (128, 192 or 256 bits) + long - is %s + ''', + len(key) + )) + + if len(iv) != 16: + raise ValueError(pretty_message( + ''' + iv must be 16 bytes long - is %s + ''', + len(iv) + )) + + return _decrypt('aes', key, data, iv, True) + + +def rc4_encrypt(key, data): + """ + Encrypts plaintext using RC4 with a 40-128 bit key + + :param key: + The encryption key - a byte string 5-16 bytes long + + :param data: + The plaintext - a byte string + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + + :return: + A byte string of the ciphertext + """ + + if len(key) < 5 or len(key) > 16: + raise ValueError(pretty_message( + ''' + key must be 5 to 16 bytes (40 to 128 bits) long - is %s + ''', + len(key) + )) + + return _encrypt('rc4', key, data, None, None) + + +def rc4_decrypt(key, data): + """ + Decrypts RC4 ciphertext using a 40-128 bit key + + :param key: + The encryption key - a byte string 5-16 bytes long + + :param data: + The ciphertext - a byte string + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + + :return: + A byte string of the plaintext + """ + + if len(key) < 5 or len(key) > 16: + raise ValueError(pretty_message( + ''' + key must be 5 to 16 bytes (40 to 128 bits) long - is %s + ''', + len(key) + )) + + return _decrypt('rc4', key, data, None, None) + + +def rc2_cbc_pkcs5_encrypt(key, data, iv): + """ + Encrypts plaintext using RC2 with a 64 bit key + + :param key: + The encryption key - a byte string 8 bytes long + + :param data: + The plaintext - a byte string + + :param iv: + The 8-byte initialization vector to use - a byte string - set as None + to generate an appropriate one + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + + :return: + A tuple of two byte strings (iv, ciphertext) + """ + + if len(key) < 5 or len(key) > 16: + raise ValueError(pretty_message( + ''' + key must be 5 to 16 bytes (40 to 128 bits) long - is %s + ''', + len(key) + )) + + if not iv: + iv = rand_bytes(8) + elif len(iv) != 8: + raise ValueError(pretty_message( + ''' + iv must be 8 bytes long - is %s + ''', + len(iv) + )) + + return (iv, _encrypt('rc2', key, data, iv, True)) + + +def rc2_cbc_pkcs5_decrypt(key, data, iv): + """ + Decrypts RC2 ciphertext using a 64 bit key + + :param key: + The encryption key - a byte string 8 bytes long + + :param data: + The ciphertext - a byte string + + :param iv: + The initialization vector used for encryption - a byte string + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + + :return: + A byte string of the plaintext + """ + + if len(key) < 5 or len(key) > 16: + raise ValueError(pretty_message( + ''' + key must be 5 to 16 bytes (40 to 128 bits) long - is %s + ''', + len(key) + )) + + if len(iv) != 8: + raise ValueError(pretty_message( + ''' + iv must be 8 bytes long - is %s + ''', + len(iv) + )) + + return _decrypt('rc2', key, data, iv, True) + + +def tripledes_cbc_pkcs5_encrypt(key, data, iv): + """ + Encrypts plaintext using 3DES in either 2 or 3 key mode + + :param key: + The encryption key - a byte string 16 or 24 bytes long (2 or 3 key mode) + + :param data: + The plaintext - a byte string + + :param iv: + The 8-byte initialization vector to use - a byte string - set as None + to generate an appropriate one + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + + :return: + A tuple of two byte strings (iv, ciphertext) + """ + + if len(key) != 16 and len(key) != 24: + raise ValueError(pretty_message( + ''' + key must be 16 bytes (2 key) or 24 bytes (3 key) long - is %s + ''', + len(key) + )) + + if not iv: + iv = rand_bytes(8) + elif len(iv) != 8: + raise ValueError(pretty_message( + ''' + iv must be 8 bytes long - is %s + ''', + len(iv) + )) + + cipher = 'tripledes_3key' + if len(key) == 16: + cipher = 'tripledes_2key' + + return (iv, _encrypt(cipher, key, data, iv, True)) + + +def tripledes_cbc_pkcs5_decrypt(key, data, iv): + """ + Decrypts 3DES ciphertext in either 2 or 3 key mode + + :param key: + The encryption key - a byte string 16 or 24 bytes long (2 or 3 key mode) + + :param data: + The ciphertext - a byte string + + :param iv: + The initialization vector used for encryption - a byte string + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + + :return: + A byte string of the plaintext + """ + + if len(key) != 16 and len(key) != 24: + raise ValueError(pretty_message( + ''' + key must be 16 bytes (2 key) or 24 bytes (3 key) long - is %s + ''', + len(key) + )) + + if len(iv) != 8: + raise ValueError(pretty_message( + ''' + iv must be 8 bytes long - is %s + ''', + len(iv) + )) + + cipher = 'tripledes_3key' + if len(key) == 16: + cipher = 'tripledes_2key' + + return _decrypt(cipher, key, data, iv, True) + + +def des_cbc_pkcs5_encrypt(key, data, iv): + """ + Encrypts plaintext using DES with a 56 bit key + + :param key: + The encryption key - a byte string 8 bytes long (includes error + correction bits) + + :param data: + The plaintext - a byte string + + :param iv: + The 8-byte initialization vector to use - a byte string - set as None + to generate an appropriate one + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + + :return: + A tuple of two byte strings (iv, ciphertext) + """ + + if len(key) != 8: + raise ValueError(pretty_message( + ''' + key must be 8 bytes (56 bits + 8 parity bits) long - is %s + ''', + len(key) + )) + + if not iv: + iv = rand_bytes(8) + elif len(iv) != 8: + raise ValueError(pretty_message( + ''' + iv must be 8 bytes long - is %s + ''', + len(iv) + )) + + return (iv, _encrypt('des', key, data, iv, True)) + + +def des_cbc_pkcs5_decrypt(key, data, iv): + """ + Decrypts DES ciphertext using a 56 bit key + + :param key: + The encryption key - a byte string 8 bytes long (includes error + correction bits) + + :param data: + The ciphertext - a byte string + + :param iv: + The initialization vector used for encryption - a byte string + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + + :return: + A byte string of the plaintext + """ + + if len(key) != 8: + raise ValueError(pretty_message( + ''' + key must be 8 bytes (56 bits + 8 parity bits) long - is %s + ''', + len(key) + )) + + if len(iv) != 8: + raise ValueError(pretty_message( + ''' + iv must be 8 bytes long - is %s + ''', + len(iv) + )) + + return _decrypt('des', key, data, iv, True) + + +def _advapi32_create_handles(cipher, key, iv): + """ + Creates an HCRYPTPROV and HCRYPTKEY for symmetric encryption/decryption. The + HCRYPTPROV must be released by close_context_handle() and the + HCRYPTKEY must be released by advapi32.CryptDestroyKey() when done. + + :param cipher: + A unicode string of "aes", "des", "tripledes_2key", "tripledes_3key", + "rc2", "rc4" + + :param key: + A byte string of the symmetric key + + :param iv: + The initialization vector - a byte string - unused for RC4 + + :return: + A tuple of (HCRYPTPROV, HCRYPTKEY) + """ + + context_handle = None + + if cipher == 'aes': + algorithm_id = { + 16: Advapi32Const.CALG_AES_128, + 24: Advapi32Const.CALG_AES_192, + 32: Advapi32Const.CALG_AES_256, + }[len(key)] + else: + algorithm_id = { + 'des': Advapi32Const.CALG_DES, + 'tripledes_2key': Advapi32Const.CALG_3DES_112, + 'tripledes_3key': Advapi32Const.CALG_3DES, + 'rc2': Advapi32Const.CALG_RC2, + 'rc4': Advapi32Const.CALG_RC4, + }[cipher] + + provider = Advapi32Const.MS_ENH_RSA_AES_PROV + context_handle = open_context_handle(provider, verify_only=False) + + blob_header_pointer = struct(advapi32, 'BLOBHEADER') + blob_header = unwrap(blob_header_pointer) + blob_header.bType = Advapi32Const.PLAINTEXTKEYBLOB + blob_header.bVersion = Advapi32Const.CUR_BLOB_VERSION + blob_header.reserved = 0 + blob_header.aiKeyAlg = algorithm_id + + blob_struct_pointer = struct(advapi32, 'PLAINTEXTKEYBLOB') + blob_struct = unwrap(blob_struct_pointer) + blob_struct.hdr = blob_header + blob_struct.dwKeySize = len(key) + + blob = struct_bytes(blob_struct_pointer) + key + + flags = 0 + if cipher in set(['rc2', 'rc4']) and len(key) == 5: + flags = Advapi32Const.CRYPT_NO_SALT + + key_handle_pointer = new(advapi32, 'HCRYPTKEY *') + res = advapi32.CryptImportKey( + context_handle, + blob, + len(blob), + null(), + flags, + key_handle_pointer + ) + handle_error(res) + + key_handle = unwrap(key_handle_pointer) + + if cipher == 'rc2': + buf = new(advapi32, 'DWORD *', len(key) * 8) + res = advapi32.CryptSetKeyParam( + key_handle, + Advapi32Const.KP_EFFECTIVE_KEYLEN, + buf, + 0 + ) + handle_error(res) + + if cipher != 'rc4': + res = advapi32.CryptSetKeyParam( + key_handle, + Advapi32Const.KP_IV, + iv, + 0 + ) + handle_error(res) + + buf = new(advapi32, 'DWORD *', Advapi32Const.CRYPT_MODE_CBC) + res = advapi32.CryptSetKeyParam( + key_handle, + Advapi32Const.KP_MODE, + buf, + 0 + ) + handle_error(res) + + buf = new(advapi32, 'DWORD *', Advapi32Const.PKCS5_PADDING) + res = advapi32.CryptSetKeyParam( + key_handle, + Advapi32Const.KP_PADDING, + buf, + 0 + ) + handle_error(res) + + return (context_handle, key_handle) + + +def _bcrypt_create_key_handle(cipher, key): + """ + Creates a BCRYPT_KEY_HANDLE for symmetric encryption/decryption. The + handle must be released by bcrypt.BCryptDestroyKey() when done. + + :param cipher: + A unicode string of "aes", "des", "tripledes_2key", "tripledes_3key", + "rc2", "rc4" + + :param key: + A byte string of the symmetric key + + :return: + A BCRYPT_KEY_HANDLE + """ + + alg_handle = None + + alg_constant = { + 'aes': BcryptConst.BCRYPT_AES_ALGORITHM, + 'des': BcryptConst.BCRYPT_DES_ALGORITHM, + 'tripledes_2key': BcryptConst.BCRYPT_3DES_112_ALGORITHM, + 'tripledes_3key': BcryptConst.BCRYPT_3DES_ALGORITHM, + 'rc2': BcryptConst.BCRYPT_RC2_ALGORITHM, + 'rc4': BcryptConst.BCRYPT_RC4_ALGORITHM, + }[cipher] + + try: + alg_handle = open_alg_handle(alg_constant) + blob_type = BcryptConst.BCRYPT_KEY_DATA_BLOB + + blob_struct_pointer = struct(bcrypt, 'BCRYPT_KEY_DATA_BLOB_HEADER') + blob_struct = unwrap(blob_struct_pointer) + blob_struct.dwMagic = BcryptConst.BCRYPT_KEY_DATA_BLOB_MAGIC + blob_struct.dwVersion = BcryptConst.BCRYPT_KEY_DATA_BLOB_VERSION1 + blob_struct.cbKeyData = len(key) + + blob = struct_bytes(blob_struct_pointer) + key + + if cipher == 'rc2': + buf = new(bcrypt, 'DWORD *', len(key) * 8) + res = bcrypt.BCryptSetProperty( + alg_handle, + BcryptConst.BCRYPT_EFFECTIVE_KEY_LENGTH, + buf, + 4, + 0 + ) + handle_error(res) + + key_handle_pointer = new(bcrypt, 'BCRYPT_KEY_HANDLE *') + res = bcrypt.BCryptImportKey( + alg_handle, + null(), + blob_type, + key_handle_pointer, + null(), + 0, + blob, + len(blob), + 0 + ) + handle_error(res) + + return unwrap(key_handle_pointer) + + finally: + if alg_handle: + close_alg_handle(alg_handle) + + +def _encrypt(cipher, key, data, iv, padding): + """ + Encrypts plaintext + + :param cipher: + A unicode string of "aes", "des", "tripledes_2key", "tripledes_3key", + "rc2", "rc4" + + :param key: + The encryption key - a byte string 5-16 bytes long + + :param data: + The plaintext - a byte string + + :param iv: + The initialization vector - a byte string - unused for RC4 + + :param padding: + Boolean, if padding should be used - unused for RC4 + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + + :return: + A byte string of the ciphertext + """ + + if not isinstance(key, byte_cls): + raise TypeError(pretty_message( + ''' + key must be a byte string, not %s + ''', + type_name(key) + )) + + if not isinstance(data, byte_cls): + raise TypeError(pretty_message( + ''' + data must be a byte string, not %s + ''', + type_name(data) + )) + + if cipher != 'rc4' and not isinstance(iv, byte_cls): + raise TypeError(pretty_message( + ''' + iv must be a byte string, not %s + ''', + type_name(iv) + )) + + if cipher != 'rc4' and not padding: + # AES in CBC mode can be allowed with no padding if + # the data is an exact multiple of the key size + if not (cipher == 'aes' and padding is False and len(data) % len(key) == 0): + raise ValueError('padding must be specified') + + if _backend == 'winlegacy': + return _advapi32_encrypt(cipher, key, data, iv, padding) + return _bcrypt_encrypt(cipher, key, data, iv, padding) + + +def _advapi32_encrypt(cipher, key, data, iv, padding): + """ + Encrypts plaintext via CryptoAPI + + :param cipher: + A unicode string of "aes", "des", "tripledes_2key", "tripledes_3key", + "rc2", "rc4" + + :param key: + The encryption key - a byte string 5-16 bytes long + + :param data: + The plaintext - a byte string + + :param iv: + The initialization vector - a byte string - unused for RC4 + + :param padding: + Boolean, if padding should be used - unused for RC4 + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + + :return: + A byte string of the ciphertext + """ + + context_handle = None + key_handle = None + + try: + context_handle, key_handle = _advapi32_create_handles(cipher, key, iv) + + out_len = new(advapi32, 'DWORD *', len(data)) + res = advapi32.CryptEncrypt( + key_handle, + null(), + True, + 0, + null(), + out_len, + 0 + ) + handle_error(res) + + buffer_len = deref(out_len) + buffer = buffer_from_bytes(buffer_len) + write_to_buffer(buffer, data) + + pointer_set(out_len, len(data)) + res = advapi32.CryptEncrypt( + key_handle, + null(), + True, + 0, + buffer, + out_len, + buffer_len + ) + handle_error(res) + + output = bytes_from_buffer(buffer, deref(out_len)) + + # Remove padding when not required. CryptoAPI doesn't support this, so + # we just manually remove it. + if cipher == 'aes' and not padding and len(output) == len(data) + 16: + output = output[:-16] + + return output + + finally: + if key_handle: + advapi32.CryptDestroyKey(key_handle) + if context_handle: + close_context_handle(context_handle) + + +def _bcrypt_encrypt(cipher, key, data, iv, padding): + """ + Encrypts plaintext via CNG + + :param cipher: + A unicode string of "aes", "des", "tripledes_2key", "tripledes_3key", + "rc2", "rc4" + + :param key: + The encryption key - a byte string 5-16 bytes long + + :param data: + The plaintext - a byte string + + :param iv: + The initialization vector - a byte string - unused for RC4 + + :param padding: + Boolean, if padding should be used - unused for RC4 + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + + :return: + A byte string of the ciphertext + """ + + key_handle = None + + try: + key_handle = _bcrypt_create_key_handle(cipher, key) + + if iv is None: + iv_len = 0 + else: + iv_len = len(iv) + + flags = 0 + if padding is True: + flags = BcryptConst.BCRYPT_BLOCK_PADDING + + out_len = new(bcrypt, 'ULONG *') + res = bcrypt.BCryptEncrypt( + key_handle, + data, + len(data), + null(), + null(), + 0, + null(), + 0, + out_len, + flags + ) + handle_error(res) + + buffer_len = deref(out_len) + buffer = buffer_from_bytes(buffer_len) + iv_buffer = buffer_from_bytes(iv) if iv else null() + + res = bcrypt.BCryptEncrypt( + key_handle, + data, + len(data), + null(), + iv_buffer, + iv_len, + buffer, + buffer_len, + out_len, + flags + ) + handle_error(res) + + return bytes_from_buffer(buffer, deref(out_len)) + + finally: + if key_handle: + bcrypt.BCryptDestroyKey(key_handle) + + +def _decrypt(cipher, key, data, iv, padding): + """ + Decrypts AES/RC4/RC2/3DES/DES ciphertext + + :param cipher: + A unicode string of "aes", "des", "tripledes_2key", "tripledes_3key", + "rc2", "rc4" + + :param key: + The encryption key - a byte string 5-16 bytes long + + :param data: + The ciphertext - a byte string + + :param iv: + The initialization vector - a byte string - unused for RC4 + + :param padding: + Boolean, if padding should be used - unused for RC4 + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + + :return: + A byte string of the plaintext + """ + + if not isinstance(key, byte_cls): + raise TypeError(pretty_message( + ''' + key must be a byte string, not %s + ''', + type_name(key) + )) + + if not isinstance(data, byte_cls): + raise TypeError(pretty_message( + ''' + data must be a byte string, not %s + ''', + type_name(data) + )) + + if cipher != 'rc4' and not isinstance(iv, byte_cls): + raise TypeError(pretty_message( + ''' + iv must be a byte string, not %s + ''', + type_name(iv) + )) + + if cipher != 'rc4' and padding is None: + raise ValueError('padding must be specified') + + if _backend == 'winlegacy': + return _advapi32_decrypt(cipher, key, data, iv, padding) + return _bcrypt_decrypt(cipher, key, data, iv, padding) + + +def _advapi32_decrypt(cipher, key, data, iv, padding): + """ + Decrypts AES/RC4/RC2/3DES/DES ciphertext via CryptoAPI + + :param cipher: + A unicode string of "aes", "des", "tripledes_2key", "tripledes_3key", + "rc2", "rc4" + + :param key: + The encryption key - a byte string 5-16 bytes long + + :param data: + The ciphertext - a byte string + + :param iv: + The initialization vector - a byte string - unused for RC4 + + :param padding: + Boolean, if padding should be used - unused for RC4 + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + + :return: + A byte string of the plaintext + """ + + context_handle = None + key_handle = None + + try: + context_handle, key_handle = _advapi32_create_handles(cipher, key, iv) + + if cipher == 'aes' and not padding and len(data) % 16 != 0: + raise ValueError('Invalid data - ciphertext length must be a multiple of 16') + + buffer = buffer_from_bytes(data) + out_len = new(advapi32, 'DWORD *', len(data)) + res = advapi32.CryptDecrypt( + key_handle, + null(), + # To skip padding, we have to tell the API that this is not + # the final block + False if cipher == 'aes' and not padding else True, + 0, + buffer, + out_len + ) + handle_error(res) + + return bytes_from_buffer(buffer, deref(out_len)) + + finally: + if key_handle: + advapi32.CryptDestroyKey(key_handle) + if context_handle: + close_context_handle(context_handle) + + +def _bcrypt_decrypt(cipher, key, data, iv, padding): + """ + Decrypts AES/RC4/RC2/3DES/DES ciphertext via CNG + + :param cipher: + A unicode string of "aes", "des", "tripledes_2key", "tripledes_3key", + "rc2", "rc4" + + :param key: + The encryption key - a byte string 5-16 bytes long + + :param data: + The ciphertext - a byte string + + :param iv: + The initialization vector - a byte string - unused for RC4 + + :param padding: + Boolean, if padding should be used - unused for RC4 + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + + :return: + A byte string of the plaintext + """ + + key_handle = None + + try: + key_handle = _bcrypt_create_key_handle(cipher, key) + + if iv is None: + iv_len = 0 + else: + iv_len = len(iv) + + flags = 0 + if padding is True: + flags = BcryptConst.BCRYPT_BLOCK_PADDING + + out_len = new(bcrypt, 'ULONG *') + res = bcrypt.BCryptDecrypt( + key_handle, + data, + len(data), + null(), + null(), + 0, + null(), + 0, + out_len, + flags + ) + handle_error(res) + + buffer_len = deref(out_len) + buffer = buffer_from_bytes(buffer_len) + iv_buffer = buffer_from_bytes(iv) if iv else null() + + res = bcrypt.BCryptDecrypt( + key_handle, + data, + len(data), + null(), + iv_buffer, + iv_len, + buffer, + buffer_len, + out_len, + flags + ) + handle_error(res) + + return bytes_from_buffer(buffer, deref(out_len)) + + finally: + if key_handle: + bcrypt.BCryptDestroyKey(key_handle) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_win/tls.py b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_win/tls.py new file mode 100644 index 00000000..fcb31665 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_win/tls.py @@ -0,0 +1,1593 @@ +# coding: utf-8 +from __future__ import unicode_literals, division, absolute_import, print_function + +import sys +import re +import socket as socket_ +import select +import numbers + +from .._asn1 import Certificate as Asn1Certificate +from .._errors import pretty_message +from .._ffi import ( + buffer_from_bytes, + buffer_from_unicode, + bytes_from_buffer, + cast, + deref, + is_null, + native, + new, + null, + ref, + sizeof, + struct, + unwrap, + write_to_buffer, +) +from ._secur32 import secur32, Secur32Const, handle_error +from ._crypt32 import crypt32, Crypt32Const, handle_error as handle_crypt32_error +from ._kernel32 import kernel32 +from .._types import type_name, str_cls, byte_cls, int_types +from ..errors import TLSError, TLSVerificationError, TLSDisconnectError, TLSGracefulDisconnectError +from .._tls import ( + detect_client_auth_request, + detect_other_protocol, + extract_chain, + get_dh_params_length, + parse_alert, + parse_session_info, + raise_client_auth, + raise_dh_params, + raise_disconnection, + raise_expired_not_yet_valid, + raise_handshake, + raise_hostname, + raise_no_issuer, + raise_protocol_error, + raise_protocol_version, + raise_revoked, + raise_self_signed, + raise_verification, + raise_weak_signature, +) +from .asymmetric import load_certificate, Certificate +from ..keys import parse_certificate + +if sys.version_info < (3,): + range = xrange # noqa + socket_error_cls = socket_.error +else: + socket_error_cls = WindowsError + +if sys.version_info < (3, 7): + Pattern = re._pattern_type +else: + Pattern = re.Pattern + + +__all__ = [ + 'TLSSession', + 'TLSSocket', +] + + +_line_regex = re.compile(b'(\r\n|\r|\n)') + +_gwv = sys.getwindowsversion() +_win_version_info = (_gwv[0], _gwv[1]) + + +class _TLSDowngradeError(TLSVerificationError): + + pass + + +class _TLSRetryError(TLSError): + + """ + TLSv1.2 on Windows 7 and 8 seems to have isuses with some DHE_RSA + ServerKeyExchange messages due to variable length integer encoding. This + exception is used to trigger a reconnection to attempt the handshake again. + """ + + pass + + +class TLSSession(object): + """ + A TLS session object that multiple TLSSocket objects can share for the + sake of session reuse + """ + + _protocols = None + _ciphers = None + _manual_validation = None + _extra_trust_roots = None + _credentials_handle = None + + def __init__(self, protocol=None, manual_validation=False, extra_trust_roots=None): + """ + :param protocol: + A unicode string or set of unicode strings representing allowable + protocols to negotiate with the server: + + - "TLSv1.2" + - "TLSv1.1" + - "TLSv1" + - "SSLv3" + + Default is: {"TLSv1", "TLSv1.1", "TLSv1.2"} + + :param manual_validation: + If certificate and certificate path validation should be skipped + and left to the developer to implement + + :param extra_trust_roots: + A list containing one or more certificates to be treated as trust + roots, in one of the following formats: + - A byte string of the DER encoded certificate + - A unicode string of the certificate filename + - An asn1crypto.x509.Certificate object + - An oscrypto.asymmetric.Certificate object + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + """ + + if not isinstance(manual_validation, bool): + raise TypeError(pretty_message( + ''' + manual_validation must be a boolean, not %s + ''', + type_name(manual_validation) + )) + + self._manual_validation = manual_validation + + if protocol is None: + protocol = set(['TLSv1', 'TLSv1.1', 'TLSv1.2']) + + if isinstance(protocol, str_cls): + protocol = set([protocol]) + elif not isinstance(protocol, set): + raise TypeError(pretty_message( + ''' + protocol must be a unicode string or set of unicode strings, + not %s + ''', + type_name(protocol) + )) + + unsupported_protocols = protocol - set(['SSLv3', 'TLSv1', 'TLSv1.1', 'TLSv1.2']) + if unsupported_protocols: + raise ValueError(pretty_message( + ''' + protocol must contain only the unicode strings "SSLv3", "TLSv1", + "TLSv1.1", "TLSv1.2", not %s + ''', + repr(unsupported_protocols) + )) + + self._protocols = protocol + + self._extra_trust_roots = [] + if extra_trust_roots: + for extra_trust_root in extra_trust_roots: + if isinstance(extra_trust_root, Certificate): + extra_trust_root = extra_trust_root.asn1 + elif isinstance(extra_trust_root, byte_cls): + extra_trust_root = parse_certificate(extra_trust_root) + elif isinstance(extra_trust_root, str_cls): + with open(extra_trust_root, 'rb') as f: + extra_trust_root = parse_certificate(f.read()) + elif not isinstance(extra_trust_root, Asn1Certificate): + raise TypeError(pretty_message( + ''' + extra_trust_roots must be a list of byte strings, unicode + strings, asn1crypto.x509.Certificate objects or + oscrypto.asymmetric.Certificate objects, not %s + ''', + type_name(extra_trust_root) + )) + self._extra_trust_roots.append(extra_trust_root) + + self._obtain_credentials() + + def _obtain_credentials(self): + """ + Obtains a credentials handle from secur32.dll for use with SChannel + """ + + protocol_values = { + 'SSLv3': Secur32Const.SP_PROT_SSL3_CLIENT, + 'TLSv1': Secur32Const.SP_PROT_TLS1_CLIENT, + 'TLSv1.1': Secur32Const.SP_PROT_TLS1_1_CLIENT, + 'TLSv1.2': Secur32Const.SP_PROT_TLS1_2_CLIENT, + } + protocol_bit_mask = 0 + for key, value in protocol_values.items(): + if key in self._protocols: + protocol_bit_mask |= value + + algs = [ + Secur32Const.CALG_AES_128, + Secur32Const.CALG_AES_256, + Secur32Const.CALG_3DES, + Secur32Const.CALG_SHA1, + Secur32Const.CALG_ECDHE, + Secur32Const.CALG_DH_EPHEM, + Secur32Const.CALG_RSA_KEYX, + Secur32Const.CALG_RSA_SIGN, + Secur32Const.CALG_ECDSA, + Secur32Const.CALG_DSS_SIGN, + ] + if 'TLSv1.2' in self._protocols: + algs.extend([ + Secur32Const.CALG_SHA512, + Secur32Const.CALG_SHA384, + Secur32Const.CALG_SHA256, + ]) + + alg_array = new(secur32, 'ALG_ID[%s]' % len(algs)) + for index, alg in enumerate(algs): + alg_array[index] = alg + + flags = Secur32Const.SCH_USE_STRONG_CRYPTO | Secur32Const.SCH_CRED_NO_DEFAULT_CREDS + if not self._manual_validation and not self._extra_trust_roots: + flags |= Secur32Const.SCH_CRED_AUTO_CRED_VALIDATION + else: + flags |= Secur32Const.SCH_CRED_MANUAL_CRED_VALIDATION + + schannel_cred_pointer = struct(secur32, 'SCHANNEL_CRED') + schannel_cred = unwrap(schannel_cred_pointer) + + schannel_cred.dwVersion = Secur32Const.SCHANNEL_CRED_VERSION + schannel_cred.cCreds = 0 + schannel_cred.paCred = null() + schannel_cred.hRootStore = null() + schannel_cred.cMappers = 0 + schannel_cred.aphMappers = null() + schannel_cred.cSupportedAlgs = len(alg_array) + schannel_cred.palgSupportedAlgs = alg_array + schannel_cred.grbitEnabledProtocols = protocol_bit_mask + schannel_cred.dwMinimumCipherStrength = 0 + schannel_cred.dwMaximumCipherStrength = 0 + # Default session lifetime is 10 hours + schannel_cred.dwSessionLifespan = 0 + schannel_cred.dwFlags = flags + schannel_cred.dwCredFormat = 0 + + cred_handle_pointer = new(secur32, 'CredHandle *') + + result = secur32.AcquireCredentialsHandleW( + null(), + Secur32Const.UNISP_NAME, + Secur32Const.SECPKG_CRED_OUTBOUND, + null(), + schannel_cred_pointer, + null(), + null(), + cred_handle_pointer, + null() + ) + handle_error(result) + + self._credentials_handle = cred_handle_pointer + + def __del__(self): + if self._credentials_handle: + result = secur32.FreeCredentialsHandle(self._credentials_handle) + handle_error(result) + self._credentials_handle = None + + +class TLSSocket(object): + """ + A wrapper around a socket.socket that adds TLS + """ + + _socket = None + _session = None + + _context_handle_pointer = None + _context_flags = None + _hostname = None + + _header_size = None + _message_size = None + _trailer_size = None + + _received_bytes = None + _decrypted_bytes = None + + _encrypt_desc = None + _encrypt_buffers = None + _encrypt_data_buffer = None + + _decrypt_desc = None + _decrypt_buffers = None + _decrypt_data_buffer = None + + _certificate = None + _intermediates = None + + _protocol = None + _cipher_suite = None + _compression = None + _session_id = None + _session_ticket = None + + _remote_closed = False + + @classmethod + def wrap(cls, socket, hostname, session=None): + """ + Takes an existing socket and adds TLS + + :param socket: + A socket.socket object to wrap with TLS + + :param hostname: + A unicode string of the hostname or IP the socket is connected to + + :param session: + An existing TLSSession object to allow for session reuse, specific + protocol or manual certificate validation + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + """ + + if not isinstance(socket, socket_.socket): + raise TypeError(pretty_message( + ''' + socket must be an instance of socket.socket, not %s + ''', + type_name(socket) + )) + + if not isinstance(hostname, str_cls): + raise TypeError(pretty_message( + ''' + hostname must be a unicode string, not %s + ''', + type_name(hostname) + )) + + if session is not None and not isinstance(session, TLSSession): + raise TypeError(pretty_message( + ''' + session must be an instance of oscrypto.tls.TLSSession, not %s + ''', + type_name(session) + )) + + new_socket = cls(None, None, session=session) + new_socket._socket = socket + new_socket._hostname = hostname + + # Since we don't create the socket connection here, we can't try to + # reconnect with a lower version of the TLS protocol, so we just + # move the data to public exception type TLSVerificationError() + try: + new_socket._handshake() + except (_TLSDowngradeError) as e: + new_e = TLSVerificationError(e.message, e.certificate) + raise new_e + except (_TLSRetryError) as e: + new_e = TLSError(e.message) + raise new_e + + return new_socket + + def __init__(self, address, port, timeout=10, session=None): + """ + :param address: + A unicode string of the domain name or IP address to conenct to + + :param port: + An integer of the port number to connect to + + :param timeout: + An integer timeout to use for the socket + + :param session: + An oscrypto.tls.TLSSession object to allow for session reuse and + controlling the protocols and validation performed + """ + + self._received_bytes = b'' + self._decrypted_bytes = b'' + + if address is None and port is None: + self._socket = None + + else: + if not isinstance(address, str_cls): + raise TypeError(pretty_message( + ''' + address must be a unicode string, not %s + ''', + type_name(address) + )) + + if not isinstance(port, int_types): + raise TypeError(pretty_message( + ''' + port must be an integer, not %s + ''', + type_name(port) + )) + + if timeout is not None and not isinstance(timeout, numbers.Number): + raise TypeError(pretty_message( + ''' + timeout must be a number, not %s + ''', + type_name(timeout) + )) + + self._socket = socket_.create_connection((address, port), timeout) + self._socket.settimeout(timeout) + + if session is None: + session = TLSSession() + + elif not isinstance(session, TLSSession): + raise TypeError(pretty_message( + ''' + session must be an instance of oscrypto.tls.TLSSession, not %s + ''', + type_name(session) + )) + + self._session = session + + if self._socket: + self._hostname = address + + try: + self._handshake() + except (_TLSDowngradeError): + self.close() + new_session = TLSSession( + session._protocols - set(['TLSv1.2']), + session._manual_validation, + session._extra_trust_roots + ) + session.__del__() + self._received_bytes = b'' + self._session = new_session + self._socket = socket_.create_connection((address, port), timeout) + self._socket.settimeout(timeout) + self._handshake() + except (_TLSRetryError): + self._received_bytes = b'' + self._socket = socket_.create_connection((address, port), timeout) + self._socket.settimeout(timeout) + self._handshake() + + def _create_buffers(self, number): + """ + Creates a SecBufferDesc struct and contained SecBuffer structs + + :param number: + The number of contains SecBuffer objects to create + + :return: + A tuple of (SecBufferDesc pointer, SecBuffer array) + """ + + buffers = new(secur32, 'SecBuffer[%d]' % number) + + for index in range(0, number): + buffers[index].cbBuffer = 0 + buffers[index].BufferType = Secur32Const.SECBUFFER_EMPTY + buffers[index].pvBuffer = null() + + sec_buffer_desc_pointer = struct(secur32, 'SecBufferDesc') + sec_buffer_desc = unwrap(sec_buffer_desc_pointer) + + sec_buffer_desc.ulVersion = Secur32Const.SECBUFFER_VERSION + sec_buffer_desc.cBuffers = number + sec_buffer_desc.pBuffers = buffers + + return (sec_buffer_desc_pointer, buffers) + + def _extra_trust_root_validation(self): + """ + Manually invoked windows certificate chain builder and verification + step when there are extra trust roots to include in the search process + """ + + store = None + cert_chain_context_pointer = None + + try: + # We set up an in-memory store to pass as an extra store to grab + # certificates from when performing the verification + store = crypt32.CertOpenStore( + Crypt32Const.CERT_STORE_PROV_MEMORY, + Crypt32Const.X509_ASN_ENCODING, + null(), + 0, + null() + ) + if is_null(store): + handle_crypt32_error(0) + + cert_hashes = set() + for cert in self._session._extra_trust_roots: + cert_data = cert.dump() + result = crypt32.CertAddEncodedCertificateToStore( + store, + Crypt32Const.X509_ASN_ENCODING, + cert_data, + len(cert_data), + Crypt32Const.CERT_STORE_ADD_USE_EXISTING, + null() + ) + if not result: + handle_crypt32_error(0) + cert_hashes.add(cert.sha256) + + cert_context_pointer_pointer = new(crypt32, 'PCERT_CONTEXT *') + result = secur32.QueryContextAttributesW( + self._context_handle_pointer, + Secur32Const.SECPKG_ATTR_REMOTE_CERT_CONTEXT, + cert_context_pointer_pointer + ) + handle_error(result) + + cert_context_pointer = unwrap(cert_context_pointer_pointer) + cert_context_pointer = cast(crypt32, 'PCERT_CONTEXT', cert_context_pointer) + + # We have to do a funky shuffle here because FILETIME from kernel32 + # is different than FILETIME from crypt32 when using cffi. If we + # overwrite the "now_pointer" variable, cffi releases the backing + # memory and we end up getting a validation error about certificate + # expiration time. + orig_now_pointer = new(kernel32, 'FILETIME *') + kernel32.GetSystemTimeAsFileTime(orig_now_pointer) + now_pointer = cast(crypt32, 'FILETIME *', orig_now_pointer) + + usage_identifiers = new(crypt32, 'char *[3]') + usage_identifiers[0] = cast(crypt32, 'char *', Crypt32Const.PKIX_KP_SERVER_AUTH) + usage_identifiers[1] = cast(crypt32, 'char *', Crypt32Const.SERVER_GATED_CRYPTO) + usage_identifiers[2] = cast(crypt32, 'char *', Crypt32Const.SGC_NETSCAPE) + + cert_enhkey_usage_pointer = struct(crypt32, 'CERT_ENHKEY_USAGE') + cert_enhkey_usage = unwrap(cert_enhkey_usage_pointer) + cert_enhkey_usage.cUsageIdentifier = 3 + cert_enhkey_usage.rgpszUsageIdentifier = cast(crypt32, 'char **', usage_identifiers) + + cert_usage_match_pointer = struct(crypt32, 'CERT_USAGE_MATCH') + cert_usage_match = unwrap(cert_usage_match_pointer) + cert_usage_match.dwType = Crypt32Const.USAGE_MATCH_TYPE_OR + cert_usage_match.Usage = cert_enhkey_usage + + cert_chain_para_pointer = struct(crypt32, 'CERT_CHAIN_PARA') + cert_chain_para = unwrap(cert_chain_para_pointer) + cert_chain_para.RequestedUsage = cert_usage_match + cert_chain_para_size = sizeof(crypt32, cert_chain_para) + cert_chain_para.cbSize = cert_chain_para_size + + cert_chain_context_pointer_pointer = new(crypt32, 'PCERT_CHAIN_CONTEXT *') + result = crypt32.CertGetCertificateChain( + null(), + cert_context_pointer, + now_pointer, + store, + cert_chain_para_pointer, + Crypt32Const.CERT_CHAIN_CACHE_END_CERT | Crypt32Const.CERT_CHAIN_REVOCATION_CHECK_CACHE_ONLY, + null(), + cert_chain_context_pointer_pointer + ) + handle_crypt32_error(result) + + cert_chain_policy_para_flags = Crypt32Const.CERT_CHAIN_POLICY_IGNORE_ALL_REV_UNKNOWN_FLAGS + + cert_chain_context_pointer = unwrap(cert_chain_context_pointer_pointer) + + # Unwrap the chain and if the final element in the chain is one of + # extra trust roots, set flags so that we trust the certificate even + # though it is not in the Trusted Roots store + cert_chain_context = unwrap(cert_chain_context_pointer) + num_chains = native(int, cert_chain_context.cChain) + if num_chains == 1: + first_simple_chain_pointer = unwrap(cert_chain_context.rgpChain) + first_simple_chain = unwrap(first_simple_chain_pointer) + num_elements = native(int, first_simple_chain.cElement) + last_element_pointer = first_simple_chain.rgpElement[num_elements - 1] + last_element = unwrap(last_element_pointer) + last_element_cert = unwrap(last_element.pCertContext) + last_element_cert_data = bytes_from_buffer( + last_element_cert.pbCertEncoded, + native(int, last_element_cert.cbCertEncoded) + ) + last_cert = Asn1Certificate.load(last_element_cert_data) + if last_cert.sha256 in cert_hashes: + cert_chain_policy_para_flags |= Crypt32Const.CERT_CHAIN_POLICY_ALLOW_UNKNOWN_CA_FLAG + + ssl_extra_cert_chain_policy_para_pointer = struct(crypt32, 'SSL_EXTRA_CERT_CHAIN_POLICY_PARA') + ssl_extra_cert_chain_policy_para = unwrap(ssl_extra_cert_chain_policy_para_pointer) + ssl_extra_cert_chain_policy_para.cbSize = sizeof(crypt32, ssl_extra_cert_chain_policy_para) + ssl_extra_cert_chain_policy_para.dwAuthType = Crypt32Const.AUTHTYPE_SERVER + ssl_extra_cert_chain_policy_para.fdwChecks = 0 + ssl_extra_cert_chain_policy_para.pwszServerName = cast( + crypt32, + 'wchar_t *', + buffer_from_unicode(self._hostname) + ) + + cert_chain_policy_para_pointer = struct(crypt32, 'CERT_CHAIN_POLICY_PARA') + cert_chain_policy_para = unwrap(cert_chain_policy_para_pointer) + cert_chain_policy_para.cbSize = sizeof(crypt32, cert_chain_policy_para) + cert_chain_policy_para.dwFlags = cert_chain_policy_para_flags + cert_chain_policy_para.pvExtraPolicyPara = cast(crypt32, 'void *', ssl_extra_cert_chain_policy_para_pointer) + + cert_chain_policy_status_pointer = struct(crypt32, 'CERT_CHAIN_POLICY_STATUS') + cert_chain_policy_status = unwrap(cert_chain_policy_status_pointer) + cert_chain_policy_status.cbSize = sizeof(crypt32, cert_chain_policy_status) + + result = crypt32.CertVerifyCertificateChainPolicy( + Crypt32Const.CERT_CHAIN_POLICY_SSL, + cert_chain_context_pointer, + cert_chain_policy_para_pointer, + cert_chain_policy_status_pointer + ) + handle_crypt32_error(result) + + cert_context = unwrap(cert_context_pointer) + cert_data = bytes_from_buffer(cert_context.pbCertEncoded, native(int, cert_context.cbCertEncoded)) + cert = Asn1Certificate.load(cert_data) + + error = cert_chain_policy_status.dwError + if error: + if error == Crypt32Const.CERT_E_EXPIRED: + raise_expired_not_yet_valid(cert) + if error == Crypt32Const.CERT_E_UNTRUSTEDROOT: + oscrypto_cert = load_certificate(cert) + if oscrypto_cert.self_signed: + raise_self_signed(cert) + else: + raise_no_issuer(cert) + if error == Crypt32Const.CERT_E_CN_NO_MATCH: + raise_hostname(cert, self._hostname) + + if error == Crypt32Const.TRUST_E_CERT_SIGNATURE: + raise_weak_signature(cert) + + if error == Crypt32Const.CRYPT_E_REVOKED: + raise_revoked(cert) + + raise_verification(cert) + + if cert.hash_algo in set(['md5', 'md2']): + raise_weak_signature(cert) + + finally: + if store: + crypt32.CertCloseStore(store, 0) + if cert_chain_context_pointer: + crypt32.CertFreeCertificateChain(cert_chain_context_pointer) + + def _handshake(self, renegotiate=False): + """ + Perform an initial TLS handshake, or a renegotiation + + :param renegotiate: + If the handshake is for a renegotiation + """ + + in_buffers = None + out_buffers = None + new_context_handle_pointer = None + + try: + if renegotiate: + temp_context_handle_pointer = self._context_handle_pointer + else: + new_context_handle_pointer = new(secur32, 'CtxtHandle *') + temp_context_handle_pointer = new_context_handle_pointer + + requested_flags = { + Secur32Const.ISC_REQ_REPLAY_DETECT: 'replay detection', + Secur32Const.ISC_REQ_SEQUENCE_DETECT: 'sequence detection', + Secur32Const.ISC_REQ_CONFIDENTIALITY: 'confidentiality', + Secur32Const.ISC_REQ_ALLOCATE_MEMORY: 'memory allocation', + Secur32Const.ISC_REQ_INTEGRITY: 'integrity', + Secur32Const.ISC_REQ_STREAM: 'stream orientation', + Secur32Const.ISC_REQ_USE_SUPPLIED_CREDS: 'disable automatic client auth', + } + + self._context_flags = 0 + for flag in requested_flags: + self._context_flags |= flag + + in_sec_buffer_desc_pointer, in_buffers = self._create_buffers(2) + in_buffers[0].BufferType = Secur32Const.SECBUFFER_TOKEN + + out_sec_buffer_desc_pointer, out_buffers = self._create_buffers(2) + out_buffers[0].BufferType = Secur32Const.SECBUFFER_TOKEN + out_buffers[1].BufferType = Secur32Const.SECBUFFER_ALERT + + output_context_flags_pointer = new(secur32, 'ULONG *') + + if renegotiate: + first_handle = temp_context_handle_pointer + second_handle = null() + else: + first_handle = null() + second_handle = temp_context_handle_pointer + + result = secur32.InitializeSecurityContextW( + self._session._credentials_handle, + first_handle, + self._hostname, + self._context_flags, + 0, + 0, + null(), + 0, + second_handle, + out_sec_buffer_desc_pointer, + output_context_flags_pointer, + null() + ) + if result not in set([Secur32Const.SEC_E_OK, Secur32Const.SEC_I_CONTINUE_NEEDED]): + handle_error(result, TLSError) + + if not renegotiate: + temp_context_handle_pointer = second_handle + else: + temp_context_handle_pointer = first_handle + + handshake_server_bytes = b'' + handshake_client_bytes = b'' + + if out_buffers[0].cbBuffer > 0: + token = bytes_from_buffer(out_buffers[0].pvBuffer, out_buffers[0].cbBuffer) + handshake_client_bytes += token + self._socket.send(token) + out_buffers[0].cbBuffer = 0 + secur32.FreeContextBuffer(out_buffers[0].pvBuffer) + out_buffers[0].pvBuffer = null() + + in_data_buffer = buffer_from_bytes(32768) + in_buffers[0].pvBuffer = cast(secur32, 'BYTE *', in_data_buffer) + + bytes_read = b'' + while result != Secur32Const.SEC_E_OK: + try: + fail_late = False + bytes_read = self._socket.recv(8192) + if bytes_read == b'': + raise_disconnection() + except (socket_error_cls): + fail_late = True + handshake_server_bytes += bytes_read + self._received_bytes += bytes_read + + in_buffers[0].cbBuffer = len(self._received_bytes) + write_to_buffer(in_data_buffer, self._received_bytes) + + result = secur32.InitializeSecurityContextW( + self._session._credentials_handle, + temp_context_handle_pointer, + self._hostname, + self._context_flags, + 0, + 0, + in_sec_buffer_desc_pointer, + 0, + null(), + out_sec_buffer_desc_pointer, + output_context_flags_pointer, + null() + ) + + if result == Secur32Const.SEC_E_INCOMPLETE_MESSAGE: + in_buffers[0].BufferType = Secur32Const.SECBUFFER_TOKEN + # Windows 10 seems to fill the second input buffer with + # a BufferType of SECBUFFER_MISSING (4), which if not + # cleared causes the handshake to fail. + if in_buffers[1].BufferType != Secur32Const.SECBUFFER_EMPTY: + in_buffers[1].BufferType = Secur32Const.SECBUFFER_EMPTY + in_buffers[1].cbBuffer = 0 + if not is_null(in_buffers[1].pvBuffer): + secur32.FreeContextBuffer(in_buffers[1].pvBuffer) + in_buffers[1].pvBuffer = null() + + if fail_late: + raise_disconnection() + + continue + + if result == Secur32Const.SEC_E_ILLEGAL_MESSAGE: + if detect_client_auth_request(handshake_server_bytes): + raise_client_auth() + alert_info = parse_alert(handshake_server_bytes) + if alert_info and alert_info == (2, 70): + raise_protocol_version() + raise_handshake() + + if result == Secur32Const.SEC_E_WRONG_PRINCIPAL: + chain = extract_chain(handshake_server_bytes) + raise_hostname(chain[0], self._hostname) + + if result == Secur32Const.SEC_E_CERT_EXPIRED: + chain = extract_chain(handshake_server_bytes) + raise_expired_not_yet_valid(chain[0]) + + if result == Secur32Const.SEC_E_UNTRUSTED_ROOT: + chain = extract_chain(handshake_server_bytes) + cert = chain[0] + oscrypto_cert = load_certificate(cert) + if not oscrypto_cert.self_signed: + raise_no_issuer(cert) + raise_self_signed(cert) + + if result == Secur32Const.SEC_E_INTERNAL_ERROR: + if get_dh_params_length(handshake_server_bytes) < 1024: + raise_dh_params() + + if result == Secur32Const.SEC_I_INCOMPLETE_CREDENTIALS: + raise_client_auth() + + if result == Crypt32Const.TRUST_E_CERT_SIGNATURE: + raise_weak_signature(cert) + + if result == Secur32Const.SEC_E_INVALID_TOKEN: + # If an alert it present, there may have been a handshake + # error due to the server using a certificate path with a + # trust root using MD2 or MD5 combined with TLS 1.2. To + # work around this, if the user allows anything other than + # TLS 1.2, we just remove it from the acceptable protocols + # and try again. + if out_buffers[1].cbBuffer > 0: + alert_bytes = bytes_from_buffer(out_buffers[1].pvBuffer, out_buffers[1].cbBuffer) + handshake_client_bytes += alert_bytes + alert_number = alert_bytes[6:7] + if alert_number == b'\x28' or alert_number == b'\x2b': + if 'TLSv1.2' in self._session._protocols and len(self._session._protocols) > 1: + chain = extract_chain(handshake_server_bytes) + raise _TLSDowngradeError( + 'Server certificate verification failed - weak certificate signature algorithm', + chain[0] + ) + if detect_client_auth_request(handshake_server_bytes): + raise_client_auth() + if detect_other_protocol(handshake_server_bytes): + raise_protocol_error(handshake_server_bytes) + raise_handshake() + + # These are semi-common errors with TLSv1.2 on Windows 7 an 8 + # that appears to be due to poor handling of the + # ServerKeyExchange for DHE_RSA cipher suites. The solution + # is to retry the handshake. + if result == Secur32Const.SEC_E_BUFFER_TOO_SMALL or result == Secur32Const.SEC_E_MESSAGE_ALTERED: + if 'TLSv1.2' in self._session._protocols: + raise _TLSRetryError('TLS handshake failed') + + if fail_late: + raise_disconnection() + + if result == Secur32Const.SEC_E_INVALID_PARAMETER: + if get_dh_params_length(handshake_server_bytes) < 1024: + raise_dh_params() + + if result not in set([Secur32Const.SEC_E_OK, Secur32Const.SEC_I_CONTINUE_NEEDED]): + handle_error(result, TLSError) + + if out_buffers[0].cbBuffer > 0: + token = bytes_from_buffer(out_buffers[0].pvBuffer, out_buffers[0].cbBuffer) + handshake_client_bytes += token + self._socket.send(token) + out_buffers[0].cbBuffer = 0 + secur32.FreeContextBuffer(out_buffers[0].pvBuffer) + out_buffers[0].pvBuffer = null() + + if in_buffers[1].BufferType == Secur32Const.SECBUFFER_EXTRA: + extra_amount = in_buffers[1].cbBuffer + self._received_bytes = self._received_bytes[-extra_amount:] + in_buffers[1].BufferType = Secur32Const.SECBUFFER_EMPTY + in_buffers[1].cbBuffer = 0 + secur32.FreeContextBuffer(in_buffers[1].pvBuffer) + in_buffers[1].pvBuffer = null() + + # The handshake is complete, so discard any extra bytes + if result == Secur32Const.SEC_E_OK: + handshake_server_bytes = handshake_server_bytes[-extra_amount:] + + else: + self._received_bytes = b'' + + connection_info_pointer = struct(secur32, 'SecPkgContext_ConnectionInfo') + result = secur32.QueryContextAttributesW( + temp_context_handle_pointer, + Secur32Const.SECPKG_ATTR_CONNECTION_INFO, + connection_info_pointer + ) + handle_error(result, TLSError) + + connection_info = unwrap(connection_info_pointer) + + self._protocol = { + Secur32Const.SP_PROT_SSL2_CLIENT: 'SSLv2', + Secur32Const.SP_PROT_SSL3_CLIENT: 'SSLv3', + Secur32Const.SP_PROT_TLS1_CLIENT: 'TLSv1', + Secur32Const.SP_PROT_TLS1_1_CLIENT: 'TLSv1.1', + Secur32Const.SP_PROT_TLS1_2_CLIENT: 'TLSv1.2', + }.get(native(int, connection_info.dwProtocol), str_cls(connection_info.dwProtocol)) + + if self._protocol in set(['SSLv3', 'TLSv1', 'TLSv1.1', 'TLSv1.2']): + session_info = parse_session_info(handshake_server_bytes, handshake_client_bytes) + self._cipher_suite = session_info['cipher_suite'] + self._compression = session_info['compression'] + self._session_id = session_info['session_id'] + self._session_ticket = session_info['session_ticket'] + + output_context_flags = deref(output_context_flags_pointer) + + for flag in requested_flags: + if (flag | output_context_flags) == 0: + raise OSError(pretty_message( + ''' + Unable to obtain a credential context with the property %s + ''', + requested_flags[flag] + )) + + if not renegotiate: + self._context_handle_pointer = temp_context_handle_pointer + new_context_handle_pointer = None + + stream_sizes_pointer = struct(secur32, 'SecPkgContext_StreamSizes') + result = secur32.QueryContextAttributesW( + self._context_handle_pointer, + Secur32Const.SECPKG_ATTR_STREAM_SIZES, + stream_sizes_pointer + ) + handle_error(result) + + stream_sizes = unwrap(stream_sizes_pointer) + self._header_size = native(int, stream_sizes.cbHeader) + self._message_size = native(int, stream_sizes.cbMaximumMessage) + self._trailer_size = native(int, stream_sizes.cbTrailer) + self._buffer_size = self._header_size + self._message_size + self._trailer_size + + if self._session._extra_trust_roots: + self._extra_trust_root_validation() + + except (OSError, socket_.error): + self.close() + + raise + + finally: + if out_buffers: + if not is_null(out_buffers[0].pvBuffer): + secur32.FreeContextBuffer(out_buffers[0].pvBuffer) + if not is_null(out_buffers[1].pvBuffer): + secur32.FreeContextBuffer(out_buffers[1].pvBuffer) + if new_context_handle_pointer: + secur32.DeleteSecurityContext(new_context_handle_pointer) + + def read(self, max_length): + """ + Reads data from the TLS-wrapped socket + + :param max_length: + The number of bytes to read + + :raises: + socket.socket - when a non-TLS socket error occurs + oscrypto.errors.TLSError - when a TLS-related error occurs + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + + :return: + A byte string of the data read + """ + + if not isinstance(max_length, int_types): + raise TypeError(pretty_message( + ''' + max_length must be an integer, not %s + ''', + type_name(max_length) + )) + + if self._context_handle_pointer is None: + + # Allow the user to read any remaining decrypted data + if self._decrypted_bytes != b'': + output = self._decrypted_bytes[0:max_length] + self._decrypted_bytes = self._decrypted_bytes[max_length:] + return output + + self._raise_closed() + + # The first time read is called, set up a single contiguous buffer that + # it used by DecryptMessage() to populate the three output buffers. + # Since we are creating the buffer, we do not need to free it other + # than allowing Python to GC it once this object is GCed. + if not self._decrypt_data_buffer: + self._decrypt_data_buffer = buffer_from_bytes(self._buffer_size) + self._decrypt_desc, self._decrypt_buffers = self._create_buffers(4) + self._decrypt_buffers[0].BufferType = Secur32Const.SECBUFFER_DATA + self._decrypt_buffers[0].pvBuffer = cast(secur32, 'BYTE *', self._decrypt_data_buffer) + + to_recv = max(max_length, self._buffer_size) + + # These variables are set to reduce dict access and function calls + # in the read loop. Also makes the code easier to read. + null_value = null() + buf0 = self._decrypt_buffers[0] + buf1 = self._decrypt_buffers[1] + buf2 = self._decrypt_buffers[2] + buf3 = self._decrypt_buffers[3] + + def _reset_buffers(): + buf0.BufferType = Secur32Const.SECBUFFER_DATA + buf0.pvBuffer = cast(secur32, 'BYTE *', self._decrypt_data_buffer) + buf0.cbBuffer = 0 + + buf1.BufferType = Secur32Const.SECBUFFER_EMPTY + buf1.pvBuffer = null_value + buf1.cbBuffer = 0 + + buf2.BufferType = Secur32Const.SECBUFFER_EMPTY + buf2.pvBuffer = null_value + buf2.cbBuffer = 0 + + buf3.BufferType = Secur32Const.SECBUFFER_EMPTY + buf3.pvBuffer = null_value + buf3.cbBuffer = 0 + + output = self._decrypted_bytes + output_len = len(output) + + self._decrypted_bytes = b'' + + # Don't block if we have buffered data available + if output_len > 0 and not self.select_read(0): + self._decrypted_bytes = b'' + return output + + # This read loop will only be run if there wasn't enough + # buffered data to fulfill the requested max_length + do_read = len(self._received_bytes) == 0 + + while output_len < max_length: + if do_read: + self._received_bytes += self._socket.recv(to_recv) + if len(self._received_bytes) == 0: + raise_disconnection() + + data_len = min(len(self._received_bytes), self._buffer_size) + if data_len == 0: + break + self._decrypt_buffers[0].cbBuffer = data_len + write_to_buffer(self._decrypt_data_buffer, self._received_bytes[0:data_len]) + + result = secur32.DecryptMessage( + self._context_handle_pointer, + self._decrypt_desc, + 0, + null() + ) + + do_read = False + + if result == Secur32Const.SEC_E_INCOMPLETE_MESSAGE: + _reset_buffers() + do_read = True + continue + + elif result == Secur32Const.SEC_I_CONTEXT_EXPIRED: + self._remote_closed = True + self.shutdown() + break + + elif result == Secur32Const.SEC_I_RENEGOTIATE: + self._handshake(renegotiate=True) + return self.read(max_length) + + elif result != Secur32Const.SEC_E_OK: + handle_error(result, TLSError) + + valid_buffer_types = set([ + Secur32Const.SECBUFFER_EMPTY, + Secur32Const.SECBUFFER_STREAM_HEADER, + Secur32Const.SECBUFFER_STREAM_TRAILER + ]) + extra_amount = None + for buf in (buf0, buf1, buf2, buf3): + buffer_type = buf.BufferType + if buffer_type == Secur32Const.SECBUFFER_DATA: + output += bytes_from_buffer(buf.pvBuffer, buf.cbBuffer) + output_len = len(output) + elif buffer_type == Secur32Const.SECBUFFER_EXTRA: + extra_amount = native(int, buf.cbBuffer) + elif buffer_type not in valid_buffer_types: + raise OSError(pretty_message( + ''' + Unexpected decrypt output buffer of type %s + ''', + buffer_type + )) + + if extra_amount: + self._received_bytes = self._received_bytes[data_len - extra_amount:] + else: + self._received_bytes = self._received_bytes[data_len:] + + # Here we reset the structs for the next call to DecryptMessage() + _reset_buffers() + + # If we have read something, but there is nothing left to read, we + # break so that we don't block for longer than necessary + if self.select_read(0): + do_read = True + + if not do_read and len(self._received_bytes) == 0: + break + + # If the output is more than we requested (because data is decrypted in + # blocks), we save the extra in a buffer + if len(output) > max_length: + self._decrypted_bytes = output[max_length:] + output = output[0:max_length] + + return output + + def select_read(self, timeout=None): + """ + Blocks until the socket is ready to be read from, or the timeout is hit + + :param timeout: + A float - the period of time to wait for data to be read. None for + no time limit. + + :return: + A boolean - if data is ready to be read. Will only be False if + timeout is not None. + """ + + # If we have buffered data, we consider a read possible + if len(self._decrypted_bytes) > 0: + return True + + read_ready, _, _ = select.select([self._socket], [], [], timeout) + return len(read_ready) > 0 + + def read_until(self, marker): + """ + Reads data from the socket until a marker is found. Data read may + include data beyond the marker. + + :param marker: + A byte string or regex object from re.compile(). Used to determine + when to stop reading. Regex objects are more inefficient since + they must scan the entire byte string of read data each time data + is read off the socket. + + :return: + A byte string of the data read + """ + + if not isinstance(marker, byte_cls) and not isinstance(marker, Pattern): + raise TypeError(pretty_message( + ''' + marker must be a byte string or compiled regex object, not %s + ''', + type_name(marker) + )) + + output = b'' + + is_regex = isinstance(marker, Pattern) + + while True: + if len(self._decrypted_bytes) > 0: + chunk = self._decrypted_bytes + self._decrypted_bytes = b'' + else: + chunk = self.read(8192) + + offset = len(output) + output += chunk + + if is_regex: + match = marker.search(output) + if match is not None: + end = match.end() + break + else: + # If the marker was not found last time, we have to start + # at a position where the marker would have its final char + # in the newly read chunk + start = max(0, offset - len(marker) - 1) + match = output.find(marker, start) + if match != -1: + end = match + len(marker) + break + + self._decrypted_bytes = output[end:] + self._decrypted_bytes + return output[0:end] + + def read_line(self): + r""" + Reads a line from the socket, including the line ending of "\r\n", "\r", + or "\n" + + :return: + A byte string of the next line from the socket + """ + + return self.read_until(_line_regex) + + def read_exactly(self, num_bytes): + """ + Reads exactly the specified number of bytes from the socket + + :param num_bytes: + An integer - the exact number of bytes to read + + :return: + A byte string of the data that was read + """ + + output = b'' + remaining = num_bytes + while remaining > 0: + output += self.read(remaining) + remaining = num_bytes - len(output) + + return output + + def write(self, data): + """ + Writes data to the TLS-wrapped socket + + :param data: + A byte string to write to the socket + + :raises: + socket.socket - when a non-TLS socket error occurs + oscrypto.errors.TLSError - when a TLS-related error occurs + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + """ + + if self._context_handle_pointer is None: + self._raise_closed() + + if not self._encrypt_data_buffer: + self._encrypt_data_buffer = buffer_from_bytes(self._header_size + self._message_size + self._trailer_size) + self._encrypt_desc, self._encrypt_buffers = self._create_buffers(4) + + self._encrypt_buffers[0].BufferType = Secur32Const.SECBUFFER_STREAM_HEADER + self._encrypt_buffers[0].cbBuffer = self._header_size + self._encrypt_buffers[0].pvBuffer = cast(secur32, 'BYTE *', self._encrypt_data_buffer) + + self._encrypt_buffers[1].BufferType = Secur32Const.SECBUFFER_DATA + self._encrypt_buffers[1].pvBuffer = ref(self._encrypt_data_buffer, self._header_size) + + self._encrypt_buffers[2].BufferType = Secur32Const.SECBUFFER_STREAM_TRAILER + self._encrypt_buffers[2].cbBuffer = self._trailer_size + self._encrypt_buffers[2].pvBuffer = ref(self._encrypt_data_buffer, self._header_size + self._message_size) + + while len(data) > 0: + to_write = min(len(data), self._message_size) + write_to_buffer(self._encrypt_data_buffer, data[0:to_write], self._header_size) + + self._encrypt_buffers[1].cbBuffer = to_write + self._encrypt_buffers[2].pvBuffer = ref(self._encrypt_data_buffer, self._header_size + to_write) + + result = secur32.EncryptMessage( + self._context_handle_pointer, + 0, + self._encrypt_desc, + 0 + ) + + if result != Secur32Const.SEC_E_OK: + handle_error(result, TLSError) + + to_send = native(int, self._encrypt_buffers[0].cbBuffer) + to_send += native(int, self._encrypt_buffers[1].cbBuffer) + to_send += native(int, self._encrypt_buffers[2].cbBuffer) + try: + self._socket.send(bytes_from_buffer(self._encrypt_data_buffer, to_send)) + except (socket_.error) as e: + if e.errno == 10053: + raise_disconnection() + raise + + data = data[to_send:] + + def select_write(self, timeout=None): + """ + Blocks until the socket is ready to be written to, or the timeout is hit + + :param timeout: + A float - the period of time to wait for the socket to be ready to + written to. None for no time limit. + + :return: + A boolean - if the socket is ready for writing. Will only be False + if timeout is not None. + """ + + _, write_ready, _ = select.select([], [self._socket], [], timeout) + return len(write_ready) > 0 + + def shutdown(self): + """ + Shuts down the TLS session and then shuts down the underlying socket + + :raises: + OSError - when an error is returned by the OS crypto library + """ + + if self._context_handle_pointer is None: + return + + out_buffers = None + try: + # ApplyControlToken fails with SEC_E_UNSUPPORTED_FUNCTION + # when called on Windows 7 + if _win_version_info >= (6, 2): + buffers = new(secur32, 'SecBuffer[1]') + + # This is a SCHANNEL_SHUTDOWN token (DWORD of 1) + buffers[0].cbBuffer = 4 + buffers[0].BufferType = Secur32Const.SECBUFFER_TOKEN + buffers[0].pvBuffer = cast(secur32, 'BYTE *', buffer_from_bytes(b'\x01\x00\x00\x00')) + + sec_buffer_desc_pointer = struct(secur32, 'SecBufferDesc') + sec_buffer_desc = unwrap(sec_buffer_desc_pointer) + + sec_buffer_desc.ulVersion = Secur32Const.SECBUFFER_VERSION + sec_buffer_desc.cBuffers = 1 + sec_buffer_desc.pBuffers = buffers + + result = secur32.ApplyControlToken(self._context_handle_pointer, sec_buffer_desc_pointer) + handle_error(result, TLSError) + + out_sec_buffer_desc_pointer, out_buffers = self._create_buffers(2) + out_buffers[0].BufferType = Secur32Const.SECBUFFER_TOKEN + out_buffers[1].BufferType = Secur32Const.SECBUFFER_ALERT + + output_context_flags_pointer = new(secur32, 'ULONG *') + + result = secur32.InitializeSecurityContextW( + self._session._credentials_handle, + self._context_handle_pointer, + self._hostname, + self._context_flags, + 0, + 0, + null(), + 0, + null(), + out_sec_buffer_desc_pointer, + output_context_flags_pointer, + null() + ) + acceptable_results = set([ + Secur32Const.SEC_E_OK, + Secur32Const.SEC_E_CONTEXT_EXPIRED, + Secur32Const.SEC_I_CONTINUE_NEEDED + ]) + if result not in acceptable_results: + handle_error(result, TLSError) + + token = bytes_from_buffer(out_buffers[0].pvBuffer, out_buffers[0].cbBuffer) + try: + # If there is an error sending the shutdown, ignore it since the + # connection is likely gone at this point + self._socket.send(token) + except (socket_.error): + pass + + finally: + if out_buffers: + if not is_null(out_buffers[0].pvBuffer): + secur32.FreeContextBuffer(out_buffers[0].pvBuffer) + if not is_null(out_buffers[1].pvBuffer): + secur32.FreeContextBuffer(out_buffers[1].pvBuffer) + + secur32.DeleteSecurityContext(self._context_handle_pointer) + self._context_handle_pointer = None + + try: + self._socket.shutdown(socket_.SHUT_RDWR) + except (socket_.error): + pass + + def close(self): + """ + Shuts down the TLS session and socket and forcibly closes it + """ + + try: + self.shutdown() + + finally: + if self._socket: + try: + self._socket.close() + except (socket_.error): + pass + self._socket = None + + def _read_certificates(self): + """ + Reads end-entity and intermediate certificate information from the + TLS session + """ + + cert_context_pointer_pointer = new(crypt32, 'CERT_CONTEXT **') + result = secur32.QueryContextAttributesW( + self._context_handle_pointer, + Secur32Const.SECPKG_ATTR_REMOTE_CERT_CONTEXT, + cert_context_pointer_pointer + ) + handle_error(result, TLSError) + + cert_context_pointer = unwrap(cert_context_pointer_pointer) + cert_context_pointer = cast(crypt32, 'CERT_CONTEXT *', cert_context_pointer) + cert_context = unwrap(cert_context_pointer) + + cert_data = bytes_from_buffer(cert_context.pbCertEncoded, native(int, cert_context.cbCertEncoded)) + self._certificate = Asn1Certificate.load(cert_data) + + self._intermediates = [] + + store_handle = None + try: + store_handle = cert_context.hCertStore + context_pointer = crypt32.CertEnumCertificatesInStore(store_handle, null()) + while not is_null(context_pointer): + context = unwrap(context_pointer) + data = bytes_from_buffer(context.pbCertEncoded, native(int, context.cbCertEncoded)) + # The cert store seems to include the end-entity certificate as + # the last entry, but we already have that from the struct. + if data != cert_data: + self._intermediates.append(Asn1Certificate.load(data)) + context_pointer = crypt32.CertEnumCertificatesInStore(store_handle, context_pointer) + + finally: + if store_handle: + crypt32.CertCloseStore(store_handle, 0) + + def _raise_closed(self): + """ + Raises an exception describing if the local or remote end closed the + connection + """ + + if self._remote_closed: + raise TLSGracefulDisconnectError('The remote end closed the connection') + else: + raise TLSDisconnectError('The connection was already closed') + + @property + def certificate(self): + """ + An asn1crypto.x509.Certificate object of the end-entity certificate + presented by the server + """ + + if self._context_handle_pointer is None: + self._raise_closed() + + if self._certificate is None: + self._read_certificates() + + return self._certificate + + @property + def intermediates(self): + """ + A list of asn1crypto.x509.Certificate objects that were presented as + intermediates by the server + """ + + if self._context_handle_pointer is None: + self._raise_closed() + + if self._certificate is None: + self._read_certificates() + + return self._intermediates + + @property + def cipher_suite(self): + """ + A unicode string of the IANA cipher suite name of the negotiated + cipher suite + """ + + return self._cipher_suite + + @property + def protocol(self): + """ + A unicode string of: "TLSv1.2", "TLSv1.1", "TLSv1", "SSLv3" + """ + + return self._protocol + + @property + def compression(self): + """ + A boolean if compression is enabled + """ + + return self._compression + + @property + def session_id(self): + """ + A unicode string of "new" or "reused" or None for no ticket + """ + + return self._session_id + + @property + def session_ticket(self): + """ + A unicode string of "new" or "reused" or None for no ticket + """ + + return self._session_ticket + + @property + def session(self): + """ + The oscrypto.tls.TLSSession object used for this connection + """ + + return self._session + + @property + def hostname(self): + """ + A unicode string of the TLS server domain name or IP address + """ + + return self._hostname + + @property + def port(self): + """ + An integer of the port number the socket is connected to + """ + + return self.socket.getpeername()[1] + + @property + def socket(self): + """ + The underlying socket.socket connection + """ + + if self._context_handle_pointer is None: + self._raise_closed() + + return self._socket + + def __del__(self): + self.close() diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_win/trust_list.py b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_win/trust_list.py new file mode 100644 index 00000000..6bd99e3c --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_win/trust_list.py @@ -0,0 +1,226 @@ +# coding: utf-8 +from __future__ import unicode_literals, division, absolute_import, print_function + +import datetime +import hashlib +import struct + +from .._asn1 import Certificate +from .._ffi import ( + array_from_pointer, + buffer_from_bytes, + bytes_from_buffer, + cast, + deref, + is_null, + new, + null, + struct_from_buffer, + unwrap, +) +from ._crypt32 import crypt32, Crypt32Const, get_error, handle_error +from .._types import str_cls + + +__all__ = [ + 'extract_from_system', + 'system_path', +] + + +def system_path(): + return None + + +def extract_from_system(cert_callback=None, callback_only_on_failure=False): + """ + Extracts trusted CA certificates from the Windows certificate store + + :param cert_callback: + A callback that is called once for each certificate in the trust store. + It should accept two parameters: an asn1crypto.x509.Certificate object, + and a reason. The reason will be None if the certificate is being + exported, otherwise it will be a unicode string of the reason it won't. + + :param callback_only_on_failure: + A boolean - if the callback should only be called when a certificate is + not exported. + + :raises: + OSError - when an error is returned by the OS crypto library + + :return: + A list of 3-element tuples: + - 0: a byte string of a DER-encoded certificate + - 1: a set of unicode strings that are OIDs of purposes to trust the + certificate for + - 2: a set of unicode strings that are OIDs of purposes to reject the + certificate for + """ + + certificates = {} + processed = {} + + now = datetime.datetime.utcnow() + + for store in ["ROOT", "CA"]: + store_handle = crypt32.CertOpenSystemStoreW(null(), store) + handle_error(store_handle) + + context_pointer = null() + while True: + context_pointer = crypt32.CertEnumCertificatesInStore(store_handle, context_pointer) + if is_null(context_pointer): + break + context = unwrap(context_pointer) + + trust_all = False + data = None + digest = None + + if context.dwCertEncodingType != Crypt32Const.X509_ASN_ENCODING: + continue + + data = bytes_from_buffer(context.pbCertEncoded, int(context.cbCertEncoded)) + digest = hashlib.sha1(data).digest() + if digest in processed: + continue + + processed[digest] = True + cert_info = unwrap(context.pCertInfo) + + not_before_seconds = _convert_filetime_to_timestamp(cert_info.NotBefore) + try: + not_before = datetime.datetime.fromtimestamp(not_before_seconds) + if not_before > now: + if cert_callback: + cert_callback(Certificate.load(data), 'not yet valid') + continue + except (ValueError, OSError): + # If there is an error converting the not before timestamp, + # it is almost certainly because it is from too long ago, + # which means the cert is definitely valid by now. + pass + + not_after_seconds = _convert_filetime_to_timestamp(cert_info.NotAfter) + try: + not_after = datetime.datetime.fromtimestamp(not_after_seconds) + if not_after < now: + if cert_callback: + cert_callback(Certificate.load(data), 'no longer valid') + continue + except (ValueError, OSError) as e: + # The only reason we would get an exception here is if the + # expiration time is so far in the future that it can't be + # used as a timestamp, or it is before 0. If it is very far + # in the future, the cert is still valid, so we only raise + # an exception if the timestamp is less than zero. + if not_after_seconds < 0: + message = e.args[0] + ' - ' + str_cls(not_after_seconds) + e.args = (message,) + e.args[1:] + raise e + + trust_oids = set() + reject_oids = set() + + # Here we grab the extended key usage properties that Windows + # layers on top of the extended key usage extension that is + # part of the certificate itself. For highest security, users + # should only use certificates for the intersection of the two + # lists of purposes. However, many seen to treat the OS trust + # list as an override. + to_read = new(crypt32, 'DWORD *', 0) + res = crypt32.CertGetEnhancedKeyUsage( + context_pointer, + Crypt32Const.CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG, + null(), + to_read + ) + + # Per the Microsoft documentation, if CRYPT_E_NOT_FOUND is returned + # from get_error(), it means the certificate is valid for all purposes + error_code, _ = get_error() + if not res and error_code != Crypt32Const.CRYPT_E_NOT_FOUND: + handle_error(res) + + if error_code == Crypt32Const.CRYPT_E_NOT_FOUND: + trust_all = True + else: + usage_buffer = buffer_from_bytes(deref(to_read)) + res = crypt32.CertGetEnhancedKeyUsage( + context_pointer, + Crypt32Const.CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG, + cast(crypt32, 'CERT_ENHKEY_USAGE *', usage_buffer), + to_read + ) + handle_error(res) + + key_usage_pointer = struct_from_buffer(crypt32, 'CERT_ENHKEY_USAGE', usage_buffer) + key_usage = unwrap(key_usage_pointer) + + # Having no enhanced usage properties means a cert is distrusted + if key_usage.cUsageIdentifier == 0: + if cert_callback: + cert_callback(Certificate.load(data), 'explicitly distrusted') + continue + + oids = array_from_pointer( + crypt32, + 'LPCSTR', + key_usage.rgpszUsageIdentifier, + key_usage.cUsageIdentifier + ) + for oid in oids: + trust_oids.add(oid.decode('ascii')) + + cert = None + + # If the certificate is not under blanket trust, we have to + # determine what purposes it is rejected for by diffing the + # set of OIDs from the certificate with the OIDs that are + # trusted. + if not trust_all: + cert = Certificate.load(data) + if cert.extended_key_usage_value: + for cert_oid in cert.extended_key_usage_value: + oid = cert_oid.dotted + if oid not in trust_oids: + reject_oids.add(oid) + + if cert_callback and not callback_only_on_failure: + if cert is None: + cert = Certificate.load(data) + cert_callback(cert, None) + + certificates[digest] = (data, trust_oids, reject_oids) + + result = crypt32.CertCloseStore(store_handle, 0) + handle_error(result) + store_handle = None + + return certificates.values() + + +def _convert_filetime_to_timestamp(filetime): + """ + Windows returns times as 64-bit unsigned longs that are the number + of hundreds of nanoseconds since Jan 1 1601. This converts it to + a datetime object. + + :param filetime: + A FILETIME struct object + + :return: + An integer unix timestamp + """ + + hundreds_nano_seconds = struct.unpack( + b'>Q', + struct.pack( + b'>LL', + filetime.dwHighDateTime, + filetime.dwLowDateTime + ) + )[0] + seconds_since_1601 = hundreds_nano_seconds / 10000000 + return seconds_since_1601 - 11644473600 # Seconds from Jan 1 1601 to Jan 1 1970 diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_win/util.py b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_win/util.py new file mode 100644 index 00000000..610ca5bc --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_win/util.py @@ -0,0 +1,180 @@ +# coding: utf-8 +from __future__ import unicode_literals, division, absolute_import, print_function + +from .. import backend +from .._errors import pretty_message +from .._ffi import buffer_from_bytes, bytes_from_buffer +from .._pkcs12 import pkcs12_kdf +from .._types import type_name, byte_cls, int_types + + +__all__ = [ + 'pbkdf2', + 'pkcs12_kdf', + 'rand_bytes', +] + + +_backend = backend() + + +if _backend == 'win': + from ._cng import bcrypt, BcryptConst, handle_error, open_alg_handle, close_alg_handle + + def pbkdf2(hash_algorithm, password, salt, iterations, key_length): + """ + PBKDF2 from PKCS#5 + + :param hash_algorithm: + The string name of the hash algorithm to use: "sha1", "sha256", "sha384", "sha512" + + :param password: + A byte string of the password to use an input to the KDF + + :param salt: + A cryptographic random byte string + + :param iterations: + The numbers of iterations to use when deriving the key + + :param key_length: + The length of the desired key in bytes + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + + :return: + The derived key as a byte string + """ + + if not isinstance(password, byte_cls): + raise TypeError(pretty_message( + ''' + password must be a byte string, not %s + ''', + type_name(password) + )) + + if not isinstance(salt, byte_cls): + raise TypeError(pretty_message( + ''' + salt must be a byte string, not %s + ''', + type_name(salt) + )) + + if not isinstance(iterations, int_types): + raise TypeError(pretty_message( + ''' + iterations must be an integer, not %s + ''', + type_name(iterations) + )) + + if iterations < 1: + raise ValueError('iterations must be greater than 0') + + if not isinstance(key_length, int_types): + raise TypeError(pretty_message( + ''' + key_length must be an integer, not %s + ''', + type_name(key_length) + )) + + if key_length < 1: + raise ValueError('key_length must be greater than 0') + + if hash_algorithm not in set(['sha1', 'sha256', 'sha384', 'sha512']): + raise ValueError(pretty_message( + ''' + hash_algorithm must be one of "sha1", "sha256", "sha384", "sha512", + not %s + ''', + repr(hash_algorithm) + )) + + alg_constant = { + 'sha1': BcryptConst.BCRYPT_SHA1_ALGORITHM, + 'sha256': BcryptConst.BCRYPT_SHA256_ALGORITHM, + 'sha384': BcryptConst.BCRYPT_SHA384_ALGORITHM, + 'sha512': BcryptConst.BCRYPT_SHA512_ALGORITHM + }[hash_algorithm] + + alg_handle = None + + try: + alg_handle = open_alg_handle(alg_constant, BcryptConst.BCRYPT_ALG_HANDLE_HMAC_FLAG) + + output_buffer = buffer_from_bytes(key_length) + res = bcrypt.BCryptDeriveKeyPBKDF2( + alg_handle, + password, + len(password), + salt, + len(salt), + iterations, + output_buffer, + key_length, + 0 + ) + handle_error(res) + + return bytes_from_buffer(output_buffer) + finally: + if alg_handle: + close_alg_handle(alg_handle) + + pbkdf2.pure_python = False + + def rand_bytes(length): + """ + Returns a number of random bytes suitable for cryptographic purposes + + :param length: + The desired number of bytes + + :raises: + ValueError - when any of the parameters contain an invalid value + TypeError - when any of the parameters are of the wrong type + OSError - when an error is returned by the OS crypto library + + :return: + A byte string + """ + + if not isinstance(length, int_types): + raise TypeError(pretty_message( + ''' + length must be an integer, not %s + ''', + type_name(length) + )) + + if length < 1: + raise ValueError('length must be greater than 0') + + if length > 1024: + raise ValueError('length must not be greater than 1024') + + alg_handle = None + + try: + alg_handle = open_alg_handle(BcryptConst.BCRYPT_RNG_ALGORITHM) + buffer = buffer_from_bytes(length) + + res = bcrypt.BCryptGenRandom(alg_handle, buffer, length, 0) + handle_error(res) + + return bytes_from_buffer(buffer) + + finally: + if alg_handle: + close_alg_handle(alg_handle) + +# winlegacy backend +else: + from .._pkcs5 import pbkdf2 + from .._rand import rand_bytes diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/asymmetric.py b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/asymmetric.py new file mode 100644 index 00000000..353d2fdf --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/asymmetric.py @@ -0,0 +1,458 @@ +# coding: utf-8 +from __future__ import unicode_literals, division, absolute_import, print_function + +import hashlib +import binascii + +from . import backend +from ._asn1 import ( + armor, + Certificate as Asn1Certificate, + DHParameters, + EncryptedPrivateKeyInfo, + Null, + OrderedDict, + Pbkdf2Salt, + PrivateKeyInfo, + PublicKeyInfo, +) +from ._asymmetric import _unwrap_private_key_info +from ._errors import pretty_message +from ._types import type_name, str_cls +from .kdf import pbkdf2, pbkdf2_iteration_calculator +from .symmetric import aes_cbc_pkcs7_encrypt +from .util import rand_bytes + + +_backend = backend() + + +if _backend == 'mac': + from ._mac.asymmetric import ( + Certificate, + dsa_sign, + dsa_verify, + ecdsa_sign, + ecdsa_verify, + generate_pair, + generate_dh_parameters, + load_certificate, + load_pkcs12, + load_private_key, + load_public_key, + PrivateKey, + PublicKey, + rsa_pkcs1v15_sign, + rsa_pkcs1v15_verify, + rsa_pss_sign, + rsa_pss_verify, + rsa_pkcs1v15_encrypt, + rsa_pkcs1v15_decrypt, + rsa_oaep_encrypt, + rsa_oaep_decrypt, + ) + +elif _backend == 'win' or _backend == 'winlegacy': + from ._win.asymmetric import ( + Certificate, + dsa_sign, + dsa_verify, + ecdsa_sign, + ecdsa_verify, + generate_pair, + generate_dh_parameters, + load_certificate, + load_pkcs12, + load_private_key, + load_public_key, + PrivateKey, + PublicKey, + rsa_pkcs1v15_sign, + rsa_pkcs1v15_verify, + rsa_pss_sign, + rsa_pss_verify, + rsa_pkcs1v15_encrypt, + rsa_pkcs1v15_decrypt, + rsa_oaep_encrypt, + rsa_oaep_decrypt, + ) + +else: + from ._openssl.asymmetric import ( + Certificate, + dsa_sign, + dsa_verify, + ecdsa_sign, + ecdsa_verify, + generate_pair, + generate_dh_parameters, + load_certificate, + load_pkcs12, + load_private_key, + load_public_key, + PrivateKey, + PublicKey, + rsa_pkcs1v15_sign, + rsa_pkcs1v15_verify, + rsa_pss_sign, + rsa_pss_verify, + rsa_pkcs1v15_encrypt, + rsa_pkcs1v15_decrypt, + rsa_oaep_encrypt, + rsa_oaep_decrypt, + ) + + +__all__ = [ + 'Certificate', + 'dsa_sign', + 'dsa_verify', + 'dump_certificate', + 'dump_dh_parameters', + 'dump_openssl_private_key', + 'dump_private_key', + 'dump_public_key', + 'ecdsa_sign', + 'ecdsa_verify', + 'generate_pair', + 'generate_dh_parameters', + 'load_certificate', + 'load_pkcs12', + 'load_private_key', + 'load_public_key', + 'PrivateKey', + 'PublicKey', + 'rsa_oaep_decrypt', + 'rsa_oaep_encrypt', + 'rsa_pkcs1v15_decrypt', + 'rsa_pkcs1v15_encrypt', + 'rsa_pkcs1v15_sign', + 'rsa_pkcs1v15_verify', + 'rsa_pss_sign', + 'rsa_pss_verify', +] + + +def dump_dh_parameters(dh_parameters, encoding='pem'): + """ + Serializes an asn1crypto.algos.DHParameters object into a byte string + + :param dh_parameters: + An asn1crypto.algos.DHParameters object + + :param encoding: + A unicode string of "pem" or "der" + + :return: + A byte string of the encoded DH parameters + """ + + if encoding not in set(['pem', 'der']): + raise ValueError(pretty_message( + ''' + encoding must be one of "pem", "der", not %s + ''', + repr(encoding) + )) + + if not isinstance(dh_parameters, DHParameters): + raise TypeError(pretty_message( + ''' + dh_parameters must be an instance of asn1crypto.algos.DHParameters, + not %s + ''', + type_name(dh_parameters) + )) + + output = dh_parameters.dump() + if encoding == 'pem': + output = armor('DH PARAMETERS', output) + return output + + +def dump_public_key(public_key, encoding='pem'): + """ + Serializes a public key object into a byte string + + :param public_key: + An oscrypto.asymmetric.PublicKey or asn1crypto.keys.PublicKeyInfo object + + :param encoding: + A unicode string of "pem" or "der" + + :return: + A byte string of the encoded public key + """ + + if encoding not in set(['pem', 'der']): + raise ValueError(pretty_message( + ''' + encoding must be one of "pem", "der", not %s + ''', + repr(encoding) + )) + + is_oscrypto = isinstance(public_key, PublicKey) + if not isinstance(public_key, PublicKeyInfo) and not is_oscrypto: + raise TypeError(pretty_message( + ''' + public_key must be an instance of oscrypto.asymmetric.PublicKey or + asn1crypto.keys.PublicKeyInfo, not %s + ''', + type_name(public_key) + )) + + if is_oscrypto: + public_key = public_key.asn1 + + output = public_key.dump() + if encoding == 'pem': + output = armor('PUBLIC KEY', output) + return output + + +def dump_certificate(certificate, encoding='pem'): + """ + Serializes a certificate object into a byte string + + :param certificate: + An oscrypto.asymmetric.Certificate or asn1crypto.x509.Certificate object + + :param encoding: + A unicode string of "pem" or "der" + + :return: + A byte string of the encoded certificate + """ + + if encoding not in set(['pem', 'der']): + raise ValueError(pretty_message( + ''' + encoding must be one of "pem", "der", not %s + ''', + repr(encoding) + )) + + is_oscrypto = isinstance(certificate, Certificate) + if not isinstance(certificate, Asn1Certificate) and not is_oscrypto: + raise TypeError(pretty_message( + ''' + certificate must be an instance of oscrypto.asymmetric.Certificate + or asn1crypto.x509.Certificate, not %s + ''', + type_name(certificate) + )) + + if is_oscrypto: + certificate = certificate.asn1 + + output = certificate.dump() + if encoding == 'pem': + output = armor('CERTIFICATE', output) + return output + + +def dump_private_key(private_key, passphrase, encoding='pem', target_ms=200): + """ + Serializes a private key object into a byte string of the PKCS#8 format + + :param private_key: + An oscrypto.asymmetric.PrivateKey or asn1crypto.keys.PrivateKeyInfo + object + + :param passphrase: + A unicode string of the passphrase to encrypt the private key with. + A passphrase of None will result in no encryption. A blank string will + result in a ValueError to help ensure that the lack of passphrase is + intentional. + + :param encoding: + A unicode string of "pem" or "der" + + :param target_ms: + Use PBKDF2 with the number of iterations that takes about this many + milliseconds on the current machine. + + :raises: + ValueError - when a blank string is provided for the passphrase + + :return: + A byte string of the encoded and encrypted public key + """ + + if encoding not in set(['pem', 'der']): + raise ValueError(pretty_message( + ''' + encoding must be one of "pem", "der", not %s + ''', + repr(encoding) + )) + + if passphrase is not None: + if not isinstance(passphrase, str_cls): + raise TypeError(pretty_message( + ''' + passphrase must be a unicode string, not %s + ''', + type_name(passphrase) + )) + if passphrase == '': + raise ValueError(pretty_message( + ''' + passphrase may not be a blank string - pass None to disable + encryption + ''' + )) + + is_oscrypto = isinstance(private_key, PrivateKey) + if not isinstance(private_key, PrivateKeyInfo) and not is_oscrypto: + raise TypeError(pretty_message( + ''' + private_key must be an instance of oscrypto.asymmetric.PrivateKey + or asn1crypto.keys.PrivateKeyInfo, not %s + ''', + type_name(private_key) + )) + + if is_oscrypto: + private_key = private_key.asn1 + + output = private_key.dump() + + if passphrase is not None: + cipher = 'aes256_cbc' + key_length = 32 + kdf_hmac = 'sha256' + kdf_salt = rand_bytes(key_length) + iterations = pbkdf2_iteration_calculator(kdf_hmac, key_length, target_ms=target_ms, quiet=True) + # Need a bare minimum of 10,000 iterations for PBKDF2 as of 2015 + if iterations < 10000: + iterations = 10000 + + passphrase_bytes = passphrase.encode('utf-8') + key = pbkdf2(kdf_hmac, passphrase_bytes, kdf_salt, iterations, key_length) + iv, ciphertext = aes_cbc_pkcs7_encrypt(key, output, None) + + output = EncryptedPrivateKeyInfo({ + 'encryption_algorithm': { + 'algorithm': 'pbes2', + 'parameters': { + 'key_derivation_func': { + 'algorithm': 'pbkdf2', + 'parameters': { + 'salt': Pbkdf2Salt( + name='specified', + value=kdf_salt + ), + 'iteration_count': iterations, + 'prf': { + 'algorithm': kdf_hmac, + 'parameters': Null() + } + } + }, + 'encryption_scheme': { + 'algorithm': cipher, + 'parameters': iv + } + } + }, + 'encrypted_data': ciphertext + }).dump() + + if encoding == 'pem': + if passphrase is None: + object_type = 'PRIVATE KEY' + else: + object_type = 'ENCRYPTED PRIVATE KEY' + output = armor(object_type, output) + + return output + + +def dump_openssl_private_key(private_key, passphrase): + """ + Serializes a private key object into a byte string of the PEM formats used + by OpenSSL. The format chosen will depend on the type of private key - RSA, + DSA or EC. + + Do not use this method unless you really must interact with a system that + does not support PKCS#8 private keys. The encryption provided by PKCS#8 is + far superior to the OpenSSL formats. This is due to the fact that the + OpenSSL formats don't stretch the passphrase, making it very easy to + brute-force. + + :param private_key: + An oscrypto.asymmetric.PrivateKey or asn1crypto.keys.PrivateKeyInfo + object + + :param passphrase: + A unicode string of the passphrase to encrypt the private key with. + A passphrase of None will result in no encryption. A blank string will + result in a ValueError to help ensure that the lack of passphrase is + intentional. + + :raises: + ValueError - when a blank string is provided for the passphrase + + :return: + A byte string of the encoded and encrypted public key + """ + + if passphrase is not None: + if not isinstance(passphrase, str_cls): + raise TypeError(pretty_message( + ''' + passphrase must be a unicode string, not %s + ''', + type_name(passphrase) + )) + if passphrase == '': + raise ValueError(pretty_message( + ''' + passphrase may not be a blank string - pass None to disable + encryption + ''' + )) + + is_oscrypto = isinstance(private_key, PrivateKey) + if not isinstance(private_key, PrivateKeyInfo) and not is_oscrypto: + raise TypeError(pretty_message( + ''' + private_key must be an instance of oscrypto.asymmetric.PrivateKey or + asn1crypto.keys.PrivateKeyInfo, not %s + ''', + type_name(private_key) + )) + + if is_oscrypto: + private_key = private_key.asn1 + + output = _unwrap_private_key_info(private_key).dump() + + headers = None + if passphrase is not None: + iv = rand_bytes(16) + + headers = OrderedDict() + headers['Proc-Type'] = '4,ENCRYPTED' + headers['DEK-Info'] = 'AES-128-CBC,%s' % binascii.hexlify(iv).decode('ascii') + + key_length = 16 + passphrase_bytes = passphrase.encode('utf-8') + + key = hashlib.md5(passphrase_bytes + iv[0:8]).digest() + while key_length > len(key): + key += hashlib.md5(key + passphrase_bytes + iv[0:8]).digest() + key = key[0:key_length] + + iv, output = aes_cbc_pkcs7_encrypt(key, output, iv) + + if private_key.algorithm == 'ec': + object_type = 'EC PRIVATE KEY' + elif private_key.algorithm == 'rsa': + object_type = 'RSA PRIVATE KEY' + elif private_key.algorithm == 'dsa': + object_type = 'DSA PRIVATE KEY' + + return armor(object_type, output, headers=headers) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/errors.py b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/errors.py new file mode 100644 index 00000000..581b76f3 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/errors.py @@ -0,0 +1,111 @@ +# coding: utf-8 +from __future__ import unicode_literals, division, absolute_import, print_function + +import sys +import socket + + +__all__ = [ + 'AsymmetricKeyError', + 'CACertsError', + 'LibraryNotFoundError', + 'SignatureError', + 'TLSError', + 'TLSConnectionError', + 'TLSDisconnectError', + 'TLSGracefulDisconnectError', + 'TLSVerificationError', +] + + +class LibraryNotFoundError(Exception): + + """ + An exception when trying to find a shared library + """ + + pass + + +class SignatureError(Exception): + + """ + An exception when validating a signature + """ + + pass + + +class AsymmetricKeyError(Exception): + + """ + An exception when a key is invalid or unsupported + """ + + pass + + +class IncompleteAsymmetricKeyError(AsymmetricKeyError): + + """ + An exception when a key is missing necessary information + """ + + pass + + +class CACertsError(Exception): + + """ + An exception when exporting CA certs from the OS trust store + """ + + pass + + +class TLSError(socket.error): + + """ + An exception related to TLS functionality + """ + + message = None + + def __init__(self, message): + self.args = (message,) + self.message = message + + def __str__(self): + output = self.__unicode__() + if sys.version_info < (3,): + output = output.encode('utf-8') + return output + + def __unicode__(self): + return self.message + + +class TLSConnectionError(TLSError): + pass + + +class TLSDisconnectError(TLSConnectionError): + pass + + +class TLSGracefulDisconnectError(TLSDisconnectError): + pass + + +class TLSVerificationError(TLSError): + + """ + A server certificate verification error happened during a TLS handshake + """ + + certificate = None + + def __init__(self, message, certificate): + TLSError.__init__(self, message) + self.certificate = certificate + self.args = (message, certificate) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/kdf.py b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/kdf.py new file mode 100644 index 00000000..5db07cd7 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/kdf.py @@ -0,0 +1,261 @@ +# coding: utf-8 +from __future__ import unicode_literals, division, absolute_import, print_function + +import sys +import hashlib +from datetime import datetime + +from . import backend +from .util import rand_bytes +from ._types import type_name, byte_cls, int_types +from ._errors import pretty_message +from ._ffi import new, deref + + +_backend = backend() + + +if _backend == 'mac': + from ._mac.util import pbkdf2, pkcs12_kdf +elif _backend == 'win' or _backend == 'winlegacy': + from ._win.util import pbkdf2, pkcs12_kdf + from ._win._kernel32 import kernel32, handle_error +else: + from ._openssl.util import pbkdf2, pkcs12_kdf + + +__all__ = [ + 'pbkdf1', + 'pbkdf2', + 'pbkdf2_iteration_calculator', + 'pkcs12_kdf', +] + + +if sys.platform == 'win32': + def _get_start(): + number = new(kernel32, 'LARGE_INTEGER *') + res = kernel32.QueryPerformanceCounter(number) + handle_error(res) + return deref(number) + + def _get_elapsed(start): + length = _get_start() - start + return int(length / 1000.0) + +else: + def _get_start(): + return datetime.now() + + def _get_elapsed(start): + length = datetime.now() - start + seconds = length.seconds + (length.days * 24 * 3600) + milliseconds = (length.microseconds / 10 ** 3) + return int(milliseconds + (seconds * 10 ** 3)) + + +def pbkdf2_iteration_calculator(hash_algorithm, key_length, target_ms=100, quiet=False): + """ + Runs pbkdf2() twice to determine the approximate number of iterations to + use to hit a desired time per run. Use this on a production machine to + dynamically adjust the number of iterations as high as you can. + + :param hash_algorithm: + The string name of the hash algorithm to use: "md5", "sha1", "sha224", + "sha256", "sha384", "sha512" + + :param key_length: + The length of the desired key in bytes + + :param target_ms: + The number of milliseconds the derivation should take + + :param quiet: + If no output should be printed as attempts are made + + :return: + An integer number of iterations of PBKDF2 using the specified hash + that will take at least target_ms + """ + + if hash_algorithm not in set(['sha1', 'sha224', 'sha256', 'sha384', 'sha512']): + raise ValueError(pretty_message( + ''' + hash_algorithm must be one of "sha1", "sha224", "sha256", "sha384", + "sha512", not %s + ''', + repr(hash_algorithm) + )) + + if not isinstance(key_length, int_types): + raise TypeError(pretty_message( + ''' + key_length must be an integer, not %s + ''', + type_name(key_length) + )) + + if key_length < 1: + raise ValueError(pretty_message( + ''' + key_length must be greater than 0 - is %s + ''', + repr(key_length) + )) + + if not isinstance(target_ms, int_types): + raise TypeError(pretty_message( + ''' + target_ms must be an integer, not %s + ''', + type_name(target_ms) + )) + + if target_ms < 1: + raise ValueError(pretty_message( + ''' + target_ms must be greater than 0 - is %s + ''', + repr(target_ms) + )) + + if pbkdf2.pure_python: + raise OSError(pretty_message( + ''' + Only a very slow, pure-python version of PBKDF2 is available, + making this function useless + ''' + )) + + iterations = 10000 + password = 'this is a test'.encode('utf-8') + salt = rand_bytes(key_length) + + def _measure(): + start = _get_start() + pbkdf2(hash_algorithm, password, salt, iterations, key_length) + observed_ms = _get_elapsed(start) + if not quiet: + print('%s iterations in %sms' % (iterations, observed_ms)) + return 1.0 / target_ms * observed_ms + + # Measure the initial guess, then estimate how many iterations it would + # take to reach 1/2 of the target ms and try it to get a good final number + fraction = _measure() + iterations = int(iterations / fraction / 2.0) + + fraction = _measure() + iterations = iterations / fraction + + # < 20,000 round to 1000 + # 20,000-100,000 round to 5,000 + # > 100,000 round to 10,000 + round_factor = -3 if iterations < 100000 else -4 + result = int(round(iterations, round_factor)) + if result > 20000: + result = (result // 5000) * 5000 + return result + + +def pbkdf1(hash_algorithm, password, salt, iterations, key_length): + """ + An implementation of PBKDF1 - should only be used for interop with legacy + systems, not new architectures + + :param hash_algorithm: + The string name of the hash algorithm to use: "md2", "md5", "sha1" + + :param password: + A byte string of the password to use an input to the KDF + + :param salt: + A cryptographic random byte string + + :param iterations: + The numbers of iterations to use when deriving the key + + :param key_length: + The length of the desired key in bytes + + :return: + The derived key as a byte string + """ + + if not isinstance(password, byte_cls): + raise TypeError(pretty_message( + ''' + password must be a byte string, not %s + ''', + (type_name(password)) + )) + + if not isinstance(salt, byte_cls): + raise TypeError(pretty_message( + ''' + salt must be a byte string, not %s + ''', + (type_name(salt)) + )) + + if not isinstance(iterations, int_types): + raise TypeError(pretty_message( + ''' + iterations must be an integer, not %s + ''', + (type_name(iterations)) + )) + + if iterations < 1: + raise ValueError(pretty_message( + ''' + iterations must be greater than 0 - is %s + ''', + repr(iterations) + )) + + if not isinstance(key_length, int_types): + raise TypeError(pretty_message( + ''' + key_length must be an integer, not %s + ''', + (type_name(key_length)) + )) + + if key_length < 1: + raise ValueError(pretty_message( + ''' + key_length must be greater than 0 - is %s + ''', + repr(key_length) + )) + + if hash_algorithm not in set(['md2', 'md5', 'sha1']): + raise ValueError(pretty_message( + ''' + hash_algorithm must be one of "md2", "md5", "sha1", not %s + ''', + repr(hash_algorithm) + )) + + if key_length > 16 and hash_algorithm in set(['md2', 'md5']): + raise ValueError(pretty_message( + ''' + key_length can not be longer than 16 for %s - is %s + ''', + (hash_algorithm, repr(key_length)) + )) + + if key_length > 20 and hash_algorithm == 'sha1': + raise ValueError(pretty_message( + ''' + key_length can not be longer than 20 for sha1 - is %s + ''', + repr(key_length) + )) + + algo = getattr(hashlib, hash_algorithm) + output = algo(password + salt).digest() + for _ in range(2, iterations + 1): + output = algo(output).digest() + + return output[:key_length] diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/keys.py b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/keys.py new file mode 100644 index 00000000..0fd689b6 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/keys.py @@ -0,0 +1,24 @@ +# coding: utf-8 +from __future__ import unicode_literals, division, absolute_import, print_function + +from . import backend +from ._asymmetric import parse_certificate, parse_private, parse_public + + +_backend = backend() + + +if _backend == 'mac': + from ._mac.asymmetric import parse_pkcs12 +elif _backend == 'win' or _backend == 'winlegacy': + from ._win.asymmetric import parse_pkcs12 +else: + from ._openssl.asymmetric import parse_pkcs12 + + +__all__ = [ + 'parse_certificate', + 'parse_pkcs12', + 'parse_private', + 'parse_public', +] diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/symmetric.py b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/symmetric.py new file mode 100644 index 00000000..00b03c00 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/symmetric.py @@ -0,0 +1,72 @@ +# coding: utf-8 +from __future__ import unicode_literals, division, absolute_import, print_function + +from . import backend + + +_backend = backend() + + +if _backend == 'mac': + from ._mac.symmetric import ( + aes_cbc_no_padding_decrypt, + aes_cbc_no_padding_encrypt, + aes_cbc_pkcs7_decrypt, + aes_cbc_pkcs7_encrypt, + des_cbc_pkcs5_decrypt, + des_cbc_pkcs5_encrypt, + rc2_cbc_pkcs5_decrypt, + rc2_cbc_pkcs5_encrypt, + rc4_decrypt, + rc4_encrypt, + tripledes_cbc_pkcs5_decrypt, + tripledes_cbc_pkcs5_encrypt, + ) + +elif _backend == 'win' or _backend == 'winlegacy': + from ._win.symmetric import ( + aes_cbc_no_padding_decrypt, + aes_cbc_no_padding_encrypt, + aes_cbc_pkcs7_decrypt, + aes_cbc_pkcs7_encrypt, + des_cbc_pkcs5_decrypt, + des_cbc_pkcs5_encrypt, + rc2_cbc_pkcs5_decrypt, + rc2_cbc_pkcs5_encrypt, + rc4_decrypt, + rc4_encrypt, + tripledes_cbc_pkcs5_decrypt, + tripledes_cbc_pkcs5_encrypt, + ) + +else: + from ._openssl.symmetric import ( + aes_cbc_no_padding_decrypt, + aes_cbc_no_padding_encrypt, + aes_cbc_pkcs7_decrypt, + aes_cbc_pkcs7_encrypt, + des_cbc_pkcs5_decrypt, + des_cbc_pkcs5_encrypt, + rc2_cbc_pkcs5_decrypt, + rc2_cbc_pkcs5_encrypt, + rc4_decrypt, + rc4_encrypt, + tripledes_cbc_pkcs5_decrypt, + tripledes_cbc_pkcs5_encrypt, + ) + + +__all__ = [ + 'aes_cbc_no_padding_decrypt', + 'aes_cbc_no_padding_encrypt', + 'aes_cbc_pkcs7_decrypt', + 'aes_cbc_pkcs7_encrypt', + 'des_cbc_pkcs5_decrypt', + 'des_cbc_pkcs5_encrypt', + 'rc2_cbc_pkcs5_decrypt', + 'rc2_cbc_pkcs5_encrypt', + 'rc4_decrypt', + 'rc4_encrypt', + 'tripledes_cbc_pkcs5_decrypt', + 'tripledes_cbc_pkcs5_encrypt', +] diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/tls.py b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/tls.py new file mode 100644 index 00000000..018b68c1 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/tls.py @@ -0,0 +1,32 @@ +# coding: utf-8 +from __future__ import unicode_literals, division, absolute_import, print_function + +from . import backend + + +_backend = backend() + + +if _backend == 'mac': + from ._mac.tls import ( + TLSSession, + TLSSocket, + ) + +elif _backend == 'win' or _backend == 'winlegacy': + from ._win.tls import ( + TLSSession, + TLSSocket, + ) + +else: + from ._openssl.tls import ( + TLSSession, + TLSSocket, + ) + + +__all__ = [ + 'TLSSession', + 'TLSSocket', +] diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/trust_list.py b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/trust_list.py new file mode 100644 index 00000000..f07dfe4f --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/trust_list.py @@ -0,0 +1,347 @@ +# coding: utf-8 +from __future__ import unicode_literals, division, absolute_import, print_function + +import os +import time +import sys +import tempfile +import threading + +from ._asn1 import armor, Certificate +from ._errors import pretty_message +from .errors import CACertsError + +if sys.platform == 'win32': + from ._win.trust_list import extract_from_system, system_path +elif sys.platform == 'darwin': + from ._mac.trust_list import extract_from_system, system_path +else: + from ._linux_bsd.trust_list import extract_from_system, system_path + + +__all__ = [ + 'clear_cache', + 'get_list', + 'get_path', +] + + +path_lock = threading.Lock() +memory_lock = threading.Lock() +_module_values = { + 'last_update': None, + 'certs': None +} + +_oid_map = { + # apple_smime -> email_protection + '1.2.840.113635.100.1.8': set(['1.3.6.1.5.5.7.3.4']), + # apple_code_signing -> code_signing + '1.2.840.113635.100.1.16': set(['1.3.6.1.5.5.7.3.3']), + # apple_time_stamping -> time_stamping + '1.2.840.113635.100.1.20': set(['1.3.6.1.5.5.7.3.8']), + # microsoft_time_stamp_signing -> time_stamping + '1.3.6.1.4.1.311.10.3.2': set(['1.3.6.1.5.5.7.3.8']), + # apple_ssl -> (server_auth, client_auth) + '1.2.840.113635.100.1.3': set([ + '1.3.6.1.5.5.7.3.1', + '1.3.6.1.5.5.7.3.2', + ]), + # apple_eap -> (eap_over_ppp, eap_over_lan) + '1.2.840.113635.100.1.9': set([ + '1.3.6.1.5.5.7.3.13', + '1.3.6.1.5.5.7.3.14', + ]), + # apple_ipsec -> (ipsec_end_system, ipsec_tunnel, ipsec_user, ipsec_ike) + '1.2.840.113635.100.1.11': set([ + '1.3.6.1.5.5.7.3.5', + '1.3.6.1.5.5.7.3.6', + '1.3.6.1.5.5.7.3.7', + '1.3.6.1.5.5.7.3.17', + ]) +} + + +def get_path(temp_dir=None, cache_length=24, cert_callback=None): + """ + Get the filesystem path to a file that contains OpenSSL-compatible CA certs. + + On OS X and Windows, there are extracted from the system certificate store + and cached in a file on the filesystem. This path should not be writable + by other users, otherwise they could inject CA certs into the trust list. + + :param temp_dir: + The temporary directory to cache the CA certs in on OS X and Windows. + Needs to have secure permissions so other users can not modify the + contents. + + :param cache_length: + The number of hours to cache the CA certs on OS X and Windows + + :param cert_callback: + A callback that is called once for each certificate in the trust store. + It should accept two parameters: an asn1crypto.x509.Certificate object, + and a reason. The reason will be None if the certificate is being + exported, otherwise it will be a unicode string of the reason it won't. + This is only called on Windows and OS X when passed to this function. + + :raises: + oscrypto.errors.CACertsError - when an error occurs exporting/locating certs + + :return: + The full filesystem path to a CA certs file + """ + + ca_path, temp = _ca_path(temp_dir) + + # Windows and OS X + if temp and _cached_path_needs_update(ca_path, cache_length): + empty_set = set() + + any_purpose = '2.5.29.37.0' + apple_ssl = '1.2.840.113635.100.1.3' + win_server_auth = '1.3.6.1.5.5.7.3.1' + + with path_lock: + if _cached_path_needs_update(ca_path, cache_length): + with open(ca_path, 'wb') as f: + for cert, trust_oids, reject_oids in extract_from_system(cert_callback, True): + if sys.platform == 'darwin': + if trust_oids != empty_set and any_purpose not in trust_oids \ + and apple_ssl not in trust_oids: + if cert_callback: + cert_callback(Certificate.load(cert), 'implicitly distrusted for TLS') + continue + if reject_oids != empty_set and (apple_ssl in reject_oids + or any_purpose in reject_oids): + if cert_callback: + cert_callback(Certificate.load(cert), 'explicitly distrusted for TLS') + continue + elif sys.platform == 'win32': + if trust_oids != empty_set and any_purpose not in trust_oids \ + and win_server_auth not in trust_oids: + if cert_callback: + cert_callback(Certificate.load(cert), 'implicitly distrusted for TLS') + continue + if reject_oids != empty_set and (win_server_auth in reject_oids + or any_purpose in reject_oids): + if cert_callback: + cert_callback(Certificate.load(cert), 'explicitly distrusted for TLS') + continue + if cert_callback: + cert_callback(Certificate.load(cert), None) + f.write(armor('CERTIFICATE', cert)) + + if not ca_path: + raise CACertsError('No CA certs found') + + return ca_path + + +def get_list(cache_length=24, map_vendor_oids=True, cert_callback=None): + """ + Retrieves (and caches in memory) the list of CA certs from the OS. Includes + trust information from the OS - purposes the certificate should be trusted + or rejected for. + + Trust information is encoded via object identifiers (OIDs) that are sourced + from various RFCs and vendors (Apple and Microsoft). This trust information + augments what is in the certificate itself. Any OID that is in the set of + trusted purposes indicates the certificate has been explicitly trusted for + a purpose beyond the extended key purpose extension. Any OID in the reject + set is a purpose that the certificate should not be trusted for, even if + present in the extended key purpose extension. + + *A list of common trust OIDs can be found as part of the `KeyPurposeId()` + class in the `asn1crypto.x509` module of the `asn1crypto` package.* + + :param cache_length: + The number of hours to cache the CA certs in memory before they are + refreshed + + :param map_vendor_oids: + A bool indicating if the following mapping of OIDs should happen for + trust information from the OS trust list: + - 1.2.840.113635.100.1.3 (apple_ssl) -> 1.3.6.1.5.5.7.3.1 (server_auth) + - 1.2.840.113635.100.1.3 (apple_ssl) -> 1.3.6.1.5.5.7.3.2 (client_auth) + - 1.2.840.113635.100.1.8 (apple_smime) -> 1.3.6.1.5.5.7.3.4 (email_protection) + - 1.2.840.113635.100.1.9 (apple_eap) -> 1.3.6.1.5.5.7.3.13 (eap_over_ppp) + - 1.2.840.113635.100.1.9 (apple_eap) -> 1.3.6.1.5.5.7.3.14 (eap_over_lan) + - 1.2.840.113635.100.1.11 (apple_ipsec) -> 1.3.6.1.5.5.7.3.5 (ipsec_end_system) + - 1.2.840.113635.100.1.11 (apple_ipsec) -> 1.3.6.1.5.5.7.3.6 (ipsec_tunnel) + - 1.2.840.113635.100.1.11 (apple_ipsec) -> 1.3.6.1.5.5.7.3.7 (ipsec_user) + - 1.2.840.113635.100.1.11 (apple_ipsec) -> 1.3.6.1.5.5.7.3.17 (ipsec_ike) + - 1.2.840.113635.100.1.16 (apple_code_signing) -> 1.3.6.1.5.5.7.3.3 (code_signing) + - 1.2.840.113635.100.1.20 (apple_time_stamping) -> 1.3.6.1.5.5.7.3.8 (time_stamping) + - 1.3.6.1.4.1.311.10.3.2 (microsoft_time_stamp_signing) -> 1.3.6.1.5.5.7.3.8 (time_stamping) + + :param cert_callback: + A callback that is called once for each certificate in the trust store. + It should accept two parameters: an asn1crypto.x509.Certificate object, + and a reason. The reason will be None if the certificate is being + exported, otherwise it will be a unicode string of the reason it won't. + + :raises: + oscrypto.errors.CACertsError - when an error occurs exporting/locating certs + + :return: + A (copied) list of 3-element tuples containing CA certs from the OS + trust ilst: + - 0: an asn1crypto.x509.Certificate object + - 1: a set of unicode strings of OIDs of trusted purposes + - 2: a set of unicode strings of OIDs of rejected purposes + """ + + if not _in_memory_up_to_date(cache_length): + with memory_lock: + if not _in_memory_up_to_date(cache_length): + certs = [] + for cert_bytes, trust_oids, reject_oids in extract_from_system(cert_callback): + if map_vendor_oids: + trust_oids = _map_oids(trust_oids) + reject_oids = _map_oids(reject_oids) + certs.append((Certificate.load(cert_bytes), trust_oids, reject_oids)) + _module_values['certs'] = certs + _module_values['last_update'] = time.time() + + return list(_module_values['certs']) + + +def clear_cache(temp_dir=None): + """ + Clears any cached info that was exported from the OS trust store. This will + ensure the latest changes are returned from calls to get_list() and + get_path(), but at the expense of re-exporting and parsing all certificates. + + :param temp_dir: + The temporary directory to cache the CA certs in on OS X and Windows. + Needs to have secure permissions so other users can not modify the + contents. Must be the same value passed to get_path(). + """ + + with memory_lock: + _module_values['last_update'] = None + _module_values['certs'] = None + + ca_path, temp = _ca_path(temp_dir) + if temp: + with path_lock: + if os.path.exists(ca_path): + os.remove(ca_path) + + +def _ca_path(temp_dir=None): + """ + Returns the file path to the CA certs file + + :param temp_dir: + The temporary directory to cache the CA certs in on OS X and Windows. + Needs to have secure permissions so other users can not modify the + contents. + + :return: + A 2-element tuple: + - 0: A unicode string of the file path + - 1: A bool if the file is a temporary file + """ + + ca_path = system_path() + + # Windows and OS X + if ca_path is None: + if temp_dir is None: + temp_dir = tempfile.gettempdir() + + if not os.path.isdir(temp_dir): + raise CACertsError(pretty_message( + ''' + The temp dir specified, "%s", is not a directory + ''', + temp_dir + )) + + ca_path = os.path.join(temp_dir, 'oscrypto-ca-bundle.crt') + return (ca_path, True) + + return (ca_path, False) + + +def _map_oids(oids): + """ + Takes a set of unicode string OIDs and converts vendor-specific OIDs into + generics OIDs from RFCs. + + - 1.2.840.113635.100.1.3 (apple_ssl) -> 1.3.6.1.5.5.7.3.1 (server_auth) + - 1.2.840.113635.100.1.3 (apple_ssl) -> 1.3.6.1.5.5.7.3.2 (client_auth) + - 1.2.840.113635.100.1.8 (apple_smime) -> 1.3.6.1.5.5.7.3.4 (email_protection) + - 1.2.840.113635.100.1.9 (apple_eap) -> 1.3.6.1.5.5.7.3.13 (eap_over_ppp) + - 1.2.840.113635.100.1.9 (apple_eap) -> 1.3.6.1.5.5.7.3.14 (eap_over_lan) + - 1.2.840.113635.100.1.11 (apple_ipsec) -> 1.3.6.1.5.5.7.3.5 (ipsec_end_system) + - 1.2.840.113635.100.1.11 (apple_ipsec) -> 1.3.6.1.5.5.7.3.6 (ipsec_tunnel) + - 1.2.840.113635.100.1.11 (apple_ipsec) -> 1.3.6.1.5.5.7.3.7 (ipsec_user) + - 1.2.840.113635.100.1.11 (apple_ipsec) -> 1.3.6.1.5.5.7.3.17 (ipsec_ike) + - 1.2.840.113635.100.1.16 (apple_code_signing) -> 1.3.6.1.5.5.7.3.3 (code_signing) + - 1.2.840.113635.100.1.20 (apple_time_stamping) -> 1.3.6.1.5.5.7.3.8 (time_stamping) + - 1.3.6.1.4.1.311.10.3.2 (microsoft_time_stamp_signing) -> 1.3.6.1.5.5.7.3.8 (time_stamping) + + :param oids: + A set of unicode strings + + :return: + The original set of OIDs with any mapped OIDs added + """ + + new_oids = set() + for oid in oids: + if oid in _oid_map: + new_oids |= _oid_map[oid] + return oids | new_oids + + +def _cached_path_needs_update(ca_path, cache_length): + """ + Checks to see if a cache file needs to be refreshed + + :param ca_path: + A unicode string of the path to the cache file + + :param cache_length: + An integer representing the number of hours the cache is valid for + + :return: + A boolean - True if the cache needs to be updated, False if the file + is up-to-date + """ + + exists = os.path.exists(ca_path) + if not exists: + return True + + stats = os.stat(ca_path) + + if stats.st_mtime < time.time() - cache_length * 60 * 60: + return True + + if stats.st_size == 0: + return True + + return False + + +def _in_memory_up_to_date(cache_length): + """ + Checks to see if the in-memory cache of certificates is fresh + + :param cache_length: + An integer representing the number of hours the cache is valid for + + :return: + A boolean - True if the cache is up-to-date, False if it needs to be + refreshed + """ + + return ( + _module_values['certs'] and + _module_values['last_update'] and + _module_values['last_update'] > time.time() - (cache_length * 60 * 60) + ) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/util.py b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/util.py new file mode 100644 index 00000000..f5e4cf5d --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/util.py @@ -0,0 +1,63 @@ +# coding: utf-8 +from __future__ import unicode_literals, division, absolute_import, print_function + +import sys + +from ._errors import pretty_message +from ._types import type_name, byte_cls + +if sys.platform == 'darwin': + from ._mac.util import rand_bytes +elif sys.platform == 'win32': + from ._win.util import rand_bytes +else: + from ._openssl.util import rand_bytes + + +__all__ = [ + 'constant_compare', + 'rand_bytes', +] + + +def constant_compare(a, b): + """ + Compares two byte strings in constant time to see if they are equal + + :param a: + The first byte string + + :param b: + The second byte string + + :return: + A boolean if the two byte strings are equal + """ + + if not isinstance(a, byte_cls): + raise TypeError(pretty_message( + ''' + a must be a byte string, not %s + ''', + type_name(a) + )) + + if not isinstance(b, byte_cls): + raise TypeError(pretty_message( + ''' + b must be a byte string, not %s + ''', + type_name(b) + )) + + if len(a) != len(b): + return False + + if sys.version_info < (3,): + a = [ord(char) for char in a] + b = [ord(char) for char in b] + + result = 0 + for x, y in zip(a, b): + result |= x ^ y + return result == 0 diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/version.py b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/version.py new file mode 100644 index 00000000..85da1435 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/version.py @@ -0,0 +1,6 @@ +# coding: utf-8 +from __future__ import unicode_literals, division, absolute_import, print_function + + +__version__ = '1.2.1' +__version_info__ = (1, 2, 1) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/readme.md b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/readme.md new file mode 100644 index 00000000..4da9789c --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/readme.md @@ -0,0 +1,356 @@ +# oscrypto + +A compilation-free, always up-to-date encryption library for Python that works +on Windows, OS X, Linux and BSD. Supports the following versions of Python: +2.6, 2.7, 3.2, 3.3, 3.4, 3.5, 3.6, 3.7, 3.8 and pypy. + + - [Supported Operating Systems](#supported-operationg-systems) + - [Features](#features) + - [Why Another Python Crypto Library?](#why-another-python-crypto-library) + - [Related Crypto Libraries](#related-crypto-libraries) + - [Current Release](#current-release) + - [Dependencies](#dependencies) + - [Installation](#installation) + - [License](#license) + - [Documentation](#documentation) + - [Continuous Integration](#continuous-integration) + - [Testing](#testing) + - [Development](#development) + - [CI Tasks](#ci-tasks) + +[![GitHub Actions CI](https://github.com/wbond/oscrypto/workflows/CI/badge.svg)](https://github.com/wbond/oscrypto/actions?workflow=CI) +[![Travis CI](https://api.travis-ci.org/wbond/oscrypto.svg?branch=master)](https://travis-ci.org/wbond/oscrypto) +[![AppVeyor](https://ci.appveyor.com/api/projects/status/github/wbond/oscrypto?branch=master&svg=true)](https://ci.appveyor.com/project/wbond/oscrypto) +[![CircleCI](https://circleci.com/gh/wbond/oscrypto.svg?style=shield)](https://circleci.com/gh/wbond/oscrypto) +[![PyPI](https://img.shields.io/pypi/v/oscrypto.svg)](https://pypi.python.org/pypi/oscrypto) + +## Supported Operating Systems + +The library integrates with the encryption library that is part of the operating +system. This means that a compiler is never needed, and OS security updates take +care of patching vulnerabilities. Supported operating systems include: + + - Windows XP or newer + - Uses: + - [Cryptography API: Next Generation (CNG)](https://msdn.microsoft.com/en-us/library/windows/desktop/aa376210(v=vs.85).aspx) + - [Secure Channel](https://msdn.microsoft.com/en-us/library/windows/desktop/aa380123(v=vs.85).aspx) for TLS + - [CryptoAPI](https://msdn.microsoft.com/en-us/library/windows/desktop/aa380256(v=vs.85).aspx) for trust lists and XP support + - Tested on: + - Windows XP (no SNI) + - Windows 7 + - Windows 8.1 + - Windows Server 2012 + - Windows 10 + - OS X 10.7 or newer + - Uses: + - [Security.framework](https://developer.apple.com/library/prerelease/mac/documentation/Security/Reference/SecurityFrameworkReference/index.html) + - [Secure Transport](https://developer.apple.com/library/prerelease/mac/documentation/Security/Reference/secureTransportRef/index.html#//apple_ref/doc/uid/TP30000155) for TLS + - [CommonCrypto](http://www.opensource.apple.com/source/CommonCrypto/CommonCrypto-55010/CommonCrypto/) for PBKDF2 + - OpenSSL (or LibreSSL on macOS 10.13) for the PKCS #12 KDF + - Tested on: + - OS X 10.7 + - OS X 10.8 + - OS X 10.9 + - OS X 10.10 + - OS X 10.11 + - OS X 10.11 with OpenSSL 1.1.0 + - macOS 10.12 + - macOS 10.13 with LibreSSL 2.2.7 + - macOS 10.14 + - macOS 10.15 + - macOS 11 + - Linux or BSD + - Uses one of: + - [OpenSSL 0.9.8](https://www.openssl.org/docs/man0.9.8/) + - [OpenSSL 1.0.x](https://www.openssl.org/docs/man1.0.0/) + - [OpenSSL 1.1.0](https://www.openssl.org/docs/man1.1.0/) + - [LibreSSL](http://www.libressl.org/) + - Tested on: + - Arch Linux with OpenSSL 1.0.2 + - OpenBSD 5.7 with LibreSSL + - Ubuntu 10.04 with OpenSSL 0.9.8 + - Ubuntu 12.04 with OpenSSL 1.0.1 + - Ubuntu 15.04 with OpenSSL 1.0.1 + - Ubuntu 16.04 with OpenSSL 1.0.2 on Raspberry Pi 3 (armhf) + - Ubuntu 18.04 with OpenSSL 1.1.x (amd64, arm64, ppc64el) + +*OS X 10.6 will not be supported due to a lack of available +cryptographic primitives and due to lack of vendor support.* + +## Features + +Currently the following features are implemented. Many of these should only be +used for integration with existing/legacy systems. If you don't know which you +should, or should not use, please see [Learning](docs/readme.md#learning). + + - [TLSv1.x socket wrappers](docs/tls.md) + - Certificate verification performed by OS trust roots + - Custom CA certificate support + - SNI support (except Windows XP) + - Session reuse via IDs/tickets + - Modern cipher suites (RC4, DES, anon and NULL ciphers disabled) + - Weak DH parameters and certificate signatures rejected + - SSLv3 disabled by default, SSLv2 unimplemented + - CRL/OCSP revocation checks consistenty disabled + - [Exporting OS trust roots](docs/trust_list.md) + - PEM-formatted CA certs from the OS for OpenSSL-based code + - [Encryption/decryption](docs/symmetric.md) + - AES (128, 192, 256), CBC mode, PKCS7 padding + - AES (128, 192, 256), CBC mode, no padding + - TripleDES 3-key, CBC mode, PKCS5 padding + - TripleDes 2-key, CBC mode, PKCS5 padding + - DES, CBC mode, PKCS5 padding + - RC2 (40-128), CBC mode, PKCS5 padding + - RC4 (40-128) + - RSA PKCSv1.5 + - RSA OAEP (SHA1 only) + - [Generating public/private key pairs](docs/asymmetric.md) + - RSA (1024, 2048, 3072, 4096 bit) + - DSA (1024 bit on all platforms - 2048, 3072 bit with OpenSSL 1.x or + Windows 8) + - EC (secp256r1, secp384r1, secp521r1 curves) + - [Generating DH parameters](docs/asymmetric.md) + - [Signing and verification](docs/asymmetric.md) + - RSA PKCSv1.5 + - RSA PSS + - DSA + - EC + - [Loading and normalizing DER and PEM formatted keys](docs/keys.md) + - RSA public and private keys + - DSA public and private keys + - EC public and private keys + - X.509 Certificates + - PKCS#12 archives (`.pfx`/`.p12`) + - [Key derivation](docs/kdf.md) + - PBKDF2 + - PBKDF1 + - PKCS#12 KDF + - [Random byte generation](docs/util.md) + +The feature set was largely driven by the technologies used related to +generating and validating X.509 certificates. The various CBC encryption schemes +and KDFs are used to load encrypted private keys, and the various RSA padding +schemes are part of X.509 signatures. + +For modern cryptography not tied to an existing system, please see the +[Modern Cryptography](docs/readme.md#modern-cryptography) section of the docs. + +*Please note that this library does not include modern block modes such as CTR +and GCM due to lack of support from both OS X and OpenSSL 0.9.8.* + +## Why Another Python Crypto Library? + +In short, the existing cryptography libraries for Python didn't fit the needs of +a couple of projects I was working on. Primarily these are applications +distributed to end-users who aren't programmers, that need to handle TLS and +various technologies related to X.509 certificates. + +If your system is not tied to AES, TLS, X.509, or related technologies, you +probably want [more modern cryptography](docs/readme.md#modern-cryptography). + +Depending on your needs, the [cryptography](https://cryptography.io) package may +be a good (or better) fit. + +Some things that make oscrypto unique: + + - No compiler needed, ever. No need to pre-compile shared libraries. Just + distribute the Python source files, any way you want. + - Uses the operating system's crypto library - does not require OpenSSL on + Windows or OS X. + - Relies on the operating system for security patching. You don't need to + rebuild all of your apps every time there is a new TLS vulnerability. + - Intentionally limited in scope to crypto primitives. Other libraries + built upon it deal with certificate path validation, creating certificates + and CSRs, constructing CMS structures. + - Built on top of a fast, pure-Python ASN.1 parser, + [asn1crypto](https://github.com/wbond/asn1crypto). + - TLS functionality uses the operating system's trust list/CA certs and is + pre-configured with sane defaults + - Public APIs are simple and use strict type checks to avoid errors + +Some downsides include: + + - Does not currently implement: + - standalone DH key exchange + - various encryption modes such as GCM, CCM, CTR, CFB, OFB, ECB + - key wrapping + - CMAC + - HKDF + - Non-TLS functionality is architected for dealing with data that fits in + memory and is available all at once + - Developed by a single developer + +## Related Crypto Libraries + +*oscrypto* is part of the modularcrypto family of Python packages: + + - [asn1crypto](https://github.com/wbond/asn1crypto) + - [oscrypto](https://github.com/wbond/oscrypto) + - [csrbuilder](https://github.com/wbond/csrbuilder) + - [certbuilder](https://github.com/wbond/certbuilder) + - [crlbuilder](https://github.com/wbond/crlbuilder) + - [ocspbuilder](https://github.com/wbond/ocspbuilder) + - [certvalidator](https://github.com/wbond/certvalidator) + +## Current Release + +1.2.1 - [changelog](changelog.md) + +## Dependencies + + - [*asn1crypto*](https://github.com/wbond/asn1crypto) + - Python 2.6, 2.7, 3.2, 3.3, 3.4, 3.5, 3.6, 3.7, 3.8 or pypy + +## Installation + +```bash +pip install oscrypto +``` + +## License + +*oscrypto* is licensed under the terms of the MIT license. See the +[LICENSE](LICENSE) file for the exact license text. + +## Documentation + +[*oscrypto* documentation](docs/readme.md) + +## Continuous Integration + +Various combinations of platforms and versions of Python are tested via: + + - [AppVeyor](https://ci.appveyor.com/project/wbond/oscrypto/history) + - [CircleCI](https://circleci.com/gh/wbond/oscrypto) + - [GitHub Actions](https://github.com/wbond/oscrypto/actions) + - [Travis CI](https://travis-ci.org/wbond/oscrypto/builds) + +## Testing + +Tests are written using `unittest` and require no third-party packages. + +Depending on what type of source is available for the package, the following +commands can be used to run the test suite. + +### Git Repository + +When working within a Git working copy, or an archive of the Git repository, +the full test suite is run via: + +```bash +python run.py tests +``` + +To run only some tests, pass a regular expression as a parameter to `tests`. + +```bash +python run.py tests aes +``` + +To run tests multiple times, in order to catch edge-case bugs, pass an integer +to `tests`. If combined with a regular expression for filtering, pass the +repeat count after the regular expression. + +```bash +python run.py tests 20 +python run.py tests aes 20 +``` + +To run tests using a custom build of OpenSSL, or to use OpenSSL on Windows or +Mac, add `use_openssl` after `run.py`, like: + +```bash +python run.py use_openssl=/path/to/libcrypto.dylib,/path/to/libssl.dylib tests +``` + +### PyPi Source Distribution + +When working within an extracted source distribution (aka `.tar.gz`) from +PyPi, the full test suite is run via: + +```bash +python setup.py test +``` + +### Package + +When the package has been installed via pip (or another method), the package +`oscrypto_tests` may be installed and invoked to run the full test suite: + +```bash +pip install oscrypto_tests +python -m oscrypto_tests +``` + +## Development + +To install the package used for linting, execute: + +```bash +pip install --user -r requires/lint +``` + +The following command will run the linter: + +```bash +python run.py lint +``` + +Support for code coverage can be installed via: + +```bash +pip install --user -r requires/coverage +``` + +Coverage is measured by running: + +```bash +python run.py coverage +``` + +To install the packages requires to generate the API documentation, run: + +```bash +pip install --user -r requires/api_docs +``` + +The documentation can then be generated by running: + +```bash +python run.py api_docs +``` + +To install the necessary packages for releasing a new version on PyPI, run: + +```bash +pip install --user -r requires/release +``` + +Releases are created by: + + - Making a git tag in [semver](http://semver.org/) format + - Running the command: + + ```bash + python run.py release + ``` + +Existing releases can be found at https://pypi.python.org/pypi/oscrypto. + +## CI Tasks + +A task named `deps` exists to download and stage all necessary testing +dependencies. On posix platforms, `curl` is used for downloads and on Windows +PowerShell with `Net.WebClient` is used. This configuration sidesteps issues +related to getting pip to work properly and messing with `site-packages` for +the version of Python being used. + +The `ci` task runs `lint` (if flake8 is avaiable for the version of Python) and +`coverage` (or `tests` if coverage is not available for the version of Python). +If the current directory is a clean git working copy, the coverage data is +submitted to codecov.io. + +```bash +python run.py deps +python run.py ci +``` diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/setup.cfg b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/setup.cfg new file mode 100644 index 00000000..8bfd5a12 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/setup.cfg @@ -0,0 +1,4 @@ +[egg_info] +tag_build = +tag_date = 0 + diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/setup.py b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/setup.py new file mode 100644 index 00000000..3d2d207b --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/oscrypto/setup.py @@ -0,0 +1,157 @@ +import codecs +import os +import shutil +import sys +import warnings + +import setuptools +from setuptools import find_packages, setup, Command +from setuptools.command.egg_info import egg_info + + +PACKAGE_NAME = 'oscrypto' +PACKAGE_VERSION = '1.2.1' +PACKAGE_ROOT = os.path.dirname(os.path.abspath(__file__)) + + +# setuptools 38.6.0 and newer know about long_description_content_type, but +# distutils still complains about it, so silence the warning +sv = setuptools.__version__ +svi = tuple(int(o) if o.isdigit() else o for o in sv.split('.')) +if svi >= (38, 6): + warnings.filterwarnings( + 'ignore', + "Unknown distribution option: 'long_description_content_type'", + module='distutils.dist' + ) + + +# Try to load the tests first from the source repository layout. If that +# doesn't work, we assume this file is in the release package, and the tests +# are part of the package {PACKAGE_NAME}_tests. +if os.path.exists(os.path.join(PACKAGE_ROOT, 'tests')): + tests_require = [] + test_suite = 'tests.make_suite' +else: + tests_require = ['%s_tests' % PACKAGE_NAME] + test_suite = '%s_tests.make_suite' % PACKAGE_NAME + + +# This allows us to send the LICENSE and docs when creating a sdist. Wheels +# automatically include the LICENSE, and don't need the docs. For these +# to be included, the command must be "python setup.py sdist". +package_data = {} +if sys.argv[1:] == ['sdist'] or sorted(sys.argv[1:]) == ['-q', 'sdist']: + package_data[PACKAGE_NAME] = [ + '../LICENSE', + '../*.md', + '../docs/*.md', + ] + + +# Ensures a copy of the LICENSE is included with the egg-info for +# install and bdist_egg commands +class EggInfoCommand(egg_info): + def run(self): + egg_info_path = os.path.join( + PACKAGE_ROOT, + '%s.egg-info' % PACKAGE_NAME + ) + if not os.path.exists(egg_info_path): + os.mkdir(egg_info_path) + shutil.copy2( + os.path.join(PACKAGE_ROOT, 'LICENSE'), + os.path.join(egg_info_path, 'LICENSE') + ) + egg_info.run(self) + + +class CleanCommand(Command): + user_options = [ + ('all', 'a', '(Compatibility with original clean command)'), + ] + + def initialize_options(self): + self.all = False + + def finalize_options(self): + pass + + def run(self): + sub_folders = ['build', 'temp', '%s.egg-info' % PACKAGE_NAME] + if self.all: + sub_folders.append('dist') + for sub_folder in sub_folders: + full_path = os.path.join(PACKAGE_ROOT, sub_folder) + if os.path.exists(full_path): + shutil.rmtree(full_path) + for root, dirs, files in os.walk(os.path.join(PACKAGE_ROOT, PACKAGE_NAME)): + for filename in files: + if filename[-4:] == '.pyc': + os.unlink(os.path.join(root, filename)) + for dirname in list(dirs): + if dirname == '__pycache__': + shutil.rmtree(os.path.join(root, dirname)) + + +readme = '' +with codecs.open(os.path.join(PACKAGE_ROOT, 'readme.md'), 'r', 'utf-8') as f: + readme = f.read() + + +setup( + name=PACKAGE_NAME, + version=PACKAGE_VERSION, + + description=( + 'TLS (SSL) sockets, key generation, encryption, decryption, signing, ' + 'verification and KDFs using the OS crypto libraries. Does not require ' + 'a compiler, and relies on the OS for patching. Works on Windows, OS X ' + 'and Linux/BSD.' + ), + long_description=readme, + long_description_content_type='text/markdown', + + url='https://github.com/wbond/oscrypto', + + author='wbond', + author_email='will@wbond.net', + + license='MIT', + + classifiers=[ + 'Development Status :: 5 - Production/Stable', + + 'Intended Audience :: Developers', + + 'License :: OSI Approved :: MIT License', + + 'Programming Language :: Python :: 2.6', + 'Programming Language :: Python :: 2.7', + 'Programming Language :: Python :: 3.2', + 'Programming Language :: Python :: 3.3', + 'Programming Language :: Python :: 3.4', + 'Programming Language :: Python :: 3.5', + 'Programming Language :: Python :: 3.6', + 'Programming Language :: Python :: 3.7', + 'Programming Language :: Python :: 3.8', + 'Programming Language :: Python :: Implementation :: PyPy', + + 'Topic :: Security :: Cryptography', + ], + + keywords='crypto pki tls ssl x509 certificate encrypt decrypt sign verify rsa dsa ec dh', + + install_requires=['asn1crypto>=1.0.0'], + + packages=find_packages(exclude=['tests*', 'dev*']), + package_data=package_data, + + tests_require=tests_require, + test_suite=test_suite, + + cmdclass={ + 'clean': CleanCommand, + 'egg_info': EggInfoCommand, + } +) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/CHANGES.rst b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/CHANGES.rst new file mode 100644 index 00000000..3ba82c06 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/CHANGES.rst @@ -0,0 +1,716 @@ + +Revision 0.4.8, released 16-11-2019 +----------------------------------- + +- Added ability of combining `SingleValueConstraint` and + `PermittedAlphabetConstraint` objects into one for proper modeling + `FROM ... EXCEPT ...` ASN.1 clause. + +Revision 0.4.7, released 01-09-2019 +----------------------------------- + +- Added `isInconsistent` property to all constructed types. This property + conceptually replaces `verifySizeSpec` method to serve a more general + purpose e.g. ensuring all required fields are in a good shape. By default + this check invokes subtype constraints verification and is run by codecs + on value de/serialisation. +- Deprecate `subtypeSpec` attributes and keyword argument. It is now + recommended to pass `ValueSizeConstraint`, as well as all other constraints, + to `subtypeSpec`. +- Fixed a design bug in a way of how the items assigned to constructed + types are verified. Now if `Asn1Type`-based object is assigned, its + compatibility is verified based on having all tags and constraint + objects as the type in field definition. When a bare Python value is + assigned, then field type object is cloned and initialized with the + bare value (constraints verificaton would run at this moment). +- Added `WithComponentsConstraint` along with related + `ComponentPresentConstraint` and `ComponentAbsentConstraint` classes + to be used with `Sequence`/`Set` types representing + `SET ... WITH COMPONENTS ...` like ASN.1 constructs. + +Revision 0.4.6, released 31-07-2019 +----------------------------------- + +- Added previously missing `SET OF ANY` construct encoding/decoding support. +- Added `omitEmptyOptionals` option which is respected by `Sequence` + and `Set` encoders. When `omitEmptyOptionals` is set to `True`, empty + initialized optional components are not encoded. Default is `False`. +- New elements to `SequenceOf`/`SetOf` objects can now be added at any + position - the requirement for the new elements to reside at the end + of the existing ones (i.e. s[len(s)] = 123) is removed. +- List-like slicing support added to `SequenceOf`/`SetOf` objects. +- Removed default initializer from `SequenceOf`/`SetOf` types to ensure + consistent behaviour with the rest of ASN.1 types. Before this change, + `SequenceOf`/`SetOf` instances immediately become value objects behaving + like an empty list. With this change, `SequenceOf`/`SetOf` objects + remain schema objects unless a component is added or `.clear()` is + called. + This change can potentially cause incompatibilities with existing + pyasn1 objects which assume `SequenceOf`/`SetOf` instances are value + objects right upon instantiation. + The behaviour of `Sequence`/`Set` types depends on the `componentType` + initializer: if on `componentType` is given, the behaviour is the + same as `SequenceOf`/`SetOf` have. IF `componentType` is given, but + neither optional nor defaulted components are present, the created + instance remains schema object, If, however, either optional or + defaulted component isi present, the created instance immediately + becomes a value object. +- Added `.reset()` method to all constructed types to turn value object + into a schema object. +- Added `PyAsn1UnicodeDecodeError`/`PyAsn1UnicodeDecodeError` exceptions + to help the caller treating unicode errors happening internally + to pyasn1 at the upper layers. +- Added support for subseconds CER/DER encoding edge cases in + `GeneralizedTime` codec. +- Fixed 3-digit fractional seconds value CER/DER encoding of + `GeneralizedTime`. +- Fixed `AnyDecoder` to accept possible `TagMap` as `asn1Spec` + to make dumping raw value operational + +Revision 0.4.5, released 29-12-2018 +----------------------------------- + +- Debug logging refactored for more efficiency when disabled and + for more functionality when in use. Specifically, the global + LOG object can easily be used from any function/method, not just + from codec main loop as it used to be. +- More debug logging added to BER family of codecs to ease encoding + problems troubleshooting. +- Copyright notice extended to the year 2019 +- Fixed defaulted constructed SEQUENCE component initialization. + +Revision 0.4.4, released 26-07-2018 +----------------------------------- + +- Fixed native encoder type map to include all ASN.1 types + rather than just ambiguous ones +- Fixed crash in `.prettyPrint` of `Sequence` and `Set` occurring + at OPTIONAL components + +Revision 0.4.3, released 23-05-2018 +----------------------------------- + +- Copyright notice extended to the year 2018 +- Fixed GeneralizedTime.asDateTime to perform milliseconds conversion + correctly + +Revision 0.4.2, released 23-11-2017 +----------------------------------- + +- Fixed explicit tag splitting in chunked encoding mode at + OctetString and BitString encoders + +Revision 0.4.1, released 23-11-2017 +----------------------------------- + +- ANY DEFINED BY clause support implemented +- Encoders refactored to take either a value (as ASN.1 object) + or a Python value plus ASN.1 schema +- BitString decoder optimised for better performance when running on + constructed encoding +- Constructed types' .getComponentBy*() methods accept the `default` + parameter to return instead if schema object is to be returned +- Constructed types' .getComponentBy*() methods accept the `instantiate` + parameter to disable automatic inner component instantiation +- The ASN.1 types' `__repr__` implementation reworked for better readability + at the cost of not being `eval`-compliant +- Most ASN.1 types' `__str__` magic methods (except for OctetString and + character types) reworked to call `.prettyPrint()` rather than + `.prettyPrint` calling `__str__` as it was before. The intention is + to eventually deprecate `.prettyPrint()` in favor of `str()`. + The other related change is that `str()` of enumerations and boolean + types will return string label instead of number. +- Fixed Choice.clear() to fully reset internal state of the object +- Sphinx documentation rearranged, simplified and reworded +- The `isValue` singleton is now the only way to indicate ASN.1 schema + as opposed to ASN.1 schema instance. The legacy `None` initializer + support has been removed. +- Changed `Null` object initialization behaviour: previous default + value (`''`) is not set anymore. Thus `Null()` call produces a + ASN.1 schema object, while `Null('')` - value object. +- Migrated all docs and references from SourceForge +- Imports PEP8'ed +- Fixed ASN.1 encoder not to omit empty substrate produced for inner + component if the inner component belongs to the simple class (as + opposed to constructed class) +- Fixed CER/DER encoders to respect tagged CHOICE when ordering + SET components +- Fixed ASN.1 types not to interfere with the Pickle protocol +- Fixed Sequence/SequenceOf types decoding heuristics in schema-less + decoding mode + +Revision 0.3.7, released 04-10-2017 +----------------------------------- + +- Fixed ASN.1 time types pickling/deepcopy'ing + +Revision 0.3.6, released 21-09-2017 +----------------------------------- + +- End-of-octets encoding optimized at ASN.1 encoders +- The __getitem__/__setitem__ behavior of Set/Sequence and SetOf/SequenceOf + objects aligned with the canonical Mapping and Sequence protocols in part +- Fixed crash in ASN.1 encoder when encoding an explicitly tagged + component of a Sequence + +Revision 0.3.5, released 16-09-2017 +----------------------------------- + +- Codecs signatures unified and pass the options kwargs through the + call chain +- Explicit tag encoding optimized to avoid unnecessary copying +- End-of-octets sentinel encoding optimized +- Refactored ASN.1 codecs properties to silently enforce proper + length and chunk size encoding modes +- Fixed DER encoder to always produce primitive encoding +- Fixed crash at SequenceOf native decoder +- Fixed Real.prettyPrint() to fail gracefully on overflow +- Fixed a couple of crashes when debug mode is enabled + +Revision 0.3.4, released 07-09-2017 +----------------------------------- + +- Fixed Native encoder to handle SEQUENCE/SET objects without + the componentType property +- Added missing component-less SEQUENCE/SET objects dict duck-typing support +- Fixed unnecessary duplicate tags detection at NamesType.tagMap +- Fixed crash at SEQUENCE and SEQUENCE OF CER encoder when running + in schemaless mode +- Fixed Character types instantiation from OctetString type -- double + unicode decoding may have scrambled the data + +Revision 0.3.3, released 27-08-2017 +----------------------------------- + +- Improved ASN.1 types instantiation performance +- Improved BER/CER/DER decoder performance by not unconditionally casting + substrate into str/bytes. +- Fixed exponential index size growth bug when building ambiguous + NamedTypes tree +- Fixed constructed types decoding failure at BER codec if running + in schema-less mode +- Fixed crash on prettyPrint'ing a SEQUENCE with no defined components +- Fixed SetOf ordering at CER/DER encoder +- Fixed crash on conditional binascii module import +- Fix to TagSet hash value build + +Revision 0.3.2, released 04-08-2017 +----------------------------------- + +- Fixed SequenceOf/SetOf types initialization syntax to remain + backward compatible with pyasn1 0.2.* +- Rectified thread safety issues by moving lazy, run-time computation + into object initializer. +- Fixed .isValue property to return True for empty SetOf/SequenceOf + objects +- Fixed GeneralizedTime/UTCTime CER/DER codecs to actually get invoked +- Fixed DER/CER encoders handling optional SEQUENCE/SET fields containing + nested SEQUENCE/SET with optional fields. +- Fixed crash in SequenceOf/SetOf pretty printing and decoding (in some + cases) +- Fixed documentation markup issues. + +Revision 0.3.1, released 26-07-2017 +----------------------------------- + +- ASN.1 types __init__(), .clone() and .subtype() signatures + refactored into keyword arguments to simplify their signatures. +- ASN.1 types initialization refactored to minimize the use of + relatively expensive isNoValue() call +- Lazily pre-populate list of values of Sequence/Set/Choice types +- NamedTypes comparison made more efficient +- More efficient constraints computation and code clean up +- The __getitem__() implementation of some ASN.1 types & tag object + refactored for better performance +- BER/CER/DER value encoders refactored to produce either tuple of + bytes or octet-stream depending on what is more optimal +- Reduced the frequency of expensive isinstance() calls +- Tag-related classes optimized, refactored into properties and + documented. +- The NamedValues implementation refactored to mimic Python dict, its use + in ASN.1 types refactored into properties and better documented. + WARNING: this change introduces a deviation from original API. +- NamedType family of classes overhauled, optimized and documented. +- The `componentType` attribute of constructed ASN.1 types turned + read-only on instances. +- Sequence/Set DER/CER/DER decoder optimized to skip the case of + reordered components handling when not necessary. +- Tags and constraints-related getter methods refactored into read-only + instance attributes. +- The .hasValue() method refactored into .isValue property. All ASN.1 + objects now support them, not just scalars. +- The Real.{isInfinity, isPlusInfinity, isMinusInfinity} methods + refactored into properties and renamed into IsInf, IsPlusInf and isMinusInf +- The end-of-octets type refactored to ensure it is a singleton. Codecs + changed to rely on that for better performance. +- Codecs lookup made more efficient at BER/CER/DER decoder main loop by + assigning `typeId` to every ASN.1 type, not just ambiguous ones. +- The .getComponent*() methods of constructed ASN.1 types changed + to lazily instantiate underlying type rather than return `None`. + This should simplify its API as initialization like `X[0][1] = 2` becomes + possible. + WARNING: this change introduces a deviation from the original API. +- The .setComponent*() methods of SetOf/SequenceOf types changed not + to allow uninitialized "holes" inside the sequences of their components. + They now behave similarly to Python lists. + WARNING: this change introduces a deviation from the original API. +- Default and optional components en/decoding of Constructed type + refactored towards better efficiency and more control. +- OctetsString and Any decoder optimized to avoid creating ASN.1 + objects for chunks of substrate. Instead they now join substrate + chunks together and create ASN.1 object from it just once. +- The GeneralizedTime and UTCTime types now support to/from Python + datetime object conversion. +- Unit tests added for the `compat` sub-package. +- Fixed BitString named bits initialization bug. +- Fixed non-functional tag cache (when running Python 2) at DER decoder. +- Fixed chunked encoding restriction on DER encoder. +- Fixed SET components ordering at DER encoder. +- Fixed BIT STRING & OCTET STRING encoding to be always non-chunked (e.g. + primitive) at DER encoder +- Fixed `compat.integer.from_bytes()` behaviour on empty input. + +Revision 0.2.3, released 25-02-2017 +----------------------------------- + +- Improved SEQUENCE/SET/CHOICE decoding performance by maintaining a single shared + NamedType object for all instances of SEQUENCE/SET object. +- Improved INTEGER encoding/decoding by switching to Python's built-in + integer serialisation functions. +- Improved BitString performance by rebasing it onto Python int type and leveraging + fast Integer serialisation functions. +- BitString type usability improved in many ways: for example bitshifting and + numeric operation on BitString is now possible. +- Minor ObjectIdentifier type performance optimization. +- ASN.1 character types refactored to keep unicode contents internally + (rather than serialised octet stream) and duck-type it directly. +- ASN.1 OctetString initialized from a Python object performs bytes() + on it when running on Python 3 (used to do str() which is probably + less logical). +- Missing support for NoValue.__sizeof__ added. +- Added checks to make sure SEQUENCE/SET components being assigned + match the prototypes. +- Setter methods for constructed types consistently accept matchTags + and matchConstraints flags to control the strictness of inner + components compatibility verification. Previously, these checks + were tied to verifyConstraints flag, now they are all independent. +- General documentation improvements here and there. +- Fix to __reversed__() magic to make it returning an iterator. +- Test suite simplified and unified. +- The __all__ variable added to most of the Python modules. +- The "test" directory renamed into "tests" not to collide with + the "test" module. + +Revision 0.2.2, released 07-02-2017 +----------------------------------- + +- FIX TO A SECURITY WEAKNESS: define length only decoders could have successfully + processed indefinite length serialisation. +- FIX TO A SECURITY WEAKNESS: canonical decoders (CER/DER) may have successfully + consumed non-canonical variations of (otherwise valid) serialisation. +- Broken Enumerated subtyping fixed. + +Revision 0.2.1, released 05-02-2017 +----------------------------------- + +- FIX TO A SECURITY WEAKNESS: BER decoder improperly cached long tags. +- New "native" codec implemented to transform pyasn1 types to Python built-in types and back. +- Switched to new-style classes. +- Sphinx documentation added. +- BitString improvements: + + * simple string of binary digits is now supported as initializer + * default str() yields string of binary digits (used to yield str(tuple()) + * binValue and hexValue initializers added + * .asNumbers(), .asOctets() and asInteger() representation added + +- Components of constructed ASN.1 types can now be populated with + uninitialized ASN.1 objects by assigning either noValue sentinel or + setupComponent() function return in addition to now-legacy None sentinel. + This should improve code readability. +- NoValue class improved to become a singleton and catch more kinds + of access to it. +- Compatibility wrappers str2octs() and oct2strs() fixed to run over + iso-8859-1 encoding. +- Integer changed to emit Real instance if division produces a float. +- True division operation now supported by Integer type. +- The __contains__(), __reverse__() methods implemented for container types +- Iterator protocol support implemented for all container types. + Warning, warning, warning: this change may potentially affect backward + compatibility when: + + * user class overrides __getitem__() without overriding __iter__() + * when user code iterates over SEQUENCE object to get its components (now keys will be yielded) + +- Almost complete Python list and dict protocols added to SequenceOf/SetOf and + Sequence/Set respectively +- Fix to divmod operation implementation in Integer type. +- Fix to IntegerDecoder's precomputed value map on Python 3. +- Fix to base ASN.1 types to run in "unicode_literals" mode. +- Fix to composite constraints "+" operands ordering (AbstractConstraintSet.__radd__) +- Fix to constraints merge in .subtype() -- on merge existing constraints are + expanded to accommodate new constraints, not the other way round. When existing + constraints are wrapped in ConstraintsIntersection composite, additional + constraints being added on subtyping effectively further narrow the set of + allowed values, which aligns well with the notion of subtyping. +- Fix to NamedTypes methods to handle .getTagMap() returning None +- Fix to Set/Sequence.setDefaultComponents() to return self +- Copyright notice added to non-trivial source code files. +- Author's email changed, copyright extended to 2017 + +Revision 0.1.9, released 28-09-2015 +----------------------------------- + +- Wheel distribution format now supported. +- Extensions added to text files, CVS attic flushed. +- Fix to make uninitialized pyasn1 objects failing properly on hash(). +- Fix to ObjectIdentifier initialization from unicode string. +- Fix to CER/DER Boolean decoder - fail on non single-octet payload. + +Revision 0.1.8, released 22-06-2015 +----------------------------------- + +- ObjectIdentifier codec fixed to work properly with arc 0 and arc 2 values. +- Explicit limit on ObjectIdentifier arc value size removed. +- Unicode initializer support added to OctetString type and derivatives. +- New prettyPrintType() abstract method implemented to base pyasn1 types + to facilitate encoding errors analysis. +- The __str__() method implemented to Tag, TagSet and TagMap classes to + ease encoding errors troubleshooting. + easing encoding errors +- Fix to SEQUENCE and SET types to give them their private componentTypes + collection (which is a NamedTypes object) so that they won't collide in + a MT execution environment. +- Missing T61String,ISO646String character types and ObjectDescriptor useful + type added. +- Distribute is gone, switched to setuptools completely. +- Missing NamedValues.__repr__() added. +- The base.NoValue() class, that indicates uninitialized ASN.1 object, + made public. +- The base.NoValue() class instances now support __repr__() what makes + possible to perform repr() on uninitialized pyasn1 types objects. +- When comparing ASN.1 types, by-tag and/or by-constraints matching + can now be performed with the isSuperTypeOf()/isSameTypeWith() optional + flags. +- Constructed types now verify their consistency by invoking + isSameTypeWith(matchTags=True, matchConstraints=False) and + isSuperTypeOf(matchTags=False, matchConstraints=True) for each of their + components rather than isSuperTypeOf() as it used to be. Constriants check + could be enforced to isSameTypeWith() with the strictConstraints=True + constructed classes attribute. +- Constructed types can now be initialized with new .setComponents() method + which accepts both var-args and keyword-args. Default repr() modified to + reflect this change. +- NamedTypes() and NamedValues() made comparable. +- Test coverage extended to cover pyasn1 types __repr__() function. +- The abs(Integer()) & abs(Real()) operation now returns respective pyasn1 + type, not a Python type. +- More Python magic methods implementations added to Integer & Real classes + (e.g. __pos__, __neg__, __round__, __floor__, __ceil__, __trunc__) +- The Integer.__invert__ Python magic method implemented. +- The OctetString.__int__() and .__float__() magic methods implemented. +- Handle the case of null writer at Debug printer. +- BitString encoder/decoder performance improved. +- Built-in debugging is now based on Python logging module. +- Fix to NamedType.__repr__() to work properly. +- Fixes to __repr__() implementation of many built-in ASN.1 types to take into + account all of their initializers such as tagSet, subtypeSpec etc. +- String typed float initializer to REAL type now supported. +- Float typed mantissa initializer to REAL type for base 2 added. +- Encoding bases 8 and 16 support for REAL type binary encoder added. +- More strict CER/DER encoders added for GeneralizedTime and UTCTime types. +- Asn1Item.hasValue() added to easily distinguish initalized ASN.1 objects + from uninitialized ones (e.g. pure types). +- Fix to REAL type binary decoder to handle different bases and scale factor. +- Fix to TagSet.repr() to include [obsolete] baseTag information. +- Fix to broken REAL type decoding handling. +- Fix to BitString and OctetString decoders dealing with constructed + encoding -- it used to be possible to embed other types in substrate. +- DER codec hardened not to tolerate indefinite length encoding/decoding. +- Fix to end-of-octest sentinel handling: + + + require strict two-zeros sentinel encoding + + recognize EOO sentinel only when explicitly requested by caller + of the decoder via allowEoo=True parameter (warning: API change) + +Revision 0.1.7 +-------------- + +- License updated to vanilla BSD 2-Clause to ease package use + (https://opensource.org/licenses/BSD-2-Clause). +- Test suite made discoverable by unittest/unittest2 discovery feature. +- Fix to decoder working on indefinite length substrate -- end-of-octets + marker is now detected by both tag and value. Otherwise zero values may + interfere with end-of-octets marker. +- Fix to decoder to fail in cases where tagFormat indicates inappropriate + format for the type (e.g. BOOLEAN is always PRIMITIVE, SET is always + CONSTRUCTED and OCTET STRING is either of the two) +- Fix to REAL type encoder to force primitive encoding form encoding. +- Fix to CHOICE decoder to handle explicitly tagged, indefinite length + mode encoding +- Fix to REAL type decoder to handle negative REAL values correctly. Test + case added. + +Revision 0.1.6 +-------------- + +- The compact (valueless) way of encoding zero INTEGERs introduced in + 0.1.5 seems to fail miserably as the world is filled with broken + BER decoders. So we had to back off the *encoder* for a while. + There's still the IntegerEncoder.supportCompactZero flag which + enables compact encoding form whenever it evaluates to True. +- Report package version on debugging code initialization. + +Revision 0.1.5 +-------------- + +- Documentation updated and split into chapters to better match + web-site contents. +- Make prettyPrint() working for non-initialized pyasn1 data objects. It + used to throw an exception. +- Fix to encoder to produce empty-payload INTEGER values for zeros +- Fix to decoder to support empty-payload INTEGER and REAL values +- Fix to unit test suites imports to be able to run each from + their current directory + +Revision 0.1.4 +-------------- + +- Built-in codec debugging facility added +- Added some more checks to ObjectIdentifier BER encoder catching + posible 2^8 overflow condition by two leading sub-OIDs +- Implementations overriding the AbstractDecoder.valueDecoder method + changed to return the rest of substrate behind the item being processed + rather than the unprocessed substrate within the item (which is usually + empty). +- Decoder's recursiveFlag feature generalized as a user callback function + which is passed an uninitialized object recovered from substrate and + its uninterpreted payload. +- Catch inappropriate substrate type passed to decoder. +- Expose tagMap/typeMap/Decoder objects at DER decoder to uniform API. +- Obsolete __init__.MajorVersionId replaced with __init__.__version__ + which is now in-sync with distutils. +- Package classifiers updated. +- The __init__.py's made non-empty (rumors are that they may be optimized + out by package managers). +- Bail out gracefully whenever Python version is older than 2.4. +- Fix to Real codec exponent encoding (should be in 2's complement form), + some more test cases added. +- Fix in Boolean truth testing built-in methods +- Fix to substrate underrun error handling at ObjectIdentifier BER decoder +- Fix to BER Boolean decoder that allows other pre-computed + values besides 0 and 1 +- Fix to leading 0x80 octet handling in DER/CER/DER ObjectIdentifier decoder. + See https://www.esat.kuleuven.be/cosic/publications/article-1432.pdf + +Revision 0.1.3 +-------------- + +- Include class name into asn1 value constraint violation exception. +- Fix to OctetString.prettyOut() method that looses leading zero when + building hex string. + +Revision 0.1.2 +-------------- + +- Fix to __long__() to actually return longs on py2k +- Fix to OctetString.__str__() workings of a non-initialized object. +- Fix to quote initializer of OctetString.__repr__() +- Minor fix towards ObjectIdentifier.prettyIn() reliability +- ObjectIdentifier.__str__() is aliased to prettyPrint() +- Exlicit repr() calls replaced with '%r' + +Revision 0.1.1 +-------------- + +- Hex/bin string initializer to OctetString object reworked + (in a backward-incompatible manner) +- Fixed float() infinity compatibility issue (affects 2.5 and earlier) +- Fixed a bug/typo at Boolean CER encoder. +- Major overhawl for Python 2.4 -- 3.2 compatibility: + + get rid of old-style types + + drop string module usage + + switch to rich comparation + + drop explicit long integer type use + + map()/filter() replaced with list comprehension + + apply() replaced with \*/\*\*args + + switched to use 'key' sort() callback function + + support both __nonzero__() and __bool__() methods + + modified not to use py3k-incompatible exception syntax + + getslice() operator fully replaced with getitem() + + dictionary operations made 2K/3K compatible + + base type for encoding substrate and OctetString-based types + is now 'bytes' when running py3k and 'str' otherwise + + OctetString and derivatives now unicode compliant. + + OctetString now supports two python-neutral getters: asOcts() & asInts() + + print OctetString content in hex whenever it is not printable otherwise + + in test suite, implicit relative import replaced with the absolute one + + in test suite, string constants replaced with numerics + +Revision 0.0.13 +--------------- + +- Fix to base10 normalization function that loops on univ.Real(0) + +Revision 0.0.13b +---------------- + +- ASN.1 Real type is now supported properly. +- Objects of Constructed types now support __setitem__() +- Set/Sequence objects can now be addressed by their field names (string index) + and position (integer index). +- Typo fix to ber.SetDecoder code that prevented with schema decoding + operation. +- Fix to explicitly tagged items decoding support. +- Fix to OctetString.prettyPrint() to better handle non-printable content. +- Fix to repr() workings of Choice objects. + +Revision 0.0.13a +---------------- + +- Major codec re-design. +- Documentation significantly improved. +- ASN.1 Any type is now supported. +- All example ASN.1 modules moved to separate pyasn1-modules package. +- Fix to initial sub-OID overflow condition detection an encoder. +- BitString initialization value verification improved. +- The Set/Sequence.getNameByPosition() method implemented. +- Fix to proper behaviour of PermittedAlphabetConstraint object. +- Fix to improper Boolean substrate handling at CER/DER decoders. +- Changes towards performance improvement: + + + all dict.has_key() & dict.get() invocations replaced with modern syntax + (this breaks compatibility with Python 2.1 and older). + + tag and tagset caches introduced to decoder + + decoder code improved to prevent unnecessary pyasn1 objects creation + + allow disabling components verification when setting components to + structured types, this is used by decoder whilst running with schema + mode. + + BER decoder for integer values now looks up a small set of pre-computed + substrate values to save on decoding. + + a few pre-computed values configured to ObjectIdentifier BER encoder. + + ChoiceDecoder split-off SequenceOf one to save on unnecessary checks. + + replace slow hasattr()/getattr() calls with isinstance() introspection. + + track the number of initialized components of Constructed types to save + on default/optional components initialization. + + added a shortcut ObjectIdentifier.asTuple() to be used instead of + __getitem__() in hotspots. + + use Tag.asTuple() and pure integers at tag encoder. + + introduce and use in decoder the baseTagSet attribute of the built-in + ASN.1 types. + +Revision 0.0.12a +---------------- + +- The individual tag/length/value processing methods of + encoder.AbstractItemEncoder renamed (leading underscore stripped) + to promote overloading in cases where partial substrate processing + is required. +- The ocsp.py, ldap.py example scripts added. +- Fix to univ.ObjectIdentifier input value handler to disallow negative + sub-IDs. + +Revision 0.0.11a +---------------- + +- Decoder can now treat values of unknown types as opaque OctetString. +- Fix to Set/SetOf type decoder to handle uninitialized scalar SetOf + components correctly. + +Revision 0.0.10a +---------------- + +- API versioning mechanics retired (pyasn1.v1 -> pyasn1) what makes + it possible to zip-import pyasn1 sources (used by egg and py2exe). + +Revision 0.0.9a +--------------- + +- Allow any non-zero values in Boolean type BER decoder, as it's in + accordnance with the standard. + +Revision 0.0.8a +--------------- + +- Integer.__index__() now supported (for Python 2.5+). +- Fix to empty value encoding in BitString encoder, test case added. +- Fix to SequenceOf decoder that prevents it skipping possible Choice + typed inner component. +- Choice.getName() method added for getting currently set component + name. +- OctetsString.prettyPrint() does a single str() against its value + eliminating an extra quotes. + +Revision 0.0.7a +--------------- + +- Large tags (>31) now supported by codecs. +- Fix to encoder to properly handle explicitly tagged untagged items. +- All possible value lengths (up to 256^126) now supported by encoders. +- Fix to Tag class constructor to prevent negative IDs. + +Revision 0.0.6a +--------------- + +- Make use of setuptools. +- Constraints derivation verification (isSuperTypeOf()/isSubTypeOf()) fixed. +- Fix to constraints comparation logic -- can't cmp() hash values as it + may cause false positives due to hash conflicts. + +Revision 0.0.5a +--------------- + +- Integer BER codec reworked fixing negative values encoding bug. +- clone() and subtype() methods of Constructed ASN.1 classes now + accept optional cloneValueFlag flag which controls original value + inheritance. The default is *not* to inherit original value for + performance reasons (this may affect backward compatibility). + Performance penalty may be huge on deeply nested Constructed objects + re-creation. +- Base ASN.1 types (pyasn1.type.univ.*) do not have default values + anymore. They remain uninitialized acting as ASN.1 types. In + this model, initialized ASN.1 types represent either types with + default value installed or a type instance. +- Decoders' prototypes are now class instances rather than classes. + This is to simplify initial value installation to decoder's + prototype value. +- Bugfix to BitString BER decoder (trailing bits not regarded). +- Bugfix to Constraints use as mapping keys. +- Bugfix to Integer & BitString clone() methods +- Bugix to the way to distinguish Set from SetOf at CER/DER SetOfEncoder +- Adjustments to make it running on Python 1.5. +- In tests, substrate constants converted from hex escaped literals into + octals to overcome indefinite hex width issue occuring in young Python. +- Minor performance optimization of TagSet.isSuperTagSetOf() method +- examples/sshkey.py added + +Revision 0.0.4a +--------------- + +* Asn1Type.prettyPrinter() -> \*.prettyPrint() + +Revision 0.0.3a +--------------- + +* Simple ASN1 objects now hash to their Python value and don't + depend upon tag/constraints/etc. +* prettyIn & prettyOut methods of SimplleAsn1Object become public +* many syntax fixes + +Revision 0.0.2a +--------------- + +* ConstraintsIntersection.isSuperTypeOf() and + ConstraintsIntersection.hasConstraint() implemented +* Bugfix to NamedValues initialization code +* +/- operators added to NamedValues objects +* Integer.__abs__() & Integer.subtype() added +* ObjectIdentifier.prettyOut() fixes +* Allow subclass components at SequenceAndSetBase +* AbstractConstraint.__cmp__() dropped +* error.Asn1Error replaced with error.PyAsn1Error + +Revision 0.0.1a +--------------- + +* Initial public alpha release diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/LICENSE.rst b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/LICENSE.rst new file mode 100644 index 00000000..ac630e82 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/LICENSE.rst @@ -0,0 +1,24 @@ +Copyright (c) 2005-2019, Ilya Etingof <etingof@gmail.com> +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/MANIFEST.in b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/MANIFEST.in new file mode 100644 index 00000000..c605b0ee --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/MANIFEST.in @@ -0,0 +1,5 @@ +include *.rst *.md +recursive-include tests *.py +recursive-include docs Makefile *.rst *.svg conf.py +prune docs/build +prune docs/source/.templates diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/PKG-INFO b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/PKG-INFO new file mode 100644 index 00000000..45d958b1 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/PKG-INFO @@ -0,0 +1,35 @@ +Metadata-Version: 1.2 +Name: pyasn1 +Version: 0.4.8 +Summary: ASN.1 types and codecs +Home-page: https://github.com/etingof/pyasn1 +Author: Ilya Etingof +Author-email: etingof@gmail.com +Maintainer: Ilya Etingof <etingof@gmail.com> +License: BSD +Description: Pure-Python implementation of ASN.1 types and DER/BER/CER codecs (X.208) +Platform: any +Classifier: Development Status :: 5 - Production/Stable +Classifier: Environment :: Console +Classifier: Intended Audience :: Developers +Classifier: Intended Audience :: Education +Classifier: Intended Audience :: Information Technology +Classifier: Intended Audience :: System Administrators +Classifier: Intended Audience :: Telecommunications Industry +Classifier: License :: OSI Approved :: BSD License +Classifier: Natural Language :: English +Classifier: Operating System :: OS Independent +Classifier: Programming Language :: Python :: 2 +Classifier: Programming Language :: Python :: 2.4 +Classifier: Programming Language :: Python :: 2.5 +Classifier: Programming Language :: Python :: 2.6 +Classifier: Programming Language :: Python :: 2.7 +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3.2 +Classifier: Programming Language :: Python :: 3.3 +Classifier: Programming Language :: Python :: 3.4 +Classifier: Programming Language :: Python :: 3.5 +Classifier: Programming Language :: Python :: 3.6 +Classifier: Programming Language :: Python :: 3.7 +Classifier: Topic :: Communications +Classifier: Topic :: Software Development :: Libraries :: Python Modules diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/README.md b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/README.md new file mode 100644 index 00000000..e36324b0 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/README.md @@ -0,0 +1,184 @@ + +ASN.1 library for Python +------------------------ +[![PyPI](https://img.shields.io/pypi/v/pyasn1.svg?maxAge=2592000)](https://pypi.org/project/pyasn1) +[![Python Versions](https://img.shields.io/pypi/pyversions/pyasn1.svg)](https://pypi.org/project/pyasn1/) +[![Build status](https://travis-ci.org/etingof/pyasn1.svg?branch=master)](https://secure.travis-ci.org/etingof/pyasn1) +[![Coverage Status](https://img.shields.io/codecov/c/github/etingof/pyasn1.svg)](https://codecov.io/github/etingof/pyasn1) +[![GitHub license](https://img.shields.io/badge/license-BSD-blue.svg)](https://raw.githubusercontent.com/etingof/pyasn1/master/LICENSE.txt) + +This is a free and open source implementation of ASN.1 types and codecs +as a Python package. It has been first written to support particular +protocol (SNMP) but then generalized to be suitable for a wide range +of protocols based on +[ASN.1 specification](https://www.itu.int/rec/dologin_pub.asp?lang=e&id=T-REC-X.208-198811-W!!PDF-E&type=items). + +Features +-------- + +* Generic implementation of ASN.1 types (X.208) +* Standards compliant BER/CER/DER codecs +* Dumps/loads ASN.1 structures from Python types +* 100% Python, works with Python 2.4 up to Python 3.7 +* MT-safe +* Contributed ASN.1 compiler [Asn1ate](https://github.com/kimgr/asn1ate) + +Why using pyasn1 +---------------- + +ASN.1 solves the data serialisation problem. This solution was +designed long ago by the wise Ancients. Back then, they did not +have the luxury of wasting bits. That is why ASN.1 is designed +to serialise data structures of unbounded complexity into +something compact and efficient when it comes to processing +the data. + +That probably explains why many network protocols and file formats +still rely on the 30+ years old technology. Including a number of +high-profile Internet protocols and file formats. + +Quite a number of books cover the topic of ASN.1. +[Communication between heterogeneous systems](http://www.oss.com/asn1/dubuisson.html) +by Olivier Dubuisson is one of those high quality books freely +available on the Internet. + +The pyasn1 package is designed to help Python programmers tackling +network protocols and file formats at the comfort of their Python +prompt. The tool struggles to capture all aspects of a rather +complicated ASN.1 system and to represent it on the Python terms. + +How to use pyasn1 +----------------- + +With pyasn1 you can build Python objects from ASN.1 data structures. +For example, the following ASN.1 data structure: + +```bash +Record ::= SEQUENCE { + id INTEGER, + room [0] INTEGER OPTIONAL, + house [1] INTEGER DEFAULT 0 +} +``` + +Could be expressed in pyasn1 like this: + +```python +class Record(Sequence): + componentType = NamedTypes( + NamedType('id', Integer()), + OptionalNamedType( + 'room', Integer().subtype( + implicitTag=Tag(tagClassContext, tagFormatSimple, 0) + ) + ), + DefaultedNamedType( + 'house', Integer(0).subtype( + implicitTag=Tag(tagClassContext, tagFormatSimple, 1) + ) + ) + ) +``` + +It is in the spirit of ASN.1 to take abstract data description +and turn it into a programming language specific form. +Once you have your ASN.1 data structure expressed in Python, you +can use it along the lines of similar Python type (e.g. ASN.1 +`SET` is similar to Python `dict`, `SET OF` to `list`): + +```python +>>> record = Record() +>>> record['id'] = 123 +>>> record['room'] = 321 +>>> str(record) +Record: + id=123 + room=321 +>>> +``` + +Part of the power of ASN.1 comes from its serialisation features. You +can serialise your data structure and send it over the network. + +```python +>>> from pyasn1.codec.der.encoder import encode +>>> substrate = encode(record) +>>> hexdump(substrate) +00000: 30 07 02 01 7B 80 02 01 41 +``` + +Conversely, you can turn serialised ASN.1 content, as received from +network or read from a file, into a Python object which you can +introspect, modify, encode and send back. + +```python +>>> from pyasn1.codec.der.decoder import decode +>>> received_record, rest_of_substrate = decode(substrate, asn1Spec=Record()) +>>> +>>> for field in received_record: +>>> print('{} is {}'.format(field, received_record[field])) +id is 123 +room is 321 +house is 0 +>>> +>>> record == received_record +True +>>> received_record.update(room=123) +>>> substrate = encode(received_record) +>>> hexdump(substrate) +00000: 30 06 02 01 7B 80 01 7B +``` + +The pyasn1 classes struggle to emulate their Python prototypes (e.g. int, +list, dict etc.). But ASN.1 types exhibit more complicated behaviour. +To make life easier for a Pythonista, they can turn their pyasn1 +classes into Python built-ins: + +```python +>>> from pyasn1.codec.native.encoder import encode +>>> encode(record) +{'id': 123, 'room': 321, 'house': 0} +``` + +Or vice-versa -- you can initialize an ASN.1 structure from a tree of +Python objects: + +```python +>>> from pyasn1.codec.native.decoder import decode +>>> record = decode({'id': 123, 'room': 321, 'house': 0}, asn1Spec=Record()) +>>> str(record) +Record: + id=123 + room=321 +>>> +``` + +With ASN.1 design, serialisation codecs are decoupled from data objects, +so you could turn every single ASN.1 object into many different +serialised forms. As of this moment, pyasn1 supports BER, DER, CER and +Python built-ins codecs. The extremely compact PER encoding is expected +to be introduced in the upcoming pyasn1 release. + +More information on pyasn1 APIs can be found in the +[documentation](http://snmplabs.com/pyasn1/), +compiled ASN.1 modules for different protocols and file formats +could be found in the pyasn1-modules +[repo](https://github.com/etingof/pyasn1-modules). + +How to get pyasn1 +----------------- + +The pyasn1 package is distributed under terms and conditions of 2-clause +BSD [license](http://snmplabs.com/pyasn1/license.html). Source code is freely +available as a GitHub [repo](https://github.com/etingof/pyasn1). + +You could `pip install pyasn1` or download it from [PyPI](https://pypi.org/project/pyasn1). + +If something does not work as expected, +[open an issue](https://github.com/etingof/pyasn1/issues) at GitHub or +post your question [on Stack Overflow](https://stackoverflow.com/questions/ask) +or try browsing pyasn1 +[mailing list archives](https://sourceforge.net/p/pyasn1/mailman/pyasn1-users/). + +Copyright (c) 2005-2019, [Ilya Etingof](mailto:etingof@gmail.com). +All rights reserved. diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/TODO.rst b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/TODO.rst new file mode 100644 index 00000000..5c79ee7c --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/TODO.rst @@ -0,0 +1,92 @@ + +Things to be done +================= + +Big things to tackle, anyone interested is welcome to fork pyasn1, work on +it and come up with a PR! + +New codecs +---------- + +* PER +* OER +* XER +* LWER +* JSON (alinged with existing experimental schemas) + +Lazy codecs +----------- + +Implement a thin layer over base types to cache pieces +of substrate being decoded till the very moment of ASN.1 +object access in the parse tree. + +Codecs generator interface +-------------------------- + +For indefinite length or chunked encoding mode, make codecs +iterable producing/consuming substrate/objects. + +ASN.1 schema compiler +--------------------- + +Ideally, the compiler should parse modern schema files and be +designed to emit code for arbitrary languages (including SQL). + +Base types +---------- + +Implement X.680 constructs, including information schema. + +Examples +-------- + +Add examples, including advanced/obscure use cases. + +Documentation +------------- + +Document more API, add notes and example snippets. + +More fresh modules +------------------ + +Compile and ship more Pythonized ASN.1 modules for +various ASN.1-based protocols (e.g. Kerberos etc). +Refresh outdated modules in pyasn1-packages. + +Minor, housekeeping things +-------------------------- + +* more PEP8'ing at places +* consider simplifying repr(), otherwise it tend to be too hard to grasp +* Specialize ASN.1 character and useful types + +* ber.decoder: + + * suspend codec on underrun error ? + * present subtypes ? + * component presence check wont work at innertypeconst + * type vs value, defaultValue + +* ber.encoder: + + * Asn1Item.clone() / shallowcopy issue + * large length encoder? + * lookup type by tag first to allow custom codecs for non-base types + +* type.useful: + + * may need to implement prettyIn/Out + +* type.char: + + * may need to implement constraints + +* type.namedtypes + + * type vs tagset name convention + +* how untagged TagSet should be initialized? + +* type and codecs for Real needs refactoring diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/Makefile b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/Makefile new file mode 100644 index 00000000..214532e6 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/Makefile @@ -0,0 +1,192 @@ +# Makefile for Sphinx documentation +# + +# You can set these variables from the command line. +SPHINXOPTS = +SPHINXBUILD = sphinx-build +PAPER = +BUILDDIR = build + +# User-friendly check for sphinx-build +ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1) +$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/) +endif + +# Internal variables. +PAPEROPT_a4 = -D latex_paper_size=a4 +PAPEROPT_letter = -D latex_paper_size=letter +ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source +# the i18n builder cannot share the environment and doctrees with the others +I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source + +.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest coverage gettext + +help: + @echo "Please use \`make <target>' where <target> is one of" + @echo " html to make standalone HTML files" + @echo " dirhtml to make HTML files named index.html in directories" + @echo " singlehtml to make a single large HTML file" + @echo " pickle to make pickle files" + @echo " json to make JSON files" + @echo " htmlhelp to make HTML files and a HTML help project" + @echo " qthelp to make HTML files and a qthelp project" + @echo " applehelp to make an Apple Help Book" + @echo " devhelp to make HTML files and a Devhelp project" + @echo " epub to make an epub" + @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" + @echo " latexpdf to make LaTeX files and run them through pdflatex" + @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx" + @echo " text to make text files" + @echo " man to make manual pages" + @echo " texinfo to make Texinfo files" + @echo " info to make Texinfo files and run them through makeinfo" + @echo " gettext to make PO message catalogs" + @echo " changes to make an overview of all changed/added/deprecated items" + @echo " xml to make Docutils-native XML files" + @echo " pseudoxml to make pseudoxml-XML files for display purposes" + @echo " linkcheck to check all external links for integrity" + @echo " doctest to run all doctests embedded in the documentation (if enabled)" + @echo " coverage to run coverage check of the documentation (if enabled)" + +clean: + rm -rf $(BUILDDIR)/* + +html: + $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." + +dirhtml: + $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." + +singlehtml: + $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml + @echo + @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." + +pickle: + $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle + @echo + @echo "Build finished; now you can process the pickle files." + +json: + $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json + @echo + @echo "Build finished; now you can process the JSON files." + +htmlhelp: + $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp + @echo + @echo "Build finished; now you can run HTML Help Workshop with the" \ + ".hhp project file in $(BUILDDIR)/htmlhelp." + +qthelp: + $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp + @echo + @echo "Build finished; now you can run "qcollectiongenerator" with the" \ + ".qhcp project file in $(BUILDDIR)/qthelp, like this:" + @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/PyASN1.qhcp" + @echo "To view the help file:" + @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/PyASN1.qhc" + +applehelp: + $(SPHINXBUILD) -b applehelp $(ALLSPHINXOPTS) $(BUILDDIR)/applehelp + @echo + @echo "Build finished. The help book is in $(BUILDDIR)/applehelp." + @echo "N.B. You won't be able to view it unless you put it in" \ + "~/Library/Documentation/Help or install it in your application" \ + "bundle." + +devhelp: + $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp + @echo + @echo "Build finished." + @echo "To view the help file:" + @echo "# mkdir -p $$HOME/.local/share/devhelp/PyASN1" + @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/PyASN1" + @echo "# devhelp" + +epub: + $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub + @echo + @echo "Build finished. The epub file is in $(BUILDDIR)/epub." + +latex: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo + @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." + @echo "Run \`make' in that directory to run these through (pdf)latex" \ + "(use \`make latexpdf' here to do that automatically)." + +latexpdf: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo "Running LaTeX files through pdflatex..." + $(MAKE) -C $(BUILDDIR)/latex all-pdf + @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." + +latexpdfja: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo "Running LaTeX files through platex and dvipdfmx..." + $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja + @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." + +text: + $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text + @echo + @echo "Build finished. The text files are in $(BUILDDIR)/text." + +man: + $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man + @echo + @echo "Build finished. The manual pages are in $(BUILDDIR)/man." + +texinfo: + $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo + @echo + @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." + @echo "Run \`make' in that directory to run these through makeinfo" \ + "(use \`make info' here to do that automatically)." + +info: + $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo + @echo "Running Texinfo files through makeinfo..." + make -C $(BUILDDIR)/texinfo info + @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." + +gettext: + $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale + @echo + @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." + +changes: + $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes + @echo + @echo "The overview file is in $(BUILDDIR)/changes." + +linkcheck: + $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck + @echo + @echo "Link check complete; look for any errors in the above output " \ + "or in $(BUILDDIR)/linkcheck/output.txt." + +doctest: + $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest + @echo "Testing of doctests in the sources finished, look at the " \ + "results in $(BUILDDIR)/doctest/output.txt." + +coverage: + $(SPHINXBUILD) -b coverage $(ALLSPHINXOPTS) $(BUILDDIR)/coverage + @echo "Testing of coverage in the sources finished, look at the " \ + "results in $(BUILDDIR)/coverage/python.txt." + +xml: + $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml + @echo + @echo "Build finished. The XML files are in $(BUILDDIR)/xml." + +pseudoxml: + $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml + @echo + @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml." diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/.static/logo.svg b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/.static/logo.svg new file mode 100644 index 00000000..e6062aa7 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/.static/logo.svg @@ -0,0 +1,95 @@ +<?xml version="1.0" encoding="UTF-8"?> +<svg viewBox="0 0 788.22937 829.02386" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> + <defs> + <filter id="j"> + <feGaussianBlur stdDeviation="6.2732"/> + </filter> + <filter id="g"> + <feGaussianBlur stdDeviation=".64973"/> + </filter> + <filter id="l" x="-.06193" y="-.19499" width="1.1239" height="1.39"> + <feGaussianBlur stdDeviation="7.46855"/> + </filter> + <filter id="k" x="-.25093" y="-.14188" width="1.5019" height="1.2838"> + <feGaussianBlur stdDeviation="3.07792"/> + </filter> + <filter id="i" x="-.03871" y="-.12187" width="1.0774" height="1.2437"> + <feGaussianBlur stdDeviation="4.66785"/> + </filter> + <filter id="h" x="-.12783" y="-.07846" width="1.2557" height="1.1569"> + <feGaussianBlur stdDeviation="1.708"/> + </filter> + <linearGradient id="e"> + <stop stop-color="#817e7e" offset="0"/> + <stop stop-color="#f4ebeb" stop-opacity=".98824" offset=".5"/> + <stop stop-color="#241b1b" stop-opacity=".97826" offset="1"/> + </linearGradient> + <linearGradient id="f"> + <stop stop-color="#1a5b78" offset="0"/> + <stop stop-color="#136890" offset="1"/> + </linearGradient> + <linearGradient id="r" x1="301.38" x2="318.52" y1="716.86" y2="106.67" gradientUnits="userSpaceOnUse"> + <stop stop-color="#3aacfa" offset="0"/> + <stop stop-color="#2699d7" stop-opacity=".99608" offset=".83216"/> + <stop stop-color="#78c1e7" stop-opacity=".99216" offset=".98972"/> + <stop stop-color="#cae9f7" stop-opacity=".99216" offset="1"/> + </linearGradient> + <linearGradient id="q" x1="-6.9187" x2="583.27" gradientUnits="userSpaceOnUse"> + <stop stop-color="#d4f6f7" offset="0"/> + <stop stop-color="#bdf0f2" offset=".5"/> + <stop stop-color="#76eaf0" offset=".75"/> + <stop stop-color="#465758" offset="1"/> + </linearGradient> + <linearGradient id="d" x1="172.72" x2="402.47" gradientUnits="userSpaceOnUse"> + <stop stop-color="#2a9cf9" offset="0"/> + <stop stop-color="#afe2eb" offset="1"/> + </linearGradient> + <linearGradient id="c" x1="286.18" x2="292.27" y1="332.78" y2="297.07" gradientUnits="userSpaceOnUse"> + <stop stop-color="#241b1b" offset="0"/> + <stop stop-color="#241b1b" stop-opacity="0" offset="1"/> + </linearGradient> + <linearGradient id="b" x1="291.93" x2="290.42" y1="654.44" y2="584.74" gradientUnits="userSpaceOnUse"> + <stop stop-color="#4ec7ff" offset="0"/> + <stop stop-color="#177ba9" offset="1"/> + </linearGradient> + <linearGradient id="p" x1="166.1" x2="410.06" y1="529.93" y2="527.91" gradientUnits="userSpaceOnUse" xlink:href="#f"/> + <linearGradient id="o" x1="257.31" x2="320.16" gradientUnits="userSpaceOnUse" xlink:href="#e"/> + <linearGradient id="n" x1="229.49" x2="343.96" gradientUnits="userSpaceOnUse" xlink:href="#e"/> + <linearGradient id="m" x1="63.378" x2="507.69" y1="571" y2="567.46" gradientUnits="userSpaceOnUse" xlink:href="#f"/> + <radialGradient id="a" cx="288.79" cy="314.87" r="47.676" gradientTransform="matrix(.95889 0 0 .36279 11.873 202.26)" gradientUnits="userSpaceOnUse"> + <stop stop-color="#f9faf8" offset="0"/> + <stop stop-color="#ccceca" stop-opacity=".67816" offset=".80581"/> + <stop stop-color="#a0a39d" stop-opacity=".98551" offset="1"/> + </radialGradient> + </defs> + <g transform="translate(36.408 -60.696)"> + <path d="m217.12 214.13 1.8398 157.37s-68.072 76.035-114.07 139.69-123.27 152.07-110.39 206.89 147.18 111.4 270.45 109.63 316.44-30.06 318.28-100.79-88.31-185.67-121.43-229.87-101.19-123.78-101.19-123.78l-3.6796-159.14s-27.597 14.146-69.912 14.146-69.912-14.146-69.912-14.146z" fill="url(#q)" opacity=".59004"/> + <g transform="matrix(1.0193 0 0 .9797 275.35 -97.577)"> + <path transform="matrix(1.0949 0 0 1.1946 -27.22 -91.679)" d="m433.86 608.91c0 25.384-64.786 45.962-144.7 45.962s-144.7-20.578-144.7-45.962 64.786-45.962 144.7-45.962 144.7 20.578 144.7 45.962z" filter="url(#l)"/> + <path d="m320.16 384.59c-20.034 6.3449-42.056 6.5046-62.156 0.15625 0.29535 26.623 0.5955 5.2459 0.875 31.875 6e-3 1.2834-0.46958 2.5635-1.3125 3.5312-27.411 31.834-52.856 65.234-76.938 99.75-17.564 25.17-36.956 49.209-44.688 77.531l-0.0312 0.0625c-2.7636 9.7018-0.36414 20.52 6.75 27.375l0.0937 0.0937c19.862 20.02 48.023 30.265 75.875 37.5 41.373 10.675 85.409 6.8178 128.31 1.0625v-0.0312c28.981-4.768 58.19-10.111 82.5-24.812-3e-5 -0.0104-3e-5 -0.0208 0-0.0312 4.5579-2.7227 8.8864-6.5506 11.625-10.781s3.9643-8.6335 3.0312-13.531c-0.0253-0.1242-0.0461-0.24931-0.0625-0.375-3.0304-25.717-17.046-49.326-30.906-72.375-0.0239-0.0398-0.0386-0.0852-0.0625-0.125-26.805-42.168-58.009-81.435-89.844-120.41-0.75007-0.90889-1.1862-2.072-1.2188-3.25-0.64083-27.08-1.2331-6.1494-1.8438-33.219z" fill="url(#p)"/> + <path d="m308.76 387.93c-15.75 1.6761-28.556 1.9621-44.482-1.3589 0.21917 26.636 0.31563 3.3544 0.52303 29.996 5e-3 1.284-0.34845 2.5647-0.97395 3.533-20.341 31.85-39.222 65.266-57.092 99.798-13.034 25.182-27.423 49.233-33.161 77.569l-0.0232 0.0625c-2.0508 9.7065-0.27021 20.53 5.0089 27.388l0.0696 0.0937c11.203 12.958 20.695 21.066 48.728 28.023s68.254 7.0598 102.79 2.5782c20.824-2.7021 47.44-9.1506 61.22-16.876-3e-5 -0.0104-3e-5 -0.0208 0-0.0312 3.3822-2.724 6.5943-6.5538 8.6265-10.786s2.9418-8.6377 2.2494-13.538c-0.0188-0.12426-0.0342-0.24943-0.0464-0.37518-2.2487-25.729-12.649-49.35-22.934-72.41-0.0178-0.0398-0.0286-0.0852-0.0464-0.12506-19.891-42.189-43.047-81.475-66.67-120.46-0.5566-0.90934-0.88028-2.073-0.90439-3.2516-0.47553-27.093 0.0951-3.1219-0.35803-30.204z" fill="url(#d)" filter="url(#j)"/> + <path transform="matrix(1 0 0 .9375 0 20.254)" d="m324.07 315.36c0 4.8113-15.991 8.7116-35.718 8.7116s-35.718-3.9003-35.718-8.7116 15.991-8.7116 35.718-8.7116 35.718 3.9003 35.718 8.7116z" fill="url(#c)"/> + <path transform="matrix(1 0 0 1.087 0 -51.618)" d="m433.86 608.91c0 25.384-64.786 45.962-144.7 45.962s-144.7-20.578-144.7-45.962 64.786-45.962 144.7-45.962 144.7 20.578 144.7 45.962z" fill="url(#b)" filter="url(#i)" opacity=".7"/> + <path transform="matrix(.74812 .4869 -.42145 .93332 324.55 94.283)" d="m105.06 429.6c0 15.342-4.7487 27.779-10.607 27.779s-10.607-12.437-10.607-27.779 4.7487-27.779 10.607-27.779 10.607 12.437 10.607 27.779z" fill="#fff" filter="url(#h)"/> + <path transform="matrix(.69501 .29687 -.29983 .73496 329.84 101.99)" d="m105.06 429.6c0 15.342-4.7487 27.779-10.607 27.779s-10.607-12.437-10.607-27.779 4.7487-27.779 10.607-27.779 10.607 12.437 10.607 27.779z" fill="#fff" filter="url(#k)"/> + <path d="m293.58 299.25c4.5514 0.12881 9.3278 0.24858 13.379 0.77697 5.2851 0.68931 10.077 1.7034 14.201 3.0024s7.6027 2.8509 10.281 4.932 4.6532 4.9568 4.3302 8.2969-2.8562 6.2388-5.9368 8.3199-6.8597 3.633-11.235 4.932c-8.7499 2.598-19.953 4.0562-32.144 4.0562s-23.083-1.4582-31.33-4.0562c-4.1238-1.299-7.6317-2.8509-10.31-4.932s-4.6509-4.9799-4.328-8.3199 2.8539-6.2158 5.9346-8.2969 6.8887-3.633 11.264-4.932c6.6932-1.9873 14.805-3.3077 23.705-3.8187 2.7349-0.15701-1.2073-0.23758 1.6582-0.23758l0.0765 9.2646c-3.7487 0.11199-7.3905 0.29917-9.7411 0.60179-4.7649 0.61344-9.0159 1.4835-12.472 2.5098s-6.0905 2.2331-7.5611 3.2266-1.6214 1.4742-1.6415 1.6824 0.0354 0.71198 1.3139 1.7055 3.6792 2.2003 6.9372 3.2266c6.5161 2.0526 16.331 3.4801 27.355 3.4801s21.144-1.4275 28.057-3.4801c3.4565-1.0263 6.0905-2.2331 7.5612-3.2266s1.5946-1.4972 1.6147-1.7055-9e-3 -0.68892-1.2872-1.6824-3.6792-2.2002-6.9372-3.2266-7.348-1.8963-12.002-2.5098-5.0792-0.75252-10.591-0.75252z" fill="url(#a)" filter="url(#g)" opacity=".64751"/> + <path d="m257.31 330.38c17.886 5.8187 39.891 3.5219 62.41-1.0835l0.44026 55.295c-21.953 6.8399-42.524 6.0827-62.156 0.15625z" fill="url(#o)" opacity=".49808"/> + <path d="m286.61 386.36h0.43558v3.0491h-0.43558z" fill="#241b1b" opacity=".64751"/> + <path d="m290.1 385.92h0.43558v3.4846h-0.43558z" fill="#241b1b" opacity=".64751"/> + <path d="m317.86 382.77c0 3.7423-12.687 6.776-28.336 6.776s-28.336-3.0337-28.336-6.776 12.687-6.776 28.336-6.776 28.336 3.0337 28.336 6.776z" fill="#135f9b" opacity=".68199"/> + </g> + <path transform="matrix(1.9941 0 0 2.091 -288.72 -517.12)" d="m433.86 608.91c0 25.384-64.786 45.962-144.7 45.962s-144.7-20.578-144.7-45.962 64.786-45.962 144.7-45.962 144.7 20.578 144.7 45.962z" filter="url(#l)"/> + <path d="m343.96 316.59c-36.488 11.107-76.596 11.386-113.2 0.27351 0.53792 46.603 1.0846 9.1828 1.5936 55.796 0.0109 2.2465-0.85524 4.4873-2.3904 6.1814-49.924 55.725-96.267 114.19-140.13 174.61-31.99 44.059-67.307 86.139-81.389 135.72l-0.05682 0.1094c-5.0334 16.983-0.66321 35.921 12.294 47.919 0.05755 0.0539 0.11456 0.10871 0.17066 0.16402 36.175 35.044 87.464 52.978 138.19 65.643 75.353 18.686 155.55 11.934 233.69 1.8599v-0.0546c52.783-8.3462 105.98-17.699 150.26-43.434-5e-5 -0.0182-5e-5 -0.0364 0-0.0546 8.3013-4.766 16.185-11.467 21.173-18.872s7.2202-15.113 5.5208-23.686c-0.0461-0.21741-0.084-0.43641-0.11383-0.65643-5.5192-45.016-31.045-86.344-56.289-126.69-0.0435-0.0697-0.0703-0.14914-0.11383-0.21881-48.821-73.814-105.65-142.55-163.63-210.77-1.3661-1.591-2.1605-3.627-2.2197-5.689-1.1671-47.402-2.2458-10.764-3.358-58.149z" fill="url(#m)"/> + <path transform="matrix(1.8213 0 0 1.7505 -239.14 -356.63)" d="m308.76 387.93c-15.75 1.6761-28.556 1.9621-44.482-1.3589 0.21917 26.636 0.31563 3.3544 0.52303 29.996 5e-3 1.284-0.34845 2.5647-0.97395 3.533-20.341 31.85-39.222 65.266-57.092 99.798-13.034 25.182-27.423 49.233-33.161 77.569l-0.0232 0.0625c-2.0508 9.7065-0.27021 20.53 5.0089 27.388l0.0696 0.0937c11.203 12.958 20.695 21.066 48.728 28.023s68.254 7.0598 102.79 2.5782c20.824-2.7021 47.44-9.1506 61.22-16.876-3e-5 -0.0104-3e-5 -0.0208 0-0.0312 3.3822-2.724 6.5943-6.5538 8.6265-10.786s2.9418-8.6377 2.2494-13.538c-0.0188-0.12426-0.0342-0.24943-0.0464-0.37518-2.2487-25.729-12.649-49.35-22.934-72.41-0.0178-0.0398-0.0286-0.0852-0.0464-0.12506-19.891-42.189-43.047-81.475-66.67-120.46-0.5566-0.90934-0.88028-2.073-0.90439-3.2516-0.47553-27.093 0.0951-3.1219-0.35803-30.204z" fill="url(#d)" filter="url(#j)"/> + <path transform="matrix(1.8213 0 0 1.6411 -239.14 -321.18)" d="m324.07 315.36c0 4.8113-15.991 8.7116-35.718 8.7116s-35.718-3.9003-35.718-8.7116 15.991-8.7116 35.718-8.7116 35.718 3.9003 35.718 8.7116z" fill="url(#c)"/> + <path transform="matrix(1.8213 0 0 1.9027 -239.14 -446.99)" d="m433.86 608.91c0 25.384-64.786 45.962-144.7 45.962s-144.7-20.578-144.7-45.962 64.786-45.962 144.7-45.962 144.7 20.578 144.7 45.962z" fill="url(#b)" filter="url(#i)" opacity=".7"/> + <path transform="matrix(1.3625 .8523 -.76759 1.6338 351.96 -191.6)" d="m105.06 429.6c0 15.342-4.7487 27.779-10.607 27.779s-10.607-12.437-10.607-27.779 4.7487-27.779 10.607-27.779 10.607 12.437 10.607 27.779z" fill="#fff" filter="url(#h)"/> + <path transform="matrix(1.2658 .51966 -.54607 1.2865 361.6 -178.11)" d="m105.06 429.6c0 15.342-4.7487 27.779-10.607 27.779s-10.607-12.437-10.607-27.779 4.7487-27.779 10.607-27.779 10.607 12.437 10.607 27.779z" fill="#fff" filter="url(#k)"/> + <path d="m282.86 319.68h0.79332v5.3373h-0.79332z" fill="#241b1b" opacity=".64751"/> + <path d="m289.21 318.92h0.79332v6.0998h-0.79332z" fill="#241b1b" opacity=".64751"/> + <path d="m229.49 221.69c32.576 10.186 72.653 6.165 113.67-1.8966l0.80184 96.793c-39.983 11.973-77.45 10.648-113.2 0.27351z" fill="url(#n)" opacity=".49808"/> + <path d="m314.53 88.096c11.175-7.4188 26.676-9.6276 40.922-9.6276 20.515 0 42.424 0.67751 63.119 1.3129-14.157 12.706-20.02 32.833-20.603 60.884s7.4772 46.002 19.522 56.234 26.603 12.035 36.71 12.035c9.5446 0 23.331-0.79894 35.231-9.8464s20.303-25.487 22.083-52.296c1.8812-28.327-6.4708-49.691-19.01-63.838 12.054 0.0088 22.878-0.32242 30.962 0.43762 11.434 1.0751 18.465 3.5429 26.636 14.168 6.5038 8.4571 10.278 28.096 11.099 50.764s-0.56916 48.252-0.56916 70.183h18.213c0-21.201 1.4303-46.992 0.56916-70.785s-3.2322-45.719-14.684-60.61c-10.902-14.176-25.129-19.764-39.499-21.115s-29.235 0.31775-46.898-0.71113c-4.6471-0.27069-8.9502-0.18951-13.261-0.10941-4.37-1.2458-8.7613-2.0787-13.091-2.0787-25.276 0-63.498-2.1334-96.529-2.1334-16.045 1.8e-5 -35.249 2.0482-51.281 12.691s-27.971 33.041-27.875 62.294l-0.30018 580.36c6.7459 3.5107 13.492 6.3162 20.238 0l-0.41466-580.94c0.37865-26.774 7.5356-39.862 18.711-47.281zm147.01-5.525h0.0568c15.896 5.5007 34.337 24.301 31.759 63.127-1.5853 23.871-8.3043 34.419-15.196 39.659s-15.555 6.072-23.961 6.072c-7.843 0-17.341-1.4545-24.644-7.6583s-13.892-17.899-13.375-42.723c0.53821-25.865 5.9461-40.522 14.798-48.466 6.639-5.9586 16.402-9.3 30.564-10.011z" fill="url(#r)" stroke="#000" stroke-opacity=".51587" stroke-width=".53566"/> + <path transform="matrix(1.8213 0 0 1.7505 -239.14 -356.63)" d="m293.58 299.25c4.5514 0.12881 9.3278 0.24858 13.379 0.77697 5.2851 0.68931 10.077 1.7034 14.201 3.0024s7.6027 2.8509 10.281 4.932 4.6532 4.9568 4.3302 8.2969-2.8562 6.2388-5.9368 8.3199-6.8597 3.633-11.235 4.932c-8.7499 2.598-19.953 4.0562-32.144 4.0562s-23.083-1.4582-31.33-4.0562c-4.1238-1.299-7.6317-2.8509-10.31-4.932s-4.6509-4.9799-4.328-8.3199 2.8539-6.2158 5.9346-8.2969 6.8887-3.633 11.264-4.932c6.6932-1.9873 14.805-3.3077 23.705-3.8187 2.7349-0.15701-1.2073-0.23758 1.6582-0.23758l0.0765 9.2646c-3.7487 0.11199-7.3905 0.29917-9.7411 0.60179-4.7649 0.61344-9.0159 1.4835-12.472 2.5098s-6.0905 2.2331-7.5611 3.2266-1.6214 1.4742-1.6415 1.6824 0.0354 0.71198 1.3139 1.7055 3.6792 2.2003 6.9372 3.2266c6.5161 2.0526 16.331 3.4801 27.355 3.4801s21.144-1.4275 28.057-3.4801c3.4565-1.0263 6.0905-2.2331 7.5612-3.2266s1.5946-1.4972 1.6147-1.7055-9e-3 -0.68892-1.2872-1.6824-3.6792-2.2002-6.9372-3.2266-7.348-1.8963-12.002-2.5098-5.0792-0.75252-10.591-0.75252z" fill="url(#a)" filter="url(#g)" opacity=".64751"/> + <path transform="matrix(1.8213 0 0 1.7505 -239.14 -356.63)" d="m317.86 382.77c0 3.7423-12.687 6.776-28.336 6.776s-28.336-3.0337-28.336-6.776 12.687-6.776 28.336-6.776 28.336 3.0337 28.336 6.776z" fill="#135f9b" opacity=".68199"/> + </g> +</svg> diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/changelog.rst b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/changelog.rst new file mode 100644 index 00000000..095fc83a --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/changelog.rst @@ -0,0 +1,6 @@ + +Changelog +========= + +.. include:: ../../CHANGES.rst + diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/conf.py b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/conf.py new file mode 100644 index 00000000..6ddb3785 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/conf.py @@ -0,0 +1,326 @@ +# -*- coding: utf-8 -*- +# +# PyASN1 documentation build configuration file, created by +# sphinx-quickstart on Sat Jun 27 23:15:54 2015. +# +# This file is execfile()d with the current directory set to its +# containing dir. +# +# Note that not all possible configuration values are present in this +# autogenerated file. +# +# All configuration values have a default; values that are commented out +# serve to show the default. + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +# sys.path.insert(0, os.path.abspath('.')) + +# -- General configuration ------------------------------------------------ + +# If your documentation needs a minimal Sphinx version, state it here. +# needs_sphinx = '1.0' + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. +extensions = [ + 'sphinx.ext.autodoc', + 'sphinx.ext.napoleon', + 'sphinx.ext.intersphinx', +] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['.templates'] + +# The suffix(es) of source filenames. +# You can specify multiple suffix as a list of string: +# source_suffix = ['.rst', '.md'] +source_suffix = '.rst' + +# The encoding of source files. +# source_encoding = 'utf-8-sig' + +# The master toctree document. +master_doc = 'contents' + +# General information about the project. +project = u'ASN.1 types and codecs' +copyright = u'2005-2019, Ilya Etingof <etingof@gmail.com>' +author = u'Ilya Etingof <etingof@gmail.com>' + +# The version info for the project you're documenting, acts as replacement for +# |version| and |release|, also used in various other places throughout the +# built documents. +# +# The short X.Y version. +version = '0.4' +# The full version, including alpha/beta/rc tags. +release = '0.4' + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +# +# This is also used if you do content translation via gettext catalogs. +# Usually you set "language" from the command line for these cases. +language = None + +# There are two options for replacing |today|: either, you set today to some +# non-false value, then it is used: +# today = '' +# Else, today_fmt is used as the format for a strftime call. +# today_fmt = '%B %d, %Y' + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +exclude_patterns = [] + +# The reST default role (used for this markup: `text`) to use for all +# documents. +# default_role = None + +# If true, '()' will be appended to :func: etc. cross-reference text. +# add_function_parentheses = True + +# If true, the current module name will be prepended to all description +# unit titles (such as .. function::). +# add_module_names = True + +# If true, sectionauthor and moduleauthor directives will be shown in the +# output. They are ignored by default. +# show_authors = False + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = 'sphinx' + +# A list of ignored prefixes for module index sorting. +# modindex_common_prefix = [] + +# If true, keep warnings as "system message" paragraphs in the built documents. +# keep_warnings = False + +# If true, `todo` and `todoList` produce output, else they produce nothing. +todo_include_todos = False + +# -- Options for HTML output ---------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +html_theme = 'alabaster' + +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +html_theme_options = { + 'logo': 'logo.svg', + 'description': '<p align=left><i><b>Brewing free software for the greater good</i></b></p>', + 'show_powered_by': False, + 'github_user': 'etingof', + 'github_repo': 'pyasn1', + 'fixed_sidebar': True, +} + +html_sidebars = { + '**': [ + 'about.html', + 'navigation.html', + 'relations.html', + 'searchbox.html', + 'donate.html', + ] +} + +# Add any paths that contain custom themes here, relative to this directory. +# html_theme_path = [] + +# The name for this set of Sphinx documents. If None, it defaults to +# "<project> v<release> documentation". +# html_title = None + +# A shorter title for the navigation bar. Default is the same as html_title. +# html_short_title = None + +# The name of an image file (relative to this directory) to place at the top +# of the sidebar. +# html_logo = "" + +# The name of an image file (within the static path) to use as favicon of the +# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 +# pixels large. +html_favicon = '.static/favicon.ico' + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['.static'] + +# Add any extra paths that contain custom files (such as robots.txt or +# .htaccess) here, relative to this directory. These files are copied +# directly to the root of the documentation. +# html_extra_path = [] + +# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, +# using the given strftime format. +# html_last_updated_fmt = '%b %d, %Y' + +# If true, SmartyPants will be used to convert quotes and dashes to +# typographically correct entities. +# html_use_smartypants = True + +# Custom sidebar templates, maps document names to template names. +# html_sidebars = {} + +# Additional templates that should be rendered to pages, maps page names to +# template names. +# html_additional_pages = {} + +# If false, no module index is generated. +# html_domain_indices = True + +# If false, no index is generated. +# html_use_index = True + +# If true, the index is split into individual pages for each letter. +# html_split_index = False + +# If true, links to the reST sources are added to the pages. +html_show_sourcelink = False + +# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. +html_show_sphinx = False + +# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. +# html_show_copyright = True + +# If true, an OpenSearch description file will be output, and all pages will +# contain a <link> tag referring to it. The value of this option must be the +# base URL from which the finished HTML is served. +# html_use_opensearch = '' + +# This is the file name suffix for HTML files (e.g. ".xhtml"). +# html_file_suffix = None + +# Language to be used for generating the HTML full-text search index. +# Sphinx supports the following languages: +# 'da', 'de', 'en', 'es', 'fi', 'fr', 'hu', 'it', 'ja' +# 'nl', 'no', 'pt', 'ro', 'ru', 'sv', 'tr' +# html_search_language = 'en' + +# A dictionary with options for the search language support, empty by default. +# Now only 'ja' uses this config value +# html_search_options = {'type': 'default'} + +# The name of a javascript file (relative to the configuration directory) that +# implements a search results scorer. If empty, the default will be used. +# html_search_scorer = 'scorer.js' + +# Output file base name for HTML help builder. +htmlhelp_basename = 'pyasn1doc' + +# html_context = { +# 'include_analytics': 'PYASN1DEV' in os.environ +# } + +# -- Options for LaTeX output --------------------------------------------- + +latex_elements = { + # The paper size ('letterpaper' or 'a4paper'). + # 'papersize': 'letterpaper', + + # The font size ('10pt', '11pt' or '12pt'). + # 'pointsize': '10pt', + + # Additional stuff for the LaTeX preamble. + # 'preamble': '', + + # Latex figure (float) alignment + # 'figure_align': 'htbp', +} + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, +# author, documentclass [howto, manual, or own class]). +latex_documents = [ + (master_doc, 'PyASN1.tex', u'PyASN1 Documentation', + u'Ilya Etingof \\textless{}etingof@gmail.com\\textgreater{}', 'manual'), +] + +# The name of an image file (relative to this directory) to place at the top of +# the title page. +# latex_logo = None + +# For "manual" documents, if this is true, then toplevel headings are parts, +# not chapters. +# latex_use_parts = False + +# If true, show page references after internal links. +# latex_show_pagerefs = False + +# If true, show URL addresses after external links. +# latex_show_urls = False + +# Documents to append as an appendix to all manuals. +# latex_appendices = [] + +# If false, no module index is generated. +# latex_domain_indices = True + + +# -- Options for manual page output --------------------------------------- + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). +man_pages = [ + (master_doc, 'pyasn1', u'PyASN1 Documentation', + [author], 1) +] + +# If true, show URL addresses after external links. +# man_show_urls = False + + +# -- Options for Texinfo output ------------------------------------------- + +# Grouping the document tree into Texinfo files. List of tuples +# (source start file, target name, title, author, +# dir menu entry, description, category) +texinfo_documents = [ + (master_doc, 'PyASN1', u'PyASN1 Documentation', + author, 'PyASN1', 'One line description of project.', + 'Miscellaneous'), +] + +# Documents to append as an appendix to all manuals. +# texinfo_appendices = [] + +# If false, no module index is generated. +# texinfo_domain_indices = True + +# How to display URL addresses: 'footnote', 'no', or 'inline'. +# texinfo_show_urls = 'footnote' + +# If true, do not generate a @detailmenu in the "Top" node's menu. +# texinfo_no_detailmenu = False + + +# Example configuration for intersphinx: refer to the Python standard library. +intersphinx_mapping = {'python': ('https://docs.python.org/3.4/', None)} + +# this merges constructor docstring with class docstring +autoclass_content = 'both' +# Sort members by type +autodoc_member_order = 'bysource' +# autodoc_member_order = 'groupwise' + +# Napoleon settings +napoleon_google_docstring = False +napoleon_numpy_docstring = True +napoleon_include_private_with_doc = False +napoleon_include_special_with_doc = True +napoleon_use_admonition_for_examples = False +napoleon_use_admonition_for_notes = False +napoleon_use_admonition_for_references = False +napoleon_use_ivar = False +napoleon_use_param = False +napoleon_use_rtype = False diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/contents.rst b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/contents.rst new file mode 100644 index 00000000..a2cd805a --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/contents.rst @@ -0,0 +1,161 @@ + +ASN.1 library for Python +======================== + +.. toctree:: + :maxdepth: 1 + +Abstract Syntax Notation One (`ASN.1 +<http://en.wikipedia.org/wiki/Abstract_Syntax_Notation_1x>`_) is a +technology for exchanging structured data in a universally understood, +hardware agnostic way. Many industrial, security and telephony +applications heavily rely on ASN.1. + +The `pyasn1 <https://pypi.org/project/pyasn1/>`_ library implements +ASN.1 support in pure-Python. + +What is ASN.1 +------------- + +ASN.1 is a large, arguably over-engineered and extremely old data modelling and +serialisation tool. It is probably among the first serialisation protocols in +the history of computer science and technology. + +ASN.1 started its life over 30 years ago as a serialisation mechanism for the first +electronic mail (known as X.400). Later on if was split off the e-mail application +and become a stand-alone tech still being actively supported by its designers +and widely used in industry and technology. + +Since then ASN.1 is sort of haunted by its relations with the OSI model -- the +first, unsuccessful, version of the Internet. You can read many interesting +`discussions <https://news.ycombinator.com/item?id=8871453>`_ on that topic. + +In the following years, generations of software engineers tackled the serialisation +problem many times. We can see that in Google's `ProtoBuffers <https://developers.google.com/protocol-buffers/>`_ +or `FlatBuffers <https://google.github.io/flatbuffers/>`_, for example. +Interestingly, many new takes on binary protocol design do not depart +far from ASN.1 from technical perspective. It's more of a matter of striking +a balance between processing overhead, wire format overhead and human +readability. + +Looking at what ASN.1 has to offer, it has three loosely coupled parts: + +* Data types: the standard introduces a collection of basic data types + (integers, bits, strings, arrays and records) that can be used for describing + arbitrarily complex, nested data structures. + +* Serialisation protocols: the above data structures could be converted into a + series of octets for storage or transmission over the wire as well as + recovered back into their structured form. The system is fully agnostic + to hardware architectures differences. + +* Schema language: ASN.1 data structures could be described in terms + of a schema language for ASN.1 compiler to turn it into platform-specific + implementation. + +ASN.1 applications +------------------ + +Being an old and generally successful standard, ASN.1 is widely +adopted for many uses. To give you an example, these technologies +use ASN.1 for their data exchange needs: + +* Signaling standards for the public switched telephone network (SS7 family) +* Network management standards (SNMP, CMIP) +* Directory standards (X.500 family, LDAP) +* Public Key Infrastructure standards (X.509, etc.) +* PBX control (CSTA) +* IP-based Videoconferencing (H.323 family) +* Biometrics (BIP, CBEFF, ACBio) +* Intelligent transportation (SAE J2735) +* Cellular telephony (GSM, GPRS/EDGE, UMTS, LTE) + +ASN.1 gotchas +------------- + +Apparently, ASN.1 is hard to implement properly. Quality open-source +ASN.1 tools are rare, but ad-hoc implementations are numerous. Judging from the +`statistics <http://cve.mitre.org/cgi-bin/cvekey.cgi?keyword=ASN.1>`_ on discovered +security vulnerabilities, many people have implemented ASN.1 parsers +and oftentimes fell victim to its edge cases. + +On the bright side, ASN.1 has been around for a long time, it is well understood +and security reviewed. + +Documentation +------------- + +.. toctree:: + :maxdepth: 2 + + /pyasn1/contents + +Use case +-------- + +.. toctree:: + :maxdepth: 2 + + /example-use-case + +Download & Install +------------------ + +.. toctree:: + :maxdepth: 2 + + /download + +Changes +------- + +All changes and release history is maintained in changelog. There you +could also download the latest unreleased pyasn1 tarball containing +the latest fixes and improvements. + +.. toctree:: + :maxdepth: 1 + + /changelog + +License +------- + +The PyASN1 software is distributed under 2-clause BSD License. + +.. toctree:: + :maxdepth: 2 + + /license + +Getting help +------------ + +Please, file your `issues <https://github.com/etingof/pyasn1/issues>`_ +and `PRs <https://github.com/etingof/pyasn1/pulls>`_ at GitHub. +Alternatively, you could ask for help at +`Stack Overflow <http://stackoverflow.com/questions/tagged/pyasn1>`_ +or search +`pyasn1-users <https://lists.sourceforge.net/lists/listinfo/pyasn1-users>`_ +mailing list archive. + +Books on ASN.1 +-------------- + +The pyasn1 implementation is largely based on reading up the following awesome +books: + +* `ASN.1 - Communication between heterogeneous systems <http://www.oss.com/asn1/dubuisson.html>`_ by Olivier Dubuisson +* `ASN.1 Complete <http://www.oss.com/asn1/resources/books-whitepapers-pubs/larmouth-asn1-book.pdf>`_ by Prof John Larmouth + +Here you can get the official standards which is hard to read: + +* `ITU standards <http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-X.693-0207w.zip>`_ + +On the other end of the readability spectrum, here is a quick and sweet write up: + +* `A Layman's Guide to a Subset of ASN.1, BER, and DER <ftp://ftp.rsasecurity.com/pub/pkcs/ascii/layman.asc>`_ by Burton S. Kaliski + +If you are working with ASN.1, we'd highly recommend reading a proper +book on the subject. + diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/download.rst b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/download.rst new file mode 100644 index 00000000..bbbd66c0 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/download.rst @@ -0,0 +1,27 @@ + +Download & Install +================== + +The *pyasn1* library is a pure-Python package with no external +dependencies. Considering how much industrial or finance software +can be stuck with an old platform (think RHEL 5), we struggle to +maintain its compatibility back to the very pre-historic Python +(which is 2.4!). + +The best way to obtain PyASN1 is by running `pip`: + +.. code-block:: bash + + $ virtualenv venv + $ source venv/bin/activate + $ pip install pyasn1 + +You may also want to use `pyasn1-modules`: + +.. code-block:: bash + + $ pip install pyasn1-modules + +Alternatively, you can download the latest release from +`GitHub <https://github.com/etingof/pyasn1/releases>`_ +or `PyPI <https://pypi.org/project/pyasn1>`_. diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/example-use-case.rst b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/example-use-case.rst new file mode 100644 index 00000000..5e0a7c50 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/example-use-case.rst @@ -0,0 +1,193 @@ + +Example use case +================ + +.. toctree:: + :maxdepth: 2 + +To briefly explain how to approach pyasn1, consider a quick workflow example. + +Grab ASN.1 schema for SSH keys +------------------------------ + +ASN.1 is widely used in many Internet protocols. Frequently, whenever ASN.1 is employed, +data structures are described in ASN.1 schema language right in the RFC. +Take `RFC2437 <https://www.ietf.org/rfc/rfc2437.txt>`_ for example -- we can look into +it and weed out data structures specification into a local file: + +.. code-block:: python + + # pkcs-1.asn + + PKCS-1 {iso(1) member(2) us(840) rsadsi(113549) pkcs(1) pkcs-1(1) modules(0) pkcs-1(1)} + + DEFINITIONS EXPLICIT TAGS ::= BEGIN + RSAPrivateKey ::= SEQUENCE { + version Version, + modulus INTEGER, + publicExponent INTEGER, + privateExponent INTEGER, + prime1 INTEGER, + prime2 INTEGER, + exponent1 INTEGER, + exponent2 INTEGER, + coefficient INTEGER + } + Version ::= INTEGER + END + +Compile ASN.1 schema into Python +-------------------------------- + +In the best case, you should be able to automatically compile ASN.1 spec into +Python classes. For that purpose we have the `asn1ate <https://github.com/kimgr/asn1ate>`_ +tool: + +.. code-block:: bash + + $ asn1ate pkcs-1.asn > rsakey.py + +Though it may not work out as, as it stands now, asn1ate does not support +all ASN.1 language constructs. + +Alternatively, you could check out the `pyasn1-modules <https://github.com/etingof/pyasn1-modules>`_ +package to see if it already has the ASN.1 spec you are looking for compiled and shipped +there. Then just install the package, import the data structure you need and use it: + +.. code-block:: bash + + $ pip install pyasn1-modules + +As a last resort, you could express ASN.1 in Python by hand. The end result +should be a declarative Python code resembling original ASN.1 syntax like +this: + +.. code-block:: python + + # rsakey.py + + class Version(Integer): + pass + + class RSAPrivateKey(Sequence): + componentType = NamedTypes( + NamedType('version', Version()), + NamedType('modulus', Integer()), + NamedType('publicExponent', Integer()), + NamedType('privateExponent', Integer()), + NamedType('prime1', Integer()), + NamedType('prime2', Integer()), + NamedType('exponent1', Integer()), + NamedType('exponent2', Integer()), + NamedType('coefficient', Integer()) + ) + +Read your ~/.ssh/id_rsa +----------------------- + +Given we've put our Python classes into the `rsakey.py` module, we could import +the top-level object for SSH keys container and initialize it from our +`~/.ssh/id_rsa` file (for sake of simplicity here we assume no passphrase is +set on the key file): + +.. code-block:: python + + from base64 import b64decode + from pyasn1.codec.der.decoder import decode as der_decoder + from rsakey import RSAPrivateKey + + # Read SSH key from file (assuming no passphrase) + with open('.ssh/id_rsa') as key_file: + b64_serialisation = ''.join(key_file.readlines()[1:-1]) + + # Undo BASE64 serialisation + der_serialisation = b64decode(b64_serialisation) + + # Undo DER serialisation, reconstruct SSH key structure + private_key, rest_of_input = der_decoder(der_serialisation, asn1Spec=RSAPrivateKey()) + +Once we have Python ASN.1 structures initialized, we could inspect them: + +.. code-block:: pycon + + >>> print('%s' % private_key) + RSAPrivateKey: + version=0 + modulus=280789907761334970323210643584308373... + publicExponent=65537 + privateExponent=1704567874679144879123080924... + prime1=1780178536719561265324798296279384073... + prime2=1577313184995269616049017780493740138... + exponent1=1193974819720845247396384239609024... + exponent2=9240965721817961178848297404494811... + coefficient=10207364473358910343346707141115... + +Play with the keys +------------------ + +As well as use them nearly as we do with native Python types: + +.. code-block:: pycon + + >>> pk = private_key + >>> + >>> pk['prime1'] * pk['prime2'] == pk['modulus'] + True + >>> pk['prime1'] == pk['modulus'] // pk['prime2'] + True + >>> pk['exponent1'] == pk['privateExponent'] % (pk['prime1'] - 1) + True + >>> pk['exponent2'] == pk['privateExponent'] % (pk['prime2'] - 1) + True + +Technically, pyasn1 classes `emulate <https://docs.python.org/3/reference/datamodel.html#emulating-container-types>`_ +Python built-in types. + +Transform to built-ins +---------------------- + +ASN.1 data structures exhibit a way more complicated behaviour compared to +Python types. You may wish to simplify things by turning the whole tree of +pyasn1 objects into an analogous tree made of base Python types: + +.. code-block:: pycon + + >>> from pyasn1.codec.native.encoder import encode + >>> ... + >>> py_private_key = encode(private_key) + >>> py_private_key + {'version': 0, 'modulus': 280789907761334970323210643584308373, 'publicExponent': 65537, + 'privateExponent': 1704567874679144879123080924, 'prime1': 1780178536719561265324798296279384073, + 'prime2': 1577313184995269616049017780493740138, 'exponent1': 1193974819720845247396384239609024, + 'exponent2': 9240965721817961178848297404494811, 'coefficient': 10207364473358910343346707141115} + +You can do vice-versa: initialize ASN.1 structure from a dict: + +.. code-block:: pycon + + >>> from pyasn1.codec.native.decoder import decode + >>> py_private_key = {'modulus': 280789907761334970323210643584308373} + >>> private_key = decode(py_private_key, asn1Spec=RSAPrivateKey()) + +Write it back +------------- + +Possibly not that applicable to the SSH key example, but you can of course modify +any part of the ASN.1 data structure and serialise it back into the same or other +wire representation: + +.. code-block:: python + + from pyasn1.codec.der.encoder import encode as der_encoder + + # Serialise SSH key data structure into DER stream + der_serialisation = der_encoder(private_key) + + # Serialise DER stream into BASE64 stream + b64_serialisation = '-----BEGIN RSA PRIVATE KEY-----\n' + b64_serialisation += b64encode(der_serialisation) + b64_serialisation += '-----END RSA PRIVATE KEY-----\n' + + with open('.ssh/id_rsa.new', 'w') as key_file: + key_file.write(b64_serialisation) + diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/license.rst b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/license.rst new file mode 100644 index 00000000..643baf10 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/license.rst @@ -0,0 +1,6 @@ +.. _license: + +License +======= + +.. include:: ../../LICENSE.rst diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/codec/ber/contents.rst b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/codec/ber/contents.rst new file mode 100644 index 00000000..c7676256 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/codec/ber/contents.rst @@ -0,0 +1,7 @@ + +Basic Encoding Rules +-------------------- + +.. autofunction:: pyasn1.codec.ber.encoder.encode(value, asn1Spec=None, defMode=True, maxChunkSize=0) + +.. autofunction:: pyasn1.codec.ber.decoder.decode(substrate, asn1Spec=None) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/codec/cer/contents.rst b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/codec/cer/contents.rst new file mode 100644 index 00000000..8eec8420 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/codec/cer/contents.rst @@ -0,0 +1,7 @@ + +Canonical Encoding Rules +------------------------ + +.. autofunction:: pyasn1.codec.cer.encoder.encode(value, asn1Spec=None) + +.. autofunction:: pyasn1.codec.cer.decoder.decode(substrate, asn1Spec=None) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/codec/der/contents.rst b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/codec/der/contents.rst new file mode 100644 index 00000000..27ef4011 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/codec/der/contents.rst @@ -0,0 +1,7 @@ + +Distinguished Encoding Rules +---------------------------- + +.. autofunction:: pyasn1.codec.der.encoder.encode(value, asn1Spec=None) + +.. autofunction:: pyasn1.codec.der.decoder.decode(substrate, asn1Spec=None) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/codec/native/contents.rst b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/codec/native/contents.rst new file mode 100644 index 00000000..11e96f00 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/codec/native/contents.rst @@ -0,0 +1,7 @@ + +Native Python types +------------------- + +.. autofunction:: pyasn1.codec.native.encoder.encode(asn1Value) + +.. autofunction:: pyasn1.codec.native.decoder.decode(pyObject, asn1Spec) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/contents.rst b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/contents.rst new file mode 100644 index 00000000..eaa78358 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/contents.rst @@ -0,0 +1,228 @@ + +.. _pyasn1: + +Library documentation +===================== + +As of this moment, pyasn1 library implements all ASN.1 data +types as Python objects in accordance with X.208 standard. Later, +post-1995, revision (X.680) introduced some changes to the schema +language which may not be fully supported by pyasn1. Aside from data +types a collection of data transformation codecs comes with the +pyasn1 package. + +As for ASN.1 schema language, pyasn1 package does +not ship any compiler for it. However, there's a tool called +`asn1late <https://github.com/kimgr/asn1ate>`_ which is an ASN.1 +grammar parser paired to code generator capable of generating pyasn1 +code. So this is an alternative (or at least a good start) to manual +implementation of pyasn1 classes from ASN.1 specification. + +Both `pyasn1 <https://github.com/etingof/pyasn1>`_ and +`pyasn1-modules <https://github.com/etingof/pyasn1-modules>`_ libraries +can be used out-of-the-box with Python versions 2.4 through 3.7. +No external dependencies required. + +.. _pyasn1-types: + +ASN.1 types +----------- + +The ASN.1 data description +`language <https://www.itu.int/rec/dologin_pub.asp?lang=e&id=T-REC-X.208-198811-W!!PDF-E&type=items>`_ +defines a handful of built-in data types. ASN.1 types exhibit different +semantics (e.g. number vs string) and can be distinguished from each other by +:ref:`tags <type.tag>`. + +Subtypes can be created on top of base ASN.1 types by adding/overriding the +:ref:`tags <type.tag>` and/or imposing additional +:ref:`constraints <type.constraint>` on accepted values. + +ASN.1 types in pyasn1 are Python objects. One or more ASN.1 types +comprise a *schema* describing data structures of unbounded complexity. + +.. code-block:: python + + class RSAPublicKey(Sequence): + """ + ASN.1 specification: + + RSAPublicKey ::= SEQUENCE { + modulus INTEGER, -- n + publicExponent INTEGER -- e + } + """ + componentType = NamedTypes( + NamedType('modulus', Integer()), + NamedType('publicExponent', Integer()) + ) + +ASN.1 schema can be "instantiated" by essentially putting some concrete value +into the type container. Such instantiated schema object can still be +used as a schema, but additionally it can play a role of a value in the +context of any applicable operator (e.g. arithmetic etc.). + +.. code-block:: python + + rsaPublicKey = RSAPublicKey() + + # ASN.1 SEQUENCE type quacks like Python dict + rsaPublicKey['modulus'] = 280789907761334970323210643584308373 + rsaPublicKey['publicExponent'] = 65537 + +Main use of ASN.1 schemas is to guide data transformation. Instantiated +ASN.1 schemas carry concrete data to/from data transformation services. + +.. _isValue: + +To tell instantiated schema object from just a schema, the *.isValue* +property can come in handy: + +.. code-block:: python + + schema = RSAPublicKey() + + # non-instantiated schema + assert schema.isValue == False + + rsaPublicKey['modulus'] = 280789907761334970323210643584308373 + + # partially instantiated schema + assert schema['modulus'].isValue == True + assert schema.isValue == False + + rsaPublicKey['publicExponent'] = 65537 + + # fully instantiated schema + assert schema.isValue == True + +Copies of existing ASN.1 types can be created with *.clone()* method. +All the existing properties of the prototype ASN.1 object get copied +over the new type unless the replacements are given. Main use-case +for *.clone()* is to instantiate a schema. + +.. _clone: + +.. code-block:: python + + instantiated_schema_A = Integer(1) + + # ASN.1 INTEGER type quacks like Python int + assert instantiated_schema_A == 1 + + instantiated_schema_B = instantiated_schema_A.clone(2) + + assert instantiated_schema_B == 2 + +.. _subtype: + +New ASN.1 types can be created on top of existing ASN.1 types with +the *subtype()* method. Desired properties of the new type get +merged with the corresponding properties of the old type. Main use-case +for *.subtype()* is to assemble new ASN.1 types by :ref:`tagging <type.tag>` +or applying additional :ref:`constraints <type.constraint>` to accepted +type's values. + +.. code-block:: python + + parent_type_schema = Integer() + + child_type_schema = parent_type_schema.subtype( + explicitTag=Tag(tag.tagClassApplication, tag.tagFormatSimple, 0x06) + ) + + # test ASN.1 type relationships + assert child_type_schema.isSubtypeOf(parent_type_schema) == True + assert child_type_schema.isSameTypeWith(parent_type_schema) == False + + +.. toctree:: + :maxdepth: 2 + + /pyasn1/type/base/contents + /pyasn1/type/univ/contents + /pyasn1/type/char/contents + /pyasn1/type/useful/contents + +ASN.1 type harness +++++++++++++++++++ + +The identification and behaviour of ASN.1 types is determined by +:ref:`tags <type.tag>` and :ref:`constraints <type.constraint>`. +The inner structure of *constructed* ASN.1 types is defined by +its :ref:`fields <type.namedtype>` specification. + +.. toctree:: + :maxdepth: 2 + + /pyasn1/type/tag/contents + /pyasn1/type/constraint/contents + /pyasn1/type/namedtype/contents + /pyasn1/type/opentype/contents + /pyasn1/type/namedval/contents + +.. _pyasn1-codecs: + +Serialisation codecs +-------------------- + +Common use-case for pyasn1 is to instantiate ASN.1 schema with +user-supplied values and pass instantiated schema to the encoder. +The encoder will then turn the data structure into serialised form +(stream of bytes) suitable for storing into a file or sending over +the network. + +.. code-block:: python + + value = 1 + instantiated_schema = Integer(value) + + serialised = encode(instantiated_schema) + +Alternatively, value and schema can be passed separately: + +.. code-block:: python + + value = 1 + schema = Integer() + + serialised = encode(value, asn1Spec=schema) + +At the receiving end, a decoder would be invoked and given the +serialised data as received from the network along with the ASN.1 +schema describing the layout of the data structures. The outcome +would be an instance of ASN.1 schema filled with values as supplied +by the sender. + +.. code-block:: python + + serialised = b'\x01\x01\x01' + schema = Integer() + + value, _ = decode(serialised, asn1Spec=schema) + + assert value == 1 + +Many distinct serialisation protocols exist for ASN.1, some are +implemented in pyasn1. + +.. toctree:: + :maxdepth: 2 + + /pyasn1/codec/ber/contents + /pyasn1/codec/cer/contents + /pyasn1/codec/der/contents + /pyasn1/codec/native/contents + +Exceptions +---------- + +Operations on PyASN1 schema and value objects might cause errors. These +errors are manifested to the caller in form of Python exceptions. + +The exception hierarchy is as follows (ordered from least specific). + +.. toctree:: + :maxdepth: 2 + + /pyasn1/error/contents diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/error/contents.rst b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/error/contents.rst new file mode 100644 index 00000000..be8a04c6 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/error/contents.rst @@ -0,0 +1,60 @@ + +.. _error.PyAsn1Error: + +.. |PyAsn1Error| replace:: PyAsn1Error + +|PyAsn1Error| +------------- + +.. autoclass:: pyasn1.error.PyAsn1Error + :members: + +.. _error.ValueConstraintError: + +.. |ValueConstraintError| replace:: ValueConstraintError + +|ValueConstraintError| +---------------------- + +.. autoclass:: pyasn1.error.ValueConstraintError + :members: + +.. _error.SubstrateUnderrunError: + +.. |SubstrateUnderrunError| replace:: SubstrateUnderrunError + +|SubstrateUnderrunError| +------------------------ + +.. autoclass:: pyasn1.error.SubstrateUnderrunError + :members: + +.. _error.PyAsn1UnicodeError: + +.. |PyAsn1UnicodeError| replace:: PyAsn1UnicodeError + +|PyAsn1UnicodeError| +-------------------- + +.. autoclass:: pyasn1.error.PyAsn1UnicodeError + :members: + +.. _error.PyAsn1UnicodeDecodeError: + +.. |PyAsn1UnicodeDecodeError| replace:: PyAsn1UnicodeDecodeError + +|PyAsn1UnicodeDecodeError| +-------------------------- + +.. autoclass:: pyasn1.error.PyAsn1UnicodeDecodeError + :members: + +.. _error.PyAsn1UnicodeEncodeError: + +.. |PyAsn1UnicodeEncodeError| replace:: PyAsn1UnicodeEncodeError + +|PyAsn1UnicodeEncodeError| +-------------------------- + +.. autoclass:: pyasn1.error.PyAsn1UnicodeEncodeError + :members: diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/base/asn1type.rst b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/base/asn1type.rst new file mode 100644 index 00000000..94fe04d5 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/base/asn1type.rst @@ -0,0 +1,10 @@ + +.. _base.Asn1Type: + +.. |ASN.1| replace:: Asn1Type + +|ASN.1| type +------------ + +.. autoclass:: pyasn1.type.base.Asn1Type(tagSet=TagSet(), subtypeSpec=ConstraintsIntersection()) + :members: isSameTypeWith, isSuperTypeOf, tagSet, effectiveTagSet, tagMap, subtypeSpec diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/base/constructedasn1type.rst b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/base/constructedasn1type.rst new file mode 100644 index 00000000..87090669 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/base/constructedasn1type.rst @@ -0,0 +1,10 @@ + +.. _base.ConstructedAsn1Type: + +.. |ASN.1| replace:: ConstructedAsn1Type + +|ASN.1| type +------------ + +.. autoclass:: pyasn1.type.base.ConstructedAsn1Type(tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), componentType=None) + :members: isSameTypeWith, isSuperTypeOf, tagSet, effectiveTagSet, tagMap, subtypeSpec diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/base/contents.rst b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/base/contents.rst new file mode 100644 index 00000000..ffb325c9 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/base/contents.rst @@ -0,0 +1,20 @@ + +.. _type.base: + +ASN.1 type system +----------------- + +The ASN.1 language defines a collection of data types such as *INTEGER* +or *SET*. With pyasn1, ASN.1 types are represented by Python classes. +The base classes are described in this part of the documentation. + +User code might not need to use them directly, except for figuring out +if given object belongs to ASN.1 type or not. + +.. toctree:: + :maxdepth: 2 + + /pyasn1/type/base/asn1type + /pyasn1/type/base/simpleasn1type + /pyasn1/type/base/constructedasn1type + /pyasn1/type/base/novalue diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/base/novalue.rst b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/base/novalue.rst new file mode 100644 index 00000000..6e347926 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/base/novalue.rst @@ -0,0 +1,6 @@ +.. _type.base.NoValue: + +NoValue sentinel +---------------- + +.. autoclass:: pyasn1.type.base.NoValue() diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/base/simpleasn1type.rst b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/base/simpleasn1type.rst new file mode 100644 index 00000000..03a960df --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/base/simpleasn1type.rst @@ -0,0 +1,10 @@ + +.. _base.SimpleAsn1Type: + +.. |ASN.1| replace:: SimpleAsn1Type + +|ASN.1| type +------------ + +.. autoclass:: pyasn1.type.base.SimpleAsn1Type(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection()) + :members: isValue, isSameTypeWith, isSuperTypeOf, tagSet, effectiveTagSet, tagMap, subtypeSpec diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/char/bmpstring.rst b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/char/bmpstring.rst new file mode 100644 index 00000000..066d03ae --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/char/bmpstring.rst @@ -0,0 +1,19 @@ + +.. _char.BMPString: + +.. |ASN.1| replace:: BMPString + +.. |encoding| replace:: utf-16-be + +|ASN.1| type +------------ + +.. autoclass:: pyasn1.type.char.BMPString(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), encoding='us-ascii') + :members: isValue, isSameTypeWith, isSuperTypeOf, tagSet, effectiveTagSet, tagMap + + .. note:: + + The |ASN.1| type models a Unicode (ISO10646-1) character string implicitly serialised into UTF-16 big endian. + + .. automethod:: pyasn1.type.char.BMPString.clone(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), encoding='us-ascii') + .. automethod:: pyasn1.type.char.BMPString.subtype(value=NoValue(), implicitTag=Tag(), explicitTag=Tag(),subtypeSpec=ConstraintsIntersection(), encoding='us-ascii') diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/char/contents.rst b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/char/contents.rst new file mode 100644 index 00000000..e73c9599 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/char/contents.rst @@ -0,0 +1,30 @@ + +.. _type.char: + +Character types +--------------- + +Besides :ref:`universal types <type.univ>` also defines a collection +of text types. Most of these types come from the past trying to capture +the fragments of long-forgotten technologies. + +These *character* types are all scalars. They are similar to +:ref:`OctetString <univ.OctetString>` except that they all operate on +text, not bytes. + +.. toctree:: + :maxdepth: 2 + + /pyasn1/type/char/numericstring + /pyasn1/type/char/printablestring + /pyasn1/type/char/teletexstring + /pyasn1/type/char/t61string + /pyasn1/type/char/videotexstring + /pyasn1/type/char/ia5string + /pyasn1/type/char/graphicstring + /pyasn1/type/char/visiblestring + /pyasn1/type/char/iso646string + /pyasn1/type/char/generalstring + /pyasn1/type/char/universalstring + /pyasn1/type/char/bmpstring + /pyasn1/type/char/utf8string diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/char/generalstring.rst b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/char/generalstring.rst new file mode 100644 index 00000000..722c0620 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/char/generalstring.rst @@ -0,0 +1,20 @@ + +.. _char.GeneralString: + +.. |ASN.1| replace:: GeneralString + +.. |encoding| replace:: iso-8859-1 + +|ASN.1| type +------------ + +.. autoclass:: pyasn1.type.char.GeneralString(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), encoding='us-ascii') + :members: isValue, isSameTypeWith, isSuperTypeOf, tagSet, effectiveTagSet, tagMap + + .. note:: + + The |ASN.1| type models a character string similar to :py:class:`GraphicString` but additionally + including control characters. + + .. automethod:: pyasn1.type.char.GeneralString.clone(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), encoding='us-ascii') + .. automethod:: pyasn1.type.char.GeneralString.subtype(value=NoValue(), implicitTag=Tag(), explicitTag=Tag(),subtypeSpec=ConstraintsIntersection(), encoding='us-ascii') diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/char/graphicstring.rst b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/char/graphicstring.rst new file mode 100644 index 00000000..9a35a2a4 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/char/graphicstring.rst @@ -0,0 +1,20 @@ + +.. _char.GraphicString: + +.. |ASN.1| replace:: GraphicString + +.. |encoding| replace:: iso-8859-1 + +|ASN.1| type +------------ + +.. autoclass:: pyasn1.type.char.GraphicString(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), encoding='us-ascii') + :members: isValue, isSameTypeWith, isSuperTypeOf, tagSet, effectiveTagSet, tagMap + + .. note:: + + The |ASN.1| type models a character string that can hold any "graphical" characters + mixed with control ones to select particular alphabet. + + .. automethod:: pyasn1.type.char.GraphicString.clone(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), encoding='us-ascii') + .. automethod:: pyasn1.type.char.GraphicString.subtype(value=NoValue(), implicitTag=Tag(), explicitTag=Tag(),subtypeSpec=ConstraintsIntersection(), encoding='us-ascii') diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/char/ia5string.rst b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/char/ia5string.rst new file mode 100644 index 00000000..6d057d88 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/char/ia5string.rst @@ -0,0 +1,19 @@ + +.. _char.IA5String: + +.. |ASN.1| replace:: IA5String + +.. |encoding| replace:: us-ascii + +|ASN.1| type +------------ + +.. autoclass:: pyasn1.type.char.IA5String(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), encoding='us-ascii') + :members: isValue, isSameTypeWith, isSuperTypeOf, tagSet, effectiveTagSet, tagMap + + .. note:: + + The |ASN.1| type models a basic character string first published in 1963 as an ISO/ITU standard, then it turned into ASCII. + + .. automethod:: pyasn1.type.char.IA5String.clone(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), encoding='us-ascii') + .. automethod:: pyasn1.type.char.IA5String.subtype(value=NoValue(), implicitTag=Tag(), explicitTag=Tag(),subtypeSpec=ConstraintsIntersection(), encoding='us-ascii') diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/char/iso646string.rst b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/char/iso646string.rst new file mode 100644 index 00000000..3607616b --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/char/iso646string.rst @@ -0,0 +1,19 @@ + +.. _char.ISO646String: + +.. |ASN.1| replace:: ISO646String + +.. |encoding| replace:: us-ascii + +|ASN.1| type +------------ + +.. autoclass:: pyasn1.type.char.ISO646String(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), encoding='us-ascii') + :members: isValue, isSameTypeWith, isSuperTypeOf, tagSet, effectiveTagSet, tagMap + + .. note:: + + The |ASN.1| type is an alias to the :py:class:`VisibleString` type + + .. automethod:: pyasn1.type.char.ISO646String.clone(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), encoding='us-ascii') + .. automethod:: pyasn1.type.char.ISO646String.subtype(value=NoValue(), implicitTag=Tag(), explicitTag=Tag(),subtypeSpec=ConstraintsIntersection(), encoding='us-ascii') diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/char/numericstring.rst b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/char/numericstring.rst new file mode 100644 index 00000000..2f3cfb4b --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/char/numericstring.rst @@ -0,0 +1,19 @@ + +.. _char.NumericString: + +.. |ASN.1| replace:: NumericString + +.. |encoding| replace:: us-ascii + +|ASN.1| type +------------ + +.. autoclass:: pyasn1.type.char.NumericString(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), encoding='us-ascii') + :members: isValue, isSameTypeWith, isSuperTypeOf, tagSet, effectiveTagSet, tagMap + + .. note:: + + The |ASN.1| models character string that can be entered from a telephone handset. + + .. automethod:: pyasn1.type.char.NumericString.clone(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), encoding='us-ascii') + .. automethod:: pyasn1.type.char.NumericString.subtype(value=NoValue(), implicitTag=Tag(), explicitTag=Tag(),subtypeSpec=ConstraintsIntersection(), encoding='us-ascii') diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/char/printablestring.rst b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/char/printablestring.rst new file mode 100644 index 00000000..645c0a18 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/char/printablestring.rst @@ -0,0 +1,20 @@ + +.. _char.PrintableString: + +.. |ASN.1| replace:: PrintableString + +.. |encoding| replace:: us-ascii + +|ASN.1| type +------------ + +.. autoclass:: pyasn1.type.char.PrintableString(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), encoding='us-ascii') + :members: isValue, isSameTypeWith, isSuperTypeOf, tagSet, effectiveTagSet, tagMap + + .. note:: + + The |ASN.1| models character string that can be entered from a very rudimentary terminals featuring letters, + digits and punctuation marks. + + .. automethod:: pyasn1.type.char.PrintableString.clone(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), encoding='us-ascii') + .. automethod:: pyasn1.type.char.PrintableString.subtype(value=NoValue(), implicitTag=Tag(), explicitTag=Tag(),subtypeSpec=ConstraintsIntersection(), encoding='us-ascii') diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/char/t61string.rst b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/char/t61string.rst new file mode 100644 index 00000000..11bf3845 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/char/t61string.rst @@ -0,0 +1,19 @@ + +.. _char.T61String: + +.. |ASN.1| replace:: T61String + +.. |encoding| replace:: iso-8859-1 + +|ASN.1| type +------------ + +.. autoclass:: pyasn1.type.char.T61String(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), encoding='us-ascii') + :members: isValue, isSameTypeWith, isSuperTypeOf, tagSet, effectiveTagSet, tagMap + + .. note:: + + The |ASN.1| type is an alias to :py:class:`TeletexString` type. + + .. automethod:: pyasn1.type.char.T61String.clone(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), encoding='us-ascii') + .. automethod:: pyasn1.type.char.T61String.subtype(value=NoValue(), implicitTag=Tag(), explicitTag=Tag(),subtypeSpec=ConstraintsIntersection(), encoding='us-ascii') diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/char/teletexstring.rst b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/char/teletexstring.rst new file mode 100644 index 00000000..f025d760 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/char/teletexstring.rst @@ -0,0 +1,21 @@ + +.. _char.TeletexString: + +.. |ASN.1| replace:: TeletexString + +.. |encoding| replace:: iso-8859-1 + +|ASN.1| type +------------ + +.. autoclass:: pyasn1.type.char.TeletexString(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), encoding='us-ascii') + :members: isValue, isSameTypeWith, isSuperTypeOf, tagSet, effectiveTagSet, tagMap + + .. note:: + + The |ASN.1| type models character string that can be entered from a sophisticated text processing machines + (by 20-th century standards) featuring letters from multiple alphabets (308 characters!), digits, + punctuation marks and escape sequences. + + .. automethod:: pyasn1.type.char.TeletexString.clone(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), encoding='us-ascii') + .. automethod:: pyasn1.type.char.TeletexString.subtype(value=NoValue(), implicitTag=Tag(), explicitTag=Tag(),subtypeSpec=ConstraintsIntersection(), encoding='us-ascii') diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/char/universalstring.rst b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/char/universalstring.rst new file mode 100644 index 00000000..3c947b86 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/char/universalstring.rst @@ -0,0 +1,19 @@ + +.. _char.UniversalString: + +.. |ASN.1| replace:: UniversalString + +.. |encoding| replace:: utf-32-be + +|ASN.1| type +------------ + +.. autoclass:: pyasn1.type.char.UniversalString(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), encoding='us-ascii') + :members: isValue, isSameTypeWith, isSuperTypeOf, tagSet, effectiveTagSet, tagMap + + .. note:: + + The |ASN.1| type models a Unicode (ISO10646-1) character string implicitly serialised into UTF-32 big endian. + + .. automethod:: pyasn1.type.char.UniversalString.clone(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), encoding='us-ascii') + .. automethod:: pyasn1.type.char.UniversalString.subtype(value=NoValue(), implicitTag=Tag(), explicitTag=Tag(),subtypeSpec=ConstraintsIntersection(), encoding='us-ascii') diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/char/utf8string.rst b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/char/utf8string.rst new file mode 100644 index 00000000..cf3a80fb --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/char/utf8string.rst @@ -0,0 +1,19 @@ + +.. _char.UTF8String: + +.. |ASN.1| replace:: UTF8String + +.. |encoding| replace:: utf-8 + +|ASN.1| type +------------ + +.. autoclass:: pyasn1.type.char.UTF8String(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), encoding='us-ascii') + :members: isValue, isSameTypeWith, isSuperTypeOf, tagSet, effectiveTagSet, tagMap + + .. note:: + + The |ASN.1| type models a Unicode (ISO10646-1) character string implicitly serialised into UTF-8. + + .. automethod:: pyasn1.type.char.UTF8String.clone(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), encoding='us-ascii') + .. automethod:: pyasn1.type.char.UTF8String.subtype(value=NoValue(), implicitTag=Tag(), explicitTag=Tag(),subtypeSpec=ConstraintsIntersection(), encoding='us-ascii') diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/char/videotexstring.rst b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/char/videotexstring.rst new file mode 100644 index 00000000..27ddf808 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/char/videotexstring.rst @@ -0,0 +1,20 @@ + +.. _char.VideotexString: + +.. |ASN.1| replace:: VideotexString + +.. |encoding| replace:: iso-8859-1 + +|ASN.1| type +------------ + +.. autoclass:: pyasn1.type.char.VideotexString(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), encoding='us-ascii') + :members: isValue, isSameTypeWith, isSuperTypeOf, tagSet, effectiveTagSet, tagMap + + .. note:: + + The |ASN.1| type models character string that can be consumed by sophisticated video + terminals (by 20-th century standards) to render ascii-art style pictures and animations. + + .. automethod:: pyasn1.type.char.VideotexString.clone(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), encoding='us-ascii') + .. automethod:: pyasn1.type.char.VideotexString.subtype(value=NoValue(), implicitTag=Tag(), explicitTag=Tag(),subtypeSpec=ConstraintsIntersection(), encoding='us-ascii') diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/char/visiblestring.rst b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/char/visiblestring.rst new file mode 100644 index 00000000..778720ae --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/char/visiblestring.rst @@ -0,0 +1,20 @@ + +.. _char.VisibleString: + +.. |ASN.1| replace:: VisibleString + +.. |encoding| replace:: us-ascii + +|ASN.1| type +------------ + +.. autoclass:: pyasn1.type.char.VisibleString(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), encoding='us-ascii') + :members: isValue, isSameTypeWith, isSuperTypeOf, tagSet, effectiveTagSet, tagMap + + .. note:: + + The |ASN.1| type models a character string that can hold any "graphical" characters + mixed with control ones to select particular alphabet. + + .. automethod:: pyasn1.type.char.VisibleString.clone(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), encoding='us-ascii') + .. automethod:: pyasn1.type.char.VisibleString.subtype(value=NoValue(), implicitTag=Tag(), explicitTag=Tag(),subtypeSpec=ConstraintsIntersection(), encoding='us-ascii') diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/constraint/constraintsexclusion.rst b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/constraint/constraintsexclusion.rst new file mode 100644 index 00000000..ad5cf8af --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/constraint/constraintsexclusion.rst @@ -0,0 +1,10 @@ + +.. _constrain.ConstraintsExclusion: + +.. |Constraint| replace:: ConstraintsExclusion + +Constraints exclusion +--------------------- + +.. autoclass:: pyasn1.type.constraint.ConstraintsExclusion(constraint) + :members: diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/constraint/constraintsintersection.rst b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/constraint/constraintsintersection.rst new file mode 100644 index 00000000..15465b81 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/constraint/constraintsintersection.rst @@ -0,0 +1,10 @@ + +.. _constrain.ConstraintsIntersection: + +.. |Constraint| replace:: ConstraintsIntersection + +Constraints intersection +------------------------ + +.. autoclass:: pyasn1.type.constraint.ConstraintsIntersection(*constraints) + :members: diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/constraint/constraintsunion.rst b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/constraint/constraintsunion.rst new file mode 100644 index 00000000..d42f3d90 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/constraint/constraintsunion.rst @@ -0,0 +1,10 @@ + +.. _constrain.ConstraintsUnion: + +.. |Constraint| replace:: ConstraintsUnion + +Constraints union +----------------- + +.. autoclass:: pyasn1.type.constraint.ConstraintsUnion(*constraints) + :members: diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/constraint/containedsubtype.rst b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/constraint/containedsubtype.rst new file mode 100644 index 00000000..39fc3a1c --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/constraint/containedsubtype.rst @@ -0,0 +1,10 @@ + +.. _constrain.ContainedSubtypeConstraint: + +.. |Constraint| replace:: ContainedSubtypeConstraint + +Contained subtype constraint +---------------------------- + +.. autoclass:: pyasn1.type.constraint.ContainedSubtypeConstraint + :members: diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/constraint/contents.rst b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/constraint/contents.rst new file mode 100644 index 00000000..a4e2424a --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/constraint/contents.rst @@ -0,0 +1,68 @@ + +.. _type.constraint: + +Constraints +----------- + +ASN.1 standard has a built-in way of limiting the set of values +a type can possibly have. Imposing value constraints on an ASN.1 +type, together with :ref:`tagging <type.tag>`, is a way of creating +a more specialized subtype of an ASN.1 type. + +The pyasn1 implementation represents all flavors of constraints, +as well as their combinations, as immutable Python objects. Ultimately, +they get attached to ASN.1 type object at a *.subtypeSpec* attribute. + +.. code-block:: python + + class Age(Integer): + """ + ASN.1 specification: + + Age ::= INTEGER (0..120) + """ + subtypeSpec = ValueRangeConstraint(0, 120) + + +.. toctree:: + :maxdepth: 2 + + /pyasn1/type/constraint/singlevalue + /pyasn1/type/constraint/containedsubtype + /pyasn1/type/constraint/valuerange + /pyasn1/type/constraint/valuesize + /pyasn1/type/constraint/permittedalphabet + /pyasn1/type/constraint/withcomponents + + +Logic operations on constraints ++++++++++++++++++++++++++++++++ + +Sometimes multiple constraints are applied on an ASN.1 type. To capture +this situation, individual constraint objects can be glued together +by the logic operator objects. + +The logic operators are Python objects that exhibit similar behaviour +as the constraint objects do with the only difference that logic operators +are instantiated on the constraint and logic operator objects, not on the +bare values. + +.. code-block:: python + + class PhoneNumber(NumericString): + """ + ASN.1 specification: + + PhoneNumber ::= + NumericString (FROM ("0".."9")) (SIZE (10)) + """ + subtypeSpec = ConstraintsIntersection( + ValueRangeConstraint('0', '9'), ValueSizeConstraint(10) + ) + +.. toctree:: + :maxdepth: 2 + + /pyasn1/type/constraint/constraintsintersection + /pyasn1/type/constraint/constraintsunion + /pyasn1/type/constraint/constraintsexclusion diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/constraint/permittedalphabet.rst b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/constraint/permittedalphabet.rst new file mode 100644 index 00000000..86d08c47 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/constraint/permittedalphabet.rst @@ -0,0 +1,10 @@ + +.. _constrain.PermittedAlphabetConstraint: + +.. |Constraint| replace:: PermittedAlphabetConstraint + +Permitted alphabet constraint +----------------------------- + +.. autoclass:: pyasn1.type.constraint.PermittedAlphabetConstraint(*alphabet) + :members: diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/constraint/singlevalue.rst b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/constraint/singlevalue.rst new file mode 100644 index 00000000..26f24243 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/constraint/singlevalue.rst @@ -0,0 +1,10 @@ + +.. _constrain.SingleValueConstraint: + +.. |Constraint| replace:: SingleValueConstraint + +Single value constraint +----------------------- + +.. autoclass:: pyasn1.type.constraint.SingleValueConstraint + :members: diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/constraint/valuerange.rst b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/constraint/valuerange.rst new file mode 100644 index 00000000..a3a91ac2 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/constraint/valuerange.rst @@ -0,0 +1,10 @@ + +.. _constrain.ValueRangeConstraint: + +.. |Constraint| replace:: ValueRangeConstraint + +Value range constraint +---------------------- + +.. autoclass:: pyasn1.type.constraint.ValueRangeConstraint(start, end) + :members: diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/constraint/valuesize.rst b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/constraint/valuesize.rst new file mode 100644 index 00000000..62444df5 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/constraint/valuesize.rst @@ -0,0 +1,10 @@ + +.. _constrain.ValueSizeConstraint: + +.. |Constraint| replace:: ValueSizeConstraint + +Value size constraint +---------------------- + +.. autoclass:: pyasn1.type.constraint.ValueSizeConstraint(minimum, maximum) + :members: diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/constraint/withcomponents.rst b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/constraint/withcomponents.rst new file mode 100644 index 00000000..f1556b0a --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/constraint/withcomponents.rst @@ -0,0 +1,16 @@ + +.. _constrain.WithComponentsConstraint: + +.. |Constraint| replace:: WithComponentsConstraint + +WITH COMPONENTS constraint +-------------------------- + +.. autoclass:: pyasn1.type.constraint.WithComponentsConstraint(*fields) + :members: + +.. autoclass:: pyasn1.type.constraint.ComponentPresentConstraint() + :members: + +.. autoclass:: pyasn1.type.constraint.ComponentAbsentConstraint() + :members: diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/namedtype/contents.rst b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/namedtype/contents.rst new file mode 100644 index 00000000..2e553e63 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/namedtype/contents.rst @@ -0,0 +1,40 @@ + +.. _type.namedtype: + +Fields of constructed types +--------------------------- + +The :ref:`Sequence <univ.Sequence>`, :ref:`Set <univ.Set>` and +:ref:`Choice <univ.Choice>` ASN.1 types embed other ASN.1 types +as named fields. + +Each field can be expressed via the :ref:`NamedType <namedtype.NamedType>` +object while the individual fields are brought together by the +:ref:`NamedTypes <namedtype.NamedTypes>` object. + +Ultimately, the fields get attached to the ASN.1 type's *.componentType* +attributes. + +.. code-block:: python + + class RSAPublicKey(Sequence): + """ + ASN.1 specification: + + RSAPublicKey ::= SEQUENCE { + modulus INTEGER, -- n + publicExponent INTEGER -- e + } + """ + componentType = NamedTypes( + NamedType('modulus', Integer()), + NamedType('publicExponent', Integer()) + ) + +.. toctree:: + :maxdepth: 2 + + /pyasn1/type/namedtype/namedtype + /pyasn1/type/namedtype/optionalnamedtype + /pyasn1/type/namedtype/defaultednamedtype + /pyasn1/type/namedtype/namedtypes diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/namedtype/defaultednamedtype.rst b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/namedtype/defaultednamedtype.rst new file mode 100644 index 00000000..f203d084 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/namedtype/defaultednamedtype.rst @@ -0,0 +1,20 @@ + +.. _namedtype.DefaultedNamedType: + +.. |NamedType| replace:: DefaultedNamedType + +DefaultedNamedType +------------------ + +.. autoclass:: pyasn1.type.namedtype.DefaultedNamedType + :members: + + .. note:: + + The *DefaultedNamedType* class models named field of a constructed + ASN.1 type which has a default value. + + The *DefaultedNamedType* objects are normally utilized + by the :ref:`NamedTypes <namedtype.NamedTypes>` objects + to model individual fields of the constructed ASN.1 + types. diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/namedtype/namedtype.rst b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/namedtype/namedtype.rst new file mode 100644 index 00000000..7429ffab --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/namedtype/namedtype.rst @@ -0,0 +1,20 @@ + +.. _namedtype.NamedType: + +.. |NamedType| replace:: NamedType + +NamedType +--------- + +.. autoclass:: pyasn1.type.namedtype.NamedType + :members: + + .. note:: + + The *NamedType* class models a mandatory field of a constructed + ASN.1 type. + + The *NamedType* objects are normally utilized by the + the :ref:`NamedTypes <namedtype.NamedTypes>` objects + to model individual fields of the constructed ASN.1 + types. diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/namedtype/namedtypes.rst b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/namedtype/namedtypes.rst new file mode 100644 index 00000000..2e2bb9df --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/namedtype/namedtypes.rst @@ -0,0 +1,15 @@ + +.. _namedtype.NamedTypes: + +NamedTypes +---------- + +.. autoclass:: pyasn1.type.namedtype.NamedTypes + :members: + + .. note:: + + The *NamedTypes* objects are normally utilized by the + constructed ASN.1 types (e.g. :ref:`Sequence <univ.Sequence>`, + :ref:`Set <univ.Set>` and :ref:`Choice <univ.Choice>`) to model + the set of fields of those types. diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/namedtype/optionalnamedtype.rst b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/namedtype/optionalnamedtype.rst new file mode 100644 index 00000000..2095b056 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/namedtype/optionalnamedtype.rst @@ -0,0 +1,20 @@ + +.. _namedtype.OptionalNamedType: + +.. |NamedType| replace:: OptionalNamedType + +OptionalNamedType +----------------- + +.. autoclass:: pyasn1.type.namedtype.OptionalNamedType + :members: + + .. note:: + + The *OptionalNamedType* class models an optional field of + a constructed ASN.1 type. + + The *OptionalNamedType* objects are normally utilized by + the :ref:`NamedTypes <namedtype.NamedTypes>` objects + to model individual fields of the constructed ASN.1 + types. diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/namedval/contents.rst b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/namedval/contents.rst new file mode 100644 index 00000000..73f86c75 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/namedval/contents.rst @@ -0,0 +1,43 @@ + +.. _type.namedval: + +Enumerating numbers +------------------- + +Some ASN.1 types such as :ref:`Integer <univ.Integer>`, +:ref:`Enumerated <univ.Enumerated>` and :ref:`BitString <univ.BitString>` +may enumerate their otherwise numeric values associating them with +human-friendly labels. + +.. code-block:: python + + class ErrorStatus(Integer): + """ + ASN.1 specification: + + error-status + INTEGER { + noError(0), + tooBig(1), + noSuchName(2), + ... + } + """ + namedValues = NamedValues( + ('noError', 0), ('tooBig', 1), ('noSuchName', 2) + ) + +The enumerated types behave exactly like the non-enumerated ones but, +additionally, values can be referred by labels. + +.. code-block:: python + + errorStatus = ErrorStatus('tooBig') + + assert errorStatus == 1 + + +.. toctree:: + :maxdepth: 2 + + /pyasn1/type/namedval/namedval diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/namedval/namedval.rst b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/namedval/namedval.rst new file mode 100644 index 00000000..0bcfd69e --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/namedval/namedval.rst @@ -0,0 +1,13 @@ + +.. _namedval.NamedValues: + +.. |NamedValues| replace:: NamedValues + +|NamedValues| +------------- + +The |NamedValues| class associates human-friendly names to a set of numbers +or bits. + +.. autoclass:: pyasn1.type.namedval.NamedValues + :members: diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/opentype/contents.rst b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/opentype/contents.rst new file mode 100644 index 00000000..034870bc --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/opentype/contents.rst @@ -0,0 +1,114 @@ + +.. _type.opentype: + +Dynamic or open type +-------------------- + +ASN.1 allows data structure designer to leave "holes" in field type +specification of :ref:`Sequence <univ.Sequence>` or +:ref:`Set <univ.Set>` types. + +The idea behind that feature is that there can be times, when the +exact field type is not known at the design time, or it is anticipated +that new field types may come up in the future. + +This "hole" type is manifested in the data structure by :ref:`Any <univ.Any>` +type. Technically, the actual type is serialized into an octet stream +and then put into :ref:`Any <univ.Any>` "container", which is in fact an +(untagged, by default) specialization of ASN.1 +:ref:`OctetString <univ.OctetString>` type. + +.. code-block:: bash + + Algorithm ::= SEQUENCE { + algorithm OBJECT IDENTIFIER, + parameters ANY DEFINED BY algorithm OPTIONAL + } + +On the receiving end, to know how to interpret the open type +serialization, the receiver can rely on the supplied value in +the other field of the data structure. That other field is +semantically linked with the open type field. This link +is expressed in ASN.1 by the *DEFINE BY* clause. + +From ASN.1 perspective, it is not an error if the decoder does +not know a type selector value it receives. In that case pyasn1 decoder +just leaves serialized blob in the open type field. + +.. note:: + + By default, ASN.1 ANY type has no tag. That makes it an + "invisible" in serialization. However, like any other ASN.1 type, + ANY type can be subtyped by :ref:`tagging <type.tag>`. + +Besides scalar open type fields, ASN.1 allows using *SET OF* +or *SEQUENCE OF* containers holding zero or more of *ANY* +scalars. + +.. code-block:: bash + + AttributeTypeAndValues ::= SEQUENCE { + type OBJECT IDENTIFIER, + values SET OF ANY DEFINED BY type + } + +.. note:: + + A single type selector field is used to guide the decoder + of potentially many elements of a *SET OF* or *SEQUENCE OF* container + all at once. That implies that all *ANY* elements must be of the same + type in any given instance of a data structure. + +When expressing ASN.1 type "holes" in pyasn1, the +:ref:`OpenType <opentype.OpenType>` object should be used to establish +a semantic link between type selector field and open type field. + +.. code-block:: python + + algo_map = { + ObjectIdentifier('1.2.840.113549.1.1.1'): rsaEncryption(), + ObjectIdentifier('1.2.840.113549.1.1.2'): md2WithRSAEncryption() + } + + + class Algorithm(Sequence): + """ + Algorithm ::= SEQUENCE { + algorithm OBJECT IDENTIFIER, + parameters ANY DEFINED BY algorithm + } + """ + componentType = NamedTypes( + NamedType('algorithm', ObjectIdentifier()), + NamedType('parameters', Any(), + openType=OpenType('algorithm', algo_map)) + ) + +Similarly for `SET OF ANY DEFINED BY` or `SEQUENCE OF ANY DEFINED BY` +constructs: + +.. code-block:: python + + algo_map = { + ObjectIdentifier('1.2.840.113549.1.1.1'): rsaEncryption(), + ObjectIdentifier('1.2.840.113549.1.1.2'): md2WithRSAEncryption() + } + + + class Algorithm(Sequence): + """ + Algorithm ::= SEQUENCE { + algorithm OBJECT IDENTIFIER, + parameters SET OF ANY DEFINED BY algorithm + } + """ + componentType = NamedTypes( + NamedType('algorithm', ObjectIdentifier()), + NamedType('parameters', SetOf(componentType=Any()), + openType=OpenType('algorithm', algo_map)) + ) + +.. toctree:: + :maxdepth: 2 + + /pyasn1/type/opentype/opentype diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/opentype/opentype.rst b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/opentype/opentype.rst new file mode 100644 index 00000000..8ce93031 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/opentype/opentype.rst @@ -0,0 +1,12 @@ + +.. _opentype.OpenType: + +.. |OpenType| replace:: OpenType + +|OpenType| +----------- + +.. autoclass:: pyasn1.type.opentype.OpenType + :members: + +More information on open type use can be found :ref:`here <type.opentype>`. \ No newline at end of file diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/tag/contents.rst b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/tag/contents.rst new file mode 100644 index 00000000..4e5510c6 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/tag/contents.rst @@ -0,0 +1,54 @@ + +.. _type.tag: + +Tags +---- + +ASN.1 types formally differ from each other by carrying distinct +tags. A tag is essentially an integer exhibiting certain inner +structure. + +Individual tags are usually combined into a collection known as +*TagSet*. Tags and tag sets in pyasn1 are immutable objects assigned +to ASN.1 types as the *tagSet* attribute. + +Tags can be appended to one another (in EXPLICIT tagging mode) +or overridden (IMPLICIT tagging mode) ultimately creating a new +ASN.1 subtype. + +.. code-block:: python + + class Counter64(Integer): + """ + ASN.1 specification: + + Counter64 ::= + [APPLICATION 6] + IMPLICIT INTEGER + """ + tagSet = Integer.tagSet.tagImplicitly( + Tag(tagClassApplication, tagFormatSimple, 6) + ) + + # alternatively + counter64 = Integer().subtype( + implicitTag=Tag(tagClassApplication, tagFormatSimple, 6) + ) + +ASN.1 types can be related to each other via the *.isSameTypeWith()*, +*.isSuperTypeOf()* and *.isSubTypeOf()* methods. Internally, the *.tagSet* +of the types are compared along with the value constraints +(e.g. *.subtypeSpec*). + +.. code-block:: python + + assert Counter64().isSubTypeOf(Integer()) == True + assert Counter64().isSameTypeWith(Integer()) == False + + +.. toctree:: + :maxdepth: 2 + + /pyasn1/type/tag/tag + /pyasn1/type/tag/tagset + /pyasn1/type/tag/tagmap diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/tag/tag.rst b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/tag/tag.rst new file mode 100644 index 00000000..3aeb6703 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/tag/tag.rst @@ -0,0 +1,18 @@ + +.. _tag.tag: + +Solitary tag +------------ + +.. automodule:: pyasn1.type.tag + :members: tagClassUniversal, tagClassApplication, tagClassContext, + tagClassPrivate, tagFormatSimple, tagFormatConstructed + +.. autoclass:: pyasn1.type.tag.Tag + :members: + + .. note:: + + The *Tag* objects are normally used by the + :ref:`TagSet <tag.TagSet>`, objects to model a collection + of ASN.1 tags. diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/tag/tagmap.rst b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/tag/tagmap.rst new file mode 100644 index 00000000..05b84048 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/tag/tagmap.rst @@ -0,0 +1,14 @@ + +.. _tag.tagmap: + +Tag->type map +------------- + +.. autoclass:: pyasn1.type.tagmap.TagMap + :members: + + .. note:: + + The *TagMap* objects are used by the + :ref:`TagSet <tag.TagSet>`, objects for looking up components + of constructed ASN.1 types by :ref:`Tag <tag.Tag>`. diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/tag/tagset.rst b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/tag/tagset.rst new file mode 100644 index 00000000..c4dce2ee --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/tag/tagset.rst @@ -0,0 +1,14 @@ + +.. _tag.tagset: + +Tag set +------- + +.. autoclass:: pyasn1.type.tag.TagSet + :members: + + .. note:: + + The *TagSet* objects are normally used by all ASN.1 type + objects both simple (like :ref:`Integer <univ.Integer>`) + and constructed (e.g. :ref:`Sequence <univ.Sequence>`). diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/univ/any.rst b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/univ/any.rst new file mode 100644 index 00000000..56e593e8 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/univ/any.rst @@ -0,0 +1,22 @@ + +.. _univ.Any: + +.. |ASN.1| replace:: Any + +.. |encoding| replace:: iso-8859-1 + +|ASN.1| type +------------ + +.. autoclass:: pyasn1.type.univ.Any(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), encoding='iso-8859-1', binValue=NoValue(),hexValue=NoValue()) + :members: isValue, isSameTypeWith, isSuperTypeOf, tagSet, effectiveTagSet, tagMap, subtypeSpec + + .. note:: + + The |ASN.1| type models an arbitrary value of an arbitrary type. Typically, + a selection of types are defined in form of an + :ref:`open type <opentype.OpenType>` . Technically, the ANY + value is a serialised representation of some other ASN.1 object. + + .. automethod:: pyasn1.type.univ.Any.clone(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), encoding='iso-8859-1') + .. automethod:: pyasn1.type.univ.Any.subtype(value=NoValue(), implicitTag=Tag(), explicitTag=Tag(),subtypeSpec=ConstraintsIntersection(),encoding='iso-8859-1') diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/univ/bitstring.rst b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/univ/bitstring.rst new file mode 100644 index 00000000..7d57774d --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/univ/bitstring.rst @@ -0,0 +1,17 @@ + +.. _univ.BitString: + +.. |ASN.1| replace:: BitString + +|ASN.1| type +------------ + +.. autoclass:: pyasn1.type.univ.BitString(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), namedValues=NamedValues(),binValue=NoValue(), hexValue=NoValue()) + :members: isValue, isSameTypeWith, isSuperTypeOf, tagSet, effectiveTagSet, tagMap, subtypeSpec, asInteger, asNumbers, asOctets, asBinary, fromHexString, fromBinaryString, fromOctetString + + .. note:: + + The |ASN.1| type models an arbitrary sequence of bits. + + .. automethod:: pyasn1.type.univ.BitString.clone(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), namedValues=NamedValues(),binValue=NoValue(), hexValue=NoValue()) + .. automethod:: pyasn1.type.univ.BitString.subtype(value=NoValue(), implicitTag=Tag(), explicitTag=Tag(),subtypeSpec=ConstraintsIntersection(), , namedValues=NamedValues(),binValue=NoValue(), hexValue=NoValue()) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/univ/boolean.rst b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/univ/boolean.rst new file mode 100644 index 00000000..ab4021a6 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/univ/boolean.rst @@ -0,0 +1,17 @@ + +.. _univ.Boolean: + +.. |ASN.1| replace:: Boolean + +|ASN.1| type +------------ + +.. autoclass:: pyasn1.type.univ.Boolean(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection()) + :members: isValue, isSameTypeWith, isSuperTypeOf, tagSet, effectiveTagSet, tagMap, subtypeSpec + + .. note:: + + The |ASN.1| type models a BOOLEAN that can be either TRUE or FALSE. + + .. automethod:: pyasn1.type.univ.Boolean.clone(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection()) + .. automethod:: pyasn1.type.univ.Boolean.subtype(value=NoValue(), implicitTag=Tag(), explicitTag=Tag(), subtypeSpec=ConstraintsIntersection()) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/univ/choice.rst b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/univ/choice.rst new file mode 100644 index 00000000..323932bb --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/univ/choice.rst @@ -0,0 +1,19 @@ + +.. _univ.Choice: + +.. |ASN.1| replace:: Choice + +|ASN.1| type +------------ + +.. autoclass:: pyasn1.type.univ.Choice(componentType=None, tagSet=tagSet(), subtypeSpec=ConstraintsIntersection()) + :members: isValue, isSameTypeWith, isSuperTypeOf, tagSet, effectiveTagSet, tagMap, componentType, subtypeSpec, + getComponentByPosition, setComponentByPosition, getComponentByName, setComponentByName, setDefaultComponents, + getComponentByType, setComponentByType, getName, getComponent, isInconsistent + + .. note:: + + The |ASN.1| type can only hold a single component at a time belonging to the list of allowed types. + + .. automethod:: pyasn1.type.univ.Choice.clone(componentType=None, tagSet=tagSet(), subtypeSpec=ConstraintsIntersection()) + .. automethod:: pyasn1.type.univ.Choice.subtype(componentType=None, implicitTag=Tag(), explicitTag=Tag(),subtypeSpec=ConstraintsIntersection()) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/univ/contents.rst b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/univ/contents.rst new file mode 100644 index 00000000..d546e1c7 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/univ/contents.rst @@ -0,0 +1,34 @@ + +.. _type.univ: + +Universal types +--------------- + +The ASN.1 language defines a collection of core data types +also known as *universal* types. + +Some of these types behave like a scalar (e.g. *simple* types) while +the rest are structured types (the standard calls them *constructed*). + +Example of simple types include :ref:`Integer <univ.Integer>` or +:ref:`OctetString <univ.OctetString>`. Constructed types like +:ref:`Sequence <univ.Sequence>` embed other types, both simple +and constructed. + +.. toctree:: + :maxdepth: 2 + + /pyasn1/type/univ/integer + /pyasn1/type/univ/boolean + /pyasn1/type/univ/bitstring + /pyasn1/type/univ/octetstring + /pyasn1/type/univ/null + /pyasn1/type/univ/objectidentifier + /pyasn1/type/univ/real + /pyasn1/type/univ/enumerated + /pyasn1/type/univ/any + /pyasn1/type/univ/setof + /pyasn1/type/univ/sequenceof + /pyasn1/type/univ/set + /pyasn1/type/univ/sequence + /pyasn1/type/univ/choice diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/univ/enumerated.rst b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/univ/enumerated.rst new file mode 100644 index 00000000..ab225ae1 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/univ/enumerated.rst @@ -0,0 +1,18 @@ + +.. _univ.Enumerated: + +.. |ASN.1| replace:: Enumerated + +|ASN.1| type +------------ + +.. autoclass:: pyasn1.type.univ.Enumerated(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), namedValues=NamedValues()) + :members: isValue, isSameTypeWith, isSuperTypeOf, tagSet, effectiveTagSet, tagMap, subtypeSpec, namedValues + + .. note:: + + The |ASN.1| type models bounded set of named integer values. Other than that, it is identical to + the *Integer* class. + + .. automethod:: pyasn1.type.univ.Enumerated.clone(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), namedValues=NamedValues()) + .. automethod:: pyasn1.type.univ.Enumerated.subtype(value=NoValue(), implicitTag=Tag(), explicitTag=Tag(),subtypeSpec=ConstraintsIntersection(), namedValues=NamedValues()) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/univ/integer.rst b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/univ/integer.rst new file mode 100644 index 00000000..4dcfabb9 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/univ/integer.rst @@ -0,0 +1,19 @@ + +.. _univ.Integer: + +.. |ASN.1| replace:: Integer + +|ASN.1| type +------------ + +.. autoclass:: pyasn1.type.univ.Integer(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), namedValues=NamedValues()) + :members: isValue, isSameTypeWith, isSuperTypeOf, tagSet, effectiveTagSet, tagMap, + subtypeSpec, namedValues + + .. note:: + + The |ASN.1| type models an arbitrary integer. INTEGER values can be positive, negative, + or zero, and can have any magnitude. + + .. automethod:: pyasn1.type.univ.Integer.clone(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), namedValues=NamedValues()) + .. automethod:: pyasn1.type.univ.Integer.subtype(value=NoValue(), implicitTag=Tag(), explicitTag=Tag(),subtypeSpec=ConstraintsIntersection(), namedValues=NamedValues()) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/univ/null.rst b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/univ/null.rst new file mode 100644 index 00000000..5553fcc0 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/univ/null.rst @@ -0,0 +1,17 @@ + +.. _univ.Null: + +.. |ASN.1| replace:: Null + +|ASN.1| type +------------ + +.. autoclass:: pyasn1.type.univ.Null(value=NoValue(), tagSet=TagSet()) + :members: isValue, isSameTypeWith, isSuperTypeOf, tagSet, effectiveTagSet, tagMap, subtypeSpec + + .. note:: + + The |ASN.1| type models ASN.1 NULL. + + .. automethod:: pyasn1.type.univ.Null.clone(value=NoValue(), tagSet=TagSet()) + .. automethod:: pyasn1.type.univ.Null.subtype(value=NoValue(), implicitTag=Tag(), explicitTag=Tag()) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/univ/objectidentifier.rst b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/univ/objectidentifier.rst new file mode 100644 index 00000000..cc4ae0b9 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/univ/objectidentifier.rst @@ -0,0 +1,17 @@ + +.. _univ.ObjectIdentifier: + +.. |ASN.1| replace:: ObjectIdentifier + +|ASN.1| type +------------ + +.. autoclass:: pyasn1.type.univ.ObjectIdentifier(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection()) + :members: isValue, isSameTypeWith, isSuperTypeOf, tagSet, effectiveTagSet, tagMap, subtypeSpec, isPrefixOf + + .. note:: + + The |ASN.1| type models ASN.1 OBJECT IDENTIFIER as a sequence of integer numbers. + + .. automethod:: pyasn1.type.univ.ObjectIdentifier.clone(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection()) + .. automethod:: pyasn1.type.univ.ObjectIdentifier.subtype(value=NoValue(), implicitTag=Tag(), explicitTag=Tag(), subtypeSpec=ConstraintsIntersection()) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/univ/octetstring.rst b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/univ/octetstring.rst new file mode 100644 index 00000000..a984a346 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/univ/octetstring.rst @@ -0,0 +1,19 @@ + +.. _univ.OctetString: + +.. |ASN.1| replace:: OctetString + +.. |encoding| replace:: iso-8859-1 + +|ASN.1| type +------------ + +.. autoclass:: pyasn1.type.univ.OctetString(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), encoding='iso-8859-1', binValue=NoValue(),hexValue=NoValue()) + :members: isValue, isSameTypeWith, isSuperTypeOf, tagSet, effectiveTagSet, tagMap, subtypeSpec, fromHexString, fromBinaryString + + .. note:: + + The |ASN.1| type models an arbitrary string of octets (eight-bit numbers), not printable text string. + + .. automethod:: pyasn1.type.univ.OctetString.clone(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), encoding='iso-8859-1') + .. automethod:: pyasn1.type.univ.OctetString.subtype(value=NoValue(), implicitTag=Tag(), explicitTag=Tag(),subtypeSpec=ConstraintsIntersection(),encoding='iso-8859-1') diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/univ/real.rst b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/univ/real.rst new file mode 100644 index 00000000..31ea07b4 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/univ/real.rst @@ -0,0 +1,17 @@ + +.. _univ.Real: + +.. |ASN.1| replace:: Real + +|ASN.1| type +------------ + +.. autoclass:: pyasn1.type.univ.Real(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection()) + :members: isValue, isSameTypeWith, isSuperTypeOf, tagSet, effectiveTagSet, tagMap, subtypeSpec, isInf, isPlusInf, isMinusInf + + .. note:: + + The |ASN.1| type models a rational number of arbitrary precision. + + .. automethod:: pyasn1.type.univ.Real.clone(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection()) + .. automethod:: pyasn1.type.univ.Real.subtype(value=NoValue(), implicitTag=Tag(), explicitTag=Tag(), subtypeSpec=ConstraintsIntersection()) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/univ/sequence.rst b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/univ/sequence.rst new file mode 100644 index 00000000..163a3a05 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/univ/sequence.rst @@ -0,0 +1,20 @@ + +.. _univ.Sequence: + +.. |ASN.1| replace:: Sequence + +|ASN.1| type +------------ + +.. autoclass:: pyasn1.type.univ.Sequence(componentType=NamedTypes(), tagSet=tagSet(), subtypeSpec=ConstraintsIntersection()) + :members: isValue, isSameTypeWith, isSuperTypeOf, tagSet, effectiveTagSet, tagMap, componentType, subtypeSpec, getComponentByPosition, + setComponentByPosition, getComponentByName, setComponentByName, setDefaultComponents, + clear, reset, isInconsistent + + .. note:: + + The |ASN.1| type models a collection of named ASN.1 components. + Ordering of the components **is** preserved upon de/serialisation. + + .. automethod:: pyasn1.type.univ.Sequence.clone(componentType=NamedTypes(), tagSet=tagSet(), subtypeSpec=ConstraintsIntersection()) + .. automethod:: pyasn1.type.univ.Sequence.subtype(componentType=NamedTypes(), implicitTag=Tag(), explicitTag=Tag(),subtypeSpec=ConstraintsIntersection()) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/univ/sequenceof.rst b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/univ/sequenceof.rst new file mode 100644 index 00000000..dd4f0c52 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/univ/sequenceof.rst @@ -0,0 +1,19 @@ + +.. _univ.SequenceOf: + +.. |ASN.1| replace:: SequenceOf + +|ASN.1| type +------------ + +.. autoclass:: pyasn1.type.univ.SequenceOf(componentType=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection()) + :members: isValue, isSameTypeWith, isSuperTypeOf, tagSet, effectiveTagSet, tagMap, componentType, subtypeSpec, + getComponentByPosition, setComponentByPosition, clear, reset, isInconsistent + + .. note:: + + The |ASN.1| type models a collection of elements of a single ASN.1 type. + Ordering of the components **is** preserved upon de/serialisation. + + .. automethod:: pyasn1.type.univ.SequenceOf.clone(componentType=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection()) + .. automethod:: pyasn1.type.univ.SequenceOf.subtype(componentType=NoValue(), implicitTag=Tag(), explicitTag=Tag(),subtypeSpec=ConstraintsIntersection()) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/univ/set.rst b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/univ/set.rst new file mode 100644 index 00000000..157fed06 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/univ/set.rst @@ -0,0 +1,20 @@ + +.. _univ.Set: + +.. |ASN.1| replace:: Set + +|ASN.1| type +------------ + +.. autoclass:: pyasn1.type.univ.Set(componentType=NamedTypes(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection()) + :members: isValue, isSameTypeWith, isSuperTypeOf, tagSet, effectiveTagSet, tagMap, componentType, subtypeSpec, + getComponentByPosition, setComponentByPosition, getComponentByName, setComponentByName, setDefaultComponents, + getComponentByType, setComponentByType, clear, reset, isInconsistent + + .. note:: + + The |ASN.1| type models a collection of named ASN.1 components. + Ordering of the components **is not** preserved upon de/serialisation. + + .. automethod:: pyasn1.type.univ.Set.clone(componentType=NamedTypes(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection()) + .. automethod:: pyasn1.type.univ.Set.subtype(componentType=NamedTypes(), implicitTag=Tag(), explicitTag=Tag(),subtypeSpec=ConstraintsIntersection()) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/univ/setof.rst b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/univ/setof.rst new file mode 100644 index 00000000..581c20f9 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/univ/setof.rst @@ -0,0 +1,19 @@ + +.. _univ.SetOf: + +.. |ASN.1| replace:: SetOf + +|ASN.1| type +------------ + +.. autoclass:: pyasn1.type.univ.SetOf(componentType=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection()) + :members: isValue, isSameTypeWith, isSuperTypeOf, tagSet, effectiveTagSet, tagMap, componentType, subtypeSpec, +  getComponentByPosition, setComponentByPosition, clear, reset, isInconsistent + + .. note:: + + The |ASN.1| type models a collection of elements of a single ASN.1 type. + Ordering of the components **is not** preserved upon de/serialisation. + + .. automethod:: pyasn1.type.univ.SetOf.clone(componentType=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection()) + .. automethod:: pyasn1.type.univ.SetOf.subtype(componentType=NoValue(), implicitTag=Tag(), explicitTag=Tag(),subtypeSpec=ConstraintsIntersection()) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/useful/contents.rst b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/useful/contents.rst new file mode 100644 index 00000000..2e4ae7b7 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/useful/contents.rst @@ -0,0 +1,15 @@ + +.. _type.useful: + +Useful types +------------ + +Some assorted utility ASN.1 types belong to the *useful* group. +These types are all scalar. + +.. toctree:: + :maxdepth: 2 + + /pyasn1/type/useful/objectdescriptor + /pyasn1/type/useful/generalizedtime + /pyasn1/type/useful/utctime diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/useful/generalizedtime.rst b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/useful/generalizedtime.rst new file mode 100644 index 00000000..d1f5b851 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/useful/generalizedtime.rst @@ -0,0 +1,37 @@ + +.. _useful.GeneralizedTime: + +.. |ASN.1| replace:: GeneralizedTime + +.. |encoding| replace:: iso-8859-1 + +|ASN.1| type +------------ + +.. autoclass:: pyasn1.type.useful.GeneralizedTime(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), encoding='us-ascii') + :members: isValue, isSameTypeWith, isSuperTypeOf, tagSet, asDateTime, fromDateTime + + .. note:: + + + The |ASN.1| type models a character string representing date and time + in many different formats. + + Formal syntax for the *GeneralizedTime* value is: + + * **YYYYMMDDhh[mm[ss[(.|,)ffff]]]** standing for a local time, four + digits for the year, two for the month, two for the day and two + for the hour, followed by two digits for the minutes and two + for the seconds if required, then a dot (or a comma), and a + number for the fractions of second or + + * a string as above followed by the letter “Z” (denoting a UTC + time) or + + * a string as above followed by a string **(+|-)hh[mm]** denoting + time zone offset relative to UTC + + For example, *20170126120000Z* stands for YYYYMMDDHHMMSSZ. + + .. automethod:: pyasn1.type.useful.GeneralizedTime.clone(self, value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), encoding='us-ascii') + .. automethod:: pyasn1.type.useful.GeneralizedTime.subtype(self, value=NoValue(), implicitTag=TagSet(), explicitTag=TagSet(),subtypeSpec=ConstraintsIntersection(), encoding='us-ascii') diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/useful/objectdescriptor.rst b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/useful/objectdescriptor.rst new file mode 100644 index 00000000..f7bf4f61 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/useful/objectdescriptor.rst @@ -0,0 +1,20 @@ + +.. _useful.ObjectDescriptor: + +.. |ASN.1| replace:: ObjectDescriptor + +.. |encoding| replace:: iso-8859-1 + +|ASN.1| type +------------ + +.. autoclass:: pyasn1.type.useful.ObjectDescriptor(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), encoding='us-ascii') + :members: isValue, isSameTypeWith, isSuperTypeOf, tagSet + + .. note:: + + The |ASN.1| type models a character string that can accompany the *ObjectIdentifier* type + to serve as a human-friendly annotation for an OBJECT IDENTIFIER. + + .. automethod:: pyasn1.type.useful.ObjectDescriptor.clone(self, value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), encoding='us-ascii') + .. automethod:: pyasn1.type.useful.ObjectDescriptor.subtype(self, value=NoValue(), implicitTag=TagSet(), explicitTag=TagSet(),subtypeSpec=ConstraintsIntersection(), encoding='us-ascii') diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/useful/utctime.rst b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/useful/utctime.rst new file mode 100644 index 00000000..7bdfa8a3 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/source/pyasn1/type/useful/utctime.rst @@ -0,0 +1,34 @@ + +.. _useful.UTCTime: + +.. |ASN.1| replace:: UTCTime + +.. |encoding| replace:: iso-8859-1 + +|ASN.1| type +------------ + +.. autoclass:: pyasn1.type.useful.UTCTime(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), encoding='us-ascii') + :members: isValue, isSameTypeWith, isSuperTypeOf, tagSet, asDateTime, fromDateTime + + .. note:: + + The |ASN.1| type models a character string representing date and time. + + Formal syntax for the *UTCTime* value is: + + * **YYMMDDhhmm[ss]** standing for UTC time, two + digits for the year, two for the month, two for the day and two + for the hour, followed by two digits for the minutes and two + for the seconds if required or + + * a string as above followed by the letter “Z” (denoting a UTC + time) or + + * a string as above followed by a string **(+|-)hhmm** denoting + time zone offset relative to UTC + + For example, *170126120000Z* which stands for YYMMDDHHMMSSZ. + + .. automethod:: pyasn1.type.useful.UTCTime.clone(self, value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), encoding='us-ascii') + .. automethod:: pyasn1.type.useful.UTCTime.subtype(self, value=NoValue(), implicitTag=TagSet(), explicitTag=TagSet(),subtypeSpec=ConstraintsIntersection(), encoding='us-ascii') diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/tutorial.rst b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/tutorial.rst new file mode 100644 index 00000000..a948fe70 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/docs/tutorial.rst @@ -0,0 +1,1778 @@ + +Documentation +============= + +.. toctree:: + :maxdepth: 2 + +Data model for ASN.1 types +-------------------------- + +All ASN.1 types could be categorized into two groups: scalar (also +called simple or primitive) and constructed. The first group is +populated by well-known types like Integer or String. Members of +constructed group hold other types (simple or constructed) as their +inner components, thus they are semantically close to a programming +language records or lists. + +In pyasn1, all ASN.1 types and values are implemented as Python +objects. The same pyasn1 object can represent either ASN.1 type +and/or value depending of the presence of value initializer on object +instantiation. We will further refer to these as *pyasn1 type object* +versus *pyasn1 value object*. + +Primitive ASN.1 types are implemented as immutable scalar objects. +There values could be used just like corresponding native Python +values (integers, strings/bytes etc) and freely mixed with them in +expressions. + +.. code-block:: pycon + + >>> from pyasn1.type import univ + >>> asn1IntegerValue = univ.Integer(12) + >>> asn1IntegerValue - 2 + 10 + >>> univ.OctetString('abc') == 'abc' + True # Python 2 + >>> univ.OctetString(b'abc') == b'abc' + True # Python 3 + +It would be an error to perform an operation on a pyasn1 type object +as it holds no value to deal with: + +.. code-block:: pycon + + >>> from pyasn1.type import univ + >>> asn1IntegerType = univ.Integer() + >>> asn1IntegerType - 2 + ... + pyasn1.error.PyAsn1Error: No value for __coerce__() + + +Scalar types +------------ + +In the sub-sections that follow we will explain pyasn1 mapping to +those primitive ASN.1 types. Both, ASN.1 notation and corresponding +pyasn1 syntax will be given in each case. + +Boolean type +++++++++++++ + +*BOOLEAN* is the simplest type those values could be either True or +False. + +.. code-block:: bash + + ;; type specification + FunFactorPresent ::= BOOLEAN + + ;; values declaration and assignment + pythonFunFactor FunFactorPresent ::= TRUE + cobolFunFactor FunFactorPresent :: FALSE + +And here's pyasn1 version of :py:class:`~pyasn1.type.univ.Boolean`: + +.. code-block:: pycon + + >>> from pyasn1.type import univ + >>> class FunFactorPresent(univ.Boolean): pass + ... + >>> pythonFunFactor = FunFactorPresent(True) + >>> cobolFunFactor = FunFactorPresent(False) + >>> pythonFunFactor + FunFactorPresent('True(1)') + >>> cobolFunFactor + FunFactorPresent('False(0)') + >>> pythonFunFactor == cobolFunFactor + False + >>> + +Null type ++++++++++ + +The *NULL* type is sometimes used to express the absence of +information. + +.. code-block:: bash + + ;; type specification + Vote ::= CHOICE { + agreed BOOLEAN, + skip NULL + } + + ;; value declaration and assignment + myVote Vote ::= skip:NULL + +We will explain the CHOICE type later on, meanwhile the +:py:class:`~pyasn1.type.univ.Null` type: + +.. code-block:: pycon + + >>> from pyasn1.type import univ + >>> skip = univ.Null() + >>> skip + Null('') + >>> + +Integer type +++++++++++++ + +ASN.1 defines the values of *INTEGER* type as negative or positive of +whatever length. This definition plays nicely with Python as the +latter places no limit on Integers. However, some ASN.1 +implementations may impose certain limits of integer value ranges. +Keep that in mind when designing new data structures. + +.. code-block:: bash + + ;; values specification + age-of-universe INTEGER ::= 13750000000 + mean-martian-surface-temperature INTEGER ::= -63 + +A rather straightforward mapping into pyasn1 - +:py:class:`~pyasn1.type.univ.Integer`: + +.. code-block:: pycon + + >>> from pyasn1.type import univ + >>> ageOfUniverse = univ.Integer(13750000000) + >>> ageOfUniverse + Integer(13750000000) + >>> + >>> meanMartianSurfaceTemperature = univ.Integer(-63) + >>> meanMartianSurfaceTemperature + Integer(-63) + >>> + +ASN.1 allows to assign human-friendly names to particular values of +an INTEGER type. + +.. code-block:: bash + + Temperature ::= INTEGER { + freezing(0), + boiling(100) + } + +The Temperature type expressed in pyasn1: + +.. code-block:: pycon + + >>> from pyasn1.type import univ, namedval + >>> class Temperature(univ.Integer): + ... namedValues = namedval.NamedValues(('freezing', 0), ('boiling', 100)) + ... + >>> t = Temperature(0) + >>> t + Temperature('freezing(0)') + >>> t + 1 + Temperature(1) + >>> t + 100 + Temperature('boiling(100)') + >>> t = Temperature('boiling') + >>> t + Temperature('boiling(100)') + >>> Temperature('boiling') / 2 + Temperature(50) + >>> -1 < Temperature('freezing') + True + >>> 47 > Temperature('boiling') + False + +These values labels have no effect on Integer type operations, any value +still could be assigned to a type (information on value constraints will +follow further in the documentation). + +Enumerated type ++++++++++++++++ + +ASN.1 *ENUMERATED* type differs from an Integer type in a number of +ways. Most important is that its instance can only hold a value that +belongs to a set of values specified on type declaration. + +.. code-block:: bash + + error-status ::= ENUMERATED { + no-error(0), + authentication-error(10), + authorization-error(20), + general-failure(51) + } + +When constructing :py:class:`~pyasn1.type.univ.Enumerated` type we +will use two pyasn1 features: values labels (as mentioned above) and +value constraint (will be described in more details later on). + +.. code-block:: pycon + + >>> from pyasn1.type import univ, namedval, constraint + >>> class ErrorStatus(univ.Enumerated): + ... namedValues = namedval.NamedValues( + ... ('no-error', 0), + ... ('authentication-error', 10), + ... ('authorization-error', 20), + ... ('general-failure', 51) + ... ) + ... subtypeSpec = univ.Enumerated.subtypeSpec + \ + ... constraint.SingleValueConstraint(0, 10, 20, 51) + ... + >>> errorStatus = univ.ErrorStatus('no-error') + >>> errorStatus + ErrorStatus('no-error(0)') + >>> errorStatus == univ.ErrorStatus('general-failure') + False + >>> univ.ErrorStatus('non-existing-state') + Traceback (most recent call last): + ... + pyasn1.error.PyAsn1Error: Can't coerce non-existing-state into integer + >>> + +Particular integer values associated with Enumerated value states have +no meaning. They should not be used as such or in any kind of math +operation. Those integer values are only used by codecs to transfer +state from one entity to another. + +Real type ++++++++++ + +Values of the *REAL* type are a three-component tuple of mantissa, +base and exponent. All three are integers. + +.. code-block:: bash + + pi ::= REAL { mantissa 314159, base 10, exponent -5 } + +Corresponding pyasn1 :py:class:`~pyasn1.type.univ.Real` objects can be +initialized with either a three-component tuple or a Python float. +Infinite values could be expressed in a way, compatible with Python +float type. + +.. code-block:: pycon + + >>> from pyasn1.type import univ + >>> pi = univ.Real((314159, 10, -5)) + >>> pi + Real((314159, 10,-5)) + >>> float(pi) + 3.14159 + >>> pi == univ.Real(3.14159) + True + >>> univ.Real('inf') + Real('inf') + >>> univ.Real('-inf') == float('-inf') + True + >>> + +If a Real object is initialized from a Python float or yielded by a math +operation, the base is set to decimal 10 (what affects encoding). + +Bit string type ++++++++++++++++ + +ASN.1 *BIT STRING* type holds opaque binary data of an arbitrarily +length. A BIT STRING value could be initialized by either a binary +(base 2) or hex (base 16) value. + +.. code-block:: bash + + public-key BIT STRING ::= '1010111011110001010110101101101 + 1011000101010000010110101100010 + 0110101010000111101010111111110'B + + signature BIT STRING ::= 'AF01330CD932093392100B39FF00DE0'H + +The pyasn1 :py:class:`~pyasn1.type.univ.BitString` objects can +initialize from native ASN.1 notation (base 2 or base 16 strings) or +from a Python tuple of binary components. + +.. code-block:: pycon + + >>> from pyasn1.type import univ + >>> publicKey = univ.BitString( + ... binValue='1010111011110001010110101101101' + ... '1011000101010000010110101100010' + ... '0110101010000111101010111111110' + ) + >>> publicKey + BitString(binValue='101011101111000101011010110110110110001010100000101101011000100110101010000111101010111111110') + >>> signature = univ.BitString( + ... hexValue='AF01330CD932093392100B39FF00DE0' + ... ) + >>> signature + BitString(binValue='1010111100000001001100110000110011011001001100100000100100110011100100100001000000001011001110011111111100000000110111100000') + >>> fingerprint = univ.BitString( + ... (1, 0, 1, 1 ,0, 1, 1, 1, 0, 1, 0, 1) + ... ) + >>> fingerprint + BitString(binValue='101101110101') + >>> + +Another BIT STRING initialization method supported by ASN.1 notation +is to specify only 1-th bits along with their human-friendly label and +bit offset relative to the beginning of the bit string. With this +method, all not explicitly mentioned bits are doomed to be zeros. + +.. code-block:: bash + + bit-mask BIT STRING ::= { + read-flag(0), + write-flag(2), + run-flag(4) + } + +To express this in pyasn1, we will employ the named values feature (as +with Enumeration type). + +.. code-block:: pycon + + >>> from pyasn1.type import univ, namedval + >>> class BitMask(univ.BitString): + ... namedValues = namedval.NamedValues( + ... ('read-flag', 0), + ... ('write-flag', 2), + ... ('run-flag', 4) + ... ) + >>> bitMask = BitMask('read-flag,run-flag') + >>> bitMask + BitMask(binValue='10001') + >>> tuple(bitMask) + (1, 0, 0, 0, 1) + >>> bitMask[4] + 1 + >>> + +The BitString objects mimic the properties of Python tuple type in +part of immutable sequence object protocol support. + +OctetString type +++++++++++++++++ + +The *OCTET STRING* type is a confusing subject. According to ASN.1 +specification, this type is similar to BIT STRING, the major +difference is that the former operates in 8-bit chunks of data. What +is important to note, is that OCTET STRING was NOT designed to handle +text strings - the standard provides many other types specialized for +text content. For that reason, ASN.1 forbids to initialize OCTET +STRING values with "quoted text strings", only binary or hex +initializers, similar to BIT STRING ones, are allowed. + +.. code-block:: bash + + thumbnail OCTET STRING ::= '1000010111101110101111000000111011'B + thumbnail OCTET STRING ::= 'FA9823C43E43510DE3422'H + +However, ASN.1 users (e.g. protocols designers) seem to ignore the +original purpose of the OCTET STRING type - they used it for handling +all kinds of data, including text strings. + +.. code-block:: bash + + welcome-message OCTET STRING ::= "Welcome to ASN.1 wilderness!" + +In pyasn1, we have taken a liberal approach and allowed both BIT +STRING style and quoted text initializers for the +:py:class:`~pyasn1.type.univ.OctetString` objects. To avoid possible +collisions, quoted text is the default initialization syntax. + +.. code-block:: pycon + + >>> from pyasn1.type import univ + >>> thumbnail = univ.OctetString( + ... binValue='1000010111101110101111000000111011' + ... ) + >>> thumbnail + OctetString(hexValue='85eebcec0') + >>> thumbnail = univ.OctetString( + ... hexValue='FA9823C43E43510DE3422' + ... ) + >>> thumbnail + OctetString(hexValue='fa9823c43e4351de34220') + >>> + +Most frequent usage of the OctetString class is to instantiate it with +a text string. + +.. code-block:: pycon + + >>> from pyasn1.type import univ + >>> welcomeMessage = univ.OctetString('Welcome to ASN.1 wilderness!') + >>> welcomeMessage + OctetString(b'Welcome to ASN.1 wilderness!') + >>> print('%s' % welcomeMessage) + Welcome to ASN.1 wilderness! + >>> welcomeMessage[11:16] + OctetString(b'ASN.1') + >>> + +OctetString objects support the immutable sequence object protocol. +In other words, they behave like Python 3 bytes (or Python 2 strings). +When running pyasn1 on Python 3, it's better to use the bytes objects for +OctetString instantiation, as it's more reliable and efficient. + +Additionally, OctetString's can also be instantiated with a sequence of +8-bit integers (ASCII codes). + +.. code-block:: pycon + + >>> univ.OctetString((77, 101, 101, 103, 111)) + OctetString(b'Meego') + +It is sometimes convenient to express OctetString instances as 8-bit +characters (Python 3 bytes or Python 2 strings) or 8-bit integers. + +.. code-block:: pycon + + >>> octetString = univ.OctetString('ABCDEF') + >>> octetString.asNumbers() + (65, 66, 67, 68, 69, 70) + >>> octetString.asOctets() + b'ABCDEF' + +ObjectIdentifier type ++++++++++++++++++++++ + +Values of the *OBJECT IDENTIFIER* type are sequences of integers that +could be used to identify virtually anything in the world. Various +ASN.1-based protocols employ OBJECT IDENTIFIERs for their own +identification needs. + +.. code-block:: bash + + internet-id OBJECT IDENTIFIER ::= { + iso(1) identified-organization(3) dod(6) internet(1) + } + +One of the natural ways to map OBJECT IDENTIFIER type into a Python +one is to use Python tuples of integers. So this approach is taken by +pyasn1's :py:class:`~pyasn1.type.univ.ObjectIdentifier` class. + +.. code-block:: pycon + + >>> from pyasn1.type import univ + >>> internetId = univ.ObjectIdentifier((1, 3, 6, 1)) + >>> internetId + ObjectIdentifier('1.3.6.1') + >>> internetId[2] + 6 + >>> internetId[1:3] + ObjectIdentifier('3.6') + +A more human-friendly "dotted" notation is also supported. + +.. code-block:: pycon + + >>> from pyasn1.type import univ + >>> univ.ObjectIdentifier('1.3.6.1') + ObjectIdentifier('1.3.6.1') + +Symbolic names of the arcs of object identifier, sometimes present in +ASN.1 specifications, are not preserved and used in pyasn1 objects. + +The ObjectIdentifier objects mimic the properties of Python tuple type in +part of immutable sequence object protocol support. + +Any type +++++++++ + +The ASN.1 ANY type is a kind of wildcard or placeholder that matches +any other type without knowing it in advance. ANY has no base tag. + +.. code-block:: bash + + Error ::= SEQUENCE { + code INTEGER, + parameter ANY DEFINED BY code + } + +The ANY type is frequently used in specifications, where exact type is +not yet agreed upon between communicating parties or the number of +possible alternatives of a type is infinite. Sometimes an auxiliary +selector is kept around to help parties indicate the kind of ANY +payload in effect ("code" in the example above). + +Values of the ANY type contain serialized ASN.1 value(s) in form of an +octet string. Therefore pyasn1 :py:class:`~pyasn1.type.univ.Any` value +object share the properties of pyasn1 OctetString object. + +.. code-block:: pycon + + >>> from pyasn1.type import univ + >>> someValue = univ.Any(b'\x02\x01\x01') + >>> someValue + Any(b'\x02\x01\x01') + >>> str(someValue) + '\x02\x01\x01' + >>> bytes(someValue) + b'\x02\x01\x01' + >>> + +Receiving application is supposed to explicitly deserialize the +content of Any value object, possibly using auxiliary selector for +figuring out its ASN.1 type to pick appropriate decoder. + +There will be some more talk and code snippets covering Any type in +the codecs chapters that follow. + +Character string types +++++++++++++++++++++++ + +ASN.1 standard introduces a diverse set of text-specific types. All of +them were designed to handle various types of characters. Some of +these types seem be obsolete now days, as their target technologies are +gone. Another issue to be aware of is that raw OCTET STRING type is +sometimes used in practice by ASN.1 users instead of specialized +character string types, despite explicit prohibition imposed by ASN.1 +specification. + +The two types are specific to ASN.1 are NumericString and PrintableString. + +.. code-block:: bash + + welcome-message ::= PrintableString { + "Welcome to ASN.1 text types" + } + + dial-pad-numbers ::= NumericString { + "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" + } + +Their pyasn1 implementations are +:py:class:`~pyasn1.type.char.PrintableString` and +:py:class:`~pyasn1.type.char.NumericString`: + +.. code-block:: pycon + + >>> from pyasn1.type import char + >>> '%s' % char.PrintableString("Welcome to ASN.1 text types") + 'Welcome to ASN.1 text types' + >>> dialPadNumbers = char.NumericString( + "0" "1" "2" "3" "4" "5" "6" "7" "8" "9" + ) + >>> dialPadNumbers + NumericString(b'0123456789') + >>> + +The :py:class:`~pyasn1.type.char.VisibleString`, +:py:class:`~pyasn1.type.char.IA5String`, +:py:class:`~pyasn1.type.char.TeletexString`, +:py:class:`~pyasn1.type.char.VideotexString`, +:py:class:`~pyasn1.type.char.GraphicString` and +:py:class:`~pyasn1.type.char.GeneralString` types came to ASN.1 from +ISO standards on character sets. + +.. code-block:: pycon + + >>> from pyasn1.type import char + >>> char.VisibleString("abc") + VisibleString(b'abc') + >>> char.IA5String('abc') + IA5String(b'abc') + >>> char.TeletexString('abc') + TeletexString(b'abc') + >>> char.VideotexString('abc') + VideotexString(b'abc') + >>> char.GraphicString('abc') + GraphicString(b'abc') + >>> char.GeneralString('abc') + GeneralString(b'abc') + >>> + +The last three types are relatively recent addition to the family of +character string types: :py:class:`~pyasn1.type.char.UniversalString`, +:py:class:`~pyasn1.type.char.BMPString` and +:py:class:`~pyasn1.type.char.UTF8String`. + +.. code-block:: pycon + + >>> from pyasn1.type import char + >>> char.UniversalString("abc") + UniversalString(b'abc') + >>> char.BMPString('abc') + BMPString(b'abc') + >>> char.UTF8String('abc') + UTF8String(b'abc') + >>> utf8String = char.UTF8String('У попа была собака') + >>> utf8String + UTF8String(b'\xd0\xa3 \xd0\xbf\xd0\xbe\xd0\xbf\xd0\xb0 \xd0\xb1\xd1\x8b\xd0\xbb\xd0\xb0\xd1\x81\xd0\xbe\xd0\xb1\xd0\xb0\xd0\xba\xd0\xb0') + >>> print(utf8String) + У попа была собака + >>> + +In pyasn1, all character type objects behave like Python strings. None +of them is currently constrained in terms of valid alphabet so it's up +to the data source to keep an eye on data validation for these types. + +Useful types +++++++++++++ + +There are three so-called useful types defined in the standard: +:py:class:`~pyasn1.type.useful.ObjectDescriptor`, +:py:class:`~pyasn1.type.useful.GeneralizedTime` and +:py:class:`~pyasn1.type.useful.UTCTime`. They all are subtypes of +GraphicString or VisibleString types therefore useful types are +character string types. + +It's advised by the ASN.1 standard to have an instance of +ObjectDescriptor type holding a human-readable description of +corresponding instance of OBJECT IDENTIFIER type. There are no formal +linkage between these instances and provision for ObjectDescriptor +uniqueness in the standard. + +.. code-block:: pycon + + >>> from pyasn1.type import useful + >>> descrBER = useful.ObjectDescriptor( + "Basic encoding of a single ASN.1 type" + ) + >>> + +GeneralizedTime and UTCTime types are designed to hold a +human-readable timestamp in a universal and unambiguous form. The +former provides more flexibility in notation while the latter is more +strict but has Y2K issues. + +.. code-block:: bash + + ;; Mar 8 2010 12:00:00 MSK + moscow-time GeneralizedTime ::= "20110308120000.0" + ;; Mar 8 2010 12:00:00 UTC + utc-time GeneralizedTime ::= "201103081200Z" + ;; Mar 8 1999 12:00:00 UTC + utc-time UTCTime ::= "9803081200Z" + +In pyasn1 parlance: + +.. code-block:: pycon + + >>> from pyasn1.type import useful + >>> moscowTime = useful.GeneralizedTime("20110308120000.0") + >>> utcTime = useful.UTCTime("9803081200Z") + >>> + +Despite their intended use, these types possess no special, time-related, +handling in pyasn1. They are just printable strings. + +Tagging +------- + +In order to proceed to the Constructed ASN.1 types, we will first have +to introduce the concept of tagging (and its pyasn1 implementation), as +some of the Constructed types rely upon the tagging feature. + +When a value is coming into an ASN.1-based system (received from a network +or read from some storage), the receiving entity has to determine the +type of the value to interpret and verify it accordingly. + +Historically, the first data serialization protocol introduced in +ASN.1 was BER (Basic Encoding Rules). According to BER, any serialized +value is packed into a triplet of (Type, Length, Value) where Type is a +code that identifies the value (which is called *tag* in ASN.1), +length is the number of bytes occupied by the value in its serialized form +and value is ASN.1 value in a form suitable for serial transmission or storage. +For that reason almost every ASN.1 type has a tag (which is actually a +BER type) associated with it by default. + +An ASN.1 tag could be viewed as a tuple of three numbers: +(Class, Format, Number). While Number identifies a tag, Class component +is used to create scopes for Numbers. Four scopes are currently defined: +UNIVERSAL, context-specific, APPLICATION and PRIVATE. The Format component +is actually a one-bit flag - zero for tags associated with scalar types, +and one for constructed types (will be discussed later on). + +.. code-block:: bash + + MyIntegerType ::= [12] INTEGER + MyOctetString ::= [APPLICATION 0] OCTET STRING + +In pyasn1, tags are implemented as immutable, tuple-like objects: + +.. code-block:: pycon + + >>> from pyasn1.type import tag + >>> myTag = tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 10) + >>> myTag + Tag(tagClass=128, tagFormat=0, tagId=10) + >>> tuple(myTag) + (128, 0, 10) + >>> myTag[2] + 10 + >>> myTag == tag.Tag(tag.tagClassApplication, tag.tagFormatSimple, 10) + False + >>> + +Default tag, associated with any ASN.1 type, could be extended or +replaced to make new type distinguishable from its ancestor. The +standard provides two modes of tag mangling - IMPLICIT and EXPLICIT. + +EXPLICIT mode works by appending new tag to the existing ones thus +creating an ordered set of tags. This set will be considered as a +whole for type identification and encoding purposes. Important +property of EXPLICIT tagging mode is that it preserves base type +information in encoding what makes it possible to completely recover +type information from encoding. + +When tagging in IMPLICIT mode, the outermost existing tag is dropped +and replaced with a new one. + +.. code-block:: bash + + MyIntegerType ::= [12] IMPLICIT INTEGER + MyOctetString ::= [APPLICATION 0] EXPLICIT OCTET STRING + +To model both modes of tagging, a specialized container TagSet object +(holding zero, one or more Tag objects) is used in pyasn1. + +.. code-block:: pycon + + >>> from pyasn1.type import tag + >>> tagSet = tag.TagSet( + ... # base tag (OBSOLETE AND NOT USED ANYMORE) + ... (), + ... # effective tag + ... tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 10) + ... ) + >>> tagSet + TagSet((), Tag(tagClass=128, tagFormat=0, tagId=10)) + >>> tagSet.getBaseTag() + Tag(tagClass=128, tagFormat=0, tagId=10) + >>> tagSet = tagSet.tagExplicitly(tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 20)) + >>> tagSet + TagSet((), Tag(tagClass=128, tagFormat=0, tagId=10), + Tag(tagClass=128, tagFormat=32, tagId=20)) + >>> tagSet = tagSet.tagExplicitly(tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 30)) + >>> tagSet + TagSet((), Tag(tagClass=128, tagFormat=0, tagId=10), + Tag(tagClass=128, tagFormat=32, tagId=20), + Tag(tagClass=128, tagFormat=32, tagId=30)) + >>> tagSet = tagSet.tagImplicitly(tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 40)) + >>> tagSet + TagSet((), Tag(tagClass=128, tagFormat=0, tagId=10), + Tag(tagClass=128, tagFormat=32, tagId=20), + Tag(tagClass=128, tagFormat=32, tagId=40)) + >>> + +As a side note: the "base tag" concept is now obsolete and not used. +The "effective tag" is the one that always appears in encoding and is +used on tagSets comparison. + +Any two TagSet objects could be compared to see if one is a derivative +of the other. Figuring this out is also useful in cases when a type-specific +data processing algorithms are to be chosen. + +.. code-block:: pycon + + >>> from pyasn1.type import tag + >>> tagSet1 = tag.TagSet( + ... # base tag (OBSOLETE AND NOT USED ANYMORE) + ... (), + ... # effective tag + ... tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 10) + ... ) + >>> tagSet2 = tagSet1.tagExplicitly(tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 20)) + >>> tagSet1.isSuperTagSetOf(tagSet2) + True + >>> tagSet2.isSuperTagSetOf(tagSet1) + False + >>> + +We will complete this discussion on tagging with a real-world example. The +following ASN.1 tagged type: + +.. code-block:: bash + + MyIntegerType ::= [12] EXPLICIT INTEGER + +could be expressed in pyasn1 like this: + +.. code-block:: pycon + + >>> from pyasn1.type import univ, tag + >>> class MyIntegerType(univ.Integer): + ... tagSet = univ.Integer.tagSet.tagExplicitly(tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 12)) + >>> myInteger = MyIntegerType(12345) + >>> myInteger.tagSet + TagSet((), Tag(tagClass=0, tagFormat=0, tagId=2), + Tag(tagClass=128, tagFormat=32, tagId=12)) + >>> + +Referring to the above code, the tagSet class attribute is a property +of any pyasn1 type object that assigns default tagSet to a pyasn1 +value object. This default tagSet specification can be ignored and +effectively replaced by some other tagSet value passed on object +instantiation. + +It's important to understand that the tag set property of pyasn1 type/value +object can never be modified in place. In other words, a pyasn1 type/value +object can never change its tags. The only way is to create a new pyasn1 +type/value object and associate different tag set with it. + +Constructed types +----------------- + +Besides scalar types, ASN.1 specifies so-called constructed ones - these +are capable of holding one or more values of other types, both scalar +and constructed. + +In pyasn1 implementation, constructed ASN.1 types behave like +Python sequences, and also support additional component addressing methods, +specific to particular constructed type. + +Sequence and Set types +++++++++++++++++++++++ + +The *SEQUENCE* and *SET* types have many similar properties: + +* Both can hold any number of inner components of different types. +* Every component has a human-friendly identifier. +* Any component can have a default value. +* Some components can be absent. + +However, :py:class:`~pyasn1.type.univ.Sequence` type guarantees the +ordering of Sequence value components to match their declaration +order. By contrast, components of the +:py:class:`~pyasn1.type.univ.Set` type can be ordered to best suite +application's needs. + +.. code-block:: bash + + Record ::= SEQUENCE { + id INTEGER, + room [0] INTEGER OPTIONAL, + house [1] INTEGER DEFAULT 0 + } + +Up to this moment, the only method we used for creating new pyasn1 +types is Python sub-classing. With this method, a new, named Python +class is created what mimics type derivation in ASN.1 grammar. +However, ASN.1 also allows for defining anonymous subtypes (room and +house components in the example above). To support anonymous +subtyping in pyasn1, a cloning operation on an existing pyasn1 type +object can be invoked what creates a new instance of original object +with possibly modified properties. + +.. code-block:: pycon + + >>> from pyasn1.type import univ, namedtype, tag + >>> class Record(univ.Sequence): + ... componentType = namedtype.NamedTypes( + ... namedtype.NamedType('id', univ.Integer()), + ... namedtype.OptionalNamedType( + ... 'room', + ... univ.Integer().subtype( + ... implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0) + ... ) + ... ), + ... namedtype.DefaultedNamedType( + ... 'house', + ... univ.Integer(0).subtype( + ... implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1) + ... ) + ... ) + ... ) + >>> + +All pyasn1 constructed type classes have a class attribute +**componentType** that represent default type specification. Its +value is a NamedTypes object. + +The NamedTypes class instance holds a sequence of NameType, +OptionalNamedType or DefaultedNamedType objects which, in turn, refer +to pyasn1 type objects that represent inner SEQUENCE components +specification. + +Finally, invocation of a subtype() method of pyasn1 type objects in +the code above returns an implicitly tagged copy of original object. + +Once a SEQUENCE or SET type is declared with pyasn1, it can be +instantiated and initialized (continuing the above code): + +.. code-block:: pycon + + >>> record = Record() + >>> record['id'] = 123 + >>> print(record.prettyPrint()) + Record: + id=123 + >>> + >>> record[1] = 321 + >>> print(record.prettyPrint()) + Record: + id=123 + room=321 + >>> + >>> record.setDefaultComponents() + >>> print(record.prettyPrint()) + Record: + id=123 + room=321 + house=0 + +Inner components of pyasn1 Sequence/Set objects could be accessed +using the following methods: + +.. code-block:: pycon + + >>> record['id'] + Integer(123) + >>> record[1] + Integer(321) + >>> record[2] + Integer(0) + >>> for idx, field in enumerate(record): + ... print(record.componentType[idx].name, field) + id 123 + room 321 + house 0 + >>> + +The Set type share all the properties of Sequence type, and additionally +support by-tag component addressing (as all Set components have distinct +types). + +.. code-block:: pycon + + >>> from pyasn1.type import univ, namedtype, tag + >>> class Gamer(univ.Set): + ... componentType = namedtype.NamedTypes( + ... namedtype.NamedType('score', univ.Integer()), + ... namedtype.NamedType('player', univ.OctetString()), + ... namedtype.NamedType('id', univ.ObjectIdentifier()) + ... ) + >>> gamer = Gamer() + >>> gamer.setComponentByType(univ.Integer().tagSet, 121343) + >>> gamer.setComponentByType(univ.OctetString().tagSet, 'Pascal') + >>> gamer.setComponentByType(univ.ObjectIdentifier().tagSet, (1,3,7,2)) + >>> print(gamer.prettyPrint()) + Gamer: + score=121343 + player=b'Pascal' + id=1.3.7.2 + +SequenceOf and SetOf types +++++++++++++++++++++++++++ + +Both, *SEQUENCE OF* and *SET OF* types resemble an unlimited size list of +components. All the components must be of the same type. + +.. code-block:: bash + + Progression ::= SEQUENCE OF INTEGER + + arithmeticProgression Progression ::= { 1, 3, 5, 7 } + +:py:class:`~pyasn1.type.univ.SequenceOf` and +:py:class:`~pyasn1.type.univ.SetOf` types are expressed by the very +similar pyasn1 `list` type objects. Their components can only be addressed by +position and they both have a property of automatic resize. + +To specify inner component type, the **componentType** class +attribute should refer to another pyasn1 type object. + +.. code-block:: pycon + + >>> from pyasn1.type import univ + >>> class Progression(univ.SequenceOf): + ... componentType = univ.Integer() + >>> arithmeticProgression = Progression() + >>> arithmeticProgression[1] = 111 + >>> print(arithmeticProgression.prettyPrint()) + Progression: + -empty- 111 + >>> arithmeticProgression[0] = 100 + >>> print(arithmeticProgression.prettyPrint()) + Progression: + 100 111 + >>> + >>> for element in arithmeticProgression: + ... element + Integer(100) + Integer(111) + >>> + +Any scalar or constructed pyasn1 type object can serve as an inner +component. Missing components are prohibited in SequenceOf/SetOf +value objects. + +Choice type ++++++++++++ + +Values of ASN.1 *CHOICE* type can contain only a single value of a type +from a list of possible alternatives. Alternatives must be ASN.1 types +with distinct tags for the whole structure to remain unambiguous. +Unlike most other types, CHOICE is an untagged one, e.g. it has no +base tag of its own. + +.. code-block:: bash + + CodeOrMessage ::= CHOICE { + code INTEGER, + message OCTET STRING + } + +In pyasn1 implementation, +:py:class:`~pyasn1.type.univ.Choice` object behaves like Set but +accepts only a single inner component at a time. It also offers a few +additional methods specific to its behaviour. + +.. code-block:: pycon + + >>> from pyasn1.type import univ, namedtype + >>> class CodeOrMessage(univ.Choice): + ... componentType = namedtype.NamedTypes( + ... namedtype.NamedType('code', univ.Integer()), + ... namedtype.NamedType('message', univ.OctetString()) + ... ) + >>> + >>> codeOrMessage = CodeOrMessage() + >>> print(codeOrMessage.prettyPrint()) + CodeOrMessage: + >>> codeOrMessage['code'] = 123 + >>> print(codeOrMessage.prettyPrint()) + CodeOrMessage: + code=123 + >>> codeOrMessage['message'] = 'my string value' + >>> print(codeOrMessage.prettyPrint()) + CodeOrMessage: + message=b'my string value' + >>> + +Since there could be only a single inner component value in the pyasn1 +Choice value object, either of the following methods could be used for +fetching it (continuing previous code): + +.. code-block:: pycon + + >>> codeOrMessage.getName() + 'message' + >>> codeOrMessage.getComponent() + OctetString(b'my string value') + >>> + +Subtype constraints +------------------- + +Most ASN.1 types can correspond to an infinite set of values. To adapt +to particular application's data model and needs, ASN.1 provides a +mechanism for limiting the infinite set to values, that make sense in +particular case. Imposing value constraints on an ASN.1 type can also +be seen as creating a subtype from its base type. + +In pyasn1, constraints take shape of immutable objects capable +of evaluating given value against constraint-specific requirements. +Constraint object is a property of pyasn1 type. Like TagSet property, +associated with every pyasn1 type, constraints can never be modified +in place. The only way to modify pyasn1 type constraint is to associate +new constraint object to a new pyasn1 type object. + +A handful of different flavors of *constraints* are defined in +ASN.1. We will discuss them one by one in the following chapters and +also explain how to combine and apply them to types. + +Single value constraint ++++++++++++++++++++++++ + +This kind of constraint allows for limiting type to a finite, specified set +of values. + +.. code-block:: bash + + DialButton ::= OCTET STRING ( + "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" + ) + +Its pyasn1 implementation would look like: + +.. code-block:: pycon + + >>> from pyasn1.type import constraint + >>> c = constraint.SingleValueConstraint('0','1','2','3','4','5','6','7','8','9') + >>> c + SingleValueConstraint(0, 1, 2, 3, 4, 5, 6, 7, 8, 9) + >>> c('0') + >>> c('A') + Traceback (most recent call last): + ... + ValueConstraintError: + SingleValueConstraint(0, 1, 2, 3, 4, 5, 6, 7, 8, 9) failed at: A + >>> + +As can be seen in the snippet above, if a value violates the +constraint, an exception will be thrown. A constrained pyasn1 type +object holds a reference to a constraint object (or their combination, +as will be explained later) and calls it for value verification. + +.. code-block:: pycon + + >>> from pyasn1.type import univ, constraint + >>> class DialButton(univ.OctetString): + ... subtypeSpec = constraint.SingleValueConstraint( + ... '0','1','2','3','4','5','6','7','8','9' + ... ) + >>> DialButton('0') + DialButton(b'0') + >>> DialButton('A') + Traceback (most recent call last): + ... + ValueConstraintError: + SingleValueConstraint(0, 1, 2, 3, 4, 5, 6, 7, 8, 9) failed at: A + >>> + +Constrained pyasn1 value object can never hold a violating value. + +Value range constraint +++++++++++++++++++++++ + +A pair of values, compliant to a type to be constrained, denote low +and upper bounds of allowed range of values of a type. + +.. code-block:: bash + + Teenagers ::= INTEGER (13..19) + +And in pyasn1 terms: + +.. code-block:: pycon + + >>> from pyasn1.type import univ, constraint + >>> class Teenagers(univ.Integer): + ... subtypeSpec = constraint.ValueRangeConstraint(13, 19) + >>> Teenagers(14) + Teenagers(14) + >>> Teenagers(20) + Traceback (most recent call last): + ... + ValueConstraintError: + ValueRangeConstraint(13, 19) failed at: 20 + >>> + +ASN.1 MIN and MAX operands can be substituted with floating point +infinity values. + +.. code-block:: bash + + NegativeInt ::= INTEGER (MIN..-1) + PositiveInt ::= INTEGER (1..MAX) + +And in pyasn1 terms: + +.. code-block:: pycon + + >>> from pyasn1.type import univ, constraint + >>> class NegativeInt(univ.Integer): + ... subtypeSpec = constraint.ValueRangeConstraint(float('-inf'), -1) + >>> NegativeInt(-1) + NegativeInt(-1) + >>> NegativeInt(0) + Traceback (most recent call last): + ... + ValueConstraintError: + ValueConstraintError: ValueRangeConstraint() failed at: "0" at NegativeInt + >>> class PositiveInt(univ.Integer): + ... subtypeSpec = constraint.ValueRangeConstraint(1, float('inf')) + >> PositiveInt(1) + PositiveInt(1) + >> PositiveInt(4) + PositiveInt(4) + >> PositiveInt(-1) + Traceback (most recent call last): + ... + ValueConstraintError: + ValueConstraintError: ValueRangeConstraint() failed at: "-1" at PositiveInt + +Value range constraint usually applies to numeric types. + +Size constraint ++++++++++++++++ + +It is sometimes convenient to set or limit the allowed size of a data +item to be sent from one application to another to manage bandwidth +and memory consumption issues. Size constraint specifies the lower and +upper bounds of the size of a valid value. + +.. code-block:: bash + + TwoBits ::= BIT STRING (SIZE (2)) + +Express the same grammar in pyasn1: + +.. code-block:: pycon + + >>> from pyasn1.type import univ, constraint + >>> class TwoBits(univ.BitString): + ... subtypeSpec = constraint.ValueSizeConstraint(2, 2) + >>> TwoBits((1,1)) + TwoBits("'11'B") + >>> TwoBits((1,1,0)) + Traceback (most recent call last): + ... + ValueConstraintError: ValueSizeConstraint(2, 2) failed at: (1, 1, 0) + >>> + +Size constraint can be applied to potentially massive values - bit or +octet strings, SEQUENCE OF/SET OF values. + +Alphabet constraint ++++++++++++++++++++ + +The permitted alphabet constraint is similar to Single value +constraint but constraint applies to individual characters of a value. + +.. code-block:: bash + + MorseCode ::= PrintableString (FROM ("."|"-"|" ")) + +And in pyasn1: + +.. code-block:: pycon + + >>> from pyasn1.type import char, constraint + >>> class MorseCode(char.PrintableString): + ... subtypeSpec = constraint.PermittedAlphabetConstraint(".", "-", " ") + >>> MorseCode("...---...") + MorseCode('...---...') + >>> MorseCode("?") + Traceback (most recent call last): + ... + ValueConstraintError: PermittedAlphabetConstraint(".", "-", " ") failed at: "?" + >>> + +Current implementation does not handle ranges of characters in +constraint (FROM "A".."Z" syntax), one has to list the whole set in a +range. + +Constraint combinations ++++++++++++++++++++++++ + +Up to this moment, we used a single constraint per ASN.1 type. The +standard, however, allows for combining multiple individual +constraints into intersections, unions and exclusions. + +In pyasn1 data model, all of these methods of constraint combinations +are implemented as constraint-like objects holding individual +constraint (or combination) objects. Like terminal constraint objects, +combination objects are capable to perform value verification at its +set of enclosed constraints according to the logic of particular +combination. + +Constraints intersection verification succeeds only if a value is +compliant to each constraint in a set. To begin with, the following +specification will constitute a valid telephone number: + +.. code-block:: bash + + PhoneNumber ::= NumericString (FROM ("0".."9")) (SIZE 11) + +Constraint intersection object serves the logic above: + +.. code-block:: pycon + + >>> from pyasn1.type import char, constraint + >>> class PhoneNumber(char.NumericString): + ... subtypeSpec = constraint.ConstraintsIntersection( + ... constraint.PermittedAlphabetConstraint('0','1','2','3','4','5','6', '7','8','9'), + ... constraint.ValueSizeConstraint(11, 11) + ... ) + >>> PhoneNumber('79039343212') + PhoneNumber('79039343212') + >>> PhoneNumber('?9039343212') + Traceback (most recent call last): + ... + ValueConstraintError: ConstraintsIntersection(PermittedAlphabetConstraint('0','1','2','3','4','5','6','7','8','9'), ValueSizeConstraint(11, 11)) failed at: PermittedAlphabetConstraint('0','1','2','3','4','5','6','7','8','9') failed at: "?039343212" + >>> PhoneNumber('9343212') + Traceback (most recent call last): + ... + ValueConstraintError: + ConstraintsIntersection(PermittedAlphabetConstraint('0','1','2','3','4','5','6','7','8','9'), ValueSizeConstraint(11, 11)) failed at: ValueSizeConstraint(10, 10) failed at: "9343212" + >>> + +Union of constraints works by making sure that a value is compliant +to any of the constraint in a set. For instance: + +.. code-block:: bash + + CapitalOrSmall ::= IA5String (FROM ('A','B','C') | FROM ('a','b','c')) + +It's important to note, that a value must fully comply to any single +constraint in a set. In the specification above, a value of all small +or all capital letters is compliant, but a mix of small&capitals is +not. Here's its pyasn1 analogue: + +.. code-block:: pycon + + >>> from pyasn1.type import char, constraint + >>> class CapitalOrSmall(char.IA5String): + ... subtypeSpec = constraint.ConstraintsUnion( + ... constraint.PermittedAlphabetConstraint('A','B','C'), + ... constraint.PermittedAlphabetConstraint('a','b','c') + ... ) + >>> CapitalOrSmall('ABBA') + CapitalOrSmall('ABBA') + >>> CapitalOrSmall('abba') + CapitalOrSmall('abba') + >>> CapitalOrSmall('Abba') + Traceback (most recent call last): + ... + ValueConstraintError: ConstraintsUnion(PermittedAlphabetConstraint('A', 'B', 'C'), PermittedAlphabetConstraint('a', 'b', 'c')) failed at: failed for "Abba" + >>> + +Finally, the exclusion constraint simply negates the logic of value +verification at a constraint. In the following example, any integer +value is allowed in a type but not zero. + +.. code-block:: bash + + NoZero ::= INTEGER (ALL EXCEPT 0) + +In pyasn1 the above definition would read: + +.. code-block:: pycon + + >>> from pyasn1.type import univ, constraint + >>> class NoZero(univ.Integer): + ... subtypeSpec = constraint.ConstraintsExclusion( + ... constraint.SingleValueConstraint(0) + ... ) + >>> NoZero(1) + NoZero(1) + >>> NoZero(0) + Traceback (most recent call last): + ... + ValueConstraintError: ConstraintsExclusion(SingleValueConstraint(0)) failed at: 0 + >>> + +The depth of such a constraints tree, built with constraint +combination objects at its nodes, has not explicit limit. Value +verification is performed in a recursive manner till a definite +solution is found. + +Types relationships ++++++++++++++++++++ + +In the course of data processing in an application, it is sometimes +convenient to figure out the type relationships between pyasn1 type or +value objects. Formally, two things influence pyasn1 types +relationship: *tag set* and *subtype constraints*. One +pyasn1 type is considered to be a derivative of another if their +TagSet and Constraint objects are a derivation of one another. + +The following example illustrates the concept (we use the same tagset +but different constraints for simplicity): + +.. code-block:: pycon + + >>> from pyasn1.type import univ, constraint + >>> i1 = univ.Integer(subtypeSpec=constraint.ValueRangeConstraint(3,8)) + >>> i2 = univ.Integer(subtypeSpec=constraint.ConstraintsIntersection( + ... constraint.ValueRangeConstraint(3,8), + ... constraint.ValueRangeConstraint(4,7) + ... ) ) + >>> i1.isSameTypeWith(i2) + False + >>> i1.isSuperTypeOf(i2) + True + >>> i1.isSuperTypeOf(i1) + True + >>> i2.isSuperTypeOf(i1) + False + >>> + +As can be seen in the above code snippet, there are two methods of any +pyasn1 type/value object that test types for their relationship: +*isSameTypeWith()* and *isSuperTypeOf()*. The former is +self-descriptive while the latter yields true if the argument appears +to be a pyasn1 object which has tagset and constraints derived from +those of the object being called. + +Serialization codecs +-------------------- + +In ASN.1 context, `codec <http://en.wikipedia.org/wiki/Codec>`_ +is a program that transforms between concrete data structures and a stream +of octets, suitable for transmission over the wire. This serialized form of +data is sometimes called *substrate* or *essence*. + +In pyasn1 implementation, substrate takes shape of Python 3 bytes or +Python 2 string objects. + +One of the properties of a codec is its ability to cope with +incomplete data and/or substrate what implies codec to be stateful. In +other words, when decoder runs out of substrate and data item being +recovered is still incomplete, stateful codec would suspend and +complete data item recovery whenever the rest of substrate becomes +available. Similarly, stateful encoder would encode data items in +multiple steps waiting for source data to arrive. Codec restartability +is especially important when application deals with large volumes of +data and/or runs on low RAM. For an interesting discussion on codecs +options and design choices, refer to `Apache ASN.1 project +<http://directory.apache.org/subprojects/asn1/>`_ . + +As of this writing, codecs implemented in pyasn1 are all stateless, +mostly to keep the code simple. + +The pyasn1 package currently supports +`BER <http://en.wikipedia.org/wiki/Basic_encoding_rules>`_ codec and +its variations -- +`CER <http://en.wikipedia.org/wiki/Canonical_encoding_rules>`_ and +`DER <http://en.wikipedia.org/wiki/Distinguished_encoding_rules>`_. +More ASN.1 codecs are planned for implementation in the future. + +Encoders +++++++++ + +Encoder is used for transforming pyasn1 value objects into substrate. +Only pyasn1 value objects could be serialized, attempts to process +pyasn1 type objects will cause encoder failure. + +The following code will create a pyasn1 Integer object and serialize +it with BER encoder: + +.. code-block:: pycon + + >>> from pyasn1.type import univ + >>> from pyasn1.codec.ber import encoder + >>> encoder.encode(univ.Integer(123456)) + b'\x02\x03\x01\xe2@' + >>> + +BER standard also defines a so-called *indefinite length* +encoding form which makes large data items processing more memory +efficient. It is mostly useful when encoder does not have the whole +value all at once and the length of the value can not be determined at +the beginning of encoding. + +*Constructed encoding* is another feature of BER closely related to +the indefinite length form. In essence, a large scalar value (such as +ASN.1 character BitString type) could be chopped into smaller chunks +by encoder and transmitted incrementally to limit memory consumption. +Unlike indefinite length case, the length of the whole value must be +known in advance when using constructed, definite length encoding +form. + +Since pyasn1 codecs are not restartable, pyasn1 encoder may only +encode data item all at once. However, even in this case, generating +indefinite length encoding may help a low-memory receiver, running a +restartable decoder, to process a large data item. + +.. code-block:: pycon + + >>> from pyasn1.type import univ + >>> from pyasn1.codec.ber import encoder + >>> encoder.encode( + ... univ.OctetString('The quick brown fox jumps over the lazy dog'), + ... defMode=False, + ... maxChunkSize=8 + ... ) + b'$\x80\x04\x08The quic\x04\x08k brown \x04\x08fox jump\x04\x08s over \t\x04\x08he lazy \x04\x03dog\x00\x00' + >>> + >>> encoder.encode( + ... univ.OctetString('The quick brown fox jumps over the lazy dog'), + ... maxChunkSize=8 + ... ) + b'$7\x04\x08The quic\x04\x08k brown \x04\x08fox jump\x04\x08s over \t\x04\x08he lazy \x04\x03dog' + +The *defMode* encoder parameter disables definite length encoding +mode, while the optional *maxChunkSize* parameter specifies desired +substrate chunk size that influences memory requirements at the +decoder's end. + +To use CER or DER encoders one needs to explicitly import and call them - the +APIs are all compatible. + +.. code-block:: pycon + + >>> from pyasn1.type import univ + >>> from pyasn1.codec.ber import encoder as ber_encoder + >>> from pyasn1.codec.cer import encoder as cer_encoder + >>> from pyasn1.codec.der import encoder as der_encoder + >>> ber_encoder.encode(univ.Boolean(True)) + b'\x01\x01\x01' + >>> cer_encoder.encode(univ.Boolean(True)) + b'\x01\x01\xff' + >>> der_encoder.encode(univ.Boolean(True)) + b'\x01\x01\xff' + >>> + +Decoders +++++++++ + +In the process of decoding, pyasn1 value objects are created and +linked to each other, based on the information contained in the +substrate. Thus, the original pyasn1 value object(s) are recovered. + +.. code-block:: pycon + + >>> from pyasn1.type import univ + >>> from pyasn1.codec.ber import encoder, decoder + >>> substrate = encoder.encode(univ.Boolean(True)) + >>> decoder.decode(substrate) + (Boolean('True(1)'), b'') + >>> + +Commenting on the code snippet above, pyasn1 decoder accepts substrate +as an argument and returns a tuple of pyasn1 value object (possibly a +top-level one in case of constructed object) and unprocessed part of +input substrate. + +All pyasn1 decoders can handle both definite and indefinite length +encoding modes automatically, explicit switching into one mode to +another is not required. + +.. code-block:: pycon + + >>> from pyasn1.type import univ + >>> from pyasn1.codec.ber import encoder, decoder + >>> substrate = encoder.encode( + ... univ.OctetString('The quick brown fox jumps over the lazy dog'), + ... defMode=False, + ... maxChunkSize=8 + ... ) + >>> decoder.decode(substrate) + (OctetString(b'The quick brown fox jumps over the lazy dog'), b'') + >>> + +Speaking of BER/CER/DER encoding, in many situations substrate may not +contain all necessary information needed for complete and accurate +ASN.1 values recovery. The most obvious cases include implicitly +tagged ASN.1 types and constrained types. + +As discussed earlier in this tutorial, when an ASN.1 type is implicitly +tagged, previous outermost tag is lost and never appears in substrate. +If it is the base tag that gets lost, decoder is unable to pick type-specific +value decoder at its table of built-in types, and therefore recover +the value part, based only on the information contained in substrate. The +approach taken by pyasn1 decoder is to use a prototype pyasn1 type object (or +a set of them) to *guide* the decoding process by matching [possibly +incomplete] tags recovered from substrate with those found in prototype pyasn1 +type objects (also called pyasn1 specification object further in this +document). + +.. code-block:: pycon + + >>> from pyasn1.codec.ber import decoder + >>> decoder.decode(b'\x02\x01\x0c', asn1Spec=univ.Integer()) + Integer(12), b'' + >>> + +Decoder would neither modify pyasn1 specification object nor use its +current values (if it's a pyasn1 value object), but rather use it as a +hint for choosing proper decoder and as a pattern for creating new +objects: + +.. code-block:: pycon + + >>> from pyasn1.type import univ, tag + >>> from pyasn1.codec.ber import encoder, decoder + >>> i = univ.Integer(12345).subtype( + ... implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 40) + ... ) + >>> substrate = encoder.encode(i) + >>> substrate + b'\x9f(\x0209' + >>> decoder.decode(substrate) + Traceback (most recent call last): + ... + pyasn1.error.PyAsn1Error: TagSet(Tag(tagClass=128, tagFormat=0, tagId=40)) not in asn1Spec + >>> decoder.decode(substrate, asn1Spec=i) + (Integer(12345), b'') + >>> + +Notice in the example above, that an attempt to run decoder without +passing pyasn1 specification object fails because recovered tag does +not belong to any of the built-in types. + +Another important feature of guided decoder operation is the use of +values constraints possibly present in pyasn1 specification object. +To explain this, we will decode a random integer object into generic Integer +and the constrained one. + +.. code-block:: pycon + + >>> from pyasn1.type import univ, constraint + >>> from pyasn1.codec.ber import encoder, decoder + >>> class DialDigit(univ.Integer): + ... subtypeSpec = constraint.ValueRangeConstraint(0,9) + >>> substrate = encoder.encode(univ.Integer(13)) + >>> decoder.decode(substrate) + (Integer(13), b'') + >>> decoder.decode(substrate, asn1Spec=DialDigit()) + Traceback (most recent call last): + ... + ValueConstraintError: + ValueRangeConstraint(0, 9) failed at: 13 + >>> + +Similarly to encoders, to use CER or DER decoders application has to +explicitly import and call them - all APIs are compatible. + +.. code-block:: pycon + + >>> from pyasn1.type import univ + >>> from pyasn1.codec.ber import encoder as ber_encoder + >>> substrate = ber_encoder.encode(univ.OctetString('http://pyasn1.sf.net')) + >>> + >>> from pyasn1.codec.ber import decoder as ber_decoder + >>> from pyasn1.codec.cer import decoder as cer_decoder + >>> from pyasn1.codec.der import decoder as der_decoder + >>> + >>> ber_decoder.decode(substrate) + (OctetString(b'http://pyasn1.sf.net'), b'') + >>> cer_decoder.decode(substrate) + (OctetString(b'http://pyasn1.sf.net'), b'') + >>> der_decoder.decode(substrate) + (OctetString(b'http://pyasn1.sf.net'), b'') + >>> + +Advanced topics +--------------- + +Certain, non-trivial, ASN.1 data structures may require special +treatment, especially when running deserialization. + +Decoding untagged types ++++++++++++++++++++++++ + +It has already been mentioned, that ASN.1 has two "special case" +types: CHOICE and ANY. They are different from other types in part of +tagging - unless these two are additionally tagged, neither of them +will have their own tag. Therefore these types become invisible in +substrate and can not be recovered without passing pyasn1 +specification object to decoder. + +To explain the issue, we will first prepare a Choice object to deal with: + +.. code-block:: pycon + + >>> from pyasn1.type import univ, namedtype + >>> class CodeOrMessage(univ.Choice): + ... componentType = namedtype.NamedTypes( + ... namedtype.NamedType('code', univ.Integer()), + ... namedtype.NamedType('message', univ.OctetString()) + ... ) + >>> + >>> codeOrMessage = CodeOrMessage() + >>> codeOrMessage['message'] = 'my string value' + >>> print(codeOrMessage.prettyPrint()) + CodeOrMessage: + message=b'my string value' + >>> + +Let's now encode this Choice object and then decode its substrate +with and without pyasn1 specification object: + +.. code-block:: pycon + + >>> from pyasn1.codec.ber import encoder, decoder + >>> substrate = encoder.encode(codeOrMessage) + >>> substrate + b'\x04\x0fmy string value' + >>> encoder.encode(univ.OctetString('my string value')) + b'\x04\x0fmy string value' + >>> + >>> decoder.decode(substrate) + (OctetString(b'my string value'), b'') + >>> codeOrMessage, substrate = decoder.decode(substrate, + asn1Spec=CodeOrMessage()) + >>> print(codeOrMessage.prettyPrint()) + CodeOrMessage: + message=b'my string value' + >>> + +First thing to notice in the listing above is that the substrate +produced for our Choice value object is equivalent to the substrate +for an OctetString object initialized to the same value. In other +words, any information about the Choice component is absent in +encoding. + +Sure enough, that kind of substrate will decode into an OctetString +object, unless original Choice type object is passed to decoder to +guide the decoding process. + +Similarly untagged ANY type behaves differently on decoding phase - +when decoder bumps into an Any object in pyasn1 specification, it +stops decoding and puts all the substrate into a new Any value object +in form of an octet string. Concerned application could then re-run +decoder with an additional, more exact pyasn1 specification object to +recover the contents of Any object. + +As it was mentioned elsewhere in this documentation, Any type allows +for incomplete or changing ASN.1 specification to be handled +gracefully by decoder and applications. + +To illustrate the working of Any type, we'll have to make the stage by +encoding a pyasn1 object and then putting its substrate into an any +object. + +.. code-block:: pycon + + >>> from pyasn1.type import univ + >>> from pyasn1.codec.ber import encoder, decoder + >>> innerSubstrate = encoder.encode(univ.Integer(1234)) + >>> innerSubstrate + b'\x02\x02\x04\xd2' + >>> any = univ.Any(innerSubstrate) + >>> any + Any(b'\x02\x02\x04\xd2') + >>> substrate = encoder.encode(any) + >>> substrate + b'\x02\x02\x04\xd2' + >>> + +As with Choice type encoding, there is no traces of Any type in +substrate. Obviously, the substrate we are dealing with, will decode +into the inner [Integer] component, unless pyasn1 specification is +given to guide the decoder. Continuing previous code: + +.. code-block:: pycon + + >>> from pyasn1.type import univ + >>> from pyasn1.codec.ber import encoder, decoder + + >>> decoder.decode(substrate) + (Integer(1234), b'') + >>> any, substrate = decoder.decode(substrate, asn1Spec=univ.Any()) + >>> any + Any(b'\x02\x02\x04\xd2') + >>> decoder.decode(str(any)) + (Integer(1234), b'') + >>> + +Both CHOICE and ANY types are widely used in practice. Reader is welcome to +take a look at +`ASN.1 specifications of X.509 applications +<http://www.cs.auckland.ac.nz/~pgut001/pubs/x509guide.txt>`_ +for more information. + +Ignoring unknown types +++++++++++++++++++++++ + +When dealing with a loosely specified ASN.1 structure, the receiving +end may not be aware of some types present in the substrate. It may be +convenient then to turn decoder into a recovery mode. Whilst there, +decoder will not bail out when hit an unknown tag but rather treat it +as an Any type. + +.. code-block:: pycon + + >>> from pyasn1.type import univ, tag + >>> from pyasn1.codec.ber import encoder, decoder + >>> taggedInt = univ.Integer(12345).subtype( + ... implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 40) + ... ) + >>> substrate = encoder.encode(taggedInt) + >>> decoder.decode(substrate) + Traceback (most recent call last): + ... + pyasn1.error.PyAsn1Error: TagSet(Tag(tagClass=128, tagFormat=0, tagId=40)) + not in asn1Spec + >>> + >>> decoder.decode.defaultErrorState = decoder.stDumpRawValue + >>> decoder.decode(substrate) + (Any(b'\x9f(\x0209'), '') + >>> + +It's also possible to configure a custom decoder, to handle unknown +tags found in substrate. This can be done by means of +*defaultRawDecoder* attribute holding a reference to type decoder +object. Refer to the source for API details. diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1.egg-info/PKG-INFO b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1.egg-info/PKG-INFO new file mode 100644 index 00000000..45d958b1 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1.egg-info/PKG-INFO @@ -0,0 +1,35 @@ +Metadata-Version: 1.2 +Name: pyasn1 +Version: 0.4.8 +Summary: ASN.1 types and codecs +Home-page: https://github.com/etingof/pyasn1 +Author: Ilya Etingof +Author-email: etingof@gmail.com +Maintainer: Ilya Etingof <etingof@gmail.com> +License: BSD +Description: Pure-Python implementation of ASN.1 types and DER/BER/CER codecs (X.208) +Platform: any +Classifier: Development Status :: 5 - Production/Stable +Classifier: Environment :: Console +Classifier: Intended Audience :: Developers +Classifier: Intended Audience :: Education +Classifier: Intended Audience :: Information Technology +Classifier: Intended Audience :: System Administrators +Classifier: Intended Audience :: Telecommunications Industry +Classifier: License :: OSI Approved :: BSD License +Classifier: Natural Language :: English +Classifier: Operating System :: OS Independent +Classifier: Programming Language :: Python :: 2 +Classifier: Programming Language :: Python :: 2.4 +Classifier: Programming Language :: Python :: 2.5 +Classifier: Programming Language :: Python :: 2.6 +Classifier: Programming Language :: Python :: 2.7 +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3.2 +Classifier: Programming Language :: Python :: 3.3 +Classifier: Programming Language :: Python :: 3.4 +Classifier: Programming Language :: Python :: 3.5 +Classifier: Programming Language :: Python :: 3.6 +Classifier: Programming Language :: Python :: 3.7 +Classifier: Topic :: Communications +Classifier: Topic :: Software Development :: Libraries :: Python Modules diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1.egg-info/SOURCES.txt b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1.egg-info/SOURCES.txt new file mode 100644 index 00000000..4877900b --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1.egg-info/SOURCES.txt @@ -0,0 +1,161 @@ +CHANGES.rst +LICENSE.rst +MANIFEST.in +README.md +TODO.rst +setup.cfg +setup.py +docs/Makefile +docs/tutorial.rst +docs/source/changelog.rst +docs/source/conf.py +docs/source/contents.rst +docs/source/download.rst +docs/source/example-use-case.rst +docs/source/license.rst +docs/source/.static/logo.svg +docs/source/pyasn1/contents.rst +docs/source/pyasn1/codec/ber/contents.rst +docs/source/pyasn1/codec/cer/contents.rst +docs/source/pyasn1/codec/der/contents.rst +docs/source/pyasn1/codec/native/contents.rst +docs/source/pyasn1/error/contents.rst +docs/source/pyasn1/type/base/asn1type.rst +docs/source/pyasn1/type/base/constructedasn1type.rst +docs/source/pyasn1/type/base/contents.rst +docs/source/pyasn1/type/base/novalue.rst +docs/source/pyasn1/type/base/simpleasn1type.rst +docs/source/pyasn1/type/char/bmpstring.rst +docs/source/pyasn1/type/char/contents.rst +docs/source/pyasn1/type/char/generalstring.rst +docs/source/pyasn1/type/char/graphicstring.rst +docs/source/pyasn1/type/char/ia5string.rst +docs/source/pyasn1/type/char/iso646string.rst +docs/source/pyasn1/type/char/numericstring.rst +docs/source/pyasn1/type/char/printablestring.rst +docs/source/pyasn1/type/char/t61string.rst +docs/source/pyasn1/type/char/teletexstring.rst +docs/source/pyasn1/type/char/universalstring.rst +docs/source/pyasn1/type/char/utf8string.rst +docs/source/pyasn1/type/char/videotexstring.rst +docs/source/pyasn1/type/char/visiblestring.rst +docs/source/pyasn1/type/constraint/constraintsexclusion.rst +docs/source/pyasn1/type/constraint/constraintsintersection.rst +docs/source/pyasn1/type/constraint/constraintsunion.rst +docs/source/pyasn1/type/constraint/containedsubtype.rst +docs/source/pyasn1/type/constraint/contents.rst +docs/source/pyasn1/type/constraint/permittedalphabet.rst +docs/source/pyasn1/type/constraint/singlevalue.rst +docs/source/pyasn1/type/constraint/valuerange.rst +docs/source/pyasn1/type/constraint/valuesize.rst +docs/source/pyasn1/type/constraint/withcomponents.rst +docs/source/pyasn1/type/namedtype/contents.rst +docs/source/pyasn1/type/namedtype/defaultednamedtype.rst +docs/source/pyasn1/type/namedtype/namedtype.rst +docs/source/pyasn1/type/namedtype/namedtypes.rst +docs/source/pyasn1/type/namedtype/optionalnamedtype.rst +docs/source/pyasn1/type/namedval/contents.rst +docs/source/pyasn1/type/namedval/namedval.rst +docs/source/pyasn1/type/opentype/contents.rst +docs/source/pyasn1/type/opentype/opentype.rst +docs/source/pyasn1/type/tag/contents.rst +docs/source/pyasn1/type/tag/tag.rst +docs/source/pyasn1/type/tag/tagmap.rst +docs/source/pyasn1/type/tag/tagset.rst +docs/source/pyasn1/type/univ/any.rst +docs/source/pyasn1/type/univ/bitstring.rst +docs/source/pyasn1/type/univ/boolean.rst +docs/source/pyasn1/type/univ/choice.rst +docs/source/pyasn1/type/univ/contents.rst +docs/source/pyasn1/type/univ/enumerated.rst +docs/source/pyasn1/type/univ/integer.rst +docs/source/pyasn1/type/univ/null.rst +docs/source/pyasn1/type/univ/objectidentifier.rst +docs/source/pyasn1/type/univ/octetstring.rst +docs/source/pyasn1/type/univ/real.rst +docs/source/pyasn1/type/univ/sequence.rst +docs/source/pyasn1/type/univ/sequenceof.rst +docs/source/pyasn1/type/univ/set.rst +docs/source/pyasn1/type/univ/setof.rst +docs/source/pyasn1/type/useful/contents.rst +docs/source/pyasn1/type/useful/generalizedtime.rst +docs/source/pyasn1/type/useful/objectdescriptor.rst +docs/source/pyasn1/type/useful/utctime.rst +pyasn1/__init__.py +pyasn1/debug.py +pyasn1/error.py +pyasn1.egg-info/PKG-INFO +pyasn1.egg-info/SOURCES.txt +pyasn1.egg-info/dependency_links.txt +pyasn1.egg-info/top_level.txt +pyasn1.egg-info/zip-safe +pyasn1/codec/__init__.py +pyasn1/codec/ber/__init__.py +pyasn1/codec/ber/decoder.py +pyasn1/codec/ber/encoder.py +pyasn1/codec/ber/eoo.py +pyasn1/codec/cer/__init__.py +pyasn1/codec/cer/decoder.py +pyasn1/codec/cer/encoder.py +pyasn1/codec/der/__init__.py +pyasn1/codec/der/decoder.py +pyasn1/codec/der/encoder.py +pyasn1/codec/native/__init__.py +pyasn1/codec/native/decoder.py +pyasn1/codec/native/encoder.py +pyasn1/compat/__init__.py +pyasn1/compat/binary.py +pyasn1/compat/calling.py +pyasn1/compat/dateandtime.py +pyasn1/compat/integer.py +pyasn1/compat/octets.py +pyasn1/compat/string.py +pyasn1/type/__init__.py +pyasn1/type/base.py +pyasn1/type/char.py +pyasn1/type/constraint.py +pyasn1/type/error.py +pyasn1/type/namedtype.py +pyasn1/type/namedval.py +pyasn1/type/opentype.py +pyasn1/type/tag.py +pyasn1/type/tagmap.py +pyasn1/type/univ.py +pyasn1/type/useful.py +tests/__init__.py +tests/__main__.py +tests/base.py +tests/test_debug.py +tests/codec/__init__.py +tests/codec/__main__.py +tests/codec/ber/__init__.py +tests/codec/ber/__main__.py +tests/codec/ber/test_decoder.py +tests/codec/ber/test_encoder.py +tests/codec/cer/__init__.py +tests/codec/cer/__main__.py +tests/codec/cer/test_decoder.py +tests/codec/cer/test_encoder.py +tests/codec/der/__init__.py +tests/codec/der/__main__.py +tests/codec/der/test_decoder.py +tests/codec/der/test_encoder.py +tests/codec/native/__init__.py +tests/codec/native/__main__.py +tests/codec/native/test_decoder.py +tests/codec/native/test_encoder.py +tests/compat/__init__.py +tests/compat/__main__.py +tests/compat/test_binary.py +tests/compat/test_integer.py +tests/compat/test_octets.py +tests/type/__init__.py +tests/type/__main__.py +tests/type/test_char.py +tests/type/test_constraint.py +tests/type/test_namedtype.py +tests/type/test_namedval.py +tests/type/test_opentype.py +tests/type/test_tag.py +tests/type/test_univ.py +tests/type/test_useful.py \ No newline at end of file diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1.egg-info/dependency_links.txt b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1.egg-info/dependency_links.txt new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1.egg-info/dependency_links.txt @@ -0,0 +1 @@ + diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1.egg-info/top_level.txt b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1.egg-info/top_level.txt new file mode 100644 index 00000000..38fe4145 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1.egg-info/top_level.txt @@ -0,0 +1 @@ +pyasn1 diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1.egg-info/zip-safe b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1.egg-info/zip-safe new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1.egg-info/zip-safe @@ -0,0 +1 @@ + diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/__init__.py b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/__init__.py new file mode 100644 index 00000000..5a56a707 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/__init__.py @@ -0,0 +1,7 @@ +import sys + +# https://www.python.org/dev/peps/pep-0396/ +__version__ = '0.4.8' + +if sys.version_info[:2] < (2, 4): + raise RuntimeError('PyASN1 requires Python 2.4 or later') diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/__pycache__/__init__.cpython-310.pyc b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 00000000..d8927bbf Binary files /dev/null and b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/__pycache__/__init__.cpython-310.pyc differ diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/__pycache__/debug.cpython-310.pyc b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/__pycache__/debug.cpython-310.pyc new file mode 100644 index 00000000..26d59daa Binary files /dev/null and b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/__pycache__/debug.cpython-310.pyc differ diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/__pycache__/error.cpython-310.pyc b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/__pycache__/error.cpython-310.pyc new file mode 100644 index 00000000..2ca80f5e Binary files /dev/null and b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/__pycache__/error.cpython-310.pyc differ diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/codec/__init__.py b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/codec/__init__.py new file mode 100644 index 00000000..8c3066b2 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/codec/__init__.py @@ -0,0 +1 @@ +# This file is necessary to make this directory a package. diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/codec/__pycache__/__init__.cpython-310.pyc b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/codec/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 00000000..85759b59 Binary files /dev/null and b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/codec/__pycache__/__init__.cpython-310.pyc differ diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/codec/ber/__init__.py b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/codec/ber/__init__.py new file mode 100644 index 00000000..8c3066b2 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/codec/ber/__init__.py @@ -0,0 +1 @@ +# This file is necessary to make this directory a package. diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/codec/ber/__pycache__/__init__.cpython-310.pyc b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/codec/ber/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 00000000..492cfe87 Binary files /dev/null and b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/codec/ber/__pycache__/__init__.cpython-310.pyc differ diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/codec/ber/__pycache__/decoder.cpython-310.pyc b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/codec/ber/__pycache__/decoder.cpython-310.pyc new file mode 100644 index 00000000..3dcd2b58 Binary files /dev/null and b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/codec/ber/__pycache__/decoder.cpython-310.pyc differ diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/codec/ber/__pycache__/eoo.cpython-310.pyc b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/codec/ber/__pycache__/eoo.cpython-310.pyc new file mode 100644 index 00000000..3788fce8 Binary files /dev/null and b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/codec/ber/__pycache__/eoo.cpython-310.pyc differ diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/codec/ber/decoder.py b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/codec/ber/decoder.py new file mode 100644 index 00000000..5ff485fb --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/codec/ber/decoder.py @@ -0,0 +1,1682 @@ +# +# This file is part of pyasn1 software. +# +# Copyright (c) 2005-2019, Ilya Etingof <etingof@gmail.com> +# License: http://snmplabs.com/pyasn1/license.html +# +from pyasn1 import debug +from pyasn1 import error +from pyasn1.codec.ber import eoo +from pyasn1.compat.integer import from_bytes +from pyasn1.compat.octets import oct2int, octs2ints, ints2octs, null +from pyasn1.type import base +from pyasn1.type import char +from pyasn1.type import tag +from pyasn1.type import tagmap +from pyasn1.type import univ +from pyasn1.type import useful + +__all__ = ['decode'] + +LOG = debug.registerLoggee(__name__, flags=debug.DEBUG_DECODER) + +noValue = base.noValue + + +class AbstractDecoder(object): + protoComponent = None + + def valueDecoder(self, substrate, asn1Spec, + tagSet=None, length=None, state=None, + decodeFun=None, substrateFun=None, + **options): + raise error.PyAsn1Error('Decoder not implemented for %s' % (tagSet,)) + + def indefLenValueDecoder(self, substrate, asn1Spec, + tagSet=None, length=None, state=None, + decodeFun=None, substrateFun=None, + **options): + raise error.PyAsn1Error('Indefinite length mode decoder not implemented for %s' % (tagSet,)) + + +class AbstractSimpleDecoder(AbstractDecoder): + @staticmethod + def substrateCollector(asn1Object, substrate, length): + return substrate[:length], substrate[length:] + + def _createComponent(self, asn1Spec, tagSet, value, **options): + if options.get('native'): + return value + elif asn1Spec is None: + return self.protoComponent.clone(value, tagSet=tagSet) + elif value is noValue: + return asn1Spec + else: + return asn1Spec.clone(value) + + +class ExplicitTagDecoder(AbstractSimpleDecoder): + protoComponent = univ.Any('') + + def valueDecoder(self, substrate, asn1Spec, + tagSet=None, length=None, state=None, + decodeFun=None, substrateFun=None, + **options): + if substrateFun: + return substrateFun( + self._createComponent(asn1Spec, tagSet, '', **options), + substrate, length + ) + + head, tail = substrate[:length], substrate[length:] + + value, _ = decodeFun(head, asn1Spec, tagSet, length, **options) + + if LOG: + LOG('explicit tag container carries %d octets of trailing payload ' + '(will be lost!): %s' % (len(_), debug.hexdump(_))) + + return value, tail + + def indefLenValueDecoder(self, substrate, asn1Spec, + tagSet=None, length=None, state=None, + decodeFun=None, substrateFun=None, + **options): + if substrateFun: + return substrateFun( + self._createComponent(asn1Spec, tagSet, '', **options), + substrate, length + ) + + value, substrate = decodeFun(substrate, asn1Spec, tagSet, length, **options) + + eooMarker, substrate = decodeFun(substrate, allowEoo=True, **options) + + if eooMarker is eoo.endOfOctets: + return value, substrate + else: + raise error.PyAsn1Error('Missing end-of-octets terminator') + + +explicitTagDecoder = ExplicitTagDecoder() + + +class IntegerDecoder(AbstractSimpleDecoder): + protoComponent = univ.Integer(0) + + def valueDecoder(self, substrate, asn1Spec, + tagSet=None, length=None, state=None, + decodeFun=None, substrateFun=None, + **options): + + if tagSet[0].tagFormat != tag.tagFormatSimple: + raise error.PyAsn1Error('Simple tag format expected') + + head, tail = substrate[:length], substrate[length:] + + if not head: + return self._createComponent(asn1Spec, tagSet, 0, **options), tail + + value = from_bytes(head, signed=True) + + return self._createComponent(asn1Spec, tagSet, value, **options), tail + + +class BooleanDecoder(IntegerDecoder): + protoComponent = univ.Boolean(0) + + def _createComponent(self, asn1Spec, tagSet, value, **options): + return IntegerDecoder._createComponent( + self, asn1Spec, tagSet, value and 1 or 0, **options) + + +class BitStringDecoder(AbstractSimpleDecoder): + protoComponent = univ.BitString(()) + supportConstructedForm = True + + def valueDecoder(self, substrate, asn1Spec, + tagSet=None, length=None, state=None, + decodeFun=None, substrateFun=None, + **options): + head, tail = substrate[:length], substrate[length:] + + if substrateFun: + return substrateFun(self._createComponent( + asn1Spec, tagSet, noValue, **options), substrate, length) + + if not head: + raise error.PyAsn1Error('Empty BIT STRING substrate') + + if tagSet[0].tagFormat == tag.tagFormatSimple: # XXX what tag to check? + + trailingBits = oct2int(head[0]) + if trailingBits > 7: + raise error.PyAsn1Error( + 'Trailing bits overflow %s' % trailingBits + ) + + value = self.protoComponent.fromOctetString( + head[1:], internalFormat=True, padding=trailingBits) + + return self._createComponent(asn1Spec, tagSet, value, **options), tail + + if not self.supportConstructedForm: + raise error.PyAsn1Error('Constructed encoding form prohibited ' + 'at %s' % self.__class__.__name__) + + if LOG: + LOG('assembling constructed serialization') + + # All inner fragments are of the same type, treat them as octet string + substrateFun = self.substrateCollector + + bitString = self.protoComponent.fromOctetString(null, internalFormat=True) + + while head: + component, head = decodeFun(head, self.protoComponent, + substrateFun=substrateFun, **options) + + trailingBits = oct2int(component[0]) + if trailingBits > 7: + raise error.PyAsn1Error( + 'Trailing bits overflow %s' % trailingBits + ) + + bitString = self.protoComponent.fromOctetString( + component[1:], internalFormat=True, + prepend=bitString, padding=trailingBits + ) + + return self._createComponent(asn1Spec, tagSet, bitString, **options), tail + + def indefLenValueDecoder(self, substrate, asn1Spec, + tagSet=None, length=None, state=None, + decodeFun=None, substrateFun=None, + **options): + + if substrateFun: + return substrateFun(self._createComponent(asn1Spec, tagSet, noValue, **options), substrate, length) + + # All inner fragments are of the same type, treat them as octet string + substrateFun = self.substrateCollector + + bitString = self.protoComponent.fromOctetString(null, internalFormat=True) + + while substrate: + component, substrate = decodeFun(substrate, self.protoComponent, + substrateFun=substrateFun, + allowEoo=True, **options) + if component is eoo.endOfOctets: + break + + trailingBits = oct2int(component[0]) + if trailingBits > 7: + raise error.PyAsn1Error( + 'Trailing bits overflow %s' % trailingBits + ) + + bitString = self.protoComponent.fromOctetString( + component[1:], internalFormat=True, + prepend=bitString, padding=trailingBits + ) + + else: + raise error.SubstrateUnderrunError('No EOO seen before substrate ends') + + return self._createComponent(asn1Spec, tagSet, bitString, **options), substrate + + +class OctetStringDecoder(AbstractSimpleDecoder): + protoComponent = univ.OctetString('') + supportConstructedForm = True + + def valueDecoder(self, substrate, asn1Spec, + tagSet=None, length=None, state=None, + decodeFun=None, substrateFun=None, + **options): + head, tail = substrate[:length], substrate[length:] + + if substrateFun: + return substrateFun(self._createComponent(asn1Spec, tagSet, noValue, **options), + substrate, length) + + if tagSet[0].tagFormat == tag.tagFormatSimple: # XXX what tag to check? + return self._createComponent(asn1Spec, tagSet, head, **options), tail + + if not self.supportConstructedForm: + raise error.PyAsn1Error('Constructed encoding form prohibited at %s' % self.__class__.__name__) + + if LOG: + LOG('assembling constructed serialization') + + # All inner fragments are of the same type, treat them as octet string + substrateFun = self.substrateCollector + + header = null + + while head: + component, head = decodeFun(head, self.protoComponent, + substrateFun=substrateFun, + **options) + header += component + + return self._createComponent(asn1Spec, tagSet, header, **options), tail + + def indefLenValueDecoder(self, substrate, asn1Spec, + tagSet=None, length=None, state=None, + decodeFun=None, substrateFun=None, + **options): + if substrateFun and substrateFun is not self.substrateCollector: + asn1Object = self._createComponent(asn1Spec, tagSet, noValue, **options) + return substrateFun(asn1Object, substrate, length) + + # All inner fragments are of the same type, treat them as octet string + substrateFun = self.substrateCollector + + header = null + + while substrate: + component, substrate = decodeFun(substrate, + self.protoComponent, + substrateFun=substrateFun, + allowEoo=True, **options) + if component is eoo.endOfOctets: + break + + header += component + + else: + raise error.SubstrateUnderrunError( + 'No EOO seen before substrate ends' + ) + + return self._createComponent(asn1Spec, tagSet, header, **options), substrate + + +class NullDecoder(AbstractSimpleDecoder): + protoComponent = univ.Null('') + + def valueDecoder(self, substrate, asn1Spec, + tagSet=None, length=None, state=None, + decodeFun=None, substrateFun=None, + **options): + + if tagSet[0].tagFormat != tag.tagFormatSimple: + raise error.PyAsn1Error('Simple tag format expected') + + head, tail = substrate[:length], substrate[length:] + + component = self._createComponent(asn1Spec, tagSet, '', **options) + + if head: + raise error.PyAsn1Error('Unexpected %d-octet substrate for Null' % length) + + return component, tail + + +class ObjectIdentifierDecoder(AbstractSimpleDecoder): + protoComponent = univ.ObjectIdentifier(()) + + def valueDecoder(self, substrate, asn1Spec, + tagSet=None, length=None, state=None, + decodeFun=None, substrateFun=None, + **options): + if tagSet[0].tagFormat != tag.tagFormatSimple: + raise error.PyAsn1Error('Simple tag format expected') + + head, tail = substrate[:length], substrate[length:] + if not head: + raise error.PyAsn1Error('Empty substrate') + + head = octs2ints(head) + + oid = () + index = 0 + substrateLen = len(head) + while index < substrateLen: + subId = head[index] + index += 1 + if subId < 128: + oid += (subId,) + elif subId > 128: + # Construct subid from a number of octets + nextSubId = subId + subId = 0 + while nextSubId >= 128: + subId = (subId << 7) + (nextSubId & 0x7F) + if index >= substrateLen: + raise error.SubstrateUnderrunError( + 'Short substrate for sub-OID past %s' % (oid,) + ) + nextSubId = head[index] + index += 1 + oid += ((subId << 7) + nextSubId,) + elif subId == 128: + # ASN.1 spec forbids leading zeros (0x80) in OID + # encoding, tolerating it opens a vulnerability. See + # https://www.esat.kuleuven.be/cosic/publications/article-1432.pdf + # page 7 + raise error.PyAsn1Error('Invalid octet 0x80 in OID encoding') + + # Decode two leading arcs + if 0 <= oid[0] <= 39: + oid = (0,) + oid + elif 40 <= oid[0] <= 79: + oid = (1, oid[0] - 40) + oid[1:] + elif oid[0] >= 80: + oid = (2, oid[0] - 80) + oid[1:] + else: + raise error.PyAsn1Error('Malformed first OID octet: %s' % head[0]) + + return self._createComponent(asn1Spec, tagSet, oid, **options), tail + + +class RealDecoder(AbstractSimpleDecoder): + protoComponent = univ.Real() + + def valueDecoder(self, substrate, asn1Spec, + tagSet=None, length=None, state=None, + decodeFun=None, substrateFun=None, + **options): + if tagSet[0].tagFormat != tag.tagFormatSimple: + raise error.PyAsn1Error('Simple tag format expected') + + head, tail = substrate[:length], substrate[length:] + + if not head: + return self._createComponent(asn1Spec, tagSet, 0.0, **options), tail + + fo = oct2int(head[0]) + head = head[1:] + if fo & 0x80: # binary encoding + if not head: + raise error.PyAsn1Error("Incomplete floating-point value") + + if LOG: + LOG('decoding binary encoded REAL') + + n = (fo & 0x03) + 1 + + if n == 4: + n = oct2int(head[0]) + head = head[1:] + + eo, head = head[:n], head[n:] + + if not eo or not head: + raise error.PyAsn1Error('Real exponent screwed') + + e = oct2int(eo[0]) & 0x80 and -1 or 0 + + while eo: # exponent + e <<= 8 + e |= oct2int(eo[0]) + eo = eo[1:] + + b = fo >> 4 & 0x03 # base bits + + if b > 2: + raise error.PyAsn1Error('Illegal Real base') + + if b == 1: # encbase = 8 + e *= 3 + + elif b == 2: # encbase = 16 + e *= 4 + p = 0 + + while head: # value + p <<= 8 + p |= oct2int(head[0]) + head = head[1:] + + if fo & 0x40: # sign bit + p = -p + + sf = fo >> 2 & 0x03 # scale bits + p *= 2 ** sf + value = (p, 2, e) + + elif fo & 0x40: # infinite value + if LOG: + LOG('decoding infinite REAL') + + value = fo & 0x01 and '-inf' or 'inf' + + elif fo & 0xc0 == 0: # character encoding + if not head: + raise error.PyAsn1Error("Incomplete floating-point value") + + if LOG: + LOG('decoding character encoded REAL') + + try: + if fo & 0x3 == 0x1: # NR1 + value = (int(head), 10, 0) + + elif fo & 0x3 == 0x2: # NR2 + value = float(head) + + elif fo & 0x3 == 0x3: # NR3 + value = float(head) + + else: + raise error.SubstrateUnderrunError( + 'Unknown NR (tag %s)' % fo + ) + + except ValueError: + raise error.SubstrateUnderrunError( + 'Bad character Real syntax' + ) + + else: + raise error.SubstrateUnderrunError( + 'Unknown encoding (tag %s)' % fo + ) + + return self._createComponent(asn1Spec, tagSet, value, **options), tail + + +class AbstractConstructedDecoder(AbstractDecoder): + protoComponent = None + + +class UniversalConstructedTypeDecoder(AbstractConstructedDecoder): + protoRecordComponent = None + protoSequenceComponent = None + + def _getComponentTagMap(self, asn1Object, idx): + raise NotImplementedError() + + def _getComponentPositionByType(self, asn1Object, tagSet, idx): + raise NotImplementedError() + + def _decodeComponents(self, substrate, tagSet=None, decodeFun=None, **options): + components = [] + componentTypes = set() + + while substrate: + component, substrate = decodeFun(substrate, **options) + if component is eoo.endOfOctets: + break + + components.append(component) + componentTypes.add(component.tagSet) + + # Now we have to guess is it SEQUENCE/SET or SEQUENCE OF/SET OF + # The heuristics is: + # * 1+ components of different types -> likely SEQUENCE/SET + # * otherwise -> likely SEQUENCE OF/SET OF + if len(componentTypes) > 1: + protoComponent = self.protoRecordComponent + + else: + protoComponent = self.protoSequenceComponent + + asn1Object = protoComponent.clone( + # construct tagSet from base tag from prototype ASN.1 object + # and additional tags recovered from the substrate + tagSet=tag.TagSet(protoComponent.tagSet.baseTag, *tagSet.superTags) + ) + + if LOG: + LOG('guessed %r container type (pass `asn1Spec` to guide the ' + 'decoder)' % asn1Object) + + for idx, component in enumerate(components): + asn1Object.setComponentByPosition( + idx, component, + verifyConstraints=False, + matchTags=False, matchConstraints=False + ) + + return asn1Object, substrate + + def valueDecoder(self, substrate, asn1Spec, + tagSet=None, length=None, state=None, + decodeFun=None, substrateFun=None, + **options): + if tagSet[0].tagFormat != tag.tagFormatConstructed: + raise error.PyAsn1Error('Constructed tag format expected') + + head, tail = substrate[:length], substrate[length:] + + if substrateFun is not None: + if asn1Spec is not None: + asn1Object = asn1Spec.clone() + + elif self.protoComponent is not None: + asn1Object = self.protoComponent.clone(tagSet=tagSet) + + else: + asn1Object = self.protoRecordComponent, self.protoSequenceComponent + + return substrateFun(asn1Object, substrate, length) + + if asn1Spec is None: + asn1Object, trailing = self._decodeComponents( + head, tagSet=tagSet, decodeFun=decodeFun, **options + ) + + if trailing: + if LOG: + LOG('Unused trailing %d octets encountered: %s' % ( + len(trailing), debug.hexdump(trailing))) + + return asn1Object, tail + + asn1Object = asn1Spec.clone() + asn1Object.clear() + + if asn1Spec.typeId in (univ.Sequence.typeId, univ.Set.typeId): + + namedTypes = asn1Spec.componentType + + isSetType = asn1Spec.typeId == univ.Set.typeId + isDeterministic = not isSetType and not namedTypes.hasOptionalOrDefault + + if LOG: + LOG('decoding %sdeterministic %s type %r chosen by type ID' % ( + not isDeterministic and 'non-' or '', isSetType and 'SET' or '', + asn1Spec)) + + seenIndices = set() + idx = 0 + while head: + if not namedTypes: + componentType = None + + elif isSetType: + componentType = namedTypes.tagMapUnique + + else: + try: + if isDeterministic: + componentType = namedTypes[idx].asn1Object + + elif namedTypes[idx].isOptional or namedTypes[idx].isDefaulted: + componentType = namedTypes.getTagMapNearPosition(idx) + + else: + componentType = namedTypes[idx].asn1Object + + except IndexError: + raise error.PyAsn1Error( + 'Excessive components decoded at %r' % (asn1Spec,) + ) + + component, head = decodeFun(head, componentType, **options) + + if not isDeterministic and namedTypes: + if isSetType: + idx = namedTypes.getPositionByType(component.effectiveTagSet) + + elif namedTypes[idx].isOptional or namedTypes[idx].isDefaulted: + idx = namedTypes.getPositionNearType(component.effectiveTagSet, idx) + + asn1Object.setComponentByPosition( + idx, component, + verifyConstraints=False, + matchTags=False, matchConstraints=False + ) + + seenIndices.add(idx) + idx += 1 + + if LOG: + LOG('seen component indices %s' % seenIndices) + + if namedTypes: + if not namedTypes.requiredComponents.issubset(seenIndices): + raise error.PyAsn1Error( + 'ASN.1 object %s has uninitialized ' + 'components' % asn1Object.__class__.__name__) + + if namedTypes.hasOpenTypes: + + openTypes = options.get('openTypes', {}) + + if LOG: + LOG('user-specified open types map:') + + for k, v in openTypes.items(): + LOG('%s -> %r' % (k, v)) + + if openTypes or options.get('decodeOpenTypes', False): + + for idx, namedType in enumerate(namedTypes.namedTypes): + if not namedType.openType: + continue + + if namedType.isOptional and not asn1Object.getComponentByPosition(idx).isValue: + continue + + governingValue = asn1Object.getComponentByName( + namedType.openType.name + ) + + try: + openType = openTypes[governingValue] + + except KeyError: + + if LOG: + LOG('default open types map of component ' + '"%s.%s" governed by component "%s.%s"' + ':' % (asn1Object.__class__.__name__, + namedType.name, + asn1Object.__class__.__name__, + namedType.openType.name)) + + for k, v in namedType.openType.items(): + LOG('%s -> %r' % (k, v)) + + try: + openType = namedType.openType[governingValue] + + except KeyError: + if LOG: + LOG('failed to resolve open type by governing ' + 'value %r' % (governingValue,)) + continue + + if LOG: + LOG('resolved open type %r by governing ' + 'value %r' % (openType, governingValue)) + + containerValue = asn1Object.getComponentByPosition(idx) + + if containerValue.typeId in ( + univ.SetOf.typeId, univ.SequenceOf.typeId): + + for pos, containerElement in enumerate( + containerValue): + + component, rest = decodeFun( + containerValue[pos].asOctets(), + asn1Spec=openType, **options + ) + + containerValue[pos] = component + + else: + component, rest = decodeFun( + asn1Object.getComponentByPosition(idx).asOctets(), + asn1Spec=openType, **options + ) + + asn1Object.setComponentByPosition(idx, component) + + else: + inconsistency = asn1Object.isInconsistent + if inconsistency: + raise inconsistency + + else: + asn1Object = asn1Spec.clone() + asn1Object.clear() + + componentType = asn1Spec.componentType + + if LOG: + LOG('decoding type %r chosen by given `asn1Spec`' % componentType) + + idx = 0 + + while head: + component, head = decodeFun(head, componentType, **options) + asn1Object.setComponentByPosition( + idx, component, + verifyConstraints=False, + matchTags=False, matchConstraints=False + ) + + idx += 1 + + return asn1Object, tail + + def indefLenValueDecoder(self, substrate, asn1Spec, + tagSet=None, length=None, state=None, + decodeFun=None, substrateFun=None, + **options): + if tagSet[0].tagFormat != tag.tagFormatConstructed: + raise error.PyAsn1Error('Constructed tag format expected') + + if substrateFun is not None: + if asn1Spec is not None: + asn1Object = asn1Spec.clone() + + elif self.protoComponent is not None: + asn1Object = self.protoComponent.clone(tagSet=tagSet) + + else: + asn1Object = self.protoRecordComponent, self.protoSequenceComponent + + return substrateFun(asn1Object, substrate, length) + + if asn1Spec is None: + return self._decodeComponents( + substrate, tagSet=tagSet, decodeFun=decodeFun, + **dict(options, allowEoo=True) + ) + + asn1Object = asn1Spec.clone() + asn1Object.clear() + + if asn1Spec.typeId in (univ.Sequence.typeId, univ.Set.typeId): + + namedTypes = asn1Object.componentType + + isSetType = asn1Object.typeId == univ.Set.typeId + isDeterministic = not isSetType and not namedTypes.hasOptionalOrDefault + + if LOG: + LOG('decoding %sdeterministic %s type %r chosen by type ID' % ( + not isDeterministic and 'non-' or '', isSetType and 'SET' or '', + asn1Spec)) + + seenIndices = set() + idx = 0 + while substrate: + if len(namedTypes) <= idx: + asn1Spec = None + + elif isSetType: + asn1Spec = namedTypes.tagMapUnique + + else: + try: + if isDeterministic: + asn1Spec = namedTypes[idx].asn1Object + + elif namedTypes[idx].isOptional or namedTypes[idx].isDefaulted: + asn1Spec = namedTypes.getTagMapNearPosition(idx) + + else: + asn1Spec = namedTypes[idx].asn1Object + + except IndexError: + raise error.PyAsn1Error( + 'Excessive components decoded at %r' % (asn1Object,) + ) + + component, substrate = decodeFun(substrate, asn1Spec, allowEoo=True, **options) + if component is eoo.endOfOctets: + break + + if not isDeterministic and namedTypes: + if isSetType: + idx = namedTypes.getPositionByType(component.effectiveTagSet) + elif namedTypes[idx].isOptional or namedTypes[idx].isDefaulted: + idx = namedTypes.getPositionNearType(component.effectiveTagSet, idx) + + asn1Object.setComponentByPosition( + idx, component, + verifyConstraints=False, + matchTags=False, matchConstraints=False + ) + + seenIndices.add(idx) + idx += 1 + + else: + raise error.SubstrateUnderrunError( + 'No EOO seen before substrate ends' + ) + + if LOG: + LOG('seen component indices %s' % seenIndices) + + if namedTypes: + if not namedTypes.requiredComponents.issubset(seenIndices): + raise error.PyAsn1Error('ASN.1 object %s has uninitialized components' % asn1Object.__class__.__name__) + + if namedTypes.hasOpenTypes: + + openTypes = options.get('openTypes', {}) + + if LOG: + LOG('user-specified open types map:') + + for k, v in openTypes.items(): + LOG('%s -> %r' % (k, v)) + + if openTypes or options.get('decodeOpenTypes', False): + + for idx, namedType in enumerate(namedTypes.namedTypes): + if not namedType.openType: + continue + + if namedType.isOptional and not asn1Object.getComponentByPosition(idx).isValue: + continue + + governingValue = asn1Object.getComponentByName( + namedType.openType.name + ) + + try: + openType = openTypes[governingValue] + + except KeyError: + + if LOG: + LOG('default open types map of component ' + '"%s.%s" governed by component "%s.%s"' + ':' % (asn1Object.__class__.__name__, + namedType.name, + asn1Object.__class__.__name__, + namedType.openType.name)) + + for k, v in namedType.openType.items(): + LOG('%s -> %r' % (k, v)) + + try: + openType = namedType.openType[governingValue] + + except KeyError: + if LOG: + LOG('failed to resolve open type by governing ' + 'value %r' % (governingValue,)) + continue + + if LOG: + LOG('resolved open type %r by governing ' + 'value %r' % (openType, governingValue)) + + containerValue = asn1Object.getComponentByPosition(idx) + + if containerValue.typeId in ( + univ.SetOf.typeId, univ.SequenceOf.typeId): + + for pos, containerElement in enumerate( + containerValue): + + component, rest = decodeFun( + containerValue[pos].asOctets(), + asn1Spec=openType, **dict(options, allowEoo=True) + ) + + containerValue[pos] = component + + else: + component, rest = decodeFun( + asn1Object.getComponentByPosition(idx).asOctets(), + asn1Spec=openType, **dict(options, allowEoo=True) + ) + + if component is not eoo.endOfOctets: + asn1Object.setComponentByPosition(idx, component) + + else: + inconsistency = asn1Object.isInconsistent + if inconsistency: + raise inconsistency + + else: + asn1Object = asn1Spec.clone() + asn1Object.clear() + + componentType = asn1Spec.componentType + + if LOG: + LOG('decoding type %r chosen by given `asn1Spec`' % componentType) + + idx = 0 + + while substrate: + component, substrate = decodeFun(substrate, componentType, allowEoo=True, **options) + + if component is eoo.endOfOctets: + break + + asn1Object.setComponentByPosition( + idx, component, + verifyConstraints=False, + matchTags=False, matchConstraints=False + ) + + idx += 1 + + else: + raise error.SubstrateUnderrunError( + 'No EOO seen before substrate ends' + ) + + return asn1Object, substrate + + +class SequenceOrSequenceOfDecoder(UniversalConstructedTypeDecoder): + protoRecordComponent = univ.Sequence() + protoSequenceComponent = univ.SequenceOf() + + +class SequenceDecoder(SequenceOrSequenceOfDecoder): + protoComponent = univ.Sequence() + + +class SequenceOfDecoder(SequenceOrSequenceOfDecoder): + protoComponent = univ.SequenceOf() + + +class SetOrSetOfDecoder(UniversalConstructedTypeDecoder): + protoRecordComponent = univ.Set() + protoSequenceComponent = univ.SetOf() + + +class SetDecoder(SetOrSetOfDecoder): + protoComponent = univ.Set() + + + +class SetOfDecoder(SetOrSetOfDecoder): + protoComponent = univ.SetOf() + + +class ChoiceDecoder(AbstractConstructedDecoder): + protoComponent = univ.Choice() + + def valueDecoder(self, substrate, asn1Spec, + tagSet=None, length=None, state=None, + decodeFun=None, substrateFun=None, + **options): + head, tail = substrate[:length], substrate[length:] + + if asn1Spec is None: + asn1Object = self.protoComponent.clone(tagSet=tagSet) + + else: + asn1Object = asn1Spec.clone() + + if substrateFun: + return substrateFun(asn1Object, substrate, length) + + if asn1Object.tagSet == tagSet: + if LOG: + LOG('decoding %s as explicitly tagged CHOICE' % (tagSet,)) + + component, head = decodeFun( + head, asn1Object.componentTagMap, **options + ) + + else: + if LOG: + LOG('decoding %s as untagged CHOICE' % (tagSet,)) + + component, head = decodeFun( + head, asn1Object.componentTagMap, + tagSet, length, state, **options + ) + + effectiveTagSet = component.effectiveTagSet + + if LOG: + LOG('decoded component %s, effective tag set %s' % (component, effectiveTagSet)) + + asn1Object.setComponentByType( + effectiveTagSet, component, + verifyConstraints=False, + matchTags=False, matchConstraints=False, + innerFlag=False + ) + + return asn1Object, tail + + def indefLenValueDecoder(self, substrate, asn1Spec, + tagSet=None, length=None, state=None, + decodeFun=None, substrateFun=None, + **options): + if asn1Spec is None: + asn1Object = self.protoComponent.clone(tagSet=tagSet) + else: + asn1Object = asn1Spec.clone() + + if substrateFun: + return substrateFun(asn1Object, substrate, length) + + if asn1Object.tagSet == tagSet: + if LOG: + LOG('decoding %s as explicitly tagged CHOICE' % (tagSet,)) + + component, substrate = decodeFun( + substrate, asn1Object.componentType.tagMapUnique, **options + ) + + # eat up EOO marker + eooMarker, substrate = decodeFun( + substrate, allowEoo=True, **options + ) + + if eooMarker is not eoo.endOfOctets: + raise error.PyAsn1Error('No EOO seen before substrate ends') + + else: + if LOG: + LOG('decoding %s as untagged CHOICE' % (tagSet,)) + + component, substrate = decodeFun( + substrate, asn1Object.componentType.tagMapUnique, + tagSet, length, state, **options + ) + + effectiveTagSet = component.effectiveTagSet + + if LOG: + LOG('decoded component %s, effective tag set %s' % (component, effectiveTagSet)) + + asn1Object.setComponentByType( + effectiveTagSet, component, + verifyConstraints=False, + matchTags=False, matchConstraints=False, + innerFlag=False + ) + + return asn1Object, substrate + + +class AnyDecoder(AbstractSimpleDecoder): + protoComponent = univ.Any() + + def valueDecoder(self, substrate, asn1Spec, + tagSet=None, length=None, state=None, + decodeFun=None, substrateFun=None, + **options): + if asn1Spec is None: + isUntagged = True + + elif asn1Spec.__class__ is tagmap.TagMap: + isUntagged = tagSet not in asn1Spec.tagMap + + else: + isUntagged = tagSet != asn1Spec.tagSet + + if isUntagged: + fullSubstrate = options['fullSubstrate'] + + # untagged Any container, recover inner header substrate + length += len(fullSubstrate) - len(substrate) + substrate = fullSubstrate + + if LOG: + LOG('decoding as untagged ANY, substrate %s' % debug.hexdump(substrate)) + + if substrateFun: + return substrateFun(self._createComponent(asn1Spec, tagSet, noValue, **options), + substrate, length) + + head, tail = substrate[:length], substrate[length:] + + return self._createComponent(asn1Spec, tagSet, head, **options), tail + + def indefLenValueDecoder(self, substrate, asn1Spec, + tagSet=None, length=None, state=None, + decodeFun=None, substrateFun=None, + **options): + if asn1Spec is None: + isTagged = False + + elif asn1Spec.__class__ is tagmap.TagMap: + isTagged = tagSet in asn1Spec.tagMap + + else: + isTagged = tagSet == asn1Spec.tagSet + + if isTagged: + # tagged Any type -- consume header substrate + header = null + + if LOG: + LOG('decoding as tagged ANY') + + else: + fullSubstrate = options['fullSubstrate'] + + # untagged Any, recover header substrate + header = fullSubstrate[:-len(substrate)] + + if LOG: + LOG('decoding as untagged ANY, header substrate %s' % debug.hexdump(header)) + + # Any components do not inherit initial tag + asn1Spec = self.protoComponent + + if substrateFun and substrateFun is not self.substrateCollector: + asn1Object = self._createComponent(asn1Spec, tagSet, noValue, **options) + return substrateFun(asn1Object, header + substrate, length + len(header)) + + if LOG: + LOG('assembling constructed serialization') + + # All inner fragments are of the same type, treat them as octet string + substrateFun = self.substrateCollector + + while substrate: + component, substrate = decodeFun(substrate, asn1Spec, + substrateFun=substrateFun, + allowEoo=True, **options) + if component is eoo.endOfOctets: + break + + header += component + + else: + raise error.SubstrateUnderrunError( + 'No EOO seen before substrate ends' + ) + + if substrateFun: + return header, substrate + + else: + return self._createComponent(asn1Spec, tagSet, header, **options), substrate + + +# character string types +class UTF8StringDecoder(OctetStringDecoder): + protoComponent = char.UTF8String() + + +class NumericStringDecoder(OctetStringDecoder): + protoComponent = char.NumericString() + + +class PrintableStringDecoder(OctetStringDecoder): + protoComponent = char.PrintableString() + + +class TeletexStringDecoder(OctetStringDecoder): + protoComponent = char.TeletexString() + + +class VideotexStringDecoder(OctetStringDecoder): + protoComponent = char.VideotexString() + + +class IA5StringDecoder(OctetStringDecoder): + protoComponent = char.IA5String() + + +class GraphicStringDecoder(OctetStringDecoder): + protoComponent = char.GraphicString() + + +class VisibleStringDecoder(OctetStringDecoder): + protoComponent = char.VisibleString() + + +class GeneralStringDecoder(OctetStringDecoder): + protoComponent = char.GeneralString() + + +class UniversalStringDecoder(OctetStringDecoder): + protoComponent = char.UniversalString() + + +class BMPStringDecoder(OctetStringDecoder): + protoComponent = char.BMPString() + + +# "useful" types +class ObjectDescriptorDecoder(OctetStringDecoder): + protoComponent = useful.ObjectDescriptor() + + +class GeneralizedTimeDecoder(OctetStringDecoder): + protoComponent = useful.GeneralizedTime() + + +class UTCTimeDecoder(OctetStringDecoder): + protoComponent = useful.UTCTime() + + +tagMap = { + univ.Integer.tagSet: IntegerDecoder(), + univ.Boolean.tagSet: BooleanDecoder(), + univ.BitString.tagSet: BitStringDecoder(), + univ.OctetString.tagSet: OctetStringDecoder(), + univ.Null.tagSet: NullDecoder(), + univ.ObjectIdentifier.tagSet: ObjectIdentifierDecoder(), + univ.Enumerated.tagSet: IntegerDecoder(), + univ.Real.tagSet: RealDecoder(), + univ.Sequence.tagSet: SequenceOrSequenceOfDecoder(), # conflicts with SequenceOf + univ.Set.tagSet: SetOrSetOfDecoder(), # conflicts with SetOf + univ.Choice.tagSet: ChoiceDecoder(), # conflicts with Any + # character string types + char.UTF8String.tagSet: UTF8StringDecoder(), + char.NumericString.tagSet: NumericStringDecoder(), + char.PrintableString.tagSet: PrintableStringDecoder(), + char.TeletexString.tagSet: TeletexStringDecoder(), + char.VideotexString.tagSet: VideotexStringDecoder(), + char.IA5String.tagSet: IA5StringDecoder(), + char.GraphicString.tagSet: GraphicStringDecoder(), + char.VisibleString.tagSet: VisibleStringDecoder(), + char.GeneralString.tagSet: GeneralStringDecoder(), + char.UniversalString.tagSet: UniversalStringDecoder(), + char.BMPString.tagSet: BMPStringDecoder(), + # useful types + useful.ObjectDescriptor.tagSet: ObjectDescriptorDecoder(), + useful.GeneralizedTime.tagSet: GeneralizedTimeDecoder(), + useful.UTCTime.tagSet: UTCTimeDecoder() +} + +# Type-to-codec map for ambiguous ASN.1 types +typeMap = { + univ.Set.typeId: SetDecoder(), + univ.SetOf.typeId: SetOfDecoder(), + univ.Sequence.typeId: SequenceDecoder(), + univ.SequenceOf.typeId: SequenceOfDecoder(), + univ.Choice.typeId: ChoiceDecoder(), + univ.Any.typeId: AnyDecoder() +} + +# Put in non-ambiguous types for faster codec lookup +for typeDecoder in tagMap.values(): + if typeDecoder.protoComponent is not None: + typeId = typeDecoder.protoComponent.__class__.typeId + if typeId is not None and typeId not in typeMap: + typeMap[typeId] = typeDecoder + + +(stDecodeTag, + stDecodeLength, + stGetValueDecoder, + stGetValueDecoderByAsn1Spec, + stGetValueDecoderByTag, + stTryAsExplicitTag, + stDecodeValue, + stDumpRawValue, + stErrorCondition, + stStop) = [x for x in range(10)] + + +class Decoder(object): + defaultErrorState = stErrorCondition + #defaultErrorState = stDumpRawValue + defaultRawDecoder = AnyDecoder() + supportIndefLength = True + + # noinspection PyDefaultArgument + def __init__(self, tagMap, typeMap={}): + self.__tagMap = tagMap + self.__typeMap = typeMap + # Tag & TagSet objects caches + self.__tagCache = {} + self.__tagSetCache = {} + self.__eooSentinel = ints2octs((0, 0)) + + def __call__(self, substrate, asn1Spec=None, + tagSet=None, length=None, state=stDecodeTag, + decodeFun=None, substrateFun=None, + **options): + + if LOG: + LOG('decoder called at scope %s with state %d, working with up to %d octets of substrate: %s' % (debug.scope, state, len(substrate), debug.hexdump(substrate))) + + allowEoo = options.pop('allowEoo', False) + + # Look for end-of-octets sentinel + if allowEoo and self.supportIndefLength: + if substrate[:2] == self.__eooSentinel: + if LOG: + LOG('end-of-octets sentinel found') + return eoo.endOfOctets, substrate[2:] + + value = noValue + + tagMap = self.__tagMap + typeMap = self.__typeMap + tagCache = self.__tagCache + tagSetCache = self.__tagSetCache + + fullSubstrate = substrate + + while state is not stStop: + + if state is stDecodeTag: + if not substrate: + raise error.SubstrateUnderrunError( + 'Short octet stream on tag decoding' + ) + + # Decode tag + isShortTag = True + firstOctet = substrate[0] + substrate = substrate[1:] + + try: + lastTag = tagCache[firstOctet] + + except KeyError: + integerTag = oct2int(firstOctet) + tagClass = integerTag & 0xC0 + tagFormat = integerTag & 0x20 + tagId = integerTag & 0x1F + + if tagId == 0x1F: + isShortTag = False + lengthOctetIdx = 0 + tagId = 0 + + try: + while True: + integerTag = oct2int(substrate[lengthOctetIdx]) + lengthOctetIdx += 1 + tagId <<= 7 + tagId |= (integerTag & 0x7F) + if not integerTag & 0x80: + break + + substrate = substrate[lengthOctetIdx:] + + except IndexError: + raise error.SubstrateUnderrunError( + 'Short octet stream on long tag decoding' + ) + + lastTag = tag.Tag( + tagClass=tagClass, tagFormat=tagFormat, tagId=tagId + ) + + if isShortTag: + # cache short tags + tagCache[firstOctet] = lastTag + + if tagSet is None: + if isShortTag: + try: + tagSet = tagSetCache[firstOctet] + + except KeyError: + # base tag not recovered + tagSet = tag.TagSet((), lastTag) + tagSetCache[firstOctet] = tagSet + else: + tagSet = tag.TagSet((), lastTag) + + else: + tagSet = lastTag + tagSet + + state = stDecodeLength + + if LOG: + LOG('tag decoded into %s, decoding length' % tagSet) + + if state is stDecodeLength: + # Decode length + if not substrate: + raise error.SubstrateUnderrunError( + 'Short octet stream on length decoding' + ) + + firstOctet = oct2int(substrate[0]) + + if firstOctet < 128: + size = 1 + length = firstOctet + + elif firstOctet > 128: + size = firstOctet & 0x7F + # encoded in size bytes + encodedLength = octs2ints(substrate[1:size + 1]) + # missing check on maximum size, which shouldn't be a + # problem, we can handle more than is possible + if len(encodedLength) != size: + raise error.SubstrateUnderrunError( + '%s<%s at %s' % (size, len(encodedLength), tagSet) + ) + + length = 0 + for lengthOctet in encodedLength: + length <<= 8 + length |= lengthOctet + size += 1 + + else: + size = 1 + length = -1 + + substrate = substrate[size:] + + if length == -1: + if not self.supportIndefLength: + raise error.PyAsn1Error('Indefinite length encoding not supported by this codec') + + else: + if len(substrate) < length: + raise error.SubstrateUnderrunError('%d-octet short' % (length - len(substrate))) + + state = stGetValueDecoder + + if LOG: + LOG('value length decoded into %d, payload substrate is: %s' % (length, debug.hexdump(length == -1 and substrate or substrate[:length]))) + + if state is stGetValueDecoder: + if asn1Spec is None: + state = stGetValueDecoderByTag + + else: + state = stGetValueDecoderByAsn1Spec + # + # There're two ways of creating subtypes in ASN.1 what influences + # decoder operation. These methods are: + # 1) Either base types used in or no IMPLICIT tagging has been + # applied on subtyping. + # 2) Subtype syntax drops base type information (by means of + # IMPLICIT tagging. + # The first case allows for complete tag recovery from substrate + # while the second one requires original ASN.1 type spec for + # decoding. + # + # In either case a set of tags (tagSet) is coming from substrate + # in an incremental, tag-by-tag fashion (this is the case of + # EXPLICIT tag which is most basic). Outermost tag comes first + # from the wire. + # + if state is stGetValueDecoderByTag: + try: + concreteDecoder = tagMap[tagSet] + + except KeyError: + concreteDecoder = None + + if concreteDecoder: + state = stDecodeValue + + else: + try: + concreteDecoder = tagMap[tagSet[:1]] + + except KeyError: + concreteDecoder = None + + if concreteDecoder: + state = stDecodeValue + else: + state = stTryAsExplicitTag + + if LOG: + LOG('codec %s chosen by a built-in type, decoding %s' % (concreteDecoder and concreteDecoder.__class__.__name__ or "<none>", state is stDecodeValue and 'value' or 'as explicit tag')) + debug.scope.push(concreteDecoder is None and '?' or concreteDecoder.protoComponent.__class__.__name__) + + if state is stGetValueDecoderByAsn1Spec: + + if asn1Spec.__class__ is tagmap.TagMap: + try: + chosenSpec = asn1Spec[tagSet] + + except KeyError: + chosenSpec = None + + if LOG: + LOG('candidate ASN.1 spec is a map of:') + + for firstOctet, v in asn1Spec.presentTypes.items(): + LOG(' %s -> %s' % (firstOctet, v.__class__.__name__)) + + if asn1Spec.skipTypes: + LOG('but neither of: ') + for firstOctet, v in asn1Spec.skipTypes.items(): + LOG(' %s -> %s' % (firstOctet, v.__class__.__name__)) + LOG('new candidate ASN.1 spec is %s, chosen by %s' % (chosenSpec is None and '<none>' or chosenSpec.prettyPrintType(), tagSet)) + + elif tagSet == asn1Spec.tagSet or tagSet in asn1Spec.tagMap: + chosenSpec = asn1Spec + if LOG: + LOG('candidate ASN.1 spec is %s' % asn1Spec.__class__.__name__) + + else: + chosenSpec = None + + if chosenSpec is not None: + try: + # ambiguous type or just faster codec lookup + concreteDecoder = typeMap[chosenSpec.typeId] + + if LOG: + LOG('value decoder chosen for an ambiguous type by type ID %s' % (chosenSpec.typeId,)) + + except KeyError: + # use base type for codec lookup to recover untagged types + baseTagSet = tag.TagSet(chosenSpec.tagSet.baseTag, chosenSpec.tagSet.baseTag) + try: + # base type or tagged subtype + concreteDecoder = tagMap[baseTagSet] + + if LOG: + LOG('value decoder chosen by base %s' % (baseTagSet,)) + + except KeyError: + concreteDecoder = None + + if concreteDecoder: + asn1Spec = chosenSpec + state = stDecodeValue + + else: + state = stTryAsExplicitTag + + else: + concreteDecoder = None + state = stTryAsExplicitTag + + if LOG: + LOG('codec %s chosen by ASN.1 spec, decoding %s' % (state is stDecodeValue and concreteDecoder.__class__.__name__ or "<none>", state is stDecodeValue and 'value' or 'as explicit tag')) + debug.scope.push(chosenSpec is None and '?' or chosenSpec.__class__.__name__) + + if state is stDecodeValue: + if not options.get('recursiveFlag', True) and not substrateFun: # deprecate this + substrateFun = lambda a, b, c: (a, b[:c]) + + options.update(fullSubstrate=fullSubstrate) + + if length == -1: # indef length + value, substrate = concreteDecoder.indefLenValueDecoder( + substrate, asn1Spec, + tagSet, length, stGetValueDecoder, + self, substrateFun, + **options + ) + + else: + value, substrate = concreteDecoder.valueDecoder( + substrate, asn1Spec, + tagSet, length, stGetValueDecoder, + self, substrateFun, + **options + ) + + if LOG: + LOG('codec %s yields type %s, value:\n%s\n...remaining substrate is: %s' % (concreteDecoder.__class__.__name__, value.__class__.__name__, isinstance(value, base.Asn1Item) and value.prettyPrint() or value, substrate and debug.hexdump(substrate) or '<none>')) + + state = stStop + break + + if state is stTryAsExplicitTag: + if (tagSet and + tagSet[0].tagFormat == tag.tagFormatConstructed and + tagSet[0].tagClass != tag.tagClassUniversal): + # Assume explicit tagging + concreteDecoder = explicitTagDecoder + state = stDecodeValue + + else: + concreteDecoder = None + state = self.defaultErrorState + + if LOG: + LOG('codec %s chosen, decoding %s' % (concreteDecoder and concreteDecoder.__class__.__name__ or "<none>", state is stDecodeValue and 'value' or 'as failure')) + + if state is stDumpRawValue: + concreteDecoder = self.defaultRawDecoder + + if LOG: + LOG('codec %s chosen, decoding value' % concreteDecoder.__class__.__name__) + + state = stDecodeValue + + if state is stErrorCondition: + raise error.PyAsn1Error( + '%s not in asn1Spec: %r' % (tagSet, asn1Spec) + ) + + if LOG: + debug.scope.pop() + LOG('decoder left scope %s, call completed' % debug.scope) + + return value, substrate + + +#: Turns BER octet stream into an ASN.1 object. +#: +#: Takes BER octet-stream and decode it into an ASN.1 object +#: (e.g. :py:class:`~pyasn1.type.base.PyAsn1Item` derivative) which +#: may be a scalar or an arbitrary nested structure. +#: +#: Parameters +#: ---------- +#: substrate: :py:class:`bytes` (Python 3) or :py:class:`str` (Python 2) +#: BER octet-stream +#: +#: Keyword Args +#: ------------ +#: asn1Spec: any pyasn1 type object e.g. :py:class:`~pyasn1.type.base.PyAsn1Item` derivative +#: A pyasn1 type object to act as a template guiding the decoder. Depending on the ASN.1 structure +#: being decoded, *asn1Spec* may or may not be required. Most common reason for +#: it to require is that ASN.1 structure is encoded in *IMPLICIT* tagging mode. +#: +#: Returns +#: ------- +#: : :py:class:`tuple` +#: A tuple of pyasn1 object recovered from BER substrate (:py:class:`~pyasn1.type.base.PyAsn1Item` derivative) +#: and the unprocessed trailing portion of the *substrate* (may be empty) +#: +#: Raises +#: ------ +#: ~pyasn1.error.PyAsn1Error, ~pyasn1.error.SubstrateUnderrunError +#: On decoding errors +#: +#: Examples +#: -------- +#: Decode BER serialisation without ASN.1 schema +#: +#: .. code-block:: pycon +#: +#: >>> s, _ = decode(b'0\t\x02\x01\x01\x02\x01\x02\x02\x01\x03') +#: >>> str(s) +#: SequenceOf: +#: 1 2 3 +#: +#: Decode BER serialisation with ASN.1 schema +#: +#: .. code-block:: pycon +#: +#: >>> seq = SequenceOf(componentType=Integer()) +#: >>> s, _ = decode(b'0\t\x02\x01\x01\x02\x01\x02\x02\x01\x03', asn1Spec=seq) +#: >>> str(s) +#: SequenceOf: +#: 1 2 3 +#: +decode = Decoder(tagMap, typeMap) + +# XXX +# non-recursive decoding; return position rather than substrate diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/codec/ber/encoder.py b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/codec/ber/encoder.py new file mode 100644 index 00000000..778aa867 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/codec/ber/encoder.py @@ -0,0 +1,890 @@ +# +# This file is part of pyasn1 software. +# +# Copyright (c) 2005-2019, Ilya Etingof <etingof@gmail.com> +# License: http://snmplabs.com/pyasn1/license.html +# +import sys + +from pyasn1 import debug +from pyasn1 import error +from pyasn1.codec.ber import eoo +from pyasn1.compat.integer import to_bytes +from pyasn1.compat.octets import (int2oct, oct2int, ints2octs, null, + str2octs, isOctetsType) +from pyasn1.type import char +from pyasn1.type import tag +from pyasn1.type import univ +from pyasn1.type import useful + +__all__ = ['encode'] + +LOG = debug.registerLoggee(__name__, flags=debug.DEBUG_ENCODER) + + +class AbstractItemEncoder(object): + supportIndefLenMode = True + + # An outcome of otherwise legit call `encodeFun(eoo.endOfOctets)` + eooIntegerSubstrate = (0, 0) + eooOctetsSubstrate = ints2octs(eooIntegerSubstrate) + + # noinspection PyMethodMayBeStatic + def encodeTag(self, singleTag, isConstructed): + tagClass, tagFormat, tagId = singleTag + encodedTag = tagClass | tagFormat + if isConstructed: + encodedTag |= tag.tagFormatConstructed + + if tagId < 31: + return encodedTag | tagId, + + else: + substrate = tagId & 0x7f, + + tagId >>= 7 + + while tagId: + substrate = (0x80 | (tagId & 0x7f),) + substrate + tagId >>= 7 + + return (encodedTag | 0x1F,) + substrate + + def encodeLength(self, length, defMode): + if not defMode and self.supportIndefLenMode: + return (0x80,) + + if length < 0x80: + return length, + + else: + substrate = () + while length: + substrate = (length & 0xff,) + substrate + length >>= 8 + + substrateLen = len(substrate) + + if substrateLen > 126: + raise error.PyAsn1Error('Length octets overflow (%d)' % substrateLen) + + return (0x80 | substrateLen,) + substrate + + def encodeValue(self, value, asn1Spec, encodeFun, **options): + raise error.PyAsn1Error('Not implemented') + + def encode(self, value, asn1Spec=None, encodeFun=None, **options): + + if asn1Spec is None: + tagSet = value.tagSet + else: + tagSet = asn1Spec.tagSet + + # untagged item? + if not tagSet: + substrate, isConstructed, isOctets = self.encodeValue( + value, asn1Spec, encodeFun, **options + ) + return substrate + + defMode = options.get('defMode', True) + + substrate = null + + for idx, singleTag in enumerate(tagSet.superTags): + + defModeOverride = defMode + + # base tag? + if not idx: + try: + substrate, isConstructed, isOctets = self.encodeValue( + value, asn1Spec, encodeFun, **options + ) + + except error.PyAsn1Error: + exc = sys.exc_info() + raise error.PyAsn1Error( + 'Error encoding %r: %s' % (value, exc[1])) + + if LOG: + LOG('encoded %svalue %s into %s' % ( + isConstructed and 'constructed ' or '', value, substrate + )) + + if not substrate and isConstructed and options.get('ifNotEmpty', False): + return substrate + + if not isConstructed: + defModeOverride = True + + if LOG: + LOG('overridden encoding mode into definitive for primitive type') + + header = self.encodeTag(singleTag, isConstructed) + + if LOG: + LOG('encoded %stag %s into %s' % ( + isConstructed and 'constructed ' or '', + singleTag, debug.hexdump(ints2octs(header)))) + + header += self.encodeLength(len(substrate), defModeOverride) + + if LOG: + LOG('encoded %s octets (tag + payload) into %s' % ( + len(substrate), debug.hexdump(ints2octs(header)))) + + if isOctets: + substrate = ints2octs(header) + substrate + + if not defModeOverride: + substrate += self.eooOctetsSubstrate + + else: + substrate = header + substrate + + if not defModeOverride: + substrate += self.eooIntegerSubstrate + + if not isOctets: + substrate = ints2octs(substrate) + + return substrate + + +class EndOfOctetsEncoder(AbstractItemEncoder): + def encodeValue(self, value, asn1Spec, encodeFun, **options): + return null, False, True + + +class BooleanEncoder(AbstractItemEncoder): + supportIndefLenMode = False + + def encodeValue(self, value, asn1Spec, encodeFun, **options): + return value and (1,) or (0,), False, False + + +class IntegerEncoder(AbstractItemEncoder): + supportIndefLenMode = False + supportCompactZero = False + + def encodeValue(self, value, asn1Spec, encodeFun, **options): + if value == 0: + if LOG: + LOG('encoding %spayload for zero INTEGER' % ( + self.supportCompactZero and 'no ' or '' + )) + + # de-facto way to encode zero + if self.supportCompactZero: + return (), False, False + else: + return (0,), False, False + + return to_bytes(int(value), signed=True), False, True + + +class BitStringEncoder(AbstractItemEncoder): + def encodeValue(self, value, asn1Spec, encodeFun, **options): + if asn1Spec is not None: + # TODO: try to avoid ASN.1 schema instantiation + value = asn1Spec.clone(value) + + valueLength = len(value) + if valueLength % 8: + alignedValue = value << (8 - valueLength % 8) + else: + alignedValue = value + + maxChunkSize = options.get('maxChunkSize', 0) + if not maxChunkSize or len(alignedValue) <= maxChunkSize * 8: + substrate = alignedValue.asOctets() + return int2oct(len(substrate) * 8 - valueLength) + substrate, False, True + + if LOG: + LOG('encoding into up to %s-octet chunks' % maxChunkSize) + + baseTag = value.tagSet.baseTag + + # strip off explicit tags + if baseTag: + tagSet = tag.TagSet(baseTag, baseTag) + + else: + tagSet = tag.TagSet() + + alignedValue = alignedValue.clone(tagSet=tagSet) + + stop = 0 + substrate = null + while stop < valueLength: + start = stop + stop = min(start + maxChunkSize * 8, valueLength) + substrate += encodeFun(alignedValue[start:stop], asn1Spec, **options) + + return substrate, True, True + + +class OctetStringEncoder(AbstractItemEncoder): + + def encodeValue(self, value, asn1Spec, encodeFun, **options): + + if asn1Spec is None: + substrate = value.asOctets() + + elif not isOctetsType(value): + substrate = asn1Spec.clone(value).asOctets() + + else: + substrate = value + + maxChunkSize = options.get('maxChunkSize', 0) + + if not maxChunkSize or len(substrate) <= maxChunkSize: + return substrate, False, True + + if LOG: + LOG('encoding into up to %s-octet chunks' % maxChunkSize) + + # strip off explicit tags for inner chunks + + if asn1Spec is None: + baseTag = value.tagSet.baseTag + + # strip off explicit tags + if baseTag: + tagSet = tag.TagSet(baseTag, baseTag) + + else: + tagSet = tag.TagSet() + + asn1Spec = value.clone(tagSet=tagSet) + + elif not isOctetsType(value): + baseTag = asn1Spec.tagSet.baseTag + + # strip off explicit tags + if baseTag: + tagSet = tag.TagSet(baseTag, baseTag) + + else: + tagSet = tag.TagSet() + + asn1Spec = asn1Spec.clone(tagSet=tagSet) + + pos = 0 + substrate = null + + while True: + chunk = value[pos:pos + maxChunkSize] + if not chunk: + break + + substrate += encodeFun(chunk, asn1Spec, **options) + pos += maxChunkSize + + return substrate, True, True + + +class NullEncoder(AbstractItemEncoder): + supportIndefLenMode = False + + def encodeValue(self, value, asn1Spec, encodeFun, **options): + return null, False, True + + +class ObjectIdentifierEncoder(AbstractItemEncoder): + supportIndefLenMode = False + + def encodeValue(self, value, asn1Spec, encodeFun, **options): + if asn1Spec is not None: + value = asn1Spec.clone(value) + + oid = value.asTuple() + + # Build the first pair + try: + first = oid[0] + second = oid[1] + + except IndexError: + raise error.PyAsn1Error('Short OID %s' % (value,)) + + if 0 <= second <= 39: + if first == 1: + oid = (second + 40,) + oid[2:] + elif first == 0: + oid = (second,) + oid[2:] + elif first == 2: + oid = (second + 80,) + oid[2:] + else: + raise error.PyAsn1Error('Impossible first/second arcs at %s' % (value,)) + + elif first == 2: + oid = (second + 80,) + oid[2:] + + else: + raise error.PyAsn1Error('Impossible first/second arcs at %s' % (value,)) + + octets = () + + # Cycle through subIds + for subOid in oid: + if 0 <= subOid <= 127: + # Optimize for the common case + octets += (subOid,) + + elif subOid > 127: + # Pack large Sub-Object IDs + res = (subOid & 0x7f,) + subOid >>= 7 + + while subOid: + res = (0x80 | (subOid & 0x7f),) + res + subOid >>= 7 + + # Add packed Sub-Object ID to resulted Object ID + octets += res + + else: + raise error.PyAsn1Error('Negative OID arc %s at %s' % (subOid, value)) + + return octets, False, False + + +class RealEncoder(AbstractItemEncoder): + supportIndefLenMode = 0 + binEncBase = 2 # set to None to choose encoding base automatically + + @staticmethod + def _dropFloatingPoint(m, encbase, e): + ms, es = 1, 1 + if m < 0: + ms = -1 # mantissa sign + + if e < 0: + es = -1 # exponent sign + + m *= ms + + if encbase == 8: + m *= 2 ** (abs(e) % 3 * es) + e = abs(e) // 3 * es + + elif encbase == 16: + m *= 2 ** (abs(e) % 4 * es) + e = abs(e) // 4 * es + + while True: + if int(m) != m: + m *= encbase + e -= 1 + continue + break + + return ms, int(m), encbase, e + + def _chooseEncBase(self, value): + m, b, e = value + encBase = [2, 8, 16] + if value.binEncBase in encBase: + return self._dropFloatingPoint(m, value.binEncBase, e) + + elif self.binEncBase in encBase: + return self._dropFloatingPoint(m, self.binEncBase, e) + + # auto choosing base 2/8/16 + mantissa = [m, m, m] + exponent = [e, e, e] + sign = 1 + encbase = 2 + e = float('inf') + + for i in range(3): + (sign, + mantissa[i], + encBase[i], + exponent[i]) = self._dropFloatingPoint(mantissa[i], encBase[i], exponent[i]) + + if abs(exponent[i]) < abs(e) or (abs(exponent[i]) == abs(e) and mantissa[i] < m): + e = exponent[i] + m = int(mantissa[i]) + encbase = encBase[i] + + if LOG: + LOG('automatically chosen REAL encoding base %s, sign %s, mantissa %s, ' + 'exponent %s' % (encbase, sign, m, e)) + + return sign, m, encbase, e + + def encodeValue(self, value, asn1Spec, encodeFun, **options): + if asn1Spec is not None: + value = asn1Spec.clone(value) + + if value.isPlusInf: + return (0x40,), False, False + + if value.isMinusInf: + return (0x41,), False, False + + m, b, e = value + + if not m: + return null, False, True + + if b == 10: + if LOG: + LOG('encoding REAL into character form') + + return str2octs('\x03%dE%s%d' % (m, e == 0 and '+' or '', e)), False, True + + elif b == 2: + fo = 0x80 # binary encoding + ms, m, encbase, e = self._chooseEncBase(value) + + if ms < 0: # mantissa sign + fo |= 0x40 # sign bit + + # exponent & mantissa normalization + if encbase == 2: + while m & 0x1 == 0: + m >>= 1 + e += 1 + + elif encbase == 8: + while m & 0x7 == 0: + m >>= 3 + e += 1 + fo |= 0x10 + + else: # encbase = 16 + while m & 0xf == 0: + m >>= 4 + e += 1 + fo |= 0x20 + + sf = 0 # scale factor + + while m & 0x1 == 0: + m >>= 1 + sf += 1 + + if sf > 3: + raise error.PyAsn1Error('Scale factor overflow') # bug if raised + + fo |= sf << 2 + eo = null + if e == 0 or e == -1: + eo = int2oct(e & 0xff) + + else: + while e not in (0, -1): + eo = int2oct(e & 0xff) + eo + e >>= 8 + + if e == 0 and eo and oct2int(eo[0]) & 0x80: + eo = int2oct(0) + eo + + if e == -1 and eo and not (oct2int(eo[0]) & 0x80): + eo = int2oct(0xff) + eo + + n = len(eo) + if n > 0xff: + raise error.PyAsn1Error('Real exponent overflow') + + if n == 1: + pass + + elif n == 2: + fo |= 1 + + elif n == 3: + fo |= 2 + + else: + fo |= 3 + eo = int2oct(n & 0xff) + eo + + po = null + + while m: + po = int2oct(m & 0xff) + po + m >>= 8 + + substrate = int2oct(fo) + eo + po + + return substrate, False, True + + else: + raise error.PyAsn1Error('Prohibited Real base %s' % b) + + +class SequenceEncoder(AbstractItemEncoder): + omitEmptyOptionals = False + + # TODO: handling three flavors of input is too much -- split over codecs + + def encodeValue(self, value, asn1Spec, encodeFun, **options): + + substrate = null + + omitEmptyOptionals = options.get( + 'omitEmptyOptionals', self.omitEmptyOptionals) + + if LOG: + LOG('%sencoding empty OPTIONAL components' % ( + omitEmptyOptionals and 'not ' or '')) + + if asn1Spec is None: + # instance of ASN.1 schema + inconsistency = value.isInconsistent + if inconsistency: + raise inconsistency + + namedTypes = value.componentType + + for idx, component in enumerate(value.values()): + if namedTypes: + namedType = namedTypes[idx] + + if namedType.isOptional and not component.isValue: + if LOG: + LOG('not encoding OPTIONAL component %r' % (namedType,)) + continue + + if namedType.isDefaulted and component == namedType.asn1Object: + if LOG: + LOG('not encoding DEFAULT component %r' % (namedType,)) + continue + + if omitEmptyOptionals: + options.update(ifNotEmpty=namedType.isOptional) + + # wrap open type blob if needed + if namedTypes and namedType.openType: + + wrapType = namedType.asn1Object + + if wrapType.typeId in ( + univ.SetOf.typeId, univ.SequenceOf.typeId): + + substrate += encodeFun( + component, asn1Spec, + **dict(options, wrapType=wrapType.componentType)) + + else: + chunk = encodeFun(component, asn1Spec, **options) + + if wrapType.isSameTypeWith(component): + substrate += chunk + + else: + substrate += encodeFun(chunk, wrapType, **options) + + if LOG: + LOG('wrapped with wrap type %r' % (wrapType,)) + + else: + substrate += encodeFun(component, asn1Spec, **options) + + else: + # bare Python value + ASN.1 schema + for idx, namedType in enumerate(asn1Spec.componentType.namedTypes): + + try: + component = value[namedType.name] + + except KeyError: + raise error.PyAsn1Error('Component name "%s" not found in %r' % ( + namedType.name, value)) + + if namedType.isOptional and namedType.name not in value: + if LOG: + LOG('not encoding OPTIONAL component %r' % (namedType,)) + continue + + if namedType.isDefaulted and component == namedType.asn1Object: + if LOG: + LOG('not encoding DEFAULT component %r' % (namedType,)) + continue + + if omitEmptyOptionals: + options.update(ifNotEmpty=namedType.isOptional) + + componentSpec = namedType.asn1Object + + # wrap open type blob if needed + if namedType.openType: + + if componentSpec.typeId in ( + univ.SetOf.typeId, univ.SequenceOf.typeId): + + substrate += encodeFun( + component, componentSpec, + **dict(options, wrapType=componentSpec.componentType)) + + else: + chunk = encodeFun(component, componentSpec, **options) + + if componentSpec.isSameTypeWith(component): + substrate += chunk + + else: + substrate += encodeFun(chunk, componentSpec, **options) + + if LOG: + LOG('wrapped with wrap type %r' % (componentSpec,)) + + else: + substrate += encodeFun(component, componentSpec, **options) + + return substrate, True, True + + +class SequenceOfEncoder(AbstractItemEncoder): + def _encodeComponents(self, value, asn1Spec, encodeFun, **options): + + if asn1Spec is None: + inconsistency = value.isInconsistent + if inconsistency: + raise inconsistency + + else: + asn1Spec = asn1Spec.componentType + + chunks = [] + + wrapType = options.pop('wrapType', None) + + for idx, component in enumerate(value): + chunk = encodeFun(component, asn1Spec, **options) + + if (wrapType is not None and + not wrapType.isSameTypeWith(component)): + # wrap encoded value with wrapper container (e.g. ANY) + chunk = encodeFun(chunk, wrapType, **options) + + if LOG: + LOG('wrapped with wrap type %r' % (wrapType,)) + + chunks.append(chunk) + + return chunks + + def encodeValue(self, value, asn1Spec, encodeFun, **options): + chunks = self._encodeComponents( + value, asn1Spec, encodeFun, **options) + + return null.join(chunks), True, True + + +class ChoiceEncoder(AbstractItemEncoder): + def encodeValue(self, value, asn1Spec, encodeFun, **options): + if asn1Spec is None: + component = value.getComponent() + else: + names = [namedType.name for namedType in asn1Spec.componentType.namedTypes + if namedType.name in value] + if len(names) != 1: + raise error.PyAsn1Error('%s components for Choice at %r' % (len(names) and 'Multiple ' or 'None ', value)) + + name = names[0] + + component = value[name] + asn1Spec = asn1Spec[name] + + return encodeFun(component, asn1Spec, **options), True, True + + +class AnyEncoder(OctetStringEncoder): + def encodeValue(self, value, asn1Spec, encodeFun, **options): + if asn1Spec is None: + value = value.asOctets() + elif not isOctetsType(value): + value = asn1Spec.clone(value).asOctets() + + return value, not options.get('defMode', True), True + + +tagMap = { + eoo.endOfOctets.tagSet: EndOfOctetsEncoder(), + univ.Boolean.tagSet: BooleanEncoder(), + univ.Integer.tagSet: IntegerEncoder(), + univ.BitString.tagSet: BitStringEncoder(), + univ.OctetString.tagSet: OctetStringEncoder(), + univ.Null.tagSet: NullEncoder(), + univ.ObjectIdentifier.tagSet: ObjectIdentifierEncoder(), + univ.Enumerated.tagSet: IntegerEncoder(), + univ.Real.tagSet: RealEncoder(), + # Sequence & Set have same tags as SequenceOf & SetOf + univ.SequenceOf.tagSet: SequenceOfEncoder(), + univ.SetOf.tagSet: SequenceOfEncoder(), + univ.Choice.tagSet: ChoiceEncoder(), + # character string types + char.UTF8String.tagSet: OctetStringEncoder(), + char.NumericString.tagSet: OctetStringEncoder(), + char.PrintableString.tagSet: OctetStringEncoder(), + char.TeletexString.tagSet: OctetStringEncoder(), + char.VideotexString.tagSet: OctetStringEncoder(), + char.IA5String.tagSet: OctetStringEncoder(), + char.GraphicString.tagSet: OctetStringEncoder(), + char.VisibleString.tagSet: OctetStringEncoder(), + char.GeneralString.tagSet: OctetStringEncoder(), + char.UniversalString.tagSet: OctetStringEncoder(), + char.BMPString.tagSet: OctetStringEncoder(), + # useful types + useful.ObjectDescriptor.tagSet: OctetStringEncoder(), + useful.GeneralizedTime.tagSet: OctetStringEncoder(), + useful.UTCTime.tagSet: OctetStringEncoder() +} + +# Put in ambiguous & non-ambiguous types for faster codec lookup +typeMap = { + univ.Boolean.typeId: BooleanEncoder(), + univ.Integer.typeId: IntegerEncoder(), + univ.BitString.typeId: BitStringEncoder(), + univ.OctetString.typeId: OctetStringEncoder(), + univ.Null.typeId: NullEncoder(), + univ.ObjectIdentifier.typeId: ObjectIdentifierEncoder(), + univ.Enumerated.typeId: IntegerEncoder(), + univ.Real.typeId: RealEncoder(), + # Sequence & Set have same tags as SequenceOf & SetOf + univ.Set.typeId: SequenceEncoder(), + univ.SetOf.typeId: SequenceOfEncoder(), + univ.Sequence.typeId: SequenceEncoder(), + univ.SequenceOf.typeId: SequenceOfEncoder(), + univ.Choice.typeId: ChoiceEncoder(), + univ.Any.typeId: AnyEncoder(), + # character string types + char.UTF8String.typeId: OctetStringEncoder(), + char.NumericString.typeId: OctetStringEncoder(), + char.PrintableString.typeId: OctetStringEncoder(), + char.TeletexString.typeId: OctetStringEncoder(), + char.VideotexString.typeId: OctetStringEncoder(), + char.IA5String.typeId: OctetStringEncoder(), + char.GraphicString.typeId: OctetStringEncoder(), + char.VisibleString.typeId: OctetStringEncoder(), + char.GeneralString.typeId: OctetStringEncoder(), + char.UniversalString.typeId: OctetStringEncoder(), + char.BMPString.typeId: OctetStringEncoder(), + # useful types + useful.ObjectDescriptor.typeId: OctetStringEncoder(), + useful.GeneralizedTime.typeId: OctetStringEncoder(), + useful.UTCTime.typeId: OctetStringEncoder() +} + + +class Encoder(object): + fixedDefLengthMode = None + fixedChunkSize = None + + # noinspection PyDefaultArgument + def __init__(self, tagMap, typeMap={}): + self.__tagMap = tagMap + self.__typeMap = typeMap + + def __call__(self, value, asn1Spec=None, **options): + try: + if asn1Spec is None: + typeId = value.typeId + else: + typeId = asn1Spec.typeId + + except AttributeError: + raise error.PyAsn1Error('Value %r is not ASN.1 type instance ' + 'and "asn1Spec" not given' % (value,)) + + if LOG: + LOG('encoder called in %sdef mode, chunk size %s for ' + 'type %s, value:\n%s' % (not options.get('defMode', True) and 'in' or '', options.get('maxChunkSize', 0), asn1Spec is None and value.prettyPrintType() or asn1Spec.prettyPrintType(), value)) + + if self.fixedDefLengthMode is not None: + options.update(defMode=self.fixedDefLengthMode) + + if self.fixedChunkSize is not None: + options.update(maxChunkSize=self.fixedChunkSize) + + + try: + concreteEncoder = self.__typeMap[typeId] + + if LOG: + LOG('using value codec %s chosen by type ID %s' % (concreteEncoder.__class__.__name__, typeId)) + + except KeyError: + if asn1Spec is None: + tagSet = value.tagSet + else: + tagSet = asn1Spec.tagSet + + # use base type for codec lookup to recover untagged types + baseTagSet = tag.TagSet(tagSet.baseTag, tagSet.baseTag) + + try: + concreteEncoder = self.__tagMap[baseTagSet] + + except KeyError: + raise error.PyAsn1Error('No encoder for %r (%s)' % (value, tagSet)) + + if LOG: + LOG('using value codec %s chosen by tagSet %s' % (concreteEncoder.__class__.__name__, tagSet)) + + substrate = concreteEncoder.encode(value, asn1Spec, self, **options) + + if LOG: + LOG('codec %s built %s octets of substrate: %s\nencoder completed' % (concreteEncoder, len(substrate), debug.hexdump(substrate))) + + return substrate + +#: Turns ASN.1 object into BER octet stream. +#: +#: Takes any ASN.1 object (e.g. :py:class:`~pyasn1.type.base.PyAsn1Item` derivative) +#: walks all its components recursively and produces a BER octet stream. +#: +#: Parameters +#: ---------- +#: value: either a Python or pyasn1 object (e.g. :py:class:`~pyasn1.type.base.PyAsn1Item` derivative) +#: A Python or pyasn1 object to encode. If Python object is given, `asnSpec` +#: parameter is required to guide the encoding process. +#: +#: Keyword Args +#: ------------ +#: asn1Spec: +#: Optional ASN.1 schema or value object e.g. :py:class:`~pyasn1.type.base.PyAsn1Item` derivative +#: +#: defMode: :py:class:`bool` +#: If :obj:`False`, produces indefinite length encoding +#: +#: maxChunkSize: :py:class:`int` +#: Maximum chunk size in chunked encoding mode (0 denotes unlimited chunk size) +#: +#: Returns +#: ------- +#: : :py:class:`bytes` (Python 3) or :py:class:`str` (Python 2) +#: Given ASN.1 object encoded into BER octetstream +#: +#: Raises +#: ------ +#: ~pyasn1.error.PyAsn1Error +#: On encoding errors +#: +#: Examples +#: -------- +#: Encode Python value into BER with ASN.1 schema +#: +#: .. code-block:: pycon +#: +#: >>> seq = SequenceOf(componentType=Integer()) +#: >>> encode([1, 2, 3], asn1Spec=seq) +#: b'0\t\x02\x01\x01\x02\x01\x02\x02\x01\x03' +#: +#: Encode ASN.1 value object into BER +#: +#: .. code-block:: pycon +#: +#: >>> seq = SequenceOf(componentType=Integer()) +#: >>> seq.extend([1, 2, 3]) +#: >>> encode(seq) +#: b'0\t\x02\x01\x01\x02\x01\x02\x02\x01\x03' +#: +encode = Encoder(tagMap, typeMap) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/codec/ber/eoo.py b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/codec/ber/eoo.py new file mode 100644 index 00000000..48eb859e --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/codec/ber/eoo.py @@ -0,0 +1,28 @@ +# +# This file is part of pyasn1 software. +# +# Copyright (c) 2005-2019, Ilya Etingof <etingof@gmail.com> +# License: http://snmplabs.com/pyasn1/license.html +# +from pyasn1.type import base +from pyasn1.type import tag + +__all__ = ['endOfOctets'] + + +class EndOfOctets(base.SimpleAsn1Type): + defaultValue = 0 + tagSet = tag.initTagSet( + tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 0x00) + ) + + _instance = None + + def __new__(cls, *args, **kwargs): + if cls._instance is None: + cls._instance = object.__new__(cls, *args, **kwargs) + + return cls._instance + + +endOfOctets = EndOfOctets() diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/codec/cer/__init__.py b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/codec/cer/__init__.py new file mode 100644 index 00000000..8c3066b2 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/codec/cer/__init__.py @@ -0,0 +1 @@ +# This file is necessary to make this directory a package. diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/codec/cer/__pycache__/__init__.cpython-310.pyc b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/codec/cer/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 00000000..a46bd7ba Binary files /dev/null and b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/codec/cer/__pycache__/__init__.cpython-310.pyc differ diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/codec/cer/__pycache__/decoder.cpython-310.pyc b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/codec/cer/__pycache__/decoder.cpython-310.pyc new file mode 100644 index 00000000..2acd05bd Binary files /dev/null and b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/codec/cer/__pycache__/decoder.cpython-310.pyc differ diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/codec/cer/decoder.py b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/codec/cer/decoder.py new file mode 100644 index 00000000..3e86fd0b --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/codec/cer/decoder.py @@ -0,0 +1,114 @@ +# +# This file is part of pyasn1 software. +# +# Copyright (c) 2005-2019, Ilya Etingof <etingof@gmail.com> +# License: http://snmplabs.com/pyasn1/license.html +# +from pyasn1 import error +from pyasn1.codec.ber import decoder +from pyasn1.compat.octets import oct2int +from pyasn1.type import univ + +__all__ = ['decode'] + + +class BooleanDecoder(decoder.AbstractSimpleDecoder): + protoComponent = univ.Boolean(0) + + def valueDecoder(self, substrate, asn1Spec, + tagSet=None, length=None, state=None, + decodeFun=None, substrateFun=None, + **options): + head, tail = substrate[:length], substrate[length:] + if not head or length != 1: + raise error.PyAsn1Error('Not single-octet Boolean payload') + byte = oct2int(head[0]) + # CER/DER specifies encoding of TRUE as 0xFF and FALSE as 0x0, while + # BER allows any non-zero value as TRUE; cf. sections 8.2.2. and 11.1 + # in https://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf + if byte == 0xff: + value = 1 + elif byte == 0x00: + value = 0 + else: + raise error.PyAsn1Error('Unexpected Boolean payload: %s' % byte) + return self._createComponent(asn1Spec, tagSet, value, **options), tail + +# TODO: prohibit non-canonical encoding +BitStringDecoder = decoder.BitStringDecoder +OctetStringDecoder = decoder.OctetStringDecoder +RealDecoder = decoder.RealDecoder + +tagMap = decoder.tagMap.copy() +tagMap.update( + {univ.Boolean.tagSet: BooleanDecoder(), + univ.BitString.tagSet: BitStringDecoder(), + univ.OctetString.tagSet: OctetStringDecoder(), + univ.Real.tagSet: RealDecoder()} +) + +typeMap = decoder.typeMap.copy() + +# Put in non-ambiguous types for faster codec lookup +for typeDecoder in tagMap.values(): + if typeDecoder.protoComponent is not None: + typeId = typeDecoder.protoComponent.__class__.typeId + if typeId is not None and typeId not in typeMap: + typeMap[typeId] = typeDecoder + + +class Decoder(decoder.Decoder): + pass + + +#: Turns CER octet stream into an ASN.1 object. +#: +#: Takes CER octet-stream and decode it into an ASN.1 object +#: (e.g. :py:class:`~pyasn1.type.base.PyAsn1Item` derivative) which +#: may be a scalar or an arbitrary nested structure. +#: +#: Parameters +#: ---------- +#: substrate: :py:class:`bytes` (Python 3) or :py:class:`str` (Python 2) +#: CER octet-stream +#: +#: Keyword Args +#: ------------ +#: asn1Spec: any pyasn1 type object e.g. :py:class:`~pyasn1.type.base.PyAsn1Item` derivative +#: A pyasn1 type object to act as a template guiding the decoder. Depending on the ASN.1 structure +#: being decoded, *asn1Spec* may or may not be required. Most common reason for +#: it to require is that ASN.1 structure is encoded in *IMPLICIT* tagging mode. +#: +#: Returns +#: ------- +#: : :py:class:`tuple` +#: A tuple of pyasn1 object recovered from CER substrate (:py:class:`~pyasn1.type.base.PyAsn1Item` derivative) +#: and the unprocessed trailing portion of the *substrate* (may be empty) +#: +#: Raises +#: ------ +#: ~pyasn1.error.PyAsn1Error, ~pyasn1.error.SubstrateUnderrunError +#: On decoding errors +#: +#: Examples +#: -------- +#: Decode CER serialisation without ASN.1 schema +#: +#: .. code-block:: pycon +#: +#: >>> s, _ = decode(b'0\x80\x02\x01\x01\x02\x01\x02\x02\x01\x03\x00\x00') +#: >>> str(s) +#: SequenceOf: +#: 1 2 3 +#: +#: Decode CER serialisation with ASN.1 schema +#: +#: .. code-block:: pycon +#: +#: >>> seq = SequenceOf(componentType=Integer()) +#: >>> s, _ = decode(b'0\x80\x02\x01\x01\x02\x01\x02\x02\x01\x03\x00\x00', asn1Spec=seq) +#: >>> str(s) +#: SequenceOf: +#: 1 2 3 +#: +decode = Decoder(tagMap, decoder.typeMap) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/codec/cer/encoder.py b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/codec/cer/encoder.py new file mode 100644 index 00000000..935b6965 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/codec/cer/encoder.py @@ -0,0 +1,313 @@ +# +# This file is part of pyasn1 software. +# +# Copyright (c) 2005-2019, Ilya Etingof <etingof@gmail.com> +# License: http://snmplabs.com/pyasn1/license.html +# +from pyasn1 import error +from pyasn1.codec.ber import encoder +from pyasn1.compat.octets import str2octs, null +from pyasn1.type import univ +from pyasn1.type import useful + +__all__ = ['encode'] + + +class BooleanEncoder(encoder.IntegerEncoder): + def encodeValue(self, value, asn1Spec, encodeFun, **options): + if value == 0: + substrate = (0,) + else: + substrate = (255,) + return substrate, False, False + + +class RealEncoder(encoder.RealEncoder): + def _chooseEncBase(self, value): + m, b, e = value + return self._dropFloatingPoint(m, b, e) + + +# specialized GeneralStringEncoder here + +class TimeEncoderMixIn(object): + Z_CHAR = ord('Z') + PLUS_CHAR = ord('+') + MINUS_CHAR = ord('-') + COMMA_CHAR = ord(',') + DOT_CHAR = ord('.') + ZERO_CHAR = ord('0') + + MIN_LENGTH = 12 + MAX_LENGTH = 19 + + def encodeValue(self, value, asn1Spec, encodeFun, **options): + # CER encoding constraints: + # - minutes are mandatory, seconds are optional + # - sub-seconds must NOT be zero / no meaningless zeros + # - no hanging fraction dot + # - time in UTC (Z) + # - only dot is allowed for fractions + + if asn1Spec is not None: + value = asn1Spec.clone(value) + + numbers = value.asNumbers() + + if self.PLUS_CHAR in numbers or self.MINUS_CHAR in numbers: + raise error.PyAsn1Error('Must be UTC time: %r' % value) + + if numbers[-1] != self.Z_CHAR: + raise error.PyAsn1Error('Missing "Z" time zone specifier: %r' % value) + + if self.COMMA_CHAR in numbers: + raise error.PyAsn1Error('Comma in fractions disallowed: %r' % value) + + if self.DOT_CHAR in numbers: + + isModified = False + + numbers = list(numbers) + + searchIndex = min(numbers.index(self.DOT_CHAR) + 4, len(numbers) - 1) + + while numbers[searchIndex] != self.DOT_CHAR: + if numbers[searchIndex] == self.ZERO_CHAR: + del numbers[searchIndex] + isModified = True + + searchIndex -= 1 + + searchIndex += 1 + + if searchIndex < len(numbers): + if numbers[searchIndex] == self.Z_CHAR: + # drop hanging comma + del numbers[searchIndex - 1] + isModified = True + + if isModified: + value = value.clone(numbers) + + if not self.MIN_LENGTH < len(numbers) < self.MAX_LENGTH: + raise error.PyAsn1Error('Length constraint violated: %r' % value) + + options.update(maxChunkSize=1000) + + return encoder.OctetStringEncoder.encodeValue( + self, value, asn1Spec, encodeFun, **options + ) + + +class GeneralizedTimeEncoder(TimeEncoderMixIn, encoder.OctetStringEncoder): + MIN_LENGTH = 12 + MAX_LENGTH = 20 + + +class UTCTimeEncoder(TimeEncoderMixIn, encoder.OctetStringEncoder): + MIN_LENGTH = 10 + MAX_LENGTH = 14 + + +class SetOfEncoder(encoder.SequenceOfEncoder): + def encodeValue(self, value, asn1Spec, encodeFun, **options): + chunks = self._encodeComponents( + value, asn1Spec, encodeFun, **options) + + # sort by serialised and padded components + if len(chunks) > 1: + zero = str2octs('\x00') + maxLen = max(map(len, chunks)) + paddedChunks = [ + (x.ljust(maxLen, zero), x) for x in chunks + ] + paddedChunks.sort(key=lambda x: x[0]) + + chunks = [x[1] for x in paddedChunks] + + return null.join(chunks), True, True + + +class SequenceOfEncoder(encoder.SequenceOfEncoder): + def encodeValue(self, value, asn1Spec, encodeFun, **options): + + if options.get('ifNotEmpty', False) and not len(value): + return null, True, True + + chunks = self._encodeComponents( + value, asn1Spec, encodeFun, **options) + + return null.join(chunks), True, True + + +class SetEncoder(encoder.SequenceEncoder): + @staticmethod + def _componentSortKey(componentAndType): + """Sort SET components by tag + + Sort regardless of the Choice value (static sort) + """ + component, asn1Spec = componentAndType + + if asn1Spec is None: + asn1Spec = component + + if asn1Spec.typeId == univ.Choice.typeId and not asn1Spec.tagSet: + if asn1Spec.tagSet: + return asn1Spec.tagSet + else: + return asn1Spec.componentType.minTagSet + else: + return asn1Spec.tagSet + + def encodeValue(self, value, asn1Spec, encodeFun, **options): + + substrate = null + + comps = [] + compsMap = {} + + if asn1Spec is None: + # instance of ASN.1 schema + inconsistency = value.isInconsistent + if inconsistency: + raise inconsistency + + namedTypes = value.componentType + + for idx, component in enumerate(value.values()): + if namedTypes: + namedType = namedTypes[idx] + + if namedType.isOptional and not component.isValue: + continue + + if namedType.isDefaulted and component == namedType.asn1Object: + continue + + compsMap[id(component)] = namedType + + else: + compsMap[id(component)] = None + + comps.append((component, asn1Spec)) + + else: + # bare Python value + ASN.1 schema + for idx, namedType in enumerate(asn1Spec.componentType.namedTypes): + + try: + component = value[namedType.name] + + except KeyError: + raise error.PyAsn1Error('Component name "%s" not found in %r' % (namedType.name, value)) + + if namedType.isOptional and namedType.name not in value: + continue + + if namedType.isDefaulted and component == namedType.asn1Object: + continue + + compsMap[id(component)] = namedType + comps.append((component, asn1Spec[idx])) + + for comp, compType in sorted(comps, key=self._componentSortKey): + namedType = compsMap[id(comp)] + + if namedType: + options.update(ifNotEmpty=namedType.isOptional) + + chunk = encodeFun(comp, compType, **options) + + # wrap open type blob if needed + if namedType and namedType.openType: + wrapType = namedType.asn1Object + if wrapType.tagSet and not wrapType.isSameTypeWith(comp): + chunk = encodeFun(chunk, wrapType, **options) + + substrate += chunk + + return substrate, True, True + + +class SequenceEncoder(encoder.SequenceEncoder): + omitEmptyOptionals = True + + +tagMap = encoder.tagMap.copy() +tagMap.update({ + univ.Boolean.tagSet: BooleanEncoder(), + univ.Real.tagSet: RealEncoder(), + useful.GeneralizedTime.tagSet: GeneralizedTimeEncoder(), + useful.UTCTime.tagSet: UTCTimeEncoder(), + # Sequence & Set have same tags as SequenceOf & SetOf + univ.SetOf.tagSet: SetOfEncoder(), + univ.Sequence.typeId: SequenceEncoder() +}) + +typeMap = encoder.typeMap.copy() +typeMap.update({ + univ.Boolean.typeId: BooleanEncoder(), + univ.Real.typeId: RealEncoder(), + useful.GeneralizedTime.typeId: GeneralizedTimeEncoder(), + useful.UTCTime.typeId: UTCTimeEncoder(), + # Sequence & Set have same tags as SequenceOf & SetOf + univ.Set.typeId: SetEncoder(), + univ.SetOf.typeId: SetOfEncoder(), + univ.Sequence.typeId: SequenceEncoder(), + univ.SequenceOf.typeId: SequenceOfEncoder() +}) + + +class Encoder(encoder.Encoder): + fixedDefLengthMode = False + fixedChunkSize = 1000 + +#: Turns ASN.1 object into CER octet stream. +#: +#: Takes any ASN.1 object (e.g. :py:class:`~pyasn1.type.base.PyAsn1Item` derivative) +#: walks all its components recursively and produces a CER octet stream. +#: +#: Parameters +#: ---------- +#: value: either a Python or pyasn1 object (e.g. :py:class:`~pyasn1.type.base.PyAsn1Item` derivative) +#: A Python or pyasn1 object to encode. If Python object is given, `asnSpec` +#: parameter is required to guide the encoding process. +#: +#: Keyword Args +#: ------------ +#: asn1Spec: +#: Optional ASN.1 schema or value object e.g. :py:class:`~pyasn1.type.base.PyAsn1Item` derivative +#: +#: Returns +#: ------- +#: : :py:class:`bytes` (Python 3) or :py:class:`str` (Python 2) +#: Given ASN.1 object encoded into BER octet-stream +#: +#: Raises +#: ------ +#: ~pyasn1.error.PyAsn1Error +#: On encoding errors +#: +#: Examples +#: -------- +#: Encode Python value into CER with ASN.1 schema +#: +#: .. code-block:: pycon +#: +#: >>> seq = SequenceOf(componentType=Integer()) +#: >>> encode([1, 2, 3], asn1Spec=seq) +#: b'0\x80\x02\x01\x01\x02\x01\x02\x02\x01\x03\x00\x00' +#: +#: Encode ASN.1 value object into CER +#: +#: .. code-block:: pycon +#: +#: >>> seq = SequenceOf(componentType=Integer()) +#: >>> seq.extend([1, 2, 3]) +#: >>> encode(seq) +#: b'0\x80\x02\x01\x01\x02\x01\x02\x02\x01\x03\x00\x00' +#: +encode = Encoder(tagMap, typeMap) + +# EncoderFactory queries class instance and builds a map of tags -> encoders diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/codec/der/__init__.py b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/codec/der/__init__.py new file mode 100644 index 00000000..8c3066b2 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/codec/der/__init__.py @@ -0,0 +1 @@ +# This file is necessary to make this directory a package. diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/codec/der/__pycache__/__init__.cpython-310.pyc b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/codec/der/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 00000000..5a39e2e3 Binary files /dev/null and b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/codec/der/__pycache__/__init__.cpython-310.pyc differ diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/codec/der/__pycache__/decoder.cpython-310.pyc b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/codec/der/__pycache__/decoder.cpython-310.pyc new file mode 100644 index 00000000..b789e48b Binary files /dev/null and b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/codec/der/__pycache__/decoder.cpython-310.pyc differ diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/codec/der/decoder.py b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/codec/der/decoder.py new file mode 100644 index 00000000..1a13fdb5 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/codec/der/decoder.py @@ -0,0 +1,94 @@ +# +# This file is part of pyasn1 software. +# +# Copyright (c) 2005-2019, Ilya Etingof <etingof@gmail.com> +# License: http://snmplabs.com/pyasn1/license.html +# +from pyasn1.codec.cer import decoder +from pyasn1.type import univ + +__all__ = ['decode'] + + +class BitStringDecoder(decoder.BitStringDecoder): + supportConstructedForm = False + + +class OctetStringDecoder(decoder.OctetStringDecoder): + supportConstructedForm = False + +# TODO: prohibit non-canonical encoding +RealDecoder = decoder.RealDecoder + +tagMap = decoder.tagMap.copy() +tagMap.update( + {univ.BitString.tagSet: BitStringDecoder(), + univ.OctetString.tagSet: OctetStringDecoder(), + univ.Real.tagSet: RealDecoder()} +) + +typeMap = decoder.typeMap.copy() + +# Put in non-ambiguous types for faster codec lookup +for typeDecoder in tagMap.values(): + if typeDecoder.protoComponent is not None: + typeId = typeDecoder.protoComponent.__class__.typeId + if typeId is not None and typeId not in typeMap: + typeMap[typeId] = typeDecoder + + +class Decoder(decoder.Decoder): + supportIndefLength = False + + +#: Turns DER octet stream into an ASN.1 object. +#: +#: Takes DER octet-stream and decode it into an ASN.1 object +#: (e.g. :py:class:`~pyasn1.type.base.PyAsn1Item` derivative) which +#: may be a scalar or an arbitrary nested structure. +#: +#: Parameters +#: ---------- +#: substrate: :py:class:`bytes` (Python 3) or :py:class:`str` (Python 2) +#: DER octet-stream +#: +#: Keyword Args +#: ------------ +#: asn1Spec: any pyasn1 type object e.g. :py:class:`~pyasn1.type.base.PyAsn1Item` derivative +#: A pyasn1 type object to act as a template guiding the decoder. Depending on the ASN.1 structure +#: being decoded, *asn1Spec* may or may not be required. Most common reason for +#: it to require is that ASN.1 structure is encoded in *IMPLICIT* tagging mode. +#: +#: Returns +#: ------- +#: : :py:class:`tuple` +#: A tuple of pyasn1 object recovered from DER substrate (:py:class:`~pyasn1.type.base.PyAsn1Item` derivative) +#: and the unprocessed trailing portion of the *substrate* (may be empty) +#: +#: Raises +#: ------ +#: ~pyasn1.error.PyAsn1Error, ~pyasn1.error.SubstrateUnderrunError +#: On decoding errors +#: +#: Examples +#: -------- +#: Decode DER serialisation without ASN.1 schema +#: +#: .. code-block:: pycon +#: +#: >>> s, _ = decode(b'0\t\x02\x01\x01\x02\x01\x02\x02\x01\x03') +#: >>> str(s) +#: SequenceOf: +#: 1 2 3 +#: +#: Decode DER serialisation with ASN.1 schema +#: +#: .. code-block:: pycon +#: +#: >>> seq = SequenceOf(componentType=Integer()) +#: >>> s, _ = decode(b'0\t\x02\x01\x01\x02\x01\x02\x02\x01\x03', asn1Spec=seq) +#: >>> str(s) +#: SequenceOf: +#: 1 2 3 +#: +decode = Decoder(tagMap, typeMap) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/codec/der/encoder.py b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/codec/der/encoder.py new file mode 100644 index 00000000..90e982da --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/codec/der/encoder.py @@ -0,0 +1,107 @@ +# +# This file is part of pyasn1 software. +# +# Copyright (c) 2005-2019, Ilya Etingof <etingof@gmail.com> +# License: http://snmplabs.com/pyasn1/license.html +# +from pyasn1 import error +from pyasn1.codec.cer import encoder +from pyasn1.type import univ + +__all__ = ['encode'] + + +class SetEncoder(encoder.SetEncoder): + @staticmethod + def _componentSortKey(componentAndType): + """Sort SET components by tag + + Sort depending on the actual Choice value (dynamic sort) + """ + component, asn1Spec = componentAndType + + if asn1Spec is None: + compType = component + else: + compType = asn1Spec + + if compType.typeId == univ.Choice.typeId and not compType.tagSet: + if asn1Spec is None: + return component.getComponent().tagSet + else: + # TODO: move out of sorting key function + names = [namedType.name for namedType in asn1Spec.componentType.namedTypes + if namedType.name in component] + if len(names) != 1: + raise error.PyAsn1Error( + '%s components for Choice at %r' % (len(names) and 'Multiple ' or 'None ', component)) + + # TODO: support nested CHOICE ordering + return asn1Spec[names[0]].tagSet + + else: + return compType.tagSet + +tagMap = encoder.tagMap.copy() +tagMap.update({ + # Set & SetOf have same tags + univ.Set.tagSet: SetEncoder() +}) + +typeMap = encoder.typeMap.copy() +typeMap.update({ + # Set & SetOf have same tags + univ.Set.typeId: SetEncoder() +}) + + +class Encoder(encoder.Encoder): + fixedDefLengthMode = True + fixedChunkSize = 0 + +#: Turns ASN.1 object into DER octet stream. +#: +#: Takes any ASN.1 object (e.g. :py:class:`~pyasn1.type.base.PyAsn1Item` derivative) +#: walks all its components recursively and produces a DER octet stream. +#: +#: Parameters +#: ---------- +#: value: either a Python or pyasn1 object (e.g. :py:class:`~pyasn1.type.base.PyAsn1Item` derivative) +#: A Python or pyasn1 object to encode. If Python object is given, `asnSpec` +#: parameter is required to guide the encoding process. +#: +#: Keyword Args +#: ------------ +#: asn1Spec: +#: Optional ASN.1 schema or value object e.g. :py:class:`~pyasn1.type.base.PyAsn1Item` derivative +#: +#: Returns +#: ------- +#: : :py:class:`bytes` (Python 3) or :py:class:`str` (Python 2) +#: Given ASN.1 object encoded into BER octet-stream +#: +#: Raises +#: ------ +#: ~pyasn1.error.PyAsn1Error +#: On encoding errors +#: +#: Examples +#: -------- +#: Encode Python value into DER with ASN.1 schema +#: +#: .. code-block:: pycon +#: +#: >>> seq = SequenceOf(componentType=Integer()) +#: >>> encode([1, 2, 3], asn1Spec=seq) +#: b'0\t\x02\x01\x01\x02\x01\x02\x02\x01\x03' +#: +#: Encode ASN.1 value object into DER +#: +#: .. code-block:: pycon +#: +#: >>> seq = SequenceOf(componentType=Integer()) +#: >>> seq.extend([1, 2, 3]) +#: >>> encode(seq) +#: b'0\t\x02\x01\x01\x02\x01\x02\x02\x01\x03' +#: +encode = Encoder(tagMap, typeMap) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/codec/native/__init__.py b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/codec/native/__init__.py new file mode 100644 index 00000000..8c3066b2 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/codec/native/__init__.py @@ -0,0 +1 @@ +# This file is necessary to make this directory a package. diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/codec/native/decoder.py b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/codec/native/decoder.py new file mode 100644 index 00000000..104b92e6 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/codec/native/decoder.py @@ -0,0 +1,213 @@ +# +# This file is part of pyasn1 software. +# +# Copyright (c) 2005-2019, Ilya Etingof <etingof@gmail.com> +# License: http://snmplabs.com/pyasn1/license.html +# +from pyasn1 import debug +from pyasn1 import error +from pyasn1.type import base +from pyasn1.type import char +from pyasn1.type import tag +from pyasn1.type import univ +from pyasn1.type import useful + +__all__ = ['decode'] + +LOG = debug.registerLoggee(__name__, flags=debug.DEBUG_DECODER) + + +class AbstractScalarDecoder(object): + def __call__(self, pyObject, asn1Spec, decodeFun=None, **options): + return asn1Spec.clone(pyObject) + + +class BitStringDecoder(AbstractScalarDecoder): + def __call__(self, pyObject, asn1Spec, decodeFun=None, **options): + return asn1Spec.clone(univ.BitString.fromBinaryString(pyObject)) + + +class SequenceOrSetDecoder(object): + def __call__(self, pyObject, asn1Spec, decodeFun=None, **options): + asn1Value = asn1Spec.clone() + + componentsTypes = asn1Spec.componentType + + for field in asn1Value: + if field in pyObject: + asn1Value[field] = decodeFun(pyObject[field], componentsTypes[field].asn1Object, **options) + + return asn1Value + + +class SequenceOfOrSetOfDecoder(object): + def __call__(self, pyObject, asn1Spec, decodeFun=None, **options): + asn1Value = asn1Spec.clone() + + for pyValue in pyObject: + asn1Value.append(decodeFun(pyValue, asn1Spec.componentType), **options) + + return asn1Value + + +class ChoiceDecoder(object): + def __call__(self, pyObject, asn1Spec, decodeFun=None, **options): + asn1Value = asn1Spec.clone() + + componentsTypes = asn1Spec.componentType + + for field in pyObject: + if field in componentsTypes: + asn1Value[field] = decodeFun(pyObject[field], componentsTypes[field].asn1Object, **options) + break + + return asn1Value + + +tagMap = { + univ.Integer.tagSet: AbstractScalarDecoder(), + univ.Boolean.tagSet: AbstractScalarDecoder(), + univ.BitString.tagSet: BitStringDecoder(), + univ.OctetString.tagSet: AbstractScalarDecoder(), + univ.Null.tagSet: AbstractScalarDecoder(), + univ.ObjectIdentifier.tagSet: AbstractScalarDecoder(), + univ.Enumerated.tagSet: AbstractScalarDecoder(), + univ.Real.tagSet: AbstractScalarDecoder(), + univ.Sequence.tagSet: SequenceOrSetDecoder(), # conflicts with SequenceOf + univ.Set.tagSet: SequenceOrSetDecoder(), # conflicts with SetOf + univ.Choice.tagSet: ChoiceDecoder(), # conflicts with Any + # character string types + char.UTF8String.tagSet: AbstractScalarDecoder(), + char.NumericString.tagSet: AbstractScalarDecoder(), + char.PrintableString.tagSet: AbstractScalarDecoder(), + char.TeletexString.tagSet: AbstractScalarDecoder(), + char.VideotexString.tagSet: AbstractScalarDecoder(), + char.IA5String.tagSet: AbstractScalarDecoder(), + char.GraphicString.tagSet: AbstractScalarDecoder(), + char.VisibleString.tagSet: AbstractScalarDecoder(), + char.GeneralString.tagSet: AbstractScalarDecoder(), + char.UniversalString.tagSet: AbstractScalarDecoder(), + char.BMPString.tagSet: AbstractScalarDecoder(), + # useful types + useful.ObjectDescriptor.tagSet: AbstractScalarDecoder(), + useful.GeneralizedTime.tagSet: AbstractScalarDecoder(), + useful.UTCTime.tagSet: AbstractScalarDecoder() +} + +# Put in ambiguous & non-ambiguous types for faster codec lookup +typeMap = { + univ.Integer.typeId: AbstractScalarDecoder(), + univ.Boolean.typeId: AbstractScalarDecoder(), + univ.BitString.typeId: BitStringDecoder(), + univ.OctetString.typeId: AbstractScalarDecoder(), + univ.Null.typeId: AbstractScalarDecoder(), + univ.ObjectIdentifier.typeId: AbstractScalarDecoder(), + univ.Enumerated.typeId: AbstractScalarDecoder(), + univ.Real.typeId: AbstractScalarDecoder(), + # ambiguous base types + univ.Set.typeId: SequenceOrSetDecoder(), + univ.SetOf.typeId: SequenceOfOrSetOfDecoder(), + univ.Sequence.typeId: SequenceOrSetDecoder(), + univ.SequenceOf.typeId: SequenceOfOrSetOfDecoder(), + univ.Choice.typeId: ChoiceDecoder(), + univ.Any.typeId: AbstractScalarDecoder(), + # character string types + char.UTF8String.typeId: AbstractScalarDecoder(), + char.NumericString.typeId: AbstractScalarDecoder(), + char.PrintableString.typeId: AbstractScalarDecoder(), + char.TeletexString.typeId: AbstractScalarDecoder(), + char.VideotexString.typeId: AbstractScalarDecoder(), + char.IA5String.typeId: AbstractScalarDecoder(), + char.GraphicString.typeId: AbstractScalarDecoder(), + char.VisibleString.typeId: AbstractScalarDecoder(), + char.GeneralString.typeId: AbstractScalarDecoder(), + char.UniversalString.typeId: AbstractScalarDecoder(), + char.BMPString.typeId: AbstractScalarDecoder(), + # useful types + useful.ObjectDescriptor.typeId: AbstractScalarDecoder(), + useful.GeneralizedTime.typeId: AbstractScalarDecoder(), + useful.UTCTime.typeId: AbstractScalarDecoder() +} + + +class Decoder(object): + + # noinspection PyDefaultArgument + def __init__(self, tagMap, typeMap): + self.__tagMap = tagMap + self.__typeMap = typeMap + + def __call__(self, pyObject, asn1Spec, **options): + + if LOG: + debug.scope.push(type(pyObject).__name__) + LOG('decoder called at scope %s, working with type %s' % (debug.scope, type(pyObject).__name__)) + + if asn1Spec is None or not isinstance(asn1Spec, base.Asn1Item): + raise error.PyAsn1Error('asn1Spec is not valid (should be an instance of an ASN.1 Item, not %s)' % asn1Spec.__class__.__name__) + + try: + valueDecoder = self.__typeMap[asn1Spec.typeId] + + except KeyError: + # use base type for codec lookup to recover untagged types + baseTagSet = tag.TagSet(asn1Spec.tagSet.baseTag, asn1Spec.tagSet.baseTag) + + try: + valueDecoder = self.__tagMap[baseTagSet] + except KeyError: + raise error.PyAsn1Error('Unknown ASN.1 tag %s' % asn1Spec.tagSet) + + if LOG: + LOG('calling decoder %s on Python type %s <%s>' % (type(valueDecoder).__name__, type(pyObject).__name__, repr(pyObject))) + + value = valueDecoder(pyObject, asn1Spec, self, **options) + + if LOG: + LOG('decoder %s produced ASN.1 type %s <%s>' % (type(valueDecoder).__name__, type(value).__name__, repr(value))) + debug.scope.pop() + + return value + + +#: Turns Python objects of built-in types into ASN.1 objects. +#: +#: Takes Python objects of built-in types and turns them into a tree of +#: ASN.1 objects (e.g. :py:class:`~pyasn1.type.base.PyAsn1Item` derivative) which +#: may be a scalar or an arbitrary nested structure. +#: +#: Parameters +#: ---------- +#: pyObject: :py:class:`object` +#: A scalar or nested Python objects +#: +#: Keyword Args +#: ------------ +#: asn1Spec: any pyasn1 type object e.g. :py:class:`~pyasn1.type.base.PyAsn1Item` derivative +#: A pyasn1 type object to act as a template guiding the decoder. It is required +#: for successful interpretation of Python objects mapping into their ASN.1 +#: representations. +#: +#: Returns +#: ------- +#: : :py:class:`~pyasn1.type.base.PyAsn1Item` derivative +#: A scalar or constructed pyasn1 object +#: +#: Raises +#: ------ +#: ~pyasn1.error.PyAsn1Error +#: On decoding errors +#: +#: Examples +#: -------- +#: Decode native Python object into ASN.1 objects with ASN.1 schema +#: +#: .. code-block:: pycon +#: +#: >>> seq = SequenceOf(componentType=Integer()) +#: >>> s, _ = decode([1, 2, 3], asn1Spec=seq) +#: >>> str(s) +#: SequenceOf: +#: 1 2 3 +#: +decode = Decoder(tagMap, typeMap) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/codec/native/encoder.py b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/codec/native/encoder.py new file mode 100644 index 00000000..4318abde --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/codec/native/encoder.py @@ -0,0 +1,256 @@ +# +# This file is part of pyasn1 software. +# +# Copyright (c) 2005-2019, Ilya Etingof <etingof@gmail.com> +# License: http://snmplabs.com/pyasn1/license.html +# +try: + from collections import OrderedDict + +except ImportError: + OrderedDict = dict + +from pyasn1 import debug +from pyasn1 import error +from pyasn1.type import base +from pyasn1.type import char +from pyasn1.type import tag +from pyasn1.type import univ +from pyasn1.type import useful + +__all__ = ['encode'] + +LOG = debug.registerLoggee(__name__, flags=debug.DEBUG_ENCODER) + + +class AbstractItemEncoder(object): + def encode(self, value, encodeFun, **options): + raise error.PyAsn1Error('Not implemented') + + +class BooleanEncoder(AbstractItemEncoder): + def encode(self, value, encodeFun, **options): + return bool(value) + + +class IntegerEncoder(AbstractItemEncoder): + def encode(self, value, encodeFun, **options): + return int(value) + + +class BitStringEncoder(AbstractItemEncoder): + def encode(self, value, encodeFun, **options): + return str(value) + + +class OctetStringEncoder(AbstractItemEncoder): + def encode(self, value, encodeFun, **options): + return value.asOctets() + + +class TextStringEncoder(AbstractItemEncoder): + def encode(self, value, encodeFun, **options): + return str(value) + + +class NullEncoder(AbstractItemEncoder): + def encode(self, value, encodeFun, **options): + return None + + +class ObjectIdentifierEncoder(AbstractItemEncoder): + def encode(self, value, encodeFun, **options): + return str(value) + + +class RealEncoder(AbstractItemEncoder): + def encode(self, value, encodeFun, **options): + return float(value) + + +class SetEncoder(AbstractItemEncoder): + protoDict = dict + + def encode(self, value, encodeFun, **options): + inconsistency = value.isInconsistent + if inconsistency: + raise inconsistency + + namedTypes = value.componentType + substrate = self.protoDict() + + for idx, (key, subValue) in enumerate(value.items()): + if namedTypes and namedTypes[idx].isOptional and not value[idx].isValue: + continue + substrate[key] = encodeFun(subValue, **options) + return substrate + + +class SequenceEncoder(SetEncoder): + protoDict = OrderedDict + + +class SequenceOfEncoder(AbstractItemEncoder): + def encode(self, value, encodeFun, **options): + inconsistency = value.isInconsistent + if inconsistency: + raise inconsistency + return [encodeFun(x, **options) for x in value] + + +class ChoiceEncoder(SequenceEncoder): + pass + + +class AnyEncoder(AbstractItemEncoder): + def encode(self, value, encodeFun, **options): + return value.asOctets() + + +tagMap = { + univ.Boolean.tagSet: BooleanEncoder(), + univ.Integer.tagSet: IntegerEncoder(), + univ.BitString.tagSet: BitStringEncoder(), + univ.OctetString.tagSet: OctetStringEncoder(), + univ.Null.tagSet: NullEncoder(), + univ.ObjectIdentifier.tagSet: ObjectIdentifierEncoder(), + univ.Enumerated.tagSet: IntegerEncoder(), + univ.Real.tagSet: RealEncoder(), + # Sequence & Set have same tags as SequenceOf & SetOf + univ.SequenceOf.tagSet: SequenceOfEncoder(), + univ.SetOf.tagSet: SequenceOfEncoder(), + univ.Choice.tagSet: ChoiceEncoder(), + # character string types + char.UTF8String.tagSet: TextStringEncoder(), + char.NumericString.tagSet: TextStringEncoder(), + char.PrintableString.tagSet: TextStringEncoder(), + char.TeletexString.tagSet: TextStringEncoder(), + char.VideotexString.tagSet: TextStringEncoder(), + char.IA5String.tagSet: TextStringEncoder(), + char.GraphicString.tagSet: TextStringEncoder(), + char.VisibleString.tagSet: TextStringEncoder(), + char.GeneralString.tagSet: TextStringEncoder(), + char.UniversalString.tagSet: TextStringEncoder(), + char.BMPString.tagSet: TextStringEncoder(), + # useful types + useful.ObjectDescriptor.tagSet: OctetStringEncoder(), + useful.GeneralizedTime.tagSet: OctetStringEncoder(), + useful.UTCTime.tagSet: OctetStringEncoder() +} + + +# Put in ambiguous & non-ambiguous types for faster codec lookup +typeMap = { + univ.Boolean.typeId: BooleanEncoder(), + univ.Integer.typeId: IntegerEncoder(), + univ.BitString.typeId: BitStringEncoder(), + univ.OctetString.typeId: OctetStringEncoder(), + univ.Null.typeId: NullEncoder(), + univ.ObjectIdentifier.typeId: ObjectIdentifierEncoder(), + univ.Enumerated.typeId: IntegerEncoder(), + univ.Real.typeId: RealEncoder(), + # Sequence & Set have same tags as SequenceOf & SetOf + univ.Set.typeId: SetEncoder(), + univ.SetOf.typeId: SequenceOfEncoder(), + univ.Sequence.typeId: SequenceEncoder(), + univ.SequenceOf.typeId: SequenceOfEncoder(), + univ.Choice.typeId: ChoiceEncoder(), + univ.Any.typeId: AnyEncoder(), + # character string types + char.UTF8String.typeId: OctetStringEncoder(), + char.NumericString.typeId: OctetStringEncoder(), + char.PrintableString.typeId: OctetStringEncoder(), + char.TeletexString.typeId: OctetStringEncoder(), + char.VideotexString.typeId: OctetStringEncoder(), + char.IA5String.typeId: OctetStringEncoder(), + char.GraphicString.typeId: OctetStringEncoder(), + char.VisibleString.typeId: OctetStringEncoder(), + char.GeneralString.typeId: OctetStringEncoder(), + char.UniversalString.typeId: OctetStringEncoder(), + char.BMPString.typeId: OctetStringEncoder(), + # useful types + useful.ObjectDescriptor.typeId: OctetStringEncoder(), + useful.GeneralizedTime.typeId: OctetStringEncoder(), + useful.UTCTime.typeId: OctetStringEncoder() +} + + +class Encoder(object): + + # noinspection PyDefaultArgument + def __init__(self, tagMap, typeMap={}): + self.__tagMap = tagMap + self.__typeMap = typeMap + + def __call__(self, value, **options): + if not isinstance(value, base.Asn1Item): + raise error.PyAsn1Error('value is not valid (should be an instance of an ASN.1 Item)') + + if LOG: + debug.scope.push(type(value).__name__) + LOG('encoder called for type %s <%s>' % (type(value).__name__, value.prettyPrint())) + + tagSet = value.tagSet + + try: + concreteEncoder = self.__typeMap[value.typeId] + + except KeyError: + # use base type for codec lookup to recover untagged types + baseTagSet = tag.TagSet(value.tagSet.baseTag, value.tagSet.baseTag) + + try: + concreteEncoder = self.__tagMap[baseTagSet] + + except KeyError: + raise error.PyAsn1Error('No encoder for %s' % (value,)) + + if LOG: + LOG('using value codec %s chosen by %s' % (concreteEncoder.__class__.__name__, tagSet)) + + pyObject = concreteEncoder.encode(value, self, **options) + + if LOG: + LOG('encoder %s produced: %s' % (type(concreteEncoder).__name__, repr(pyObject))) + debug.scope.pop() + + return pyObject + + +#: Turns ASN.1 object into a Python built-in type object(s). +#: +#: Takes any ASN.1 object (e.g. :py:class:`~pyasn1.type.base.PyAsn1Item` derivative) +#: walks all its components recursively and produces a Python built-in type or a tree +#: of those. +#: +#: One exception is that instead of :py:class:`dict`, the :py:class:`OrderedDict` +#: can be produced (whenever available) to preserve ordering of the components +#: in ASN.1 SEQUENCE. +#: +#: Parameters +#: ---------- +# asn1Value: any pyasn1 object (e.g. :py:class:`~pyasn1.type.base.PyAsn1Item` derivative) +#: pyasn1 object to encode (or a tree of them) +#: +#: Returns +#: ------- +#: : :py:class:`object` +#: Python built-in type instance (or a tree of them) +#: +#: Raises +#: ------ +#: ~pyasn1.error.PyAsn1Error +#: On encoding errors +#: +#: Examples +#: -------- +#: Encode ASN.1 value object into native Python types +#: +#: .. code-block:: pycon +#: +#: >>> seq = SequenceOf(componentType=Integer()) +#: >>> seq.extend([1, 2, 3]) +#: >>> encode(seq) +#: [1, 2, 3] +#: +encode = Encoder(tagMap, typeMap) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/compat/__init__.py b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/compat/__init__.py new file mode 100644 index 00000000..8c3066b2 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/compat/__init__.py @@ -0,0 +1 @@ +# This file is necessary to make this directory a package. diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/compat/__pycache__/__init__.cpython-310.pyc b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/compat/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 00000000..a69dd661 Binary files /dev/null and b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/compat/__pycache__/__init__.cpython-310.pyc differ diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/compat/__pycache__/binary.cpython-310.pyc b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/compat/__pycache__/binary.cpython-310.pyc new file mode 100644 index 00000000..3252c06e Binary files /dev/null and b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/compat/__pycache__/binary.cpython-310.pyc differ diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/compat/__pycache__/calling.cpython-310.pyc b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/compat/__pycache__/calling.cpython-310.pyc new file mode 100644 index 00000000..6e19dc4f Binary files /dev/null and b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/compat/__pycache__/calling.cpython-310.pyc differ diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/compat/__pycache__/dateandtime.cpython-310.pyc b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/compat/__pycache__/dateandtime.cpython-310.pyc new file mode 100644 index 00000000..ea3dec95 Binary files /dev/null and b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/compat/__pycache__/dateandtime.cpython-310.pyc differ diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/compat/__pycache__/integer.cpython-310.pyc b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/compat/__pycache__/integer.cpython-310.pyc new file mode 100644 index 00000000..a9582e60 Binary files /dev/null and b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/compat/__pycache__/integer.cpython-310.pyc differ diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/compat/__pycache__/octets.cpython-310.pyc b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/compat/__pycache__/octets.cpython-310.pyc new file mode 100644 index 00000000..ba322df6 Binary files /dev/null and b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/compat/__pycache__/octets.cpython-310.pyc differ diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/compat/__pycache__/string.cpython-310.pyc b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/compat/__pycache__/string.cpython-310.pyc new file mode 100644 index 00000000..f1ed4abf Binary files /dev/null and b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/compat/__pycache__/string.cpython-310.pyc differ diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/compat/binary.py b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/compat/binary.py new file mode 100644 index 00000000..addbdc9c --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/compat/binary.py @@ -0,0 +1,33 @@ +# +# This file is part of pyasn1 software. +# +# Copyright (c) 2005-2019, Ilya Etingof <etingof@gmail.com> +# License: http://snmplabs.com/pyasn1/license.html +# +from sys import version_info + +if version_info[0:2] < (2, 6): + def bin(value): + bitstring = [] + + if value > 0: + prefix = '0b' + elif value < 0: + prefix = '-0b' + value = abs(value) + else: + prefix = '0b0' + + while value: + if value & 1 == 1: + bitstring.append('1') + else: + bitstring.append('0') + + value >>= 1 + + bitstring.reverse() + + return prefix + ''.join(bitstring) +else: + bin = bin diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/compat/calling.py b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/compat/calling.py new file mode 100644 index 00000000..778a3d15 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/compat/calling.py @@ -0,0 +1,20 @@ +# +# This file is part of pyasn1 software. +# +# Copyright (c) 2005-2019, Ilya Etingof <etingof@gmail.com> +# License: http://snmplabs.com/pyasn1/license.html +# +from sys import version_info + +__all__ = ['callable'] + + +if (2, 7) < version_info[:2] < (3, 2): + import collections + + def callable(x): + return isinstance(x, collections.Callable) + +else: + + callable = callable diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/compat/dateandtime.py b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/compat/dateandtime.py new file mode 100644 index 00000000..5e471bf7 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/compat/dateandtime.py @@ -0,0 +1,22 @@ +# +# This file is part of pyasn1 software. +# +# Copyright (c) 2005-2019, Ilya Etingof <etingof@gmail.com> +# License: http://snmplabs.com/pyasn1/license.html +# +import time +from datetime import datetime +from sys import version_info + +__all__ = ['strptime'] + + +if version_info[:2] <= (2, 4): + + def strptime(text, dateFormat): + return datetime(*(time.strptime(text, dateFormat)[0:6])) + +else: + + def strptime(text, dateFormat): + return datetime.strptime(text, dateFormat) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/compat/integer.py b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/compat/integer.py new file mode 100644 index 00000000..4b31791d --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/compat/integer.py @@ -0,0 +1,110 @@ +# +# This file is part of pyasn1 software. +# +# Copyright (c) 2005-2019, Ilya Etingof <etingof@gmail.com> +# License: http://snmplabs.com/pyasn1/license.html +# +import sys + +try: + import platform + + implementation = platform.python_implementation() + +except (ImportError, AttributeError): + implementation = 'CPython' + +from pyasn1.compat.octets import oct2int, null, ensureString + +if sys.version_info[0:2] < (3, 2) or implementation != 'CPython': + from binascii import a2b_hex, b2a_hex + + if sys.version_info[0] > 2: + long = int + + def from_bytes(octets, signed=False): + if not octets: + return 0 + + value = long(b2a_hex(ensureString(octets)), 16) + + if signed and oct2int(octets[0]) & 0x80: + return value - (1 << len(octets) * 8) + + return value + + def to_bytes(value, signed=False, length=0): + if value < 0: + if signed: + bits = bitLength(value) + + # two's complement form + maxValue = 1 << bits + valueToEncode = (value + maxValue) % maxValue + + else: + raise OverflowError('can\'t convert negative int to unsigned') + elif value == 0 and length == 0: + return null + else: + bits = 0 + valueToEncode = value + + hexValue = hex(valueToEncode)[2:] + if hexValue.endswith('L'): + hexValue = hexValue[:-1] + + if len(hexValue) & 1: + hexValue = '0' + hexValue + + # padding may be needed for two's complement encoding + if value != valueToEncode or length: + hexLength = len(hexValue) * 4 + + padLength = max(length, bits) + + if padLength > hexLength: + hexValue = '00' * ((padLength - hexLength - 1) // 8 + 1) + hexValue + elif length and hexLength - length > 7: + raise OverflowError('int too big to convert') + + firstOctet = int(hexValue[:2], 16) + + if signed: + if firstOctet & 0x80: + if value >= 0: + hexValue = '00' + hexValue + elif value < 0: + hexValue = 'ff' + hexValue + + octets_value = a2b_hex(hexValue) + + return octets_value + + def bitLength(number): + # bits in unsigned number + hexValue = hex(abs(number)) + bits = len(hexValue) - 2 + if hexValue.endswith('L'): + bits -= 1 + if bits & 1: + bits += 1 + bits *= 4 + # TODO: strip lhs zeros + return bits + +else: + + def from_bytes(octets, signed=False): + return int.from_bytes(bytes(octets), 'big', signed=signed) + + def to_bytes(value, signed=False, length=0): + length = max(value.bit_length(), length) + + if signed and length % 8 == 0: + length += 1 + + return value.to_bytes(length // 8 + (length % 8 and 1 or 0), 'big', signed=signed) + + def bitLength(number): + return int(number).bit_length() diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/compat/octets.py b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/compat/octets.py new file mode 100644 index 00000000..99d23bb3 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/compat/octets.py @@ -0,0 +1,46 @@ +# +# This file is part of pyasn1 software. +# +# Copyright (c) 2005-2019, Ilya Etingof <etingof@gmail.com> +# License: http://snmplabs.com/pyasn1/license.html +# +from sys import version_info + +if version_info[0] <= 2: + int2oct = chr + # noinspection PyPep8 + ints2octs = lambda s: ''.join([int2oct(x) for x in s]) + null = '' + oct2int = ord + # TODO: refactor to return a sequence of ints + # noinspection PyPep8 + octs2ints = lambda s: [oct2int(x) for x in s] + # noinspection PyPep8 + str2octs = lambda x: x + # noinspection PyPep8 + octs2str = lambda x: x + # noinspection PyPep8 + isOctetsType = lambda s: isinstance(s, str) + # noinspection PyPep8 + isStringType = lambda s: isinstance(s, (str, unicode)) + # noinspection PyPep8 + ensureString = str +else: + ints2octs = bytes + # noinspection PyPep8 + int2oct = lambda x: ints2octs((x,)) + null = ints2octs() + # noinspection PyPep8 + oct2int = lambda x: x + # noinspection PyPep8 + octs2ints = lambda x: x + # noinspection PyPep8 + str2octs = lambda x: x.encode('iso-8859-1') + # noinspection PyPep8 + octs2str = lambda x: x.decode('iso-8859-1') + # noinspection PyPep8 + isOctetsType = lambda s: isinstance(s, bytes) + # noinspection PyPep8 + isStringType = lambda s: isinstance(s, str) + # noinspection PyPep8 + ensureString = bytes diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/compat/string.py b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/compat/string.py new file mode 100644 index 00000000..b9bc8c38 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/compat/string.py @@ -0,0 +1,26 @@ +# +# This file is part of pyasn1 software. +# +# Copyright (c) 2005-2019, Ilya Etingof <etingof@gmail.com> +# License: http://snmplabs.com/pyasn1/license.html +# +from sys import version_info + +if version_info[:2] <= (2, 5): + + def partition(string, sep): + try: + a, c = string.split(sep, 1) + + except ValueError: + a, b, c = string, '', '' + + else: + b = sep + + return a, b, c + +else: + + def partition(string, sep): + return string.partition(sep) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/debug.py b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/debug.py new file mode 100644 index 00000000..8707aa88 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/debug.py @@ -0,0 +1,157 @@ +# +# This file is part of pyasn1 software. +# +# Copyright (c) 2005-2019, Ilya Etingof <etingof@gmail.com> +# License: http://snmplabs.com/pyasn1/license.html +# +import logging +import sys + +from pyasn1 import __version__ +from pyasn1 import error +from pyasn1.compat.octets import octs2ints + +__all__ = ['Debug', 'setLogger', 'hexdump'] + +DEBUG_NONE = 0x0000 +DEBUG_ENCODER = 0x0001 +DEBUG_DECODER = 0x0002 +DEBUG_ALL = 0xffff + +FLAG_MAP = { + 'none': DEBUG_NONE, + 'encoder': DEBUG_ENCODER, + 'decoder': DEBUG_DECODER, + 'all': DEBUG_ALL +} + +LOGGEE_MAP = {} + + +class Printer(object): + # noinspection PyShadowingNames + def __init__(self, logger=None, handler=None, formatter=None): + if logger is None: + logger = logging.getLogger('pyasn1') + + logger.setLevel(logging.DEBUG) + + if handler is None: + handler = logging.StreamHandler() + + if formatter is None: + formatter = logging.Formatter('%(asctime)s %(name)s: %(message)s') + + handler.setFormatter(formatter) + handler.setLevel(logging.DEBUG) + logger.addHandler(handler) + + self.__logger = logger + + def __call__(self, msg): + self.__logger.debug(msg) + + def __str__(self): + return '<python logging>' + + +if hasattr(logging, 'NullHandler'): + NullHandler = logging.NullHandler + +else: + # Python 2.6 and older + class NullHandler(logging.Handler): + def emit(self, record): + pass + + +class Debug(object): + defaultPrinter = Printer() + + def __init__(self, *flags, **options): + self._flags = DEBUG_NONE + + if 'loggerName' in options: + # route our logs to parent logger + self._printer = Printer( + logger=logging.getLogger(options['loggerName']), + handler=NullHandler() + ) + + elif 'printer' in options: + self._printer = options.get('printer') + + else: + self._printer = self.defaultPrinter + + self._printer('running pyasn1 %s, debug flags %s' % (__version__, ', '.join(flags))) + + for flag in flags: + inverse = flag and flag[0] in ('!', '~') + if inverse: + flag = flag[1:] + try: + if inverse: + self._flags &= ~FLAG_MAP[flag] + else: + self._flags |= FLAG_MAP[flag] + except KeyError: + raise error.PyAsn1Error('bad debug flag %s' % flag) + + self._printer("debug category '%s' %s" % (flag, inverse and 'disabled' or 'enabled')) + + def __str__(self): + return 'logger %s, flags %x' % (self._printer, self._flags) + + def __call__(self, msg): + self._printer(msg) + + def __and__(self, flag): + return self._flags & flag + + def __rand__(self, flag): + return flag & self._flags + +_LOG = DEBUG_NONE + + +def setLogger(userLogger): + global _LOG + + if userLogger: + _LOG = userLogger + else: + _LOG = DEBUG_NONE + + # Update registered logging clients + for module, (name, flags) in LOGGEE_MAP.items(): + setattr(module, name, _LOG & flags and _LOG or DEBUG_NONE) + + +def registerLoggee(module, name='LOG', flags=DEBUG_NONE): + LOGGEE_MAP[sys.modules[module]] = name, flags + setLogger(_LOG) + return _LOG + + +def hexdump(octets): + return ' '.join( + ['%s%.2X' % (n % 16 == 0 and ('\n%.5d: ' % n) or '', x) + for n, x in zip(range(len(octets)), octs2ints(octets))] + ) + + +class Scope(object): + def __init__(self): + self._list = [] + + def __str__(self): return '.'.join(self._list) + + def push(self, token): + self._list.append(token) + + def pop(self): + return self._list.pop() + + +scope = Scope() diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/error.py b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/error.py new file mode 100644 index 00000000..4f48db25 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/error.py @@ -0,0 +1,75 @@ +# +# This file is part of pyasn1 software. +# +# Copyright (c) 2005-2019, Ilya Etingof <etingof@gmail.com> +# License: http://snmplabs.com/pyasn1/license.html +# + + +class PyAsn1Error(Exception): + """Base pyasn1 exception + + `PyAsn1Error` is the base exception class (based on + :class:`Exception`) that represents all possible ASN.1 related + errors. + """ + + +class ValueConstraintError(PyAsn1Error): + """ASN.1 type constraints violation exception + + The `ValueConstraintError` exception indicates an ASN.1 value + constraint violation. + + It might happen on value object instantiation (for scalar types) or on + serialization (for constructed types). + """ + + +class SubstrateUnderrunError(PyAsn1Error): + """ASN.1 data structure deserialization error + + The `SubstrateUnderrunError` exception indicates insufficient serialised + data on input of a de-serialization codec. + """ + + +class PyAsn1UnicodeError(PyAsn1Error, UnicodeError): + """Unicode text processing error + + The `PyAsn1UnicodeError` exception is a base class for errors relating to + unicode text de/serialization. + + Apart from inheriting from :class:`PyAsn1Error`, it also inherits from + :class:`UnicodeError` to help the caller catching unicode-related errors. + """ + def __init__(self, message, unicode_error=None): + if isinstance(unicode_error, UnicodeError): + UnicodeError.__init__(self, *unicode_error.args) + PyAsn1Error.__init__(self, message) + + +class PyAsn1UnicodeDecodeError(PyAsn1UnicodeError, UnicodeDecodeError): + """Unicode text decoding error + + The `PyAsn1UnicodeDecodeError` exception represents a failure to + deserialize unicode text. + + Apart from inheriting from :class:`PyAsn1UnicodeError`, it also inherits + from :class:`UnicodeDecodeError` to help the caller catching unicode-related + errors. + """ + + +class PyAsn1UnicodeEncodeError(PyAsn1UnicodeError, UnicodeEncodeError): + """Unicode text encoding error + + The `PyAsn1UnicodeEncodeError` exception represents a failure to + serialize unicode text. + + Apart from inheriting from :class:`PyAsn1UnicodeError`, it also inherits + from :class:`UnicodeEncodeError` to help the caller catching + unicode-related errors. + """ + + diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/type/__init__.py b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/type/__init__.py new file mode 100644 index 00000000..8c3066b2 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/type/__init__.py @@ -0,0 +1 @@ +# This file is necessary to make this directory a package. diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/type/__pycache__/__init__.cpython-310.pyc b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/type/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 00000000..827810c2 Binary files /dev/null and b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/type/__pycache__/__init__.cpython-310.pyc differ diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/type/__pycache__/base.cpython-310.pyc b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/type/__pycache__/base.cpython-310.pyc new file mode 100644 index 00000000..8dc8ea59 Binary files /dev/null and b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/type/__pycache__/base.cpython-310.pyc differ diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/type/__pycache__/char.cpython-310.pyc b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/type/__pycache__/char.cpython-310.pyc new file mode 100644 index 00000000..ce7bf6ee Binary files /dev/null and b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/type/__pycache__/char.cpython-310.pyc differ diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/type/__pycache__/constraint.cpython-310.pyc b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/type/__pycache__/constraint.cpython-310.pyc new file mode 100644 index 00000000..8514fee6 Binary files /dev/null and b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/type/__pycache__/constraint.cpython-310.pyc differ diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/type/__pycache__/error.cpython-310.pyc b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/type/__pycache__/error.cpython-310.pyc new file mode 100644 index 00000000..812d7833 Binary files /dev/null and b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/type/__pycache__/error.cpython-310.pyc differ diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/type/__pycache__/namedtype.cpython-310.pyc b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/type/__pycache__/namedtype.cpython-310.pyc new file mode 100644 index 00000000..81c8799a Binary files /dev/null and b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/type/__pycache__/namedtype.cpython-310.pyc differ diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/type/__pycache__/namedval.cpython-310.pyc b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/type/__pycache__/namedval.cpython-310.pyc new file mode 100644 index 00000000..f4f74ec6 Binary files /dev/null and b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/type/__pycache__/namedval.cpython-310.pyc differ diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/type/__pycache__/tag.cpython-310.pyc b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/type/__pycache__/tag.cpython-310.pyc new file mode 100644 index 00000000..282ad1bc Binary files /dev/null and b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/type/__pycache__/tag.cpython-310.pyc differ diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/type/__pycache__/tagmap.cpython-310.pyc b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/type/__pycache__/tagmap.cpython-310.pyc new file mode 100644 index 00000000..5b05e075 Binary files /dev/null and b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/type/__pycache__/tagmap.cpython-310.pyc differ diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/type/__pycache__/univ.cpython-310.pyc b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/type/__pycache__/univ.cpython-310.pyc new file mode 100644 index 00000000..99a63f86 Binary files /dev/null and b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/type/__pycache__/univ.cpython-310.pyc differ diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/type/__pycache__/useful.cpython-310.pyc b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/type/__pycache__/useful.cpython-310.pyc new file mode 100644 index 00000000..24ec36e5 Binary files /dev/null and b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/type/__pycache__/useful.cpython-310.pyc differ diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/type/base.py b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/type/base.py new file mode 100644 index 00000000..994f1c99 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/type/base.py @@ -0,0 +1,707 @@ +# +# This file is part of pyasn1 software. +# +# Copyright (c) 2005-2019, Ilya Etingof <etingof@gmail.com> +# License: http://snmplabs.com/pyasn1/license.html +# +import sys + +from pyasn1 import error +from pyasn1.compat import calling +from pyasn1.type import constraint +from pyasn1.type import tag +from pyasn1.type import tagmap + +__all__ = ['Asn1Item', 'Asn1Type', 'SimpleAsn1Type', + 'ConstructedAsn1Type'] + + +class Asn1Item(object): + @classmethod + def getTypeId(cls, increment=1): + try: + Asn1Item._typeCounter += increment + except AttributeError: + Asn1Item._typeCounter = increment + return Asn1Item._typeCounter + + +class Asn1Type(Asn1Item): + """Base class for all classes representing ASN.1 types. + + In the user code, |ASN.1| class is normally used only for telling + ASN.1 objects from others. + + Note + ---- + For as long as ASN.1 is concerned, a way to compare ASN.1 types + is to use :meth:`isSameTypeWith` and :meth:`isSuperTypeOf` methods. + """ + #: Set or return a :py:class:`~pyasn1.type.tag.TagSet` object representing + #: ASN.1 tag(s) associated with |ASN.1| type. + tagSet = tag.TagSet() + + #: Default :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` + #: object imposing constraints on initialization values. + subtypeSpec = constraint.ConstraintsIntersection() + + # Disambiguation ASN.1 types identification + typeId = None + + def __init__(self, **kwargs): + readOnly = { + 'tagSet': self.tagSet, + 'subtypeSpec': self.subtypeSpec + } + + readOnly.update(kwargs) + + self.__dict__.update(readOnly) + + self._readOnly = readOnly + + def __setattr__(self, name, value): + if name[0] != '_' and name in self._readOnly: + raise error.PyAsn1Error('read-only instance attribute "%s"' % name) + + self.__dict__[name] = value + + def __str__(self): + return self.prettyPrint() + + @property + def readOnly(self): + return self._readOnly + + @property + def effectiveTagSet(self): + """For |ASN.1| type is equivalent to *tagSet* + """ + return self.tagSet # used by untagged types + + @property + def tagMap(self): + """Return a :class:`~pyasn1.type.tagmap.TagMap` object mapping ASN.1 tags to ASN.1 objects within callee object. + """ + return tagmap.TagMap({self.tagSet: self}) + + def isSameTypeWith(self, other, matchTags=True, matchConstraints=True): + """Examine |ASN.1| type for equality with other ASN.1 type. + + ASN.1 tags (:py:mod:`~pyasn1.type.tag`) and constraints + (:py:mod:`~pyasn1.type.constraint`) are examined when carrying + out ASN.1 types comparison. + + Python class inheritance relationship is NOT considered. + + Parameters + ---------- + other: a pyasn1 type object + Class instance representing ASN.1 type. + + Returns + ------- + : :class:`bool` + :obj:`True` if *other* is |ASN.1| type, + :obj:`False` otherwise. + """ + return (self is other or + (not matchTags or self.tagSet == other.tagSet) and + (not matchConstraints or self.subtypeSpec == other.subtypeSpec)) + + def isSuperTypeOf(self, other, matchTags=True, matchConstraints=True): + """Examine |ASN.1| type for subtype relationship with other ASN.1 type. + + ASN.1 tags (:py:mod:`~pyasn1.type.tag`) and constraints + (:py:mod:`~pyasn1.type.constraint`) are examined when carrying + out ASN.1 types comparison. + + Python class inheritance relationship is NOT considered. + + Parameters + ---------- + other: a pyasn1 type object + Class instance representing ASN.1 type. + + Returns + ------- + : :class:`bool` + :obj:`True` if *other* is a subtype of |ASN.1| type, + :obj:`False` otherwise. + """ + return (not matchTags or + (self.tagSet.isSuperTagSetOf(other.tagSet)) and + (not matchConstraints or self.subtypeSpec.isSuperTypeOf(other.subtypeSpec))) + + @staticmethod + def isNoValue(*values): + for value in values: + if value is not noValue: + return False + return True + + def prettyPrint(self, scope=0): + raise NotImplementedError() + + # backward compatibility + + def getTagSet(self): + return self.tagSet + + def getEffectiveTagSet(self): + return self.effectiveTagSet + + def getTagMap(self): + return self.tagMap + + def getSubtypeSpec(self): + return self.subtypeSpec + + # backward compatibility + def hasValue(self): + return self.isValue + +# Backward compatibility +Asn1ItemBase = Asn1Type + + +class NoValue(object): + """Create a singleton instance of NoValue class. + + The *NoValue* sentinel object represents an instance of ASN.1 schema + object as opposed to ASN.1 value object. + + Only ASN.1 schema-related operations can be performed on ASN.1 + schema objects. + + Warning + ------- + Any operation attempted on the *noValue* object will raise the + *PyAsn1Error* exception. + """ + skipMethods = set( + ('__slots__', + # attributes + '__getattribute__', + '__getattr__', + '__setattr__', + '__delattr__', + # class instance + '__class__', + '__init__', + '__del__', + '__new__', + '__repr__', + '__qualname__', + '__objclass__', + 'im_class', + '__sizeof__', + # pickle protocol + '__reduce__', + '__reduce_ex__', + '__getnewargs__', + '__getinitargs__', + '__getstate__', + '__setstate__') + ) + + _instance = None + + def __new__(cls): + if cls._instance is None: + def getPlug(name): + def plug(self, *args, **kw): + raise error.PyAsn1Error('Attempted "%s" operation on ASN.1 schema object' % name) + return plug + + op_names = [name + for typ in (str, int, list, dict) + for name in dir(typ) + if (name not in cls.skipMethods and + name.startswith('__') and + name.endswith('__') and + calling.callable(getattr(typ, name)))] + + for name in set(op_names): + setattr(cls, name, getPlug(name)) + + cls._instance = object.__new__(cls) + + return cls._instance + + def __getattr__(self, attr): + if attr in self.skipMethods: + raise AttributeError('Attribute %s not present' % attr) + + raise error.PyAsn1Error('Attempted "%s" operation on ASN.1 schema object' % attr) + + def __repr__(self): + return '<%s object>' % self.__class__.__name__ + + +noValue = NoValue() + + +class SimpleAsn1Type(Asn1Type): + """Base class for all simple classes representing ASN.1 types. + + ASN.1 distinguishes types by their ability to hold other objects. + Scalar types are known as *simple* in ASN.1. + + In the user code, |ASN.1| class is normally used only for telling + ASN.1 objects from others. + + Note + ---- + For as long as ASN.1 is concerned, a way to compare ASN.1 types + is to use :meth:`isSameTypeWith` and :meth:`isSuperTypeOf` methods. + """ + #: Default payload value + defaultValue = noValue + + def __init__(self, value=noValue, **kwargs): + Asn1Type.__init__(self, **kwargs) + if value is noValue: + value = self.defaultValue + else: + value = self.prettyIn(value) + try: + self.subtypeSpec(value) + + except error.PyAsn1Error: + exType, exValue, exTb = sys.exc_info() + raise exType('%s at %s' % (exValue, self.__class__.__name__)) + + self._value = value + + def __repr__(self): + representation = '%s %s object' % ( + self.__class__.__name__, self.isValue and 'value' or 'schema') + + for attr, value in self.readOnly.items(): + if value: + representation += ', %s %s' % (attr, value) + + if self.isValue: + value = self.prettyPrint() + if len(value) > 32: + value = value[:16] + '...' + value[-16:] + representation += ', payload [%s]' % value + + return '<%s>' % representation + + def __eq__(self, other): + return self is other and True or self._value == other + + def __ne__(self, other): + return self._value != other + + def __lt__(self, other): + return self._value < other + + def __le__(self, other): + return self._value <= other + + def __gt__(self, other): + return self._value > other + + def __ge__(self, other): + return self._value >= other + + if sys.version_info[0] <= 2: + def __nonzero__(self): + return self._value and True or False + else: + def __bool__(self): + return self._value and True or False + + def __hash__(self): + return hash(self._value) + + @property + def isValue(self): + """Indicate that |ASN.1| object represents ASN.1 value. + + If *isValue* is :obj:`False` then this object represents just + ASN.1 schema. + + If *isValue* is :obj:`True` then, in addition to its ASN.1 schema + features, this object can also be used like a Python built-in object + (e.g. :class:`int`, :class:`str`, :class:`dict` etc.). + + Returns + ------- + : :class:`bool` + :obj:`False` if object represents just ASN.1 schema. + :obj:`True` if object represents ASN.1 schema and can be used as a normal value. + + Note + ---- + There is an important distinction between PyASN1 schema and value objects. + The PyASN1 schema objects can only participate in ASN.1 schema-related + operations (e.g. defining or testing the structure of the data). Most + obvious uses of ASN.1 schema is to guide serialisation codecs whilst + encoding/decoding serialised ASN.1 contents. + + The PyASN1 value objects can **additionally** participate in many operations + involving regular Python objects (e.g. arithmetic, comprehension etc). + """ + return self._value is not noValue + + def clone(self, value=noValue, **kwargs): + """Create a modified version of |ASN.1| schema or value object. + + The `clone()` method accepts the same set arguments as |ASN.1| + class takes on instantiation except that all arguments + of the `clone()` method are optional. + + Whatever arguments are supplied, they are used to create a copy + of `self` taking precedence over the ones used to instantiate `self`. + + Note + ---- + Due to the immutable nature of the |ASN.1| object, if no arguments + are supplied, no new |ASN.1| object will be created and `self` will + be returned instead. + """ + if value is noValue: + if not kwargs: + return self + + value = self._value + + initializers = self.readOnly.copy() + initializers.update(kwargs) + + return self.__class__(value, **initializers) + + def subtype(self, value=noValue, **kwargs): + """Create a specialization of |ASN.1| schema or value object. + + The subtype relationship between ASN.1 types has no correlation with + subtype relationship between Python types. ASN.1 type is mainly identified + by its tag(s) (:py:class:`~pyasn1.type.tag.TagSet`) and value range + constraints (:py:class:`~pyasn1.type.constraint.ConstraintsIntersection`). + These ASN.1 type properties are implemented as |ASN.1| attributes. + + The `subtype()` method accepts the same set arguments as |ASN.1| + class takes on instantiation except that all parameters + of the `subtype()` method are optional. + + With the exception of the arguments described below, the rest of + supplied arguments they are used to create a copy of `self` taking + precedence over the ones used to instantiate `self`. + + The following arguments to `subtype()` create a ASN.1 subtype out of + |ASN.1| type: + + Other Parameters + ---------------- + implicitTag: :py:class:`~pyasn1.type.tag.Tag` + Implicitly apply given ASN.1 tag object to `self`'s + :py:class:`~pyasn1.type.tag.TagSet`, then use the result as + new object's ASN.1 tag(s). + + explicitTag: :py:class:`~pyasn1.type.tag.Tag` + Explicitly apply given ASN.1 tag object to `self`'s + :py:class:`~pyasn1.type.tag.TagSet`, then use the result as + new object's ASN.1 tag(s). + + subtypeSpec: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` + Add ASN.1 constraints object to one of the `self`'s, then + use the result as new object's ASN.1 constraints. + + Returns + ------- + : + new instance of |ASN.1| schema or value object + + Note + ---- + Due to the immutable nature of the |ASN.1| object, if no arguments + are supplied, no new |ASN.1| object will be created and `self` will + be returned instead. + """ + if value is noValue: + if not kwargs: + return self + + value = self._value + + initializers = self.readOnly.copy() + + implicitTag = kwargs.pop('implicitTag', None) + if implicitTag is not None: + initializers['tagSet'] = self.tagSet.tagImplicitly(implicitTag) + + explicitTag = kwargs.pop('explicitTag', None) + if explicitTag is not None: + initializers['tagSet'] = self.tagSet.tagExplicitly(explicitTag) + + for arg, option in kwargs.items(): + initializers[arg] += option + + return self.__class__(value, **initializers) + + def prettyIn(self, value): + return value + + def prettyOut(self, value): + return str(value) + + def prettyPrint(self, scope=0): + return self.prettyOut(self._value) + + def prettyPrintType(self, scope=0): + return '%s -> %s' % (self.tagSet, self.__class__.__name__) + +# Backward compatibility +AbstractSimpleAsn1Item = SimpleAsn1Type + +# +# Constructed types: +# * There are five of them: Sequence, SequenceOf/SetOf, Set and Choice +# * ASN1 types and values are represened by Python class instances +# * Value initialization is made for defaulted components only +# * Primary method of component addressing is by-position. Data model for base +# type is Python sequence. Additional type-specific addressing methods +# may be implemented for particular types. +# * SequenceOf and SetOf types do not implement any additional methods +# * Sequence, Set and Choice types also implement by-identifier addressing +# * Sequence, Set and Choice types also implement by-asn1-type (tag) addressing +# * Sequence and Set types may include optional and defaulted +# components +# * Constructed types hold a reference to component types used for value +# verification and ordering. +# * Component type is a scalar type for SequenceOf/SetOf types and a list +# of types for Sequence/Set/Choice. +# + + +class ConstructedAsn1Type(Asn1Type): + """Base class for all constructed classes representing ASN.1 types. + + ASN.1 distinguishes types by their ability to hold other objects. + Those "nesting" types are known as *constructed* in ASN.1. + + In the user code, |ASN.1| class is normally used only for telling + ASN.1 objects from others. + + Note + ---- + For as long as ASN.1 is concerned, a way to compare ASN.1 types + is to use :meth:`isSameTypeWith` and :meth:`isSuperTypeOf` methods. + """ + + #: If :obj:`True`, requires exact component type matching, + #: otherwise subtype relation is only enforced + strictConstraints = False + + componentType = None + + # backward compatibility, unused + sizeSpec = constraint.ConstraintsIntersection() + + def __init__(self, **kwargs): + readOnly = { + 'componentType': self.componentType, + # backward compatibility, unused + 'sizeSpec': self.sizeSpec + } + + # backward compatibility: preserve legacy sizeSpec support + kwargs = self._moveSizeSpec(**kwargs) + + readOnly.update(kwargs) + + Asn1Type.__init__(self, **readOnly) + + def _moveSizeSpec(self, **kwargs): + # backward compatibility, unused + sizeSpec = kwargs.pop('sizeSpec', self.sizeSpec) + if sizeSpec: + subtypeSpec = kwargs.pop('subtypeSpec', self.subtypeSpec) + if subtypeSpec: + subtypeSpec = sizeSpec + + else: + subtypeSpec += sizeSpec + + kwargs['subtypeSpec'] = subtypeSpec + + return kwargs + + def __repr__(self): + representation = '%s %s object' % ( + self.__class__.__name__, self.isValue and 'value' or 'schema' + ) + + for attr, value in self.readOnly.items(): + if value is not noValue: + representation += ', %s=%r' % (attr, value) + + if self.isValue and self.components: + representation += ', payload [%s]' % ', '.join( + [repr(x) for x in self.components]) + + return '<%s>' % representation + + def __eq__(self, other): + return self is other or self.components == other + + def __ne__(self, other): + return self.components != other + + def __lt__(self, other): + return self.components < other + + def __le__(self, other): + return self.components <= other + + def __gt__(self, other): + return self.components > other + + def __ge__(self, other): + return self.components >= other + + if sys.version_info[0] <= 2: + def __nonzero__(self): + return bool(self.components) + else: + def __bool__(self): + return bool(self.components) + + @property + def components(self): + raise error.PyAsn1Error('Method not implemented') + + def _cloneComponentValues(self, myClone, cloneValueFlag): + pass + + def clone(self, **kwargs): + """Create a modified version of |ASN.1| schema object. + + The `clone()` method accepts the same set arguments as |ASN.1| + class takes on instantiation except that all arguments + of the `clone()` method are optional. + + Whatever arguments are supplied, they are used to create a copy + of `self` taking precedence over the ones used to instantiate `self`. + + Possible values of `self` are never copied over thus `clone()` can + only create a new schema object. + + Returns + ------- + : + new instance of |ASN.1| type/value + + Note + ---- + Due to the mutable nature of the |ASN.1| object, even if no arguments + are supplied, a new |ASN.1| object will be created and returned. + """ + cloneValueFlag = kwargs.pop('cloneValueFlag', False) + + initializers = self.readOnly.copy() + initializers.update(kwargs) + + clone = self.__class__(**initializers) + + if cloneValueFlag: + self._cloneComponentValues(clone, cloneValueFlag) + + return clone + + def subtype(self, **kwargs): + """Create a specialization of |ASN.1| schema object. + + The `subtype()` method accepts the same set arguments as |ASN.1| + class takes on instantiation except that all parameters + of the `subtype()` method are optional. + + With the exception of the arguments described below, the rest of + supplied arguments they are used to create a copy of `self` taking + precedence over the ones used to instantiate `self`. + + The following arguments to `subtype()` create a ASN.1 subtype out of + |ASN.1| type. + + Other Parameters + ---------------- + implicitTag: :py:class:`~pyasn1.type.tag.Tag` + Implicitly apply given ASN.1 tag object to `self`'s + :py:class:`~pyasn1.type.tag.TagSet`, then use the result as + new object's ASN.1 tag(s). + + explicitTag: :py:class:`~pyasn1.type.tag.Tag` + Explicitly apply given ASN.1 tag object to `self`'s + :py:class:`~pyasn1.type.tag.TagSet`, then use the result as + new object's ASN.1 tag(s). + + subtypeSpec: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` + Add ASN.1 constraints object to one of the `self`'s, then + use the result as new object's ASN.1 constraints. + + + Returns + ------- + : + new instance of |ASN.1| type/value + + Note + ---- + Due to the mutable nature of the |ASN.1| object, even if no arguments + are supplied, a new |ASN.1| object will be created and returned. + """ + + initializers = self.readOnly.copy() + + cloneValueFlag = kwargs.pop('cloneValueFlag', False) + + implicitTag = kwargs.pop('implicitTag', None) + if implicitTag is not None: + initializers['tagSet'] = self.tagSet.tagImplicitly(implicitTag) + + explicitTag = kwargs.pop('explicitTag', None) + if explicitTag is not None: + initializers['tagSet'] = self.tagSet.tagExplicitly(explicitTag) + + for arg, option in kwargs.items(): + initializers[arg] += option + + clone = self.__class__(**initializers) + + if cloneValueFlag: + self._cloneComponentValues(clone, cloneValueFlag) + + return clone + + def getComponentByPosition(self, idx): + raise error.PyAsn1Error('Method not implemented') + + def setComponentByPosition(self, idx, value, verifyConstraints=True): + raise error.PyAsn1Error('Method not implemented') + + def setComponents(self, *args, **kwargs): + for idx, value in enumerate(args): + self[idx] = value + for k in kwargs: + self[k] = kwargs[k] + return self + + # backward compatibility + + def setDefaultComponents(self): + pass + + def getComponentType(self): + return self.componentType + + # backward compatibility, unused + def verifySizeSpec(self): + self.subtypeSpec(self) + + + # Backward compatibility +AbstractConstructedAsn1Item = ConstructedAsn1Type diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/type/char.py b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/type/char.py new file mode 100644 index 00000000..06074da0 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/type/char.py @@ -0,0 +1,335 @@ +# +# This file is part of pyasn1 software. +# +# Copyright (c) 2005-2019, Ilya Etingof <etingof@gmail.com> +# License: http://snmplabs.com/pyasn1/license.html +# +import sys + +from pyasn1 import error +from pyasn1.type import tag +from pyasn1.type import univ + +__all__ = ['NumericString', 'PrintableString', 'TeletexString', 'T61String', 'VideotexString', + 'IA5String', 'GraphicString', 'VisibleString', 'ISO646String', + 'GeneralString', 'UniversalString', 'BMPString', 'UTF8String'] + +NoValue = univ.NoValue +noValue = univ.noValue + + +class AbstractCharacterString(univ.OctetString): + """Creates |ASN.1| schema or value object. + + |ASN.1| class is based on :class:`~pyasn1.type.base.SimpleAsn1Type`, + its objects are immutable and duck-type Python 2 :class:`str` or Python 3 + :class:`bytes`. When used in octet-stream context, |ASN.1| type assumes + "|encoding|" encoding. + + Keyword Args + ------------ + value: :class:`unicode`, :class:`str`, :class:`bytes` or |ASN.1| object + :class:`unicode` object (Python 2) or :class:`str` (Python 3), + alternatively :class:`str` (Python 2) or :class:`bytes` (Python 3) + representing octet-stream of serialised unicode string + (note `encoding` parameter) or |ASN.1| class instance. + If `value` is not given, schema object will be created. + + tagSet: :py:class:`~pyasn1.type.tag.TagSet` + Object representing non-default ASN.1 tag(s) + + subtypeSpec: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` + Object representing non-default ASN.1 subtype constraint(s). Constraints + verification for |ASN.1| type occurs automatically on object + instantiation. + + encoding: :py:class:`str` + Unicode codec ID to encode/decode :class:`unicode` (Python 2) or + :class:`str` (Python 3) the payload when |ASN.1| object is used + in octet-stream context. + + Raises + ------ + ~pyasn1.error.ValueConstraintError, ~pyasn1.error.PyAsn1Error + On constraint violation or bad initializer. + """ + + if sys.version_info[0] <= 2: + def __str__(self): + try: + # `str` is Py2 text representation + return self._value.encode(self.encoding) + + except UnicodeEncodeError: + exc = sys.exc_info()[1] + raise error.PyAsn1UnicodeEncodeError( + "Can't encode string '%s' with codec " + "%s" % (self._value, self.encoding), exc + ) + + def __unicode__(self): + return unicode(self._value) + + def prettyIn(self, value): + try: + if isinstance(value, unicode): + return value + elif isinstance(value, str): + return value.decode(self.encoding) + elif isinstance(value, (tuple, list)): + return self.prettyIn(''.join([chr(x) for x in value])) + elif isinstance(value, univ.OctetString): + return value.asOctets().decode(self.encoding) + else: + return unicode(value) + + except (UnicodeDecodeError, LookupError): + exc = sys.exc_info()[1] + raise error.PyAsn1UnicodeDecodeError( + "Can't decode string '%s' with codec " + "%s" % (value, self.encoding), exc + ) + + def asOctets(self, padding=True): + return str(self) + + def asNumbers(self, padding=True): + return tuple([ord(x) for x in str(self)]) + + else: + def __str__(self): + # `unicode` is Py3 text representation + return str(self._value) + + def __bytes__(self): + try: + return self._value.encode(self.encoding) + except UnicodeEncodeError: + exc = sys.exc_info()[1] + raise error.PyAsn1UnicodeEncodeError( + "Can't encode string '%s' with codec " + "%s" % (self._value, self.encoding), exc + ) + + def prettyIn(self, value): + try: + if isinstance(value, str): + return value + elif isinstance(value, bytes): + return value.decode(self.encoding) + elif isinstance(value, (tuple, list)): + return self.prettyIn(bytes(value)) + elif isinstance(value, univ.OctetString): + return value.asOctets().decode(self.encoding) + else: + return str(value) + + except (UnicodeDecodeError, LookupError): + exc = sys.exc_info()[1] + raise error.PyAsn1UnicodeDecodeError( + "Can't decode string '%s' with codec " + "%s" % (value, self.encoding), exc + ) + + def asOctets(self, padding=True): + return bytes(self) + + def asNumbers(self, padding=True): + return tuple(bytes(self)) + + # + # See OctetString.prettyPrint() for the explanation + # + + def prettyOut(self, value): + return value + + def prettyPrint(self, scope=0): + # first see if subclass has its own .prettyOut() + value = self.prettyOut(self._value) + + if value is not self._value: + return value + + return AbstractCharacterString.__str__(self) + + def __reversed__(self): + return reversed(self._value) + + +class NumericString(AbstractCharacterString): + __doc__ = AbstractCharacterString.__doc__ + + #: Set (on class, not on instance) or return a + #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s) + #: associated with |ASN.1| type. + tagSet = AbstractCharacterString.tagSet.tagImplicitly( + tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 18) + ) + encoding = 'us-ascii' + + # Optimization for faster codec lookup + typeId = AbstractCharacterString.getTypeId() + + +class PrintableString(AbstractCharacterString): + __doc__ = AbstractCharacterString.__doc__ + + #: Set (on class, not on instance) or return a + #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s) + #: associated with |ASN.1| type. + tagSet = AbstractCharacterString.tagSet.tagImplicitly( + tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 19) + ) + encoding = 'us-ascii' + + # Optimization for faster codec lookup + typeId = AbstractCharacterString.getTypeId() + + +class TeletexString(AbstractCharacterString): + __doc__ = AbstractCharacterString.__doc__ + + #: Set (on class, not on instance) or return a + #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s) + #: associated with |ASN.1| type. + tagSet = AbstractCharacterString.tagSet.tagImplicitly( + tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 20) + ) + encoding = 'iso-8859-1' + + # Optimization for faster codec lookup + typeId = AbstractCharacterString.getTypeId() + + +class T61String(TeletexString): + __doc__ = TeletexString.__doc__ + + # Optimization for faster codec lookup + typeId = AbstractCharacterString.getTypeId() + + +class VideotexString(AbstractCharacterString): + __doc__ = AbstractCharacterString.__doc__ + + #: Set (on class, not on instance) or return a + #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s) + #: associated with |ASN.1| type. + tagSet = AbstractCharacterString.tagSet.tagImplicitly( + tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 21) + ) + encoding = 'iso-8859-1' + + # Optimization for faster codec lookup + typeId = AbstractCharacterString.getTypeId() + + +class IA5String(AbstractCharacterString): + __doc__ = AbstractCharacterString.__doc__ + + #: Set (on class, not on instance) or return a + #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s) + #: associated with |ASN.1| type. + tagSet = AbstractCharacterString.tagSet.tagImplicitly( + tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 22) + ) + encoding = 'us-ascii' + + # Optimization for faster codec lookup + typeId = AbstractCharacterString.getTypeId() + + +class GraphicString(AbstractCharacterString): + __doc__ = AbstractCharacterString.__doc__ + + #: Set (on class, not on instance) or return a + #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s) + #: associated with |ASN.1| type. + tagSet = AbstractCharacterString.tagSet.tagImplicitly( + tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 25) + ) + encoding = 'iso-8859-1' + + # Optimization for faster codec lookup + typeId = AbstractCharacterString.getTypeId() + + +class VisibleString(AbstractCharacterString): + __doc__ = AbstractCharacterString.__doc__ + + #: Set (on class, not on instance) or return a + #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s) + #: associated with |ASN.1| type. + tagSet = AbstractCharacterString.tagSet.tagImplicitly( + tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 26) + ) + encoding = 'us-ascii' + + # Optimization for faster codec lookup + typeId = AbstractCharacterString.getTypeId() + + +class ISO646String(VisibleString): + __doc__ = VisibleString.__doc__ + + # Optimization for faster codec lookup + typeId = AbstractCharacterString.getTypeId() + +class GeneralString(AbstractCharacterString): + __doc__ = AbstractCharacterString.__doc__ + + #: Set (on class, not on instance) or return a + #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s) + #: associated with |ASN.1| type. + tagSet = AbstractCharacterString.tagSet.tagImplicitly( + tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 27) + ) + encoding = 'iso-8859-1' + + # Optimization for faster codec lookup + typeId = AbstractCharacterString.getTypeId() + + +class UniversalString(AbstractCharacterString): + __doc__ = AbstractCharacterString.__doc__ + + #: Set (on class, not on instance) or return a + #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s) + #: associated with |ASN.1| type. + tagSet = AbstractCharacterString.tagSet.tagImplicitly( + tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 28) + ) + encoding = "utf-32-be" + + # Optimization for faster codec lookup + typeId = AbstractCharacterString.getTypeId() + + +class BMPString(AbstractCharacterString): + __doc__ = AbstractCharacterString.__doc__ + + #: Set (on class, not on instance) or return a + #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s) + #: associated with |ASN.1| type. + tagSet = AbstractCharacterString.tagSet.tagImplicitly( + tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 30) + ) + encoding = "utf-16-be" + + # Optimization for faster codec lookup + typeId = AbstractCharacterString.getTypeId() + + +class UTF8String(AbstractCharacterString): + __doc__ = AbstractCharacterString.__doc__ + + #: Set (on class, not on instance) or return a + #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s) + #: associated with |ASN.1| type. + tagSet = AbstractCharacterString.tagSet.tagImplicitly( + tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 12) + ) + encoding = "utf-8" + + # Optimization for faster codec lookup + typeId = AbstractCharacterString.getTypeId() diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/type/constraint.py b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/type/constraint.py new file mode 100644 index 00000000..8f152e9e --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/type/constraint.py @@ -0,0 +1,756 @@ +# +# This file is part of pyasn1 software. +# +# Copyright (c) 2005-2019, Ilya Etingof <etingof@gmail.com> +# License: http://snmplabs.com/pyasn1/license.html +# +# Original concept and code by Mike C. Fletcher. +# +import sys + +from pyasn1.type import error + +__all__ = ['SingleValueConstraint', 'ContainedSubtypeConstraint', + 'ValueRangeConstraint', 'ValueSizeConstraint', + 'PermittedAlphabetConstraint', 'InnerTypeConstraint', + 'ConstraintsExclusion', 'ConstraintsIntersection', + 'ConstraintsUnion'] + + +class AbstractConstraint(object): + + def __init__(self, *values): + self._valueMap = set() + self._setValues(values) + self.__hash = hash((self.__class__.__name__, self._values)) + + def __call__(self, value, idx=None): + if not self._values: + return + + try: + self._testValue(value, idx) + + except error.ValueConstraintError: + raise error.ValueConstraintError( + '%s failed at: %r' % (self, sys.exc_info()[1]) + ) + + def __repr__(self): + representation = '%s object' % (self.__class__.__name__) + + if self._values: + representation += ', consts %s' % ', '.join( + [repr(x) for x in self._values]) + + return '<%s>' % representation + + def __eq__(self, other): + return self is other and True or self._values == other + + def __ne__(self, other): + return self._values != other + + def __lt__(self, other): + return self._values < other + + def __le__(self, other): + return self._values <= other + + def __gt__(self, other): + return self._values > other + + def __ge__(self, other): + return self._values >= other + + if sys.version_info[0] <= 2: + def __nonzero__(self): + return self._values and True or False + else: + def __bool__(self): + return self._values and True or False + + def __hash__(self): + return self.__hash + + def _setValues(self, values): + self._values = values + + def _testValue(self, value, idx): + raise error.ValueConstraintError(value) + + # Constraints derivation logic + def getValueMap(self): + return self._valueMap + + def isSuperTypeOf(self, otherConstraint): + # TODO: fix possible comparison of set vs scalars here + return (otherConstraint is self or + not self._values or + otherConstraint == self or + self in otherConstraint.getValueMap()) + + def isSubTypeOf(self, otherConstraint): + return (otherConstraint is self or + not self or + otherConstraint == self or + otherConstraint in self._valueMap) + + +class SingleValueConstraint(AbstractConstraint): + """Create a SingleValueConstraint object. + + The SingleValueConstraint satisfies any value that + is present in the set of permitted values. + + Objects of this type are iterable (emitting constraint values) and + can act as operands for some arithmetic operations e.g. addition + and subtraction. The latter can be used for combining multiple + SingleValueConstraint objects into one. + + The SingleValueConstraint object can be applied to + any ASN.1 type. + + Parameters + ---------- + *values: :class:`int` + Full set of values permitted by this constraint object. + + Examples + -------- + .. code-block:: python + + class DivisorOfSix(Integer): + ''' + ASN.1 specification: + + Divisor-Of-6 ::= INTEGER (1 | 2 | 3 | 6) + ''' + subtypeSpec = SingleValueConstraint(1, 2, 3, 6) + + # this will succeed + divisor_of_six = DivisorOfSix(1) + + # this will raise ValueConstraintError + divisor_of_six = DivisorOfSix(7) + """ + def _setValues(self, values): + self._values = values + self._set = set(values) + + def _testValue(self, value, idx): + if value not in self._set: + raise error.ValueConstraintError(value) + + # Constrains can be merged or reduced + + def __contains__(self, item): + return item in self._set + + def __iter__(self): + return iter(self._set) + + def __sub__(self, constraint): + return self.__class__(*(self._set.difference(constraint))) + + def __add__(self, constraint): + return self.__class__(*(self._set.union(constraint))) + + def __sub__(self, constraint): + return self.__class__(*(self._set.difference(constraint))) + + +class ContainedSubtypeConstraint(AbstractConstraint): + """Create a ContainedSubtypeConstraint object. + + The ContainedSubtypeConstraint satisfies any value that + is present in the set of permitted values and also + satisfies included constraints. + + The ContainedSubtypeConstraint object can be applied to + any ASN.1 type. + + Parameters + ---------- + *values: + Full set of values and constraint objects permitted + by this constraint object. + + Examples + -------- + .. code-block:: python + + class DivisorOfEighteen(Integer): + ''' + ASN.1 specification: + + Divisors-of-18 ::= INTEGER (INCLUDES Divisors-of-6 | 9 | 18) + ''' + subtypeSpec = ContainedSubtypeConstraint( + SingleValueConstraint(1, 2, 3, 6), 9, 18 + ) + + # this will succeed + divisor_of_eighteen = DivisorOfEighteen(9) + + # this will raise ValueConstraintError + divisor_of_eighteen = DivisorOfEighteen(10) + """ + def _testValue(self, value, idx): + for constraint in self._values: + if isinstance(constraint, AbstractConstraint): + constraint(value, idx) + elif value not in self._set: + raise error.ValueConstraintError(value) + + +class ValueRangeConstraint(AbstractConstraint): + """Create a ValueRangeConstraint object. + + The ValueRangeConstraint satisfies any value that + falls in the range of permitted values. + + The ValueRangeConstraint object can only be applied + to :class:`~pyasn1.type.univ.Integer` and + :class:`~pyasn1.type.univ.Real` types. + + Parameters + ---------- + start: :class:`int` + Minimum permitted value in the range (inclusive) + + end: :class:`int` + Maximum permitted value in the range (inclusive) + + Examples + -------- + .. code-block:: python + + class TeenAgeYears(Integer): + ''' + ASN.1 specification: + + TeenAgeYears ::= INTEGER (13 .. 19) + ''' + subtypeSpec = ValueRangeConstraint(13, 19) + + # this will succeed + teen_year = TeenAgeYears(18) + + # this will raise ValueConstraintError + teen_year = TeenAgeYears(20) + """ + def _testValue(self, value, idx): + if value < self.start or value > self.stop: + raise error.ValueConstraintError(value) + + def _setValues(self, values): + if len(values) != 2: + raise error.PyAsn1Error( + '%s: bad constraint values' % (self.__class__.__name__,) + ) + self.start, self.stop = values + if self.start > self.stop: + raise error.PyAsn1Error( + '%s: screwed constraint values (start > stop): %s > %s' % ( + self.__class__.__name__, + self.start, self.stop + ) + ) + AbstractConstraint._setValues(self, values) + + +class ValueSizeConstraint(ValueRangeConstraint): + """Create a ValueSizeConstraint object. + + The ValueSizeConstraint satisfies any value for + as long as its size falls within the range of + permitted sizes. + + The ValueSizeConstraint object can be applied + to :class:`~pyasn1.type.univ.BitString`, + :class:`~pyasn1.type.univ.OctetString` (including + all :ref:`character ASN.1 types <type.char>`), + :class:`~pyasn1.type.univ.SequenceOf` + and :class:`~pyasn1.type.univ.SetOf` types. + + Parameters + ---------- + minimum: :class:`int` + Minimum permitted size of the value (inclusive) + + maximum: :class:`int` + Maximum permitted size of the value (inclusive) + + Examples + -------- + .. code-block:: python + + class BaseballTeamRoster(SetOf): + ''' + ASN.1 specification: + + BaseballTeamRoster ::= SET SIZE (1..25) OF PlayerNames + ''' + componentType = PlayerNames() + subtypeSpec = ValueSizeConstraint(1, 25) + + # this will succeed + team = BaseballTeamRoster() + team.extend(['Jan', 'Matej']) + encode(team) + + # this will raise ValueConstraintError + team = BaseballTeamRoster() + team.extend(['Jan'] * 26) + encode(team) + + Note + ---- + Whenever ValueSizeConstraint is applied to mutable types + (e.g. :class:`~pyasn1.type.univ.SequenceOf`, + :class:`~pyasn1.type.univ.SetOf`), constraint + validation only happens at the serialisation phase rather + than schema instantiation phase (as it is with immutable + types). + """ + def _testValue(self, value, idx): + valueSize = len(value) + if valueSize < self.start or valueSize > self.stop: + raise error.ValueConstraintError(value) + + +class PermittedAlphabetConstraint(SingleValueConstraint): + """Create a PermittedAlphabetConstraint object. + + The PermittedAlphabetConstraint satisfies any character + string for as long as all its characters are present in + the set of permitted characters. + + Objects of this type are iterable (emitting constraint values) and + can act as operands for some arithmetic operations e.g. addition + and subtraction. + + The PermittedAlphabetConstraint object can only be applied + to the :ref:`character ASN.1 types <type.char>` such as + :class:`~pyasn1.type.char.IA5String`. + + Parameters + ---------- + *alphabet: :class:`str` + Full set of characters permitted by this constraint object. + + Example + ------- + .. code-block:: python + + class BooleanValue(IA5String): + ''' + ASN.1 specification: + + BooleanValue ::= IA5String (FROM ('T' | 'F')) + ''' + subtypeSpec = PermittedAlphabetConstraint('T', 'F') + + # this will succeed + truth = BooleanValue('T') + truth = BooleanValue('TF') + + # this will raise ValueConstraintError + garbage = BooleanValue('TAF') + + ASN.1 `FROM ... EXCEPT ...` clause can be modelled by combining multiple + PermittedAlphabetConstraint objects into one: + + Example + ------- + .. code-block:: python + + class Lipogramme(IA5String): + ''' + ASN.1 specification: + + Lipogramme ::= + IA5String (FROM (ALL EXCEPT ("e"|"E"))) + ''' + subtypeSpec = ( + PermittedAlphabetConstraint(*string.printable) - + PermittedAlphabetConstraint('e', 'E') + ) + + # this will succeed + lipogramme = Lipogramme('A work of fiction?') + + # this will raise ValueConstraintError + lipogramme = Lipogramme('Eel') + + Note + ---- + Although `ConstraintsExclusion` object could seemingly be used for this + purpose, practically, for it to work, it needs to represent its operand + constraints as sets and intersect one with the other. That would require + the insight into the constraint values (and their types) that are otherwise + hidden inside the constraint object. + + Therefore it's more practical to model `EXCEPT` clause at + `PermittedAlphabetConstraint` level instead. + """ + def _setValues(self, values): + self._values = values + self._set = set(values) + + def _testValue(self, value, idx): + if not self._set.issuperset(value): + raise error.ValueConstraintError(value) + + +class ComponentPresentConstraint(AbstractConstraint): + """Create a ComponentPresentConstraint object. + + The ComponentPresentConstraint is only satisfied when the value + is not `None`. + + The ComponentPresentConstraint object is typically used with + `WithComponentsConstraint`. + + Examples + -------- + .. code-block:: python + + present = ComponentPresentConstraint() + + # this will succeed + present('whatever') + + # this will raise ValueConstraintError + present(None) + """ + def _setValues(self, values): + self._values = ('<must be present>',) + + if values: + raise error.PyAsn1Error('No arguments expected') + + def _testValue(self, value, idx): + if value is None: + raise error.ValueConstraintError( + 'Component is not present:') + + +class ComponentAbsentConstraint(AbstractConstraint): + """Create a ComponentAbsentConstraint object. + + The ComponentAbsentConstraint is only satisfied when the value + is `None`. + + The ComponentAbsentConstraint object is typically used with + `WithComponentsConstraint`. + + Examples + -------- + .. code-block:: python + + absent = ComponentAbsentConstraint() + + # this will succeed + absent(None) + + # this will raise ValueConstraintError + absent('whatever') + """ + def _setValues(self, values): + self._values = ('<must be absent>',) + + if values: + raise error.PyAsn1Error('No arguments expected') + + def _testValue(self, value, idx): + if value is not None: + raise error.ValueConstraintError( + 'Component is not absent: %r' % value) + + +class WithComponentsConstraint(AbstractConstraint): + """Create a WithComponentsConstraint object. + + The `WithComponentsConstraint` satisfies any mapping object that has + constrained fields present or absent, what is indicated by + `ComponentPresentConstraint` and `ComponentAbsentConstraint` + objects respectively. + + The `WithComponentsConstraint` object is typically applied + to :class:`~pyasn1.type.univ.Set` or + :class:`~pyasn1.type.univ.Sequence` types. + + Parameters + ---------- + *fields: :class:`tuple` + Zero or more tuples of (`field`, `constraint`) indicating constrained + fields. + + Notes + ----- + On top of the primary use of `WithComponentsConstraint` (ensuring presence + or absence of particular components of a :class:`~pyasn1.type.univ.Set` or + :class:`~pyasn1.type.univ.Sequence`), it is also possible to pass any other + constraint objects or their combinations. In case of scalar fields, these + constraints will be verified in addition to the constraints belonging to + scalar components themselves. However, formally, these additional + constraints do not change the type of these ASN.1 objects. + + Examples + -------- + + .. code-block:: python + + class Item(Sequence): # Set is similar + ''' + ASN.1 specification: + + Item ::= SEQUENCE { + id INTEGER OPTIONAL, + name OCTET STRING OPTIONAL + } WITH COMPONENTS id PRESENT, name ABSENT | id ABSENT, name PRESENT + ''' + componentType = NamedTypes( + OptionalNamedType('id', Integer()), + OptionalNamedType('name', OctetString()) + ) + withComponents = ConstraintsUnion( + WithComponentsConstraint( + ('id', ComponentPresentConstraint()), + ('name', ComponentAbsentConstraint()) + ), + WithComponentsConstraint( + ('id', ComponentAbsentConstraint()), + ('name', ComponentPresentConstraint()) + ) + ) + + item = Item() + + # This will succeed + item['id'] = 1 + + # This will succeed + item.reset() + item['name'] = 'John' + + # This will fail (on encoding) + item.reset() + descr['id'] = 1 + descr['name'] = 'John' + """ + def _testValue(self, value, idx): + for field, constraint in self._values: + constraint(value.get(field)) + + def _setValues(self, values): + AbstractConstraint._setValues(self, values) + + +# This is a bit kludgy, meaning two op modes within a single constraint +class InnerTypeConstraint(AbstractConstraint): + """Value must satisfy the type and presence constraints""" + + def _testValue(self, value, idx): + if self.__singleTypeConstraint: + self.__singleTypeConstraint(value) + elif self.__multipleTypeConstraint: + if idx not in self.__multipleTypeConstraint: + raise error.ValueConstraintError(value) + constraint, status = self.__multipleTypeConstraint[idx] + if status == 'ABSENT': # XXX presence is not checked! + raise error.ValueConstraintError(value) + constraint(value) + + def _setValues(self, values): + self.__multipleTypeConstraint = {} + self.__singleTypeConstraint = None + for v in values: + if isinstance(v, tuple): + self.__multipleTypeConstraint[v[0]] = v[1], v[2] + else: + self.__singleTypeConstraint = v + AbstractConstraint._setValues(self, values) + + +# Logic operations on constraints + +class ConstraintsExclusion(AbstractConstraint): + """Create a ConstraintsExclusion logic operator object. + + The ConstraintsExclusion logic operator succeeds when the + value does *not* satisfy the operand constraint. + + The ConstraintsExclusion object can be applied to + any constraint and logic operator object. + + Parameters + ---------- + *constraints: + Constraint or logic operator objects. + + Examples + -------- + .. code-block:: python + + class LuckyNumber(Integer): + subtypeSpec = ConstraintsExclusion( + SingleValueConstraint(13) + ) + + # this will succeed + luckyNumber = LuckyNumber(12) + + # this will raise ValueConstraintError + luckyNumber = LuckyNumber(13) + + Note + ---- + The `FROM ... EXCEPT ...` ASN.1 clause should be modeled by combining + constraint objects into one. See `PermittedAlphabetConstraint` for more + information. + """ + def _testValue(self, value, idx): + for constraint in self._values: + try: + constraint(value, idx) + + except error.ValueConstraintError: + continue + + raise error.ValueConstraintError(value) + + def _setValues(self, values): + AbstractConstraint._setValues(self, values) + + +class AbstractConstraintSet(AbstractConstraint): + + def __getitem__(self, idx): + return self._values[idx] + + def __iter__(self): + return iter(self._values) + + def __add__(self, value): + return self.__class__(*(self._values + (value,))) + + def __radd__(self, value): + return self.__class__(*((value,) + self._values)) + + def __len__(self): + return len(self._values) + + # Constraints inclusion in sets + + def _setValues(self, values): + self._values = values + for constraint in values: + if constraint: + self._valueMap.add(constraint) + self._valueMap.update(constraint.getValueMap()) + + +class ConstraintsIntersection(AbstractConstraintSet): + """Create a ConstraintsIntersection logic operator object. + + The ConstraintsIntersection logic operator only succeeds + if *all* its operands succeed. + + The ConstraintsIntersection object can be applied to + any constraint and logic operator objects. + + The ConstraintsIntersection object duck-types the immutable + container object like Python :py:class:`tuple`. + + Parameters + ---------- + *constraints: + Constraint or logic operator objects. + + Examples + -------- + .. code-block:: python + + class CapitalAndSmall(IA5String): + ''' + ASN.1 specification: + + CapitalAndSmall ::= + IA5String (FROM ("A".."Z"|"a".."z")) + ''' + subtypeSpec = ConstraintsIntersection( + PermittedAlphabetConstraint('A', 'Z'), + PermittedAlphabetConstraint('a', 'z') + ) + + # this will succeed + capital_and_small = CapitalAndSmall('Hello') + + # this will raise ValueConstraintError + capital_and_small = CapitalAndSmall('hello') + """ + def _testValue(self, value, idx): + for constraint in self._values: + constraint(value, idx) + + +class ConstraintsUnion(AbstractConstraintSet): + """Create a ConstraintsUnion logic operator object. + + The ConstraintsUnion logic operator succeeds if + *at least* a single operand succeeds. + + The ConstraintsUnion object can be applied to + any constraint and logic operator objects. + + The ConstraintsUnion object duck-types the immutable + container object like Python :py:class:`tuple`. + + Parameters + ---------- + *constraints: + Constraint or logic operator objects. + + Examples + -------- + .. code-block:: python + + class CapitalOrSmall(IA5String): + ''' + ASN.1 specification: + + CapitalOrSmall ::= + IA5String (FROM ("A".."Z") | FROM ("a".."z")) + ''' + subtypeSpec = ConstraintsUnion( + PermittedAlphabetConstraint('A', 'Z'), + PermittedAlphabetConstraint('a', 'z') + ) + + # this will succeed + capital_or_small = CapitalAndSmall('Hello') + + # this will raise ValueConstraintError + capital_or_small = CapitalOrSmall('hello!') + """ + def _testValue(self, value, idx): + for constraint in self._values: + try: + constraint(value, idx) + except error.ValueConstraintError: + pass + else: + return + + raise error.ValueConstraintError( + 'all of %s failed for "%s"' % (self._values, value) + ) + +# TODO: +# refactor InnerTypeConstraint +# add tests for type check +# implement other constraint types +# make constraint validation easy to skip diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/type/error.py b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/type/error.py new file mode 100644 index 00000000..80fcf3bd --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/type/error.py @@ -0,0 +1,11 @@ +# +# This file is part of pyasn1 software. +# +# Copyright (c) 2005-2019, Ilya Etingof <etingof@gmail.com> +# License: http://snmplabs.com/pyasn1/license.html +# +from pyasn1.error import PyAsn1Error + + +class ValueConstraintError(PyAsn1Error): + pass diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/type/namedtype.py b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/type/namedtype.py new file mode 100644 index 00000000..cbc14293 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/type/namedtype.py @@ -0,0 +1,561 @@ +# +# This file is part of pyasn1 software. +# +# Copyright (c) 2005-2019, Ilya Etingof <etingof@gmail.com> +# License: http://snmplabs.com/pyasn1/license.html +# +import sys + +from pyasn1 import error +from pyasn1.type import tag +from pyasn1.type import tagmap + +__all__ = ['NamedType', 'OptionalNamedType', 'DefaultedNamedType', + 'NamedTypes'] + +try: + any + +except NameError: + any = lambda x: bool(filter(bool, x)) + + +class NamedType(object): + """Create named field object for a constructed ASN.1 type. + + The |NamedType| object represents a single name and ASN.1 type of a constructed ASN.1 type. + + |NamedType| objects are immutable and duck-type Python :class:`tuple` objects + holding *name* and *asn1Object* components. + + Parameters + ---------- + name: :py:class:`str` + Field name + + asn1Object: + ASN.1 type object + """ + isOptional = False + isDefaulted = False + + def __init__(self, name, asn1Object, openType=None): + self.__name = name + self.__type = asn1Object + self.__nameAndType = name, asn1Object + self.__openType = openType + + def __repr__(self): + representation = '%s=%r' % (self.name, self.asn1Object) + + if self.openType: + representation += ', open type %r' % self.openType + + return '<%s object, type %s>' % ( + self.__class__.__name__, representation) + + def __eq__(self, other): + return self.__nameAndType == other + + def __ne__(self, other): + return self.__nameAndType != other + + def __lt__(self, other): + return self.__nameAndType < other + + def __le__(self, other): + return self.__nameAndType <= other + + def __gt__(self, other): + return self.__nameAndType > other + + def __ge__(self, other): + return self.__nameAndType >= other + + def __hash__(self): + return hash(self.__nameAndType) + + def __getitem__(self, idx): + return self.__nameAndType[idx] + + def __iter__(self): + return iter(self.__nameAndType) + + @property + def name(self): + return self.__name + + @property + def asn1Object(self): + return self.__type + + @property + def openType(self): + return self.__openType + + # Backward compatibility + + def getName(self): + return self.name + + def getType(self): + return self.asn1Object + + +class OptionalNamedType(NamedType): + __doc__ = NamedType.__doc__ + + isOptional = True + + +class DefaultedNamedType(NamedType): + __doc__ = NamedType.__doc__ + + isDefaulted = True + + +class NamedTypes(object): + """Create a collection of named fields for a constructed ASN.1 type. + + The NamedTypes object represents a collection of named fields of a constructed ASN.1 type. + + *NamedTypes* objects are immutable and duck-type Python :class:`dict` objects + holding *name* as keys and ASN.1 type object as values. + + Parameters + ---------- + *namedTypes: :class:`~pyasn1.type.namedtype.NamedType` + + Examples + -------- + + .. code-block:: python + + class Description(Sequence): + ''' + ASN.1 specification: + + Description ::= SEQUENCE { + surname IA5String, + first-name IA5String OPTIONAL, + age INTEGER DEFAULT 40 + } + ''' + componentType = NamedTypes( + NamedType('surname', IA5String()), + OptionalNamedType('first-name', IA5String()), + DefaultedNamedType('age', Integer(40)) + ) + + descr = Description() + descr['surname'] = 'Smith' + descr['first-name'] = 'John' + """ + def __init__(self, *namedTypes, **kwargs): + self.__namedTypes = namedTypes + self.__namedTypesLen = len(self.__namedTypes) + self.__minTagSet = self.__computeMinTagSet() + self.__nameToPosMap = self.__computeNameToPosMap() + self.__tagToPosMap = self.__computeTagToPosMap() + self.__ambiguousTypes = 'terminal' not in kwargs and self.__computeAmbiguousTypes() or {} + self.__uniqueTagMap = self.__computeTagMaps(unique=True) + self.__nonUniqueTagMap = self.__computeTagMaps(unique=False) + self.__hasOptionalOrDefault = any([True for namedType in self.__namedTypes + if namedType.isDefaulted or namedType.isOptional]) + self.__hasOpenTypes = any([True for namedType in self.__namedTypes + if namedType.openType]) + + self.__requiredComponents = frozenset( + [idx for idx, nt in enumerate(self.__namedTypes) if not nt.isOptional and not nt.isDefaulted] + ) + self.__keys = frozenset([namedType.name for namedType in self.__namedTypes]) + self.__values = tuple([namedType.asn1Object for namedType in self.__namedTypes]) + self.__items = tuple([(namedType.name, namedType.asn1Object) for namedType in self.__namedTypes]) + + def __repr__(self): + representation = ', '.join(['%r' % x for x in self.__namedTypes]) + return '<%s object, types %s>' % ( + self.__class__.__name__, representation) + + def __eq__(self, other): + return self.__namedTypes == other + + def __ne__(self, other): + return self.__namedTypes != other + + def __lt__(self, other): + return self.__namedTypes < other + + def __le__(self, other): + return self.__namedTypes <= other + + def __gt__(self, other): + return self.__namedTypes > other + + def __ge__(self, other): + return self.__namedTypes >= other + + def __hash__(self): + return hash(self.__namedTypes) + + def __getitem__(self, idx): + try: + return self.__namedTypes[idx] + + except TypeError: + return self.__namedTypes[self.__nameToPosMap[idx]] + + def __contains__(self, key): + return key in self.__nameToPosMap + + def __iter__(self): + return (x[0] for x in self.__namedTypes) + + if sys.version_info[0] <= 2: + def __nonzero__(self): + return self.__namedTypesLen > 0 + else: + def __bool__(self): + return self.__namedTypesLen > 0 + + def __len__(self): + return self.__namedTypesLen + + # Python dict protocol + + def values(self): + return self.__values + + def keys(self): + return self.__keys + + def items(self): + return self.__items + + def clone(self): + return self.__class__(*self.__namedTypes) + + class PostponedError(object): + def __init__(self, errorMsg): + self.__errorMsg = errorMsg + + def __getitem__(self, item): + raise error.PyAsn1Error(self.__errorMsg) + + def __computeTagToPosMap(self): + tagToPosMap = {} + for idx, namedType in enumerate(self.__namedTypes): + tagMap = namedType.asn1Object.tagMap + if isinstance(tagMap, NamedTypes.PostponedError): + return tagMap + if not tagMap: + continue + for _tagSet in tagMap.presentTypes: + if _tagSet in tagToPosMap: + return NamedTypes.PostponedError('Duplicate component tag %s at %s' % (_tagSet, namedType)) + tagToPosMap[_tagSet] = idx + + return tagToPosMap + + def __computeNameToPosMap(self): + nameToPosMap = {} + for idx, namedType in enumerate(self.__namedTypes): + if namedType.name in nameToPosMap: + return NamedTypes.PostponedError('Duplicate component name %s at %s' % (namedType.name, namedType)) + nameToPosMap[namedType.name] = idx + + return nameToPosMap + + def __computeAmbiguousTypes(self): + ambiguousTypes = {} + partialAmbiguousTypes = () + for idx, namedType in reversed(tuple(enumerate(self.__namedTypes))): + if namedType.isOptional or namedType.isDefaulted: + partialAmbiguousTypes = (namedType,) + partialAmbiguousTypes + else: + partialAmbiguousTypes = (namedType,) + if len(partialAmbiguousTypes) == len(self.__namedTypes): + ambiguousTypes[idx] = self + else: + ambiguousTypes[idx] = NamedTypes(*partialAmbiguousTypes, **dict(terminal=True)) + return ambiguousTypes + + def getTypeByPosition(self, idx): + """Return ASN.1 type object by its position in fields set. + + Parameters + ---------- + idx: :py:class:`int` + Field index + + Returns + ------- + : + ASN.1 type + + Raises + ------ + ~pyasn1.error.PyAsn1Error + If given position is out of fields range + """ + try: + return self.__namedTypes[idx].asn1Object + + except IndexError: + raise error.PyAsn1Error('Type position out of range') + + def getPositionByType(self, tagSet): + """Return field position by its ASN.1 type. + + Parameters + ---------- + tagSet: :class:`~pysnmp.type.tag.TagSet` + ASN.1 tag set distinguishing one ASN.1 type from others. + + Returns + ------- + : :py:class:`int` + ASN.1 type position in fields set + + Raises + ------ + ~pyasn1.error.PyAsn1Error + If *tagSet* is not present or ASN.1 types are not unique within callee *NamedTypes* + """ + try: + return self.__tagToPosMap[tagSet] + + except KeyError: + raise error.PyAsn1Error('Type %s not found' % (tagSet,)) + + def getNameByPosition(self, idx): + """Return field name by its position in fields set. + + Parameters + ---------- + idx: :py:class:`idx` + Field index + + Returns + ------- + : :py:class:`str` + Field name + + Raises + ------ + ~pyasn1.error.PyAsn1Error + If given field name is not present in callee *NamedTypes* + """ + try: + return self.__namedTypes[idx].name + + except IndexError: + raise error.PyAsn1Error('Type position out of range') + + def getPositionByName(self, name): + """Return field position by filed name. + + Parameters + ---------- + name: :py:class:`str` + Field name + + Returns + ------- + : :py:class:`int` + Field position in fields set + + Raises + ------ + ~pyasn1.error.PyAsn1Error + If *name* is not present or not unique within callee *NamedTypes* + """ + try: + return self.__nameToPosMap[name] + + except KeyError: + raise error.PyAsn1Error('Name %s not found' % (name,)) + + def getTagMapNearPosition(self, idx): + """Return ASN.1 types that are allowed at or past given field position. + + Some ASN.1 serialisation allow for skipping optional and defaulted fields. + Some constructed ASN.1 types allow reordering of the fields. When recovering + such objects it may be important to know which types can possibly be + present at any given position in the field sets. + + Parameters + ---------- + idx: :py:class:`int` + Field index + + Returns + ------- + : :class:`~pyasn1.type.tagmap.TagMap` + Map if ASN.1 types allowed at given field position + + Raises + ------ + ~pyasn1.error.PyAsn1Error + If given position is out of fields range + """ + try: + return self.__ambiguousTypes[idx].tagMap + + except KeyError: + raise error.PyAsn1Error('Type position out of range') + + def getPositionNearType(self, tagSet, idx): + """Return the closest field position where given ASN.1 type is allowed. + + Some ASN.1 serialisation allow for skipping optional and defaulted fields. + Some constructed ASN.1 types allow reordering of the fields. When recovering + such objects it may be important to know at which field position, in field set, + given *tagSet* is allowed at or past *idx* position. + + Parameters + ---------- + tagSet: :class:`~pyasn1.type.tag.TagSet` + ASN.1 type which field position to look up + + idx: :py:class:`int` + Field position at or past which to perform ASN.1 type look up + + Returns + ------- + : :py:class:`int` + Field position in fields set + + Raises + ------ + ~pyasn1.error.PyAsn1Error + If *tagSet* is not present or not unique within callee *NamedTypes* + or *idx* is out of fields range + """ + try: + return idx + self.__ambiguousTypes[idx].getPositionByType(tagSet) + + except KeyError: + raise error.PyAsn1Error('Type position out of range') + + def __computeMinTagSet(self): + minTagSet = None + for namedType in self.__namedTypes: + asn1Object = namedType.asn1Object + + try: + tagSet = asn1Object.minTagSet + + except AttributeError: + tagSet = asn1Object.tagSet + + if minTagSet is None or tagSet < minTagSet: + minTagSet = tagSet + + return minTagSet or tag.TagSet() + + @property + def minTagSet(self): + """Return the minimal TagSet among ASN.1 type in callee *NamedTypes*. + + Some ASN.1 types/serialisation protocols require ASN.1 types to be + arranged based on their numerical tag value. The *minTagSet* property + returns that. + + Returns + ------- + : :class:`~pyasn1.type.tagset.TagSet` + Minimal TagSet among ASN.1 types in callee *NamedTypes* + """ + return self.__minTagSet + + def __computeTagMaps(self, unique): + presentTypes = {} + skipTypes = {} + defaultType = None + for namedType in self.__namedTypes: + tagMap = namedType.asn1Object.tagMap + if isinstance(tagMap, NamedTypes.PostponedError): + return tagMap + for tagSet in tagMap: + if unique and tagSet in presentTypes: + return NamedTypes.PostponedError('Non-unique tagSet %s of %s at %s' % (tagSet, namedType, self)) + presentTypes[tagSet] = namedType.asn1Object + skipTypes.update(tagMap.skipTypes) + + if defaultType is None: + defaultType = tagMap.defaultType + elif tagMap.defaultType is not None: + return NamedTypes.PostponedError('Duplicate default ASN.1 type at %s' % (self,)) + + return tagmap.TagMap(presentTypes, skipTypes, defaultType) + + @property + def tagMap(self): + """Return a *TagMap* object from tags and types recursively. + + Return a :class:`~pyasn1.type.tagmap.TagMap` object by + combining tags from *TagMap* objects of children types and + associating them with their immediate child type. + + Example + ------- + .. code-block:: python + + OuterType ::= CHOICE { + innerType INTEGER + } + + Calling *.tagMap* on *OuterType* will yield a map like this: + + .. code-block:: python + + Integer.tagSet -> Choice + """ + return self.__nonUniqueTagMap + + @property + def tagMapUnique(self): + """Return a *TagMap* object from unique tags and types recursively. + + Return a :class:`~pyasn1.type.tagmap.TagMap` object by + combining tags from *TagMap* objects of children types and + associating them with their immediate child type. + + Example + ------- + .. code-block:: python + + OuterType ::= CHOICE { + innerType INTEGER + } + + Calling *.tagMapUnique* on *OuterType* will yield a map like this: + + .. code-block:: python + + Integer.tagSet -> Choice + + Note + ---- + + Duplicate *TagSet* objects found in the tree of children + types would cause error. + """ + return self.__uniqueTagMap + + @property + def hasOptionalOrDefault(self): + return self.__hasOptionalOrDefault + + @property + def hasOpenTypes(self): + return self.__hasOpenTypes + + @property + def namedTypes(self): + return tuple(self.__namedTypes) + + @property + def requiredComponents(self): + return self.__requiredComponents diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/type/namedval.py b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/type/namedval.py new file mode 100644 index 00000000..42475978 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/type/namedval.py @@ -0,0 +1,192 @@ +# +# This file is part of pyasn1 software. +# +# Copyright (c) 2005-2019, Ilya Etingof <etingof@gmail.com> +# License: http://snmplabs.com/pyasn1/license.html +# +# ASN.1 named integers +# +from pyasn1 import error + +__all__ = ['NamedValues'] + + +class NamedValues(object): + """Create named values object. + + The |NamedValues| object represents a collection of string names + associated with numeric IDs. These objects are used for giving + names to otherwise numerical values. + + |NamedValues| objects are immutable and duck-type Python + :class:`dict` object mapping ID to name and vice-versa. + + Parameters + ---------- + *args: variable number of two-element :py:class:`tuple` + + name: :py:class:`str` + Value label + + value: :py:class:`int` + Numeric value + + Keyword Args + ------------ + name: :py:class:`str` + Value label + + value: :py:class:`int` + Numeric value + + Examples + -------- + + .. code-block:: pycon + + >>> nv = NamedValues('a', 'b', ('c', 0), d=1) + >>> nv + >>> {'c': 0, 'd': 1, 'a': 2, 'b': 3} + >>> nv[0] + 'c' + >>> nv['a'] + 2 + """ + def __init__(self, *args, **kwargs): + self.__names = {} + self.__numbers = {} + + anonymousNames = [] + + for namedValue in args: + if isinstance(namedValue, (tuple, list)): + try: + name, number = namedValue + + except ValueError: + raise error.PyAsn1Error('Not a proper attribute-value pair %r' % (namedValue,)) + + else: + anonymousNames.append(namedValue) + continue + + if name in self.__names: + raise error.PyAsn1Error('Duplicate name %s' % (name,)) + + if number in self.__numbers: + raise error.PyAsn1Error('Duplicate number %s=%s' % (name, number)) + + self.__names[name] = number + self.__numbers[number] = name + + for name, number in kwargs.items(): + if name in self.__names: + raise error.PyAsn1Error('Duplicate name %s' % (name,)) + + if number in self.__numbers: + raise error.PyAsn1Error('Duplicate number %s=%s' % (name, number)) + + self.__names[name] = number + self.__numbers[number] = name + + if anonymousNames: + + number = self.__numbers and max(self.__numbers) + 1 or 0 + + for name in anonymousNames: + + if name in self.__names: + raise error.PyAsn1Error('Duplicate name %s' % (name,)) + + self.__names[name] = number + self.__numbers[number] = name + + number += 1 + + def __repr__(self): + representation = ', '.join(['%s=%d' % x for x in self.items()]) + + if len(representation) > 64: + representation = representation[:32] + '...' + representation[-32:] + + return '<%s object, enums %s>' % ( + self.__class__.__name__, representation) + + def __eq__(self, other): + return dict(self) == other + + def __ne__(self, other): + return dict(self) != other + + def __lt__(self, other): + return dict(self) < other + + def __le__(self, other): + return dict(self) <= other + + def __gt__(self, other): + return dict(self) > other + + def __ge__(self, other): + return dict(self) >= other + + def __hash__(self): + return hash(self.items()) + + # Python dict protocol (read-only) + + def __getitem__(self, key): + try: + return self.__numbers[key] + + except KeyError: + return self.__names[key] + + def __len__(self): + return len(self.__names) + + def __contains__(self, key): + return key in self.__names or key in self.__numbers + + def __iter__(self): + return iter(self.__names) + + def values(self): + return iter(self.__numbers) + + def keys(self): + return iter(self.__names) + + def items(self): + for name in self.__names: + yield name, self.__names[name] + + # support merging + + def __add__(self, namedValues): + return self.__class__(*tuple(self.items()) + tuple(namedValues.items())) + + # XXX clone/subtype? + + def clone(self, *args, **kwargs): + new = self.__class__(*args, **kwargs) + return self + new + + # legacy protocol + + def getName(self, value): + if value in self.__numbers: + return self.__numbers[value] + + def getValue(self, name): + if name in self.__names: + return self.__names[name] + + def getValues(self, *names): + try: + return [self.__names[name] for name in names] + + except KeyError: + raise error.PyAsn1Error( + 'Unknown bit identifier(s): %s' % (set(names).difference(self.__names),) + ) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/type/opentype.py b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/type/opentype.py new file mode 100644 index 00000000..29645f0f --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/type/opentype.py @@ -0,0 +1,104 @@ +# +# This file is part of pyasn1 software. +# +# Copyright (c) 2005-2019, Ilya Etingof <etingof@gmail.com> +# License: http://snmplabs.com/pyasn1/license.html +# + +__all__ = ['OpenType'] + + +class OpenType(object): + """Create ASN.1 type map indexed by a value + + The *OpenType* object models an untyped field of a constructed ASN.1 + type. In ASN.1 syntax it is usually represented by the + `ANY DEFINED BY` for scalars or `SET OF ANY DEFINED BY`, + `SEQUENCE OF ANY DEFINED BY` for container types clauses. Typically + used together with :class:`~pyasn1.type.univ.Any` object. + + OpenType objects duck-type a read-only Python :class:`dict` objects, + however the passed `typeMap` is not copied, but stored by reference. + That means the user can manipulate `typeMap` at run time having this + reflected on *OpenType* object behavior. + + The |OpenType| class models an untyped field of a constructed ASN.1 + type. In ASN.1 syntax it is usually represented by the + `ANY DEFINED BY` for scalars or `SET OF ANY DEFINED BY`, + `SEQUENCE OF ANY DEFINED BY` for container types clauses. Typically + used with :class:`~pyasn1.type.univ.Any` type. + + Parameters + ---------- + name: :py:class:`str` + Field name + + typeMap: :py:class:`dict` + A map of value->ASN.1 type. It's stored by reference and can be + mutated later to register new mappings. + + Examples + -------- + + For untyped scalars: + + .. code-block:: python + + openType = OpenType( + 'id', {1: Integer(), + 2: OctetString()} + ) + Sequence( + componentType=NamedTypes( + NamedType('id', Integer()), + NamedType('blob', Any(), openType=openType) + ) + ) + + For untyped `SET OF` or `SEQUENCE OF` vectors: + + .. code-block:: python + + openType = OpenType( + 'id', {1: Integer(), + 2: OctetString()} + ) + Sequence( + componentType=NamedTypes( + NamedType('id', Integer()), + NamedType('blob', SetOf(componentType=Any()), + openType=openType) + ) + ) + """ + + def __init__(self, name, typeMap=None): + self.__name = name + if typeMap is None: + self.__typeMap = {} + else: + self.__typeMap = typeMap + + @property + def name(self): + return self.__name + + # Python dict protocol + + def values(self): + return self.__typeMap.values() + + def keys(self): + return self.__typeMap.keys() + + def items(self): + return self.__typeMap.items() + + def __contains__(self, key): + return key in self.__typeMap + + def __getitem__(self, key): + return self.__typeMap[key] + + def __iter__(self): + return iter(self.__typeMap) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/type/tag.py b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/type/tag.py new file mode 100644 index 00000000..b88a7341 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/type/tag.py @@ -0,0 +1,335 @@ +# +# This file is part of pyasn1 software. +# +# Copyright (c) 2005-2019, Ilya Etingof <etingof@gmail.com> +# License: http://snmplabs.com/pyasn1/license.html +# +from pyasn1 import error + +__all__ = ['tagClassUniversal', 'tagClassApplication', 'tagClassContext', + 'tagClassPrivate', 'tagFormatSimple', 'tagFormatConstructed', + 'tagCategoryImplicit', 'tagCategoryExplicit', + 'tagCategoryUntagged', 'Tag', 'TagSet'] + +#: Identifier for ASN.1 class UNIVERSAL +tagClassUniversal = 0x00 + +#: Identifier for ASN.1 class APPLICATION +tagClassApplication = 0x40 + +#: Identifier for ASN.1 class context-specific +tagClassContext = 0x80 + +#: Identifier for ASN.1 class private +tagClassPrivate = 0xC0 + +#: Identifier for "simple" ASN.1 structure (e.g. scalar) +tagFormatSimple = 0x00 + +#: Identifier for "constructed" ASN.1 structure (e.g. may have inner components) +tagFormatConstructed = 0x20 + +tagCategoryImplicit = 0x01 +tagCategoryExplicit = 0x02 +tagCategoryUntagged = 0x04 + + +class Tag(object): + """Create ASN.1 tag + + Represents ASN.1 tag that can be attached to a ASN.1 type to make + types distinguishable from each other. + + *Tag* objects are immutable and duck-type Python :class:`tuple` objects + holding three integer components of a tag. + + Parameters + ---------- + tagClass: :py:class:`int` + Tag *class* value + + tagFormat: :py:class:`int` + Tag *format* value + + tagId: :py:class:`int` + Tag ID value + """ + def __init__(self, tagClass, tagFormat, tagId): + if tagId < 0: + raise error.PyAsn1Error('Negative tag ID (%s) not allowed' % tagId) + self.__tagClass = tagClass + self.__tagFormat = tagFormat + self.__tagId = tagId + self.__tagClassId = tagClass, tagId + self.__hash = hash(self.__tagClassId) + + def __repr__(self): + representation = '[%s:%s:%s]' % ( + self.__tagClass, self.__tagFormat, self.__tagId) + return '<%s object, tag %s>' % ( + self.__class__.__name__, representation) + + def __eq__(self, other): + return self.__tagClassId == other + + def __ne__(self, other): + return self.__tagClassId != other + + def __lt__(self, other): + return self.__tagClassId < other + + def __le__(self, other): + return self.__tagClassId <= other + + def __gt__(self, other): + return self.__tagClassId > other + + def __ge__(self, other): + return self.__tagClassId >= other + + def __hash__(self): + return self.__hash + + def __getitem__(self, idx): + if idx == 0: + return self.__tagClass + elif idx == 1: + return self.__tagFormat + elif idx == 2: + return self.__tagId + else: + raise IndexError() + + def __iter__(self): + yield self.__tagClass + yield self.__tagFormat + yield self.__tagId + + def __and__(self, otherTag): + return self.__class__(self.__tagClass & otherTag.tagClass, + self.__tagFormat & otherTag.tagFormat, + self.__tagId & otherTag.tagId) + + def __or__(self, otherTag): + return self.__class__(self.__tagClass | otherTag.tagClass, + self.__tagFormat | otherTag.tagFormat, + self.__tagId | otherTag.tagId) + + @property + def tagClass(self): + """ASN.1 tag class + + Returns + ------- + : :py:class:`int` + Tag class + """ + return self.__tagClass + + @property + def tagFormat(self): + """ASN.1 tag format + + Returns + ------- + : :py:class:`int` + Tag format + """ + return self.__tagFormat + + @property + def tagId(self): + """ASN.1 tag ID + + Returns + ------- + : :py:class:`int` + Tag ID + """ + return self.__tagId + + +class TagSet(object): + """Create a collection of ASN.1 tags + + Represents a combination of :class:`~pyasn1.type.tag.Tag` objects + that can be attached to a ASN.1 type to make types distinguishable + from each other. + + *TagSet* objects are immutable and duck-type Python :class:`tuple` objects + holding arbitrary number of :class:`~pyasn1.type.tag.Tag` objects. + + Parameters + ---------- + baseTag: :class:`~pyasn1.type.tag.Tag` + Base *Tag* object. This tag survives IMPLICIT tagging. + + *superTags: :class:`~pyasn1.type.tag.Tag` + Additional *Tag* objects taking part in subtyping. + + Examples + -------- + .. code-block:: python + + class OrderNumber(NumericString): + ''' + ASN.1 specification + + Order-number ::= + [APPLICATION 5] IMPLICIT NumericString + ''' + tagSet = NumericString.tagSet.tagImplicitly( + Tag(tagClassApplication, tagFormatSimple, 5) + ) + + orderNumber = OrderNumber('1234') + """ + def __init__(self, baseTag=(), *superTags): + self.__baseTag = baseTag + self.__superTags = superTags + self.__superTagsClassId = tuple( + [(superTag.tagClass, superTag.tagId) for superTag in superTags] + ) + self.__lenOfSuperTags = len(superTags) + self.__hash = hash(self.__superTagsClassId) + + def __repr__(self): + representation = '-'.join(['%s:%s:%s' % (x.tagClass, x.tagFormat, x.tagId) + for x in self.__superTags]) + if representation: + representation = 'tags ' + representation + else: + representation = 'untagged' + + return '<%s object, %s>' % (self.__class__.__name__, representation) + + def __add__(self, superTag): + return self.__class__(self.__baseTag, *self.__superTags + (superTag,)) + + def __radd__(self, superTag): + return self.__class__(self.__baseTag, *(superTag,) + self.__superTags) + + def __getitem__(self, i): + if i.__class__ is slice: + return self.__class__(self.__baseTag, *self.__superTags[i]) + else: + return self.__superTags[i] + + def __eq__(self, other): + return self.__superTagsClassId == other + + def __ne__(self, other): + return self.__superTagsClassId != other + + def __lt__(self, other): + return self.__superTagsClassId < other + + def __le__(self, other): + return self.__superTagsClassId <= other + + def __gt__(self, other): + return self.__superTagsClassId > other + + def __ge__(self, other): + return self.__superTagsClassId >= other + + def __hash__(self): + return self.__hash + + def __len__(self): + return self.__lenOfSuperTags + + @property + def baseTag(self): + """Return base ASN.1 tag + + Returns + ------- + : :class:`~pyasn1.type.tag.Tag` + Base tag of this *TagSet* + """ + return self.__baseTag + + @property + def superTags(self): + """Return ASN.1 tags + + Returns + ------- + : :py:class:`tuple` + Tuple of :class:`~pyasn1.type.tag.Tag` objects that this *TagSet* contains + """ + return self.__superTags + + def tagExplicitly(self, superTag): + """Return explicitly tagged *TagSet* + + Create a new *TagSet* representing callee *TagSet* explicitly tagged + with passed tag(s). With explicit tagging mode, new tags are appended + to existing tag(s). + + Parameters + ---------- + superTag: :class:`~pyasn1.type.tag.Tag` + *Tag* object to tag this *TagSet* + + Returns + ------- + : :class:`~pyasn1.type.tag.TagSet` + New *TagSet* object + """ + if superTag.tagClass == tagClassUniversal: + raise error.PyAsn1Error("Can't tag with UNIVERSAL class tag") + if superTag.tagFormat != tagFormatConstructed: + superTag = Tag(superTag.tagClass, tagFormatConstructed, superTag.tagId) + return self + superTag + + def tagImplicitly(self, superTag): + """Return implicitly tagged *TagSet* + + Create a new *TagSet* representing callee *TagSet* implicitly tagged + with passed tag(s). With implicit tagging mode, new tag(s) replace the + last existing tag. + + Parameters + ---------- + superTag: :class:`~pyasn1.type.tag.Tag` + *Tag* object to tag this *TagSet* + + Returns + ------- + : :class:`~pyasn1.type.tag.TagSet` + New *TagSet* object + """ + if self.__superTags: + superTag = Tag(superTag.tagClass, self.__superTags[-1].tagFormat, superTag.tagId) + return self[:-1] + superTag + + def isSuperTagSetOf(self, tagSet): + """Test type relationship against given *TagSet* + + The callee is considered to be a supertype of given *TagSet* + tag-wise if all tags in *TagSet* are present in the callee and + they are in the same order. + + Parameters + ---------- + tagSet: :class:`~pyasn1.type.tag.TagSet` + *TagSet* object to evaluate against the callee + + Returns + ------- + : :py:class:`bool` + :obj:`True` if callee is a supertype of *tagSet* + """ + if len(tagSet) < self.__lenOfSuperTags: + return False + return self.__superTags == tagSet[:self.__lenOfSuperTags] + + # Backward compatibility + + def getBaseTag(self): + return self.__baseTag + +def initTagSet(tag): + return TagSet(tag, tag) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/type/tagmap.py b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/type/tagmap.py new file mode 100644 index 00000000..6f5163b4 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/type/tagmap.py @@ -0,0 +1,96 @@ +# +# This file is part of pyasn1 software. +# +# Copyright (c) 2005-2019, Ilya Etingof <etingof@gmail.com> +# License: http://snmplabs.com/pyasn1/license.html +# +from pyasn1 import error + +__all__ = ['TagMap'] + + +class TagMap(object): + """Map *TagSet* objects to ASN.1 types + + Create an object mapping *TagSet* object to ASN.1 type. + + *TagMap* objects are immutable and duck-type read-only Python + :class:`dict` objects holding *TagSet* objects as keys and ASN.1 + type objects as values. + + Parameters + ---------- + presentTypes: :py:class:`dict` + Map of :class:`~pyasn1.type.tag.TagSet` to ASN.1 objects considered + as being unconditionally present in the *TagMap*. + + skipTypes: :py:class:`dict` + A collection of :class:`~pyasn1.type.tag.TagSet` objects considered + as absent in the *TagMap* even when *defaultType* is present. + + defaultType: ASN.1 type object + An ASN.1 type object callee *TagMap* returns for any *TagSet* key not present + in *presentTypes* (unless given key is present in *skipTypes*). + """ + def __init__(self, presentTypes=None, skipTypes=None, defaultType=None): + self.__presentTypes = presentTypes or {} + self.__skipTypes = skipTypes or {} + self.__defaultType = defaultType + + def __contains__(self, tagSet): + return (tagSet in self.__presentTypes or + self.__defaultType is not None and tagSet not in self.__skipTypes) + + def __getitem__(self, tagSet): + try: + return self.__presentTypes[tagSet] + except KeyError: + if self.__defaultType is None: + raise KeyError() + elif tagSet in self.__skipTypes: + raise error.PyAsn1Error('Key in negative map') + else: + return self.__defaultType + + def __iter__(self): + return iter(self.__presentTypes) + + def __repr__(self): + representation = '%s object' % self.__class__.__name__ + + if self.__presentTypes: + representation += ', present %s' % repr(self.__presentTypes) + + if self.__skipTypes: + representation += ', skip %s' % repr(self.__skipTypes) + + if self.__defaultType is not None: + representation += ', default %s' % repr(self.__defaultType) + + return '<%s>' % representation + + @property + def presentTypes(self): + """Return *TagSet* to ASN.1 type map present in callee *TagMap*""" + return self.__presentTypes + + @property + def skipTypes(self): + """Return *TagSet* collection unconditionally absent in callee *TagMap*""" + return self.__skipTypes + + @property + def defaultType(self): + """Return default ASN.1 type being returned for any missing *TagSet*""" + return self.__defaultType + + # Backward compatibility + + def getPosMap(self): + return self.presentTypes + + def getNegMap(self): + return self.skipTypes + + def getDef(self): + return self.defaultType diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/type/univ.py b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/type/univ.py new file mode 100644 index 00000000..aa688b22 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/type/univ.py @@ -0,0 +1,3321 @@ +# +# This file is part of pyasn1 software. +# +# Copyright (c) 2005-2019, Ilya Etingof <etingof@gmail.com> +# License: http://snmplabs.com/pyasn1/license.html +# +import math +import sys + +from pyasn1 import error +from pyasn1.codec.ber import eoo +from pyasn1.compat import binary +from pyasn1.compat import integer +from pyasn1.compat import octets +from pyasn1.type import base +from pyasn1.type import constraint +from pyasn1.type import namedtype +from pyasn1.type import namedval +from pyasn1.type import tag +from pyasn1.type import tagmap + +NoValue = base.NoValue +noValue = NoValue() + +__all__ = ['Integer', 'Boolean', 'BitString', 'OctetString', 'Null', + 'ObjectIdentifier', 'Real', 'Enumerated', + 'SequenceOfAndSetOfBase', 'SequenceOf', 'SetOf', + 'SequenceAndSetBase', 'Sequence', 'Set', 'Choice', 'Any', + 'NoValue', 'noValue'] + +# "Simple" ASN.1 types (yet incomplete) + + +class Integer(base.SimpleAsn1Type): + """Create |ASN.1| schema or value object. + + |ASN.1| class is based on :class:`~pyasn1.type.base.SimpleAsn1Type`, its + objects are immutable and duck-type Python :class:`int` objects. + + Keyword Args + ------------ + value: :class:`int`, :class:`str` or |ASN.1| object + Python :class:`int` or :class:`str` literal or |ASN.1| class + instance. If `value` is not given, schema object will be created. + + tagSet: :py:class:`~pyasn1.type.tag.TagSet` + Object representing non-default ASN.1 tag(s) + + subtypeSpec: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` + Object representing non-default ASN.1 subtype constraint(s). Constraints + verification for |ASN.1| type occurs automatically on object + instantiation. + + namedValues: :py:class:`~pyasn1.type.namedval.NamedValues` + Object representing non-default symbolic aliases for numbers + + Raises + ------ + ~pyasn1.error.ValueConstraintError, ~pyasn1.error.PyAsn1Error + On constraint violation or bad initializer. + + Examples + -------- + + .. code-block:: python + + class ErrorCode(Integer): + ''' + ASN.1 specification: + + ErrorCode ::= + INTEGER { disk-full(1), no-disk(-1), + disk-not-formatted(2) } + + error ErrorCode ::= disk-full + ''' + namedValues = NamedValues( + ('disk-full', 1), ('no-disk', -1), + ('disk-not-formatted', 2) + ) + + error = ErrorCode('disk-full') + """ + #: Set (on class, not on instance) or return a + #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s) + #: associated with |ASN.1| type. + tagSet = tag.initTagSet( + tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 0x02) + ) + + #: Set (on class, not on instance) or return a + #: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` object + #: imposing constraints on |ASN.1| type initialization values. + subtypeSpec = constraint.ConstraintsIntersection() + + #: Default :py:class:`~pyasn1.type.namedval.NamedValues` object + #: representing symbolic aliases for numbers + namedValues = namedval.NamedValues() + + # Optimization for faster codec lookup + typeId = base.SimpleAsn1Type.getTypeId() + + def __init__(self, value=noValue, **kwargs): + if 'namedValues' not in kwargs: + kwargs['namedValues'] = self.namedValues + + base.SimpleAsn1Type.__init__(self, value, **kwargs) + + def __and__(self, value): + return self.clone(self._value & value) + + def __rand__(self, value): + return self.clone(value & self._value) + + def __or__(self, value): + return self.clone(self._value | value) + + def __ror__(self, value): + return self.clone(value | self._value) + + def __xor__(self, value): + return self.clone(self._value ^ value) + + def __rxor__(self, value): + return self.clone(value ^ self._value) + + def __lshift__(self, value): + return self.clone(self._value << value) + + def __rshift__(self, value): + return self.clone(self._value >> value) + + def __add__(self, value): + return self.clone(self._value + value) + + def __radd__(self, value): + return self.clone(value + self._value) + + def __sub__(self, value): + return self.clone(self._value - value) + + def __rsub__(self, value): + return self.clone(value - self._value) + + def __mul__(self, value): + return self.clone(self._value * value) + + def __rmul__(self, value): + return self.clone(value * self._value) + + def __mod__(self, value): + return self.clone(self._value % value) + + def __rmod__(self, value): + return self.clone(value % self._value) + + def __pow__(self, value, modulo=None): + return self.clone(pow(self._value, value, modulo)) + + def __rpow__(self, value): + return self.clone(pow(value, self._value)) + + def __floordiv__(self, value): + return self.clone(self._value // value) + + def __rfloordiv__(self, value): + return self.clone(value // self._value) + + if sys.version_info[0] <= 2: + def __div__(self, value): + if isinstance(value, float): + return Real(self._value / value) + else: + return self.clone(self._value / value) + + def __rdiv__(self, value): + if isinstance(value, float): + return Real(value / self._value) + else: + return self.clone(value / self._value) + else: + def __truediv__(self, value): + return Real(self._value / value) + + def __rtruediv__(self, value): + return Real(value / self._value) + + def __divmod__(self, value): + return self.clone(divmod(self._value, value)) + + def __rdivmod__(self, value): + return self.clone(divmod(value, self._value)) + + __hash__ = base.SimpleAsn1Type.__hash__ + + def __int__(self): + return int(self._value) + + if sys.version_info[0] <= 2: + def __long__(self): + return long(self._value) + + def __float__(self): + return float(self._value) + + def __abs__(self): + return self.clone(abs(self._value)) + + def __index__(self): + return int(self._value) + + def __pos__(self): + return self.clone(+self._value) + + def __neg__(self): + return self.clone(-self._value) + + def __invert__(self): + return self.clone(~self._value) + + def __round__(self, n=0): + r = round(self._value, n) + if n: + return self.clone(r) + else: + return r + + def __floor__(self): + return math.floor(self._value) + + def __ceil__(self): + return math.ceil(self._value) + + if sys.version_info[0:2] > (2, 5): + def __trunc__(self): + return self.clone(math.trunc(self._value)) + + def __lt__(self, value): + return self._value < value + + def __le__(self, value): + return self._value <= value + + def __eq__(self, value): + return self._value == value + + def __ne__(self, value): + return self._value != value + + def __gt__(self, value): + return self._value > value + + def __ge__(self, value): + return self._value >= value + + def prettyIn(self, value): + try: + return int(value) + + except ValueError: + try: + return self.namedValues[value] + + except KeyError: + raise error.PyAsn1Error( + 'Can\'t coerce %r into integer: %s' % (value, sys.exc_info()[1]) + ) + + def prettyOut(self, value): + try: + return str(self.namedValues[value]) + + except KeyError: + return str(value) + + # backward compatibility + + def getNamedValues(self): + return self.namedValues + + +class Boolean(Integer): + """Create |ASN.1| schema or value object. + + |ASN.1| class is based on :class:`~pyasn1.type.base.SimpleAsn1Type`, its + objects are immutable and duck-type Python :class:`int` objects. + + Keyword Args + ------------ + value: :class:`int`, :class:`str` or |ASN.1| object + Python :class:`int` or :class:`str` literal or |ASN.1| class + instance. If `value` is not given, schema object will be created. + + tagSet: :py:class:`~pyasn1.type.tag.TagSet` + Object representing non-default ASN.1 tag(s) + + subtypeSpec: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` + Object representing non-default ASN.1 subtype constraint(s).Constraints + verification for |ASN.1| type occurs automatically on object + instantiation. + + namedValues: :py:class:`~pyasn1.type.namedval.NamedValues` + Object representing non-default symbolic aliases for numbers + + Raises + ------ + ~pyasn1.error.ValueConstraintError, ~pyasn1.error.PyAsn1Error + On constraint violation or bad initializer. + + Examples + -------- + .. code-block:: python + + class RoundResult(Boolean): + ''' + ASN.1 specification: + + RoundResult ::= BOOLEAN + + ok RoundResult ::= TRUE + ko RoundResult ::= FALSE + ''' + ok = RoundResult(True) + ko = RoundResult(False) + """ + #: Set (on class, not on instance) or return a + #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s) + #: associated with |ASN.1| type. + tagSet = tag.initTagSet( + tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 0x01), + ) + + #: Set (on class, not on instance) or return a + #: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` object + #: imposing constraints on |ASN.1| type initialization values. + subtypeSpec = Integer.subtypeSpec + constraint.SingleValueConstraint(0, 1) + + #: Default :py:class:`~pyasn1.type.namedval.NamedValues` object + #: representing symbolic aliases for numbers + namedValues = namedval.NamedValues(('False', 0), ('True', 1)) + + # Optimization for faster codec lookup + typeId = Integer.getTypeId() + +if sys.version_info[0] < 3: + SizedIntegerBase = long +else: + SizedIntegerBase = int + + +class SizedInteger(SizedIntegerBase): + bitLength = leadingZeroBits = None + + def setBitLength(self, bitLength): + self.bitLength = bitLength + self.leadingZeroBits = max(bitLength - integer.bitLength(self), 0) + return self + + def __len__(self): + if self.bitLength is None: + self.setBitLength(integer.bitLength(self)) + + return self.bitLength + + +class BitString(base.SimpleAsn1Type): + """Create |ASN.1| schema or value object. + + |ASN.1| class is based on :class:`~pyasn1.type.base.SimpleAsn1Type`, its + objects are immutable and duck-type both Python :class:`tuple` (as a tuple + of bits) and :class:`int` objects. + + Keyword Args + ------------ + value: :class:`int`, :class:`str` or |ASN.1| object + Python :class:`int` or :class:`str` literal representing binary + or hexadecimal number or sequence of integer bits or |ASN.1| object. + If `value` is not given, schema object will be created. + + tagSet: :py:class:`~pyasn1.type.tag.TagSet` + Object representing non-default ASN.1 tag(s) + + subtypeSpec: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` + Object representing non-default ASN.1 subtype constraint(s). Constraints + verification for |ASN.1| type occurs automatically on object + instantiation. + + namedValues: :py:class:`~pyasn1.type.namedval.NamedValues` + Object representing non-default symbolic aliases for numbers + + binValue: :py:class:`str` + Binary string initializer to use instead of the *value*. + Example: '10110011'. + + hexValue: :py:class:`str` + Hexadecimal string initializer to use instead of the *value*. + Example: 'DEADBEEF'. + + Raises + ------ + ~pyasn1.error.ValueConstraintError, ~pyasn1.error.PyAsn1Error + On constraint violation or bad initializer. + + Examples + -------- + .. code-block:: python + + class Rights(BitString): + ''' + ASN.1 specification: + + Rights ::= BIT STRING { user-read(0), user-write(1), + group-read(2), group-write(3), + other-read(4), other-write(5) } + + group1 Rights ::= { group-read, group-write } + group2 Rights ::= '0011'B + group3 Rights ::= '3'H + ''' + namedValues = NamedValues( + ('user-read', 0), ('user-write', 1), + ('group-read', 2), ('group-write', 3), + ('other-read', 4), ('other-write', 5) + ) + + group1 = Rights(('group-read', 'group-write')) + group2 = Rights('0011') + group3 = Rights(0x3) + """ + #: Set (on class, not on instance) or return a + #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s) + #: associated with |ASN.1| type. + tagSet = tag.initTagSet( + tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 0x03) + ) + + #: Set (on class, not on instance) or return a + #: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` object + #: imposing constraints on |ASN.1| type initialization values. + subtypeSpec = constraint.ConstraintsIntersection() + + #: Default :py:class:`~pyasn1.type.namedval.NamedValues` object + #: representing symbolic aliases for numbers + namedValues = namedval.NamedValues() + + # Optimization for faster codec lookup + typeId = base.SimpleAsn1Type.getTypeId() + + defaultBinValue = defaultHexValue = noValue + + def __init__(self, value=noValue, **kwargs): + if value is noValue: + if kwargs: + try: + value = self.fromBinaryString(kwargs.pop('binValue'), internalFormat=True) + + except KeyError: + pass + + try: + value = self.fromHexString(kwargs.pop('hexValue'), internalFormat=True) + + except KeyError: + pass + + if value is noValue: + if self.defaultBinValue is not noValue: + value = self.fromBinaryString(self.defaultBinValue, internalFormat=True) + + elif self.defaultHexValue is not noValue: + value = self.fromHexString(self.defaultHexValue, internalFormat=True) + + if 'namedValues' not in kwargs: + kwargs['namedValues'] = self.namedValues + + base.SimpleAsn1Type.__init__(self, value, **kwargs) + + def __str__(self): + return self.asBinary() + + def __eq__(self, other): + other = self.prettyIn(other) + return self is other or self._value == other and len(self._value) == len(other) + + def __ne__(self, other): + other = self.prettyIn(other) + return self._value != other or len(self._value) != len(other) + + def __lt__(self, other): + other = self.prettyIn(other) + return len(self._value) < len(other) or len(self._value) == len(other) and self._value < other + + def __le__(self, other): + other = self.prettyIn(other) + return len(self._value) <= len(other) or len(self._value) == len(other) and self._value <= other + + def __gt__(self, other): + other = self.prettyIn(other) + return len(self._value) > len(other) or len(self._value) == len(other) and self._value > other + + def __ge__(self, other): + other = self.prettyIn(other) + return len(self._value) >= len(other) or len(self._value) == len(other) and self._value >= other + + # Immutable sequence object protocol + + def __len__(self): + return len(self._value) + + def __getitem__(self, i): + if i.__class__ is slice: + return self.clone([self[x] for x in range(*i.indices(len(self)))]) + else: + length = len(self._value) - 1 + if i > length or i < 0: + raise IndexError('bit index out of range') + return (self._value >> (length - i)) & 1 + + def __iter__(self): + length = len(self._value) + while length: + length -= 1 + yield (self._value >> length) & 1 + + def __reversed__(self): + return reversed(tuple(self)) + + # arithmetic operators + + def __add__(self, value): + value = self.prettyIn(value) + return self.clone(SizedInteger(self._value << len(value) | value).setBitLength(len(self._value) + len(value))) + + def __radd__(self, value): + value = self.prettyIn(value) + return self.clone(SizedInteger(value << len(self._value) | self._value).setBitLength(len(self._value) + len(value))) + + def __mul__(self, value): + bitString = self._value + while value > 1: + bitString <<= len(self._value) + bitString |= self._value + value -= 1 + return self.clone(bitString) + + def __rmul__(self, value): + return self * value + + def __lshift__(self, count): + return self.clone(SizedInteger(self._value << count).setBitLength(len(self._value) + count)) + + def __rshift__(self, count): + return self.clone(SizedInteger(self._value >> count).setBitLength(max(0, len(self._value) - count))) + + def __int__(self): + return self._value + + def __float__(self): + return float(self._value) + + if sys.version_info[0] < 3: + def __long__(self): + return self._value + + def asNumbers(self): + """Get |ASN.1| value as a sequence of 8-bit integers. + + If |ASN.1| object length is not a multiple of 8, result + will be left-padded with zeros. + """ + return tuple(octets.octs2ints(self.asOctets())) + + def asOctets(self): + """Get |ASN.1| value as a sequence of octets. + + If |ASN.1| object length is not a multiple of 8, result + will be left-padded with zeros. + """ + return integer.to_bytes(self._value, length=len(self)) + + def asInteger(self): + """Get |ASN.1| value as a single integer value. + """ + return self._value + + def asBinary(self): + """Get |ASN.1| value as a text string of bits. + """ + binString = binary.bin(self._value)[2:] + return '0' * (len(self._value) - len(binString)) + binString + + @classmethod + def fromHexString(cls, value, internalFormat=False, prepend=None): + """Create a |ASN.1| object initialized from the hex string. + + Parameters + ---------- + value: :class:`str` + Text string like 'DEADBEEF' + """ + try: + value = SizedInteger(value, 16).setBitLength(len(value) * 4) + + except ValueError: + raise error.PyAsn1Error('%s.fromHexString() error: %s' % (cls.__name__, sys.exc_info()[1])) + + if prepend is not None: + value = SizedInteger( + (SizedInteger(prepend) << len(value)) | value + ).setBitLength(len(prepend) + len(value)) + + if not internalFormat: + value = cls(value) + + return value + + @classmethod + def fromBinaryString(cls, value, internalFormat=False, prepend=None): + """Create a |ASN.1| object initialized from a string of '0' and '1'. + + Parameters + ---------- + value: :class:`str` + Text string like '1010111' + """ + try: + value = SizedInteger(value or '0', 2).setBitLength(len(value)) + + except ValueError: + raise error.PyAsn1Error('%s.fromBinaryString() error: %s' % (cls.__name__, sys.exc_info()[1])) + + if prepend is not None: + value = SizedInteger( + (SizedInteger(prepend) << len(value)) | value + ).setBitLength(len(prepend) + len(value)) + + if not internalFormat: + value = cls(value) + + return value + + @classmethod + def fromOctetString(cls, value, internalFormat=False, prepend=None, padding=0): + """Create a |ASN.1| object initialized from a string. + + Parameters + ---------- + value: :class:`str` (Py2) or :class:`bytes` (Py3) + Text string like '\\\\x01\\\\xff' (Py2) or b'\\\\x01\\\\xff' (Py3) + """ + value = SizedInteger(integer.from_bytes(value) >> padding).setBitLength(len(value) * 8 - padding) + + if prepend is not None: + value = SizedInteger( + (SizedInteger(prepend) << len(value)) | value + ).setBitLength(len(prepend) + len(value)) + + if not internalFormat: + value = cls(value) + + return value + + def prettyIn(self, value): + if isinstance(value, SizedInteger): + return value + elif octets.isStringType(value): + if not value: + return SizedInteger(0).setBitLength(0) + + elif value[0] == '\'': # "'1011'B" -- ASN.1 schema representation (deprecated) + if value[-2:] == '\'B': + return self.fromBinaryString(value[1:-2], internalFormat=True) + elif value[-2:] == '\'H': + return self.fromHexString(value[1:-2], internalFormat=True) + else: + raise error.PyAsn1Error( + 'Bad BIT STRING value notation %s' % (value,) + ) + + elif self.namedValues and not value.isdigit(): # named bits like 'Urgent, Active' + names = [x.strip() for x in value.split(',')] + + try: + + bitPositions = [self.namedValues[name] for name in names] + + except KeyError: + raise error.PyAsn1Error('unknown bit name(s) in %r' % (names,)) + + rightmostPosition = max(bitPositions) + + number = 0 + for bitPosition in bitPositions: + number |= 1 << (rightmostPosition - bitPosition) + + return SizedInteger(number).setBitLength(rightmostPosition + 1) + + elif value.startswith('0x'): + return self.fromHexString(value[2:], internalFormat=True) + + elif value.startswith('0b'): + return self.fromBinaryString(value[2:], internalFormat=True) + + else: # assume plain binary string like '1011' + return self.fromBinaryString(value, internalFormat=True) + + elif isinstance(value, (tuple, list)): + return self.fromBinaryString(''.join([b and '1' or '0' for b in value]), internalFormat=True) + + elif isinstance(value, BitString): + return SizedInteger(value).setBitLength(len(value)) + + elif isinstance(value, intTypes): + return SizedInteger(value) + + else: + raise error.PyAsn1Error( + 'Bad BitString initializer type \'%s\'' % (value,) + ) + + +try: + # noinspection PyStatementEffect + all + +except NameError: # Python 2.4 + # noinspection PyShadowingBuiltins + def all(iterable): + for element in iterable: + if not element: + return False + return True + + +class OctetString(base.SimpleAsn1Type): + """Create |ASN.1| schema or value object. + + |ASN.1| class is based on :class:`~pyasn1.type.base.SimpleAsn1Type`, its + objects are immutable and duck-type Python 2 :class:`str` or + Python 3 :class:`bytes`. When used in Unicode context, |ASN.1| type + assumes "|encoding|" serialisation. + + Keyword Args + ------------ + value: :class:`unicode`, :class:`str`, :class:`bytes` or |ASN.1| object + class:`str` (Python 2) or :class:`bytes` (Python 3), alternatively + class:`unicode` object (Python 2) or :class:`str` (Python 3) + representing character string to be serialised into octets + (note `encoding` parameter) or |ASN.1| object. + If `value` is not given, schema object will be created. + + tagSet: :py:class:`~pyasn1.type.tag.TagSet` + Object representing non-default ASN.1 tag(s) + + subtypeSpec: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` + Object representing non-default ASN.1 subtype constraint(s). Constraints + verification for |ASN.1| type occurs automatically on object + instantiation. + + encoding: :py:class:`str` + Unicode codec ID to encode/decode :class:`unicode` (Python 2) or + :class:`str` (Python 3) the payload when |ASN.1| object is used + in text string context. + + binValue: :py:class:`str` + Binary string initializer to use instead of the *value*. + Example: '10110011'. + + hexValue: :py:class:`str` + Hexadecimal string initializer to use instead of the *value*. + Example: 'DEADBEEF'. + + Raises + ------ + ~pyasn1.error.ValueConstraintError, ~pyasn1.error.PyAsn1Error + On constraint violation or bad initializer. + + Examples + -------- + .. code-block:: python + + class Icon(OctetString): + ''' + ASN.1 specification: + + Icon ::= OCTET STRING + + icon1 Icon ::= '001100010011001000110011'B + icon2 Icon ::= '313233'H + ''' + icon1 = Icon.fromBinaryString('001100010011001000110011') + icon2 = Icon.fromHexString('313233') + """ + #: Set (on class, not on instance) or return a + #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s) + #: associated with |ASN.1| type. + tagSet = tag.initTagSet( + tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 0x04) + ) + + #: Set (on class, not on instance) or return a + #: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` object + #: imposing constraints on |ASN.1| type initialization values. + subtypeSpec = constraint.ConstraintsIntersection() + + # Optimization for faster codec lookup + typeId = base.SimpleAsn1Type.getTypeId() + + defaultBinValue = defaultHexValue = noValue + encoding = 'iso-8859-1' + + def __init__(self, value=noValue, **kwargs): + if kwargs: + if value is noValue: + try: + value = self.fromBinaryString(kwargs.pop('binValue')) + + except KeyError: + pass + + try: + value = self.fromHexString(kwargs.pop('hexValue')) + + except KeyError: + pass + + if value is noValue: + if self.defaultBinValue is not noValue: + value = self.fromBinaryString(self.defaultBinValue) + + elif self.defaultHexValue is not noValue: + value = self.fromHexString(self.defaultHexValue) + + if 'encoding' not in kwargs: + kwargs['encoding'] = self.encoding + + base.SimpleAsn1Type.__init__(self, value, **kwargs) + + if sys.version_info[0] <= 2: + def prettyIn(self, value): + if isinstance(value, str): + return value + + elif isinstance(value, unicode): + try: + return value.encode(self.encoding) + + except (LookupError, UnicodeEncodeError): + exc = sys.exc_info()[1] + raise error.PyAsn1UnicodeEncodeError( + "Can't encode string '%s' with codec " + "%s" % (value, self.encoding), exc + ) + + elif isinstance(value, (tuple, list)): + try: + return ''.join([chr(x) for x in value]) + + except ValueError: + raise error.PyAsn1Error( + "Bad %s initializer '%s'" % (self.__class__.__name__, value) + ) + + else: + return str(value) + + def __str__(self): + return str(self._value) + + def __unicode__(self): + try: + return self._value.decode(self.encoding) + + except UnicodeDecodeError: + exc = sys.exc_info()[1] + raise error.PyAsn1UnicodeDecodeError( + "Can't decode string '%s' with codec " + "%s" % (self._value, self.encoding), exc + ) + + def asOctets(self): + return str(self._value) + + def asNumbers(self): + return tuple([ord(x) for x in self._value]) + + else: + def prettyIn(self, value): + if isinstance(value, bytes): + return value + + elif isinstance(value, str): + try: + return value.encode(self.encoding) + + except UnicodeEncodeError: + exc = sys.exc_info()[1] + raise error.PyAsn1UnicodeEncodeError( + "Can't encode string '%s' with '%s' " + "codec" % (value, self.encoding), exc + ) + elif isinstance(value, OctetString): # a shortcut, bytes() would work the same way + return value.asOctets() + + elif isinstance(value, base.SimpleAsn1Type): # this mostly targets Integer objects + return self.prettyIn(str(value)) + + elif isinstance(value, (tuple, list)): + return self.prettyIn(bytes(value)) + + else: + return bytes(value) + + def __str__(self): + try: + return self._value.decode(self.encoding) + + except UnicodeDecodeError: + exc = sys.exc_info()[1] + raise error.PyAsn1UnicodeDecodeError( + "Can't decode string '%s' with '%s' codec at " + "'%s'" % (self._value, self.encoding, + self.__class__.__name__), exc + ) + + def __bytes__(self): + return bytes(self._value) + + def asOctets(self): + return bytes(self._value) + + def asNumbers(self): + return tuple(self._value) + + # + # Normally, `.prettyPrint()` is called from `__str__()`. Historically, + # OctetString.prettyPrint() used to return hexified payload + # representation in cases when non-printable content is present. At the + # same time `str()` used to produce either octet-stream (Py2) or + # text (Py3) representations. + # + # Therefore `OctetString.__str__()` -> `.prettyPrint()` call chain is + # reversed to preserve the original behaviour. + # + # Eventually we should deprecate `.prettyPrint()` / `.prettyOut()` harness + # and end up with just `__str__()` producing hexified representation while + # both text and octet-stream representation should only be requested via + # the `.asOctets()` method. + # + # Note: ASN.1 OCTET STRING is never mean to contain text! + # + + def prettyOut(self, value): + return value + + def prettyPrint(self, scope=0): + # first see if subclass has its own .prettyOut() + value = self.prettyOut(self._value) + + if value is not self._value: + return value + + numbers = self.asNumbers() + + for x in numbers: + # hexify if needed + if x < 32 or x > 126: + return '0x' + ''.join(('%.2x' % x for x in numbers)) + else: + # this prevents infinite recursion + return OctetString.__str__(self) + + @staticmethod + def fromBinaryString(value): + """Create a |ASN.1| object initialized from a string of '0' and '1'. + + Parameters + ---------- + value: :class:`str` + Text string like '1010111' + """ + bitNo = 8 + byte = 0 + r = [] + for v in value: + if bitNo: + bitNo -= 1 + else: + bitNo = 7 + r.append(byte) + byte = 0 + if v in ('0', '1'): + v = int(v) + else: + raise error.PyAsn1Error( + 'Non-binary OCTET STRING initializer %s' % (v,) + ) + byte |= v << bitNo + + r.append(byte) + + return octets.ints2octs(r) + + @staticmethod + def fromHexString(value): + """Create a |ASN.1| object initialized from the hex string. + + Parameters + ---------- + value: :class:`str` + Text string like 'DEADBEEF' + """ + r = [] + p = [] + for v in value: + if p: + r.append(int(p + v, 16)) + p = None + else: + p = v + if p: + r.append(int(p + '0', 16)) + + return octets.ints2octs(r) + + # Immutable sequence object protocol + + def __len__(self): + return len(self._value) + + def __getitem__(self, i): + if i.__class__ is slice: + return self.clone(self._value[i]) + else: + return self._value[i] + + def __iter__(self): + return iter(self._value) + + def __contains__(self, value): + return value in self._value + + def __add__(self, value): + return self.clone(self._value + self.prettyIn(value)) + + def __radd__(self, value): + return self.clone(self.prettyIn(value) + self._value) + + def __mul__(self, value): + return self.clone(self._value * value) + + def __rmul__(self, value): + return self * value + + def __int__(self): + return int(self._value) + + def __float__(self): + return float(self._value) + + def __reversed__(self): + return reversed(self._value) + + +class Null(OctetString): + """Create |ASN.1| schema or value object. + + |ASN.1| class is based on :class:`~pyasn1.type.base.SimpleAsn1Type`, its + objects are immutable and duck-type Python :class:`str` objects + (always empty). + + Keyword Args + ------------ + value: :class:`str` or |ASN.1| object + Python empty :class:`str` literal or any object that evaluates to :obj:`False` + If `value` is not given, schema object will be created. + + tagSet: :py:class:`~pyasn1.type.tag.TagSet` + Object representing non-default ASN.1 tag(s) + + Raises + ------ + ~pyasn1.error.ValueConstraintError, ~pyasn1.error.PyAsn1Error + On constraint violation or bad initializer. + + Examples + -------- + .. code-block:: python + + class Ack(Null): + ''' + ASN.1 specification: + + Ack ::= NULL + ''' + ack = Ack('') + """ + + #: Set (on class, not on instance) or return a + #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s) + #: associated with |ASN.1| type. + tagSet = tag.initTagSet( + tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 0x05) + ) + subtypeSpec = OctetString.subtypeSpec + constraint.SingleValueConstraint(octets.str2octs('')) + + # Optimization for faster codec lookup + typeId = OctetString.getTypeId() + + def prettyIn(self, value): + if value: + return value + + return octets.str2octs('') + +if sys.version_info[0] <= 2: + intTypes = (int, long) +else: + intTypes = (int,) + +numericTypes = intTypes + (float,) + + +class ObjectIdentifier(base.SimpleAsn1Type): + """Create |ASN.1| schema or value object. + + |ASN.1| class is based on :class:`~pyasn1.type.base.SimpleAsn1Type`, its + objects are immutable and duck-type Python :class:`tuple` objects + (tuple of non-negative integers). + + Keyword Args + ------------ + value: :class:`tuple`, :class:`str` or |ASN.1| object + Python sequence of :class:`int` or :class:`str` literal or |ASN.1| object. + If `value` is not given, schema object will be created. + + tagSet: :py:class:`~pyasn1.type.tag.TagSet` + Object representing non-default ASN.1 tag(s) + + subtypeSpec: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` + Object representing non-default ASN.1 subtype constraint(s). Constraints + verification for |ASN.1| type occurs automatically on object + instantiation. + + Raises + ------ + ~pyasn1.error.ValueConstraintError, ~pyasn1.error.PyAsn1Error + On constraint violation or bad initializer. + + Examples + -------- + .. code-block:: python + + class ID(ObjectIdentifier): + ''' + ASN.1 specification: + + ID ::= OBJECT IDENTIFIER + + id-edims ID ::= { joint-iso-itu-t mhs-motif(6) edims(7) } + id-bp ID ::= { id-edims 11 } + ''' + id_edims = ID('2.6.7') + id_bp = id_edims + (11,) + """ + #: Set (on class, not on instance) or return a + #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s) + #: associated with |ASN.1| type. + tagSet = tag.initTagSet( + tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 0x06) + ) + + #: Set (on class, not on instance) or return a + #: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` object + #: imposing constraints on |ASN.1| type initialization values. + subtypeSpec = constraint.ConstraintsIntersection() + + # Optimization for faster codec lookup + typeId = base.SimpleAsn1Type.getTypeId() + + def __add__(self, other): + return self.clone(self._value + other) + + def __radd__(self, other): + return self.clone(other + self._value) + + def asTuple(self): + return self._value + + # Sequence object protocol + + def __len__(self): + return len(self._value) + + def __getitem__(self, i): + if i.__class__ is slice: + return self.clone(self._value[i]) + else: + return self._value[i] + + def __iter__(self): + return iter(self._value) + + def __contains__(self, value): + return value in self._value + + def index(self, suboid): + return self._value.index(suboid) + + def isPrefixOf(self, other): + """Indicate if this |ASN.1| object is a prefix of other |ASN.1| object. + + Parameters + ---------- + other: |ASN.1| object + |ASN.1| object + + Returns + ------- + : :class:`bool` + :obj:`True` if this |ASN.1| object is a parent (e.g. prefix) of the other |ASN.1| object + or :obj:`False` otherwise. + """ + l = len(self) + if l <= len(other): + if self._value[:l] == other[:l]: + return True + return False + + def prettyIn(self, value): + if isinstance(value, ObjectIdentifier): + return tuple(value) + elif octets.isStringType(value): + if '-' in value: + raise error.PyAsn1Error( + 'Malformed Object ID %s at %s: %s' % (value, self.__class__.__name__, sys.exc_info()[1]) + ) + try: + return tuple([int(subOid) for subOid in value.split('.') if subOid]) + except ValueError: + raise error.PyAsn1Error( + 'Malformed Object ID %s at %s: %s' % (value, self.__class__.__name__, sys.exc_info()[1]) + ) + + try: + tupleOfInts = tuple([int(subOid) for subOid in value if subOid >= 0]) + + except (ValueError, TypeError): + raise error.PyAsn1Error( + 'Malformed Object ID %s at %s: %s' % (value, self.__class__.__name__, sys.exc_info()[1]) + ) + + if len(tupleOfInts) == len(value): + return tupleOfInts + + raise error.PyAsn1Error('Malformed Object ID %s at %s' % (value, self.__class__.__name__)) + + def prettyOut(self, value): + return '.'.join([str(x) for x in value]) + + +class Real(base.SimpleAsn1Type): + """Create |ASN.1| schema or value object. + + |ASN.1| class is based on :class:`~pyasn1.type.base.SimpleAsn1Type`, its + objects are immutable and duck-type Python :class:`float` objects. + Additionally, |ASN.1| objects behave like a :class:`tuple` in which case its + elements are mantissa, base and exponent. + + Keyword Args + ------------ + value: :class:`tuple`, :class:`float` or |ASN.1| object + Python sequence of :class:`int` (representing mantissa, base and + exponent) or :class:`float` instance or |ASN.1| object. + If `value` is not given, schema object will be created. + + tagSet: :py:class:`~pyasn1.type.tag.TagSet` + Object representing non-default ASN.1 tag(s) + + subtypeSpec: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` + Object representing non-default ASN.1 subtype constraint(s). Constraints + verification for |ASN.1| type occurs automatically on object + instantiation. + + Raises + ------ + ~pyasn1.error.ValueConstraintError, ~pyasn1.error.PyAsn1Error + On constraint violation or bad initializer. + + Examples + -------- + .. code-block:: python + + class Pi(Real): + ''' + ASN.1 specification: + + Pi ::= REAL + + pi Pi ::= { mantissa 314159, base 10, exponent -5 } + + ''' + pi = Pi((314159, 10, -5)) + """ + binEncBase = None # binEncBase = 16 is recommended for large numbers + + try: + _plusInf = float('inf') + _minusInf = float('-inf') + _inf = _plusInf, _minusInf + + except ValueError: + # Infinity support is platform and Python dependent + _plusInf = _minusInf = None + _inf = () + + #: Set (on class, not on instance) or return a + #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s) + #: associated with |ASN.1| type. + tagSet = tag.initTagSet( + tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 0x09) + ) + + #: Set (on class, not on instance) or return a + #: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` object + #: imposing constraints on |ASN.1| type initialization values. + subtypeSpec = constraint.ConstraintsIntersection() + + # Optimization for faster codec lookup + typeId = base.SimpleAsn1Type.getTypeId() + + @staticmethod + def __normalizeBase10(value): + m, b, e = value + while m and m % 10 == 0: + m /= 10 + e += 1 + return m, b, e + + def prettyIn(self, value): + if isinstance(value, tuple) and len(value) == 3: + if (not isinstance(value[0], numericTypes) or + not isinstance(value[1], intTypes) or + not isinstance(value[2], intTypes)): + raise error.PyAsn1Error('Lame Real value syntax: %s' % (value,)) + if (isinstance(value[0], float) and + self._inf and value[0] in self._inf): + return value[0] + if value[1] not in (2, 10): + raise error.PyAsn1Error( + 'Prohibited base for Real value: %s' % (value[1],) + ) + if value[1] == 10: + value = self.__normalizeBase10(value) + return value + elif isinstance(value, intTypes): + return self.__normalizeBase10((value, 10, 0)) + elif isinstance(value, float) or octets.isStringType(value): + if octets.isStringType(value): + try: + value = float(value) + except ValueError: + raise error.PyAsn1Error( + 'Bad real value syntax: %s' % (value,) + ) + if self._inf and value in self._inf: + return value + else: + e = 0 + while int(value) != value: + value *= 10 + e -= 1 + return self.__normalizeBase10((int(value), 10, e)) + elif isinstance(value, Real): + return tuple(value) + raise error.PyAsn1Error( + 'Bad real value syntax: %s' % (value,) + ) + + def prettyPrint(self, scope=0): + try: + return self.prettyOut(float(self)) + + except OverflowError: + return '<overflow>' + + @property + def isPlusInf(self): + """Indicate PLUS-INFINITY object value + + Returns + ------- + : :class:`bool` + :obj:`True` if calling object represents plus infinity + or :obj:`False` otherwise. + + """ + return self._value == self._plusInf + + @property + def isMinusInf(self): + """Indicate MINUS-INFINITY object value + + Returns + ------- + : :class:`bool` + :obj:`True` if calling object represents minus infinity + or :obj:`False` otherwise. + """ + return self._value == self._minusInf + + @property + def isInf(self): + return self._value in self._inf + + def __add__(self, value): + return self.clone(float(self) + value) + + def __radd__(self, value): + return self + value + + def __mul__(self, value): + return self.clone(float(self) * value) + + def __rmul__(self, value): + return self * value + + def __sub__(self, value): + return self.clone(float(self) - value) + + def __rsub__(self, value): + return self.clone(value - float(self)) + + def __mod__(self, value): + return self.clone(float(self) % value) + + def __rmod__(self, value): + return self.clone(value % float(self)) + + def __pow__(self, value, modulo=None): + return self.clone(pow(float(self), value, modulo)) + + def __rpow__(self, value): + return self.clone(pow(value, float(self))) + + if sys.version_info[0] <= 2: + def __div__(self, value): + return self.clone(float(self) / value) + + def __rdiv__(self, value): + return self.clone(value / float(self)) + else: + def __truediv__(self, value): + return self.clone(float(self) / value) + + def __rtruediv__(self, value): + return self.clone(value / float(self)) + + def __divmod__(self, value): + return self.clone(float(self) // value) + + def __rdivmod__(self, value): + return self.clone(value // float(self)) + + def __int__(self): + return int(float(self)) + + if sys.version_info[0] <= 2: + def __long__(self): + return long(float(self)) + + def __float__(self): + if self._value in self._inf: + return self._value + else: + return float( + self._value[0] * pow(self._value[1], self._value[2]) + ) + + def __abs__(self): + return self.clone(abs(float(self))) + + def __pos__(self): + return self.clone(+float(self)) + + def __neg__(self): + return self.clone(-float(self)) + + def __round__(self, n=0): + r = round(float(self), n) + if n: + return self.clone(r) + else: + return r + + def __floor__(self): + return self.clone(math.floor(float(self))) + + def __ceil__(self): + return self.clone(math.ceil(float(self))) + + if sys.version_info[0:2] > (2, 5): + def __trunc__(self): + return self.clone(math.trunc(float(self))) + + def __lt__(self, value): + return float(self) < value + + def __le__(self, value): + return float(self) <= value + + def __eq__(self, value): + return float(self) == value + + def __ne__(self, value): + return float(self) != value + + def __gt__(self, value): + return float(self) > value + + def __ge__(self, value): + return float(self) >= value + + if sys.version_info[0] <= 2: + def __nonzero__(self): + return bool(float(self)) + else: + def __bool__(self): + return bool(float(self)) + + __hash__ = base.SimpleAsn1Type.__hash__ + + def __getitem__(self, idx): + if self._value in self._inf: + raise error.PyAsn1Error('Invalid infinite value operation') + else: + return self._value[idx] + + # compatibility stubs + + def isPlusInfinity(self): + return self.isPlusInf + + def isMinusInfinity(self): + return self.isMinusInf + + def isInfinity(self): + return self.isInf + + +class Enumerated(Integer): + """Create |ASN.1| schema or value object. + + |ASN.1| class is based on :class:`~pyasn1.type.base.SimpleAsn1Type`, its + objects are immutable and duck-type Python :class:`int` objects. + + Keyword Args + ------------ + value: :class:`int`, :class:`str` or |ASN.1| object + Python :class:`int` or :class:`str` literal or |ASN.1| object. + If `value` is not given, schema object will be created. + + tagSet: :py:class:`~pyasn1.type.tag.TagSet` + Object representing non-default ASN.1 tag(s) + + subtypeSpec: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` + Object representing non-default ASN.1 subtype constraint(s). Constraints + verification for |ASN.1| type occurs automatically on object + instantiation. + + namedValues: :py:class:`~pyasn1.type.namedval.NamedValues` + Object representing non-default symbolic aliases for numbers + + Raises + ------ + ~pyasn1.error.ValueConstraintError, ~pyasn1.error.PyAsn1Error + On constraint violation or bad initializer. + + Examples + -------- + + .. code-block:: python + + class RadioButton(Enumerated): + ''' + ASN.1 specification: + + RadioButton ::= ENUMERATED { button1(0), button2(1), + button3(2) } + + selected-by-default RadioButton ::= button1 + ''' + namedValues = NamedValues( + ('button1', 0), ('button2', 1), + ('button3', 2) + ) + + selected_by_default = RadioButton('button1') + """ + #: Set (on class, not on instance) or return a + #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s) + #: associated with |ASN.1| type. + tagSet = tag.initTagSet( + tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 0x0A) + ) + + #: Set (on class, not on instance) or return a + #: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` object + #: imposing constraints on |ASN.1| type initialization values. + subtypeSpec = constraint.ConstraintsIntersection() + + # Optimization for faster codec lookup + typeId = Integer.getTypeId() + + #: Default :py:class:`~pyasn1.type.namedval.NamedValues` object + #: representing symbolic aliases for numbers + namedValues = namedval.NamedValues() + + +# "Structured" ASN.1 types + +class SequenceOfAndSetOfBase(base.ConstructedAsn1Type): + """Create |ASN.1| schema or value object. + + |ASN.1| class is based on :class:`~pyasn1.type.base.ConstructedAsn1Type`, + its objects are mutable and duck-type Python :class:`list` objects. + + Keyword Args + ------------ + componentType : :py:class:`~pyasn1.type.base.PyAsn1Item` derivative + A pyasn1 object representing ASN.1 type allowed within |ASN.1| type + + tagSet: :py:class:`~pyasn1.type.tag.TagSet` + Object representing non-default ASN.1 tag(s) + + subtypeSpec: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` + Object representing non-default ASN.1 subtype constraint(s). Constraints + verification for |ASN.1| type can only occur on explicit + `.isInconsistent` call. + + Examples + -------- + + .. code-block:: python + + class LotteryDraw(SequenceOf): # SetOf is similar + ''' + ASN.1 specification: + + LotteryDraw ::= SEQUENCE OF INTEGER + ''' + componentType = Integer() + + lotteryDraw = LotteryDraw() + lotteryDraw.extend([123, 456, 789]) + """ + def __init__(self, *args, **kwargs): + # support positional params for backward compatibility + if args: + for key, value in zip(('componentType', 'tagSet', + 'subtypeSpec'), args): + if key in kwargs: + raise error.PyAsn1Error('Conflicting positional and keyword params!') + kwargs['componentType'] = value + + self._componentValues = noValue + + base.ConstructedAsn1Type.__init__(self, **kwargs) + + # Python list protocol + + def __getitem__(self, idx): + try: + return self.getComponentByPosition(idx) + + except error.PyAsn1Error: + raise IndexError(sys.exc_info()[1]) + + def __setitem__(self, idx, value): + try: + self.setComponentByPosition(idx, value) + + except error.PyAsn1Error: + raise IndexError(sys.exc_info()[1]) + + def append(self, value): + if self._componentValues is noValue: + pos = 0 + + else: + pos = len(self._componentValues) + + self[pos] = value + + def count(self, value): + return list(self._componentValues.values()).count(value) + + def extend(self, values): + for value in values: + self.append(value) + + if self._componentValues is noValue: + self._componentValues = {} + + def index(self, value, start=0, stop=None): + if stop is None: + stop = len(self) + + indices, values = zip(*self._componentValues.items()) + + # TODO: remove when Py2.5 support is gone + values = list(values) + + try: + return indices[values.index(value, start, stop)] + + except error.PyAsn1Error: + raise ValueError(sys.exc_info()[1]) + + def reverse(self): + self._componentValues.reverse() + + def sort(self, key=None, reverse=False): + self._componentValues = dict( + enumerate(sorted(self._componentValues.values(), + key=key, reverse=reverse))) + + def __len__(self): + if self._componentValues is noValue or not self._componentValues: + return 0 + + return max(self._componentValues) + 1 + + def __iter__(self): + for idx in range(0, len(self)): + yield self.getComponentByPosition(idx) + + def _cloneComponentValues(self, myClone, cloneValueFlag): + for idx, componentValue in self._componentValues.items(): + if componentValue is not noValue: + if isinstance(componentValue, base.ConstructedAsn1Type): + myClone.setComponentByPosition( + idx, componentValue.clone(cloneValueFlag=cloneValueFlag) + ) + else: + myClone.setComponentByPosition(idx, componentValue.clone()) + + def getComponentByPosition(self, idx, default=noValue, instantiate=True): + """Return |ASN.1| type component value by position. + + Equivalent to Python sequence subscription operation (e.g. `[]`). + + Parameters + ---------- + idx : :class:`int` + Component index (zero-based). Must either refer to an existing + component or to N+1 component (if *componentType* is set). In the latter + case a new component type gets instantiated and appended to the |ASN.1| + sequence. + + Keyword Args + ------------ + default: :class:`object` + If set and requested component is a schema object, return the `default` + object instead of the requested component. + + instantiate: :class:`bool` + If :obj:`True` (default), inner component will be automatically instantiated. + If :obj:`False` either existing component or the :class:`NoValue` object will be + returned. + + Returns + ------- + : :py:class:`~pyasn1.type.base.PyAsn1Item` + Instantiate |ASN.1| component type or return existing component value + + Examples + -------- + + .. code-block:: python + + # can also be SetOf + class MySequenceOf(SequenceOf): + componentType = OctetString() + + s = MySequenceOf() + + # returns component #0 with `.isValue` property False + s.getComponentByPosition(0) + + # returns None + s.getComponentByPosition(0, default=None) + + s.clear() + + # returns noValue + s.getComponentByPosition(0, instantiate=False) + + # sets component #0 to OctetString() ASN.1 schema + # object and returns it + s.getComponentByPosition(0, instantiate=True) + + # sets component #0 to ASN.1 value object + s.setComponentByPosition(0, 'ABCD') + + # returns OctetString('ABCD') value object + s.getComponentByPosition(0, instantiate=False) + + s.clear() + + # returns noValue + s.getComponentByPosition(0, instantiate=False) + """ + if isinstance(idx, slice): + indices = tuple(range(len(self))) + return [self.getComponentByPosition(subidx, default, instantiate) + for subidx in indices[idx]] + + if idx < 0: + idx = len(self) + idx + if idx < 0: + raise error.PyAsn1Error( + 'SequenceOf/SetOf index is out of range') + + try: + componentValue = self._componentValues[idx] + + except (KeyError, error.PyAsn1Error): + if not instantiate: + return default + + self.setComponentByPosition(idx) + + componentValue = self._componentValues[idx] + + if default is noValue or componentValue.isValue: + return componentValue + else: + return default + + def setComponentByPosition(self, idx, value=noValue, + verifyConstraints=True, + matchTags=True, + matchConstraints=True): + """Assign |ASN.1| type component by position. + + Equivalent to Python sequence item assignment operation (e.g. `[]`) + or list.append() (when idx == len(self)). + + Parameters + ---------- + idx: :class:`int` + Component index (zero-based). Must either refer to existing + component or to N+1 component. In the latter case a new component + type gets instantiated (if *componentType* is set, or given ASN.1 + object is taken otherwise) and appended to the |ASN.1| sequence. + + Keyword Args + ------------ + value: :class:`object` or :py:class:`~pyasn1.type.base.PyAsn1Item` derivative + A Python value to initialize |ASN.1| component with (if *componentType* is set) + or ASN.1 value object to assign to |ASN.1| component. + If `value` is not given, schema object will be set as a component. + + verifyConstraints: :class:`bool` + If :obj:`False`, skip constraints validation + + matchTags: :class:`bool` + If :obj:`False`, skip component tags matching + + matchConstraints: :class:`bool` + If :obj:`False`, skip component constraints matching + + Returns + ------- + self + + Raises + ------ + ~pyasn1.error.ValueConstraintError, ~pyasn1.error.PyAsn1Error + On constraint violation or bad initializer + IndexError + When idx > len(self) + """ + if isinstance(idx, slice): + indices = tuple(range(len(self))) + startIdx = indices and indices[idx][0] or 0 + for subIdx, subValue in enumerate(value): + self.setComponentByPosition( + startIdx + subIdx, subValue, verifyConstraints, + matchTags, matchConstraints) + return self + + if idx < 0: + idx = len(self) + idx + if idx < 0: + raise error.PyAsn1Error( + 'SequenceOf/SetOf index is out of range') + + componentType = self.componentType + + if self._componentValues is noValue: + componentValues = {} + + else: + componentValues = self._componentValues + + currentValue = componentValues.get(idx, noValue) + + if value is noValue: + if componentType is not None: + value = componentType.clone() + + elif currentValue is noValue: + raise error.PyAsn1Error('Component type not defined') + + elif not isinstance(value, base.Asn1Item): + if (componentType is not None and + isinstance(componentType, base.SimpleAsn1Type)): + value = componentType.clone(value=value) + + elif (currentValue is not noValue and + isinstance(currentValue, base.SimpleAsn1Type)): + value = currentValue.clone(value=value) + + else: + raise error.PyAsn1Error( + 'Non-ASN.1 value %r and undefined component' + ' type at %r' % (value, self)) + + elif componentType is not None and (matchTags or matchConstraints): + subtypeChecker = ( + self.strictConstraints and + componentType.isSameTypeWith or + componentType.isSuperTypeOf) + + if not subtypeChecker(value, verifyConstraints and matchTags, + verifyConstraints and matchConstraints): + # TODO: we should wrap componentType with UnnamedType to carry + # additional properties associated with componentType + if componentType.typeId != Any.typeId: + raise error.PyAsn1Error( + 'Component value is tag-incompatible: %r vs ' + '%r' % (value, componentType)) + + componentValues[idx] = value + + self._componentValues = componentValues + + return self + + @property + def componentTagMap(self): + if self.componentType is not None: + return self.componentType.tagMap + + @property + def components(self): + return [self._componentValues[idx] + for idx in sorted(self._componentValues)] + + def clear(self): + """Remove all components and become an empty |ASN.1| value object. + + Has the same effect on |ASN.1| object as it does on :class:`list` + built-in. + """ + self._componentValues = {} + return self + + def reset(self): + """Remove all components and become a |ASN.1| schema object. + + See :meth:`isValue` property for more information on the + distinction between value and schema objects. + """ + self._componentValues = noValue + return self + + def prettyPrint(self, scope=0): + scope += 1 + representation = self.__class__.__name__ + ':\n' + + if not self.isValue: + return representation + + for idx, componentValue in enumerate(self): + representation += ' ' * scope + if (componentValue is noValue and + self.componentType is not None): + representation += '<empty>' + else: + representation += componentValue.prettyPrint(scope) + + return representation + + def prettyPrintType(self, scope=0): + scope += 1 + representation = '%s -> %s {\n' % (self.tagSet, self.__class__.__name__) + if self.componentType is not None: + representation += ' ' * scope + representation += self.componentType.prettyPrintType(scope) + return representation + '\n' + ' ' * (scope - 1) + '}' + + + @property + def isValue(self): + """Indicate that |ASN.1| object represents ASN.1 value. + + If *isValue* is :obj:`False` then this object represents just ASN.1 schema. + + If *isValue* is :obj:`True` then, in addition to its ASN.1 schema features, + this object can also be used like a Python built-in object + (e.g. :class:`int`, :class:`str`, :class:`dict` etc.). + + Returns + ------- + : :class:`bool` + :obj:`False` if object represents just ASN.1 schema. + :obj:`True` if object represents ASN.1 schema and can be used as a normal value. + + Note + ---- + There is an important distinction between PyASN1 schema and value objects. + The PyASN1 schema objects can only participate in ASN.1 schema-related + operations (e.g. defining or testing the structure of the data). Most + obvious uses of ASN.1 schema is to guide serialisation codecs whilst + encoding/decoding serialised ASN.1 contents. + + The PyASN1 value objects can **additionally** participate in many operations + involving regular Python objects (e.g. arithmetic, comprehension etc). + """ + if self._componentValues is noValue: + return False + + if len(self._componentValues) != len(self): + return False + + for componentValue in self._componentValues.values(): + if componentValue is noValue or not componentValue.isValue: + return False + + return True + + @property + def isInconsistent(self): + """Run necessary checks to ensure |ASN.1| object consistency. + + Default action is to verify |ASN.1| object against constraints imposed + by `subtypeSpec`. + + Raises + ------ + :py:class:`~pyasn1.error.PyAsn1tError` on any inconsistencies found + """ + if self.componentType is noValue or not self.subtypeSpec: + return False + + if self._componentValues is noValue: + return True + + mapping = {} + + for idx, value in self._componentValues.items(): + # Absent fields are not in the mapping + if value is noValue: + continue + + mapping[idx] = value + + try: + # Represent SequenceOf/SetOf as a bare dict to constraints chain + self.subtypeSpec(mapping) + + except error.PyAsn1Error: + exc = sys.exc_info()[1] + return exc + + return False + +class SequenceOf(SequenceOfAndSetOfBase): + __doc__ = SequenceOfAndSetOfBase.__doc__ + + #: Set (on class, not on instance) or return a + #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s) + #: associated with |ASN.1| type. + tagSet = tag.initTagSet( + tag.Tag(tag.tagClassUniversal, tag.tagFormatConstructed, 0x10) + ) + + #: Default :py:class:`~pyasn1.type.base.PyAsn1Item` derivative + #: object representing ASN.1 type allowed within |ASN.1| type + componentType = None + + #: Set (on class, not on instance) or return a + #: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` object + #: imposing constraints on |ASN.1| type initialization values. + subtypeSpec = constraint.ConstraintsIntersection() + + # Disambiguation ASN.1 types identification + typeId = SequenceOfAndSetOfBase.getTypeId() + + +class SetOf(SequenceOfAndSetOfBase): + __doc__ = SequenceOfAndSetOfBase.__doc__ + + #: Set (on class, not on instance) or return a + #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s) + #: associated with |ASN.1| type. + tagSet = tag.initTagSet( + tag.Tag(tag.tagClassUniversal, tag.tagFormatConstructed, 0x11) + ) + + #: Default :py:class:`~pyasn1.type.base.PyAsn1Item` derivative + #: object representing ASN.1 type allowed within |ASN.1| type + componentType = None + + #: Set (on class, not on instance) or return a + #: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` object + #: imposing constraints on |ASN.1| type initialization values. + subtypeSpec = constraint.ConstraintsIntersection() + + # Disambiguation ASN.1 types identification + typeId = SequenceOfAndSetOfBase.getTypeId() + + +class SequenceAndSetBase(base.ConstructedAsn1Type): + """Create |ASN.1| schema or value object. + + |ASN.1| class is based on :class:`~pyasn1.type.base.ConstructedAsn1Type`, + its objects are mutable and duck-type Python :class:`dict` objects. + + Keyword Args + ------------ + componentType: :py:class:`~pyasn1.type.namedtype.NamedType` + Object holding named ASN.1 types allowed within this collection + + tagSet: :py:class:`~pyasn1.type.tag.TagSet` + Object representing non-default ASN.1 tag(s) + + subtypeSpec: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` + Object representing non-default ASN.1 subtype constraint(s). Constraints + verification for |ASN.1| type can only occur on explicit + `.isInconsistent` call. + + Examples + -------- + + .. code-block:: python + + class Description(Sequence): # Set is similar + ''' + ASN.1 specification: + + Description ::= SEQUENCE { + surname IA5String, + first-name IA5String OPTIONAL, + age INTEGER DEFAULT 40 + } + ''' + componentType = NamedTypes( + NamedType('surname', IA5String()), + OptionalNamedType('first-name', IA5String()), + DefaultedNamedType('age', Integer(40)) + ) + + descr = Description() + descr['surname'] = 'Smith' + descr['first-name'] = 'John' + """ + #: Default :py:class:`~pyasn1.type.namedtype.NamedTypes` + #: object representing named ASN.1 types allowed within |ASN.1| type + componentType = namedtype.NamedTypes() + + + class DynamicNames(object): + """Fields names/positions mapping for component-less objects""" + def __init__(self): + self._keyToIdxMap = {} + self._idxToKeyMap = {} + + def __len__(self): + return len(self._keyToIdxMap) + + def __contains__(self, item): + return item in self._keyToIdxMap or item in self._idxToKeyMap + + def __iter__(self): + return (self._idxToKeyMap[idx] for idx in range(len(self._idxToKeyMap))) + + def __getitem__(self, item): + try: + return self._keyToIdxMap[item] + + except KeyError: + return self._idxToKeyMap[item] + + def getNameByPosition(self, idx): + try: + return self._idxToKeyMap[idx] + + except KeyError: + raise error.PyAsn1Error('Type position out of range') + + def getPositionByName(self, name): + try: + return self._keyToIdxMap[name] + + except KeyError: + raise error.PyAsn1Error('Name %s not found' % (name,)) + + def addField(self, idx): + self._keyToIdxMap['field-%d' % idx] = idx + self._idxToKeyMap[idx] = 'field-%d' % idx + + + def __init__(self, **kwargs): + base.ConstructedAsn1Type.__init__(self, **kwargs) + self._componentTypeLen = len(self.componentType) + if self._componentTypeLen: + self._componentValues = [] + else: + self._componentValues = noValue + self._dynamicNames = self._componentTypeLen or self.DynamicNames() + + def __getitem__(self, idx): + if octets.isStringType(idx): + try: + return self.getComponentByName(idx) + + except error.PyAsn1Error: + # duck-typing dict + raise KeyError(sys.exc_info()[1]) + + else: + try: + return self.getComponentByPosition(idx) + + except error.PyAsn1Error: + # duck-typing list + raise IndexError(sys.exc_info()[1]) + + def __setitem__(self, idx, value): + if octets.isStringType(idx): + try: + self.setComponentByName(idx, value) + + except error.PyAsn1Error: + # duck-typing dict + raise KeyError(sys.exc_info()[1]) + + else: + try: + self.setComponentByPosition(idx, value) + + except error.PyAsn1Error: + # duck-typing list + raise IndexError(sys.exc_info()[1]) + + def __contains__(self, key): + if self._componentTypeLen: + return key in self.componentType + else: + return key in self._dynamicNames + + def __len__(self): + return len(self._componentValues) + + def __iter__(self): + return iter(self.componentType or self._dynamicNames) + + # Python dict protocol + + def values(self): + for idx in range(self._componentTypeLen or len(self._dynamicNames)): + yield self[idx] + + def keys(self): + return iter(self) + + def items(self): + for idx in range(self._componentTypeLen or len(self._dynamicNames)): + if self._componentTypeLen: + yield self.componentType[idx].name, self[idx] + else: + yield self._dynamicNames[idx], self[idx] + + def update(self, *iterValue, **mappingValue): + for k, v in iterValue: + self[k] = v + for k in mappingValue: + self[k] = mappingValue[k] + + def clear(self): + """Remove all components and become an empty |ASN.1| value object. + + Has the same effect on |ASN.1| object as it does on :class:`dict` + built-in. + """ + self._componentValues = [] + self._dynamicNames = self.DynamicNames() + return self + + def reset(self): + """Remove all components and become a |ASN.1| schema object. + + See :meth:`isValue` property for more information on the + distinction between value and schema objects. + """ + self._componentValues = noValue + self._dynamicNames = self.DynamicNames() + return self + + @property + def components(self): + return self._componentValues + + def _cloneComponentValues(self, myClone, cloneValueFlag): + if self._componentValues is noValue: + return + + for idx, componentValue in enumerate(self._componentValues): + if componentValue is not noValue: + if isinstance(componentValue, base.ConstructedAsn1Type): + myClone.setComponentByPosition( + idx, componentValue.clone(cloneValueFlag=cloneValueFlag) + ) + else: + myClone.setComponentByPosition(idx, componentValue.clone()) + + def getComponentByName(self, name, default=noValue, instantiate=True): + """Returns |ASN.1| type component by name. + + Equivalent to Python :class:`dict` subscription operation (e.g. `[]`). + + Parameters + ---------- + name: :class:`str` + |ASN.1| type component name + + Keyword Args + ------------ + default: :class:`object` + If set and requested component is a schema object, return the `default` + object instead of the requested component. + + instantiate: :class:`bool` + If :obj:`True` (default), inner component will be automatically + instantiated. + If :obj:`False` either existing component or the :class:`NoValue` + object will be returned. + + Returns + ------- + : :py:class:`~pyasn1.type.base.PyAsn1Item` + Instantiate |ASN.1| component type or return existing + component value + """ + if self._componentTypeLen: + idx = self.componentType.getPositionByName(name) + else: + try: + idx = self._dynamicNames.getPositionByName(name) + + except KeyError: + raise error.PyAsn1Error('Name %s not found' % (name,)) + + return self.getComponentByPosition(idx, default=default, instantiate=instantiate) + + def setComponentByName(self, name, value=noValue, + verifyConstraints=True, + matchTags=True, + matchConstraints=True): + """Assign |ASN.1| type component by name. + + Equivalent to Python :class:`dict` item assignment operation (e.g. `[]`). + + Parameters + ---------- + name: :class:`str` + |ASN.1| type component name + + Keyword Args + ------------ + value: :class:`object` or :py:class:`~pyasn1.type.base.PyAsn1Item` derivative + A Python value to initialize |ASN.1| component with (if *componentType* is set) + or ASN.1 value object to assign to |ASN.1| component. + If `value` is not given, schema object will be set as a component. + + verifyConstraints: :class:`bool` + If :obj:`False`, skip constraints validation + + matchTags: :class:`bool` + If :obj:`False`, skip component tags matching + + matchConstraints: :class:`bool` + If :obj:`False`, skip component constraints matching + + Returns + ------- + self + """ + if self._componentTypeLen: + idx = self.componentType.getPositionByName(name) + else: + try: + idx = self._dynamicNames.getPositionByName(name) + + except KeyError: + raise error.PyAsn1Error('Name %s not found' % (name,)) + + return self.setComponentByPosition( + idx, value, verifyConstraints, matchTags, matchConstraints + ) + + def getComponentByPosition(self, idx, default=noValue, instantiate=True): + """Returns |ASN.1| type component by index. + + Equivalent to Python sequence subscription operation (e.g. `[]`). + + Parameters + ---------- + idx: :class:`int` + Component index (zero-based). Must either refer to an existing + component or (if *componentType* is set) new ASN.1 schema object gets + instantiated. + + Keyword Args + ------------ + default: :class:`object` + If set and requested component is a schema object, return the `default` + object instead of the requested component. + + instantiate: :class:`bool` + If :obj:`True` (default), inner component will be automatically + instantiated. + If :obj:`False` either existing component or the :class:`NoValue` + object will be returned. + + Returns + ------- + : :py:class:`~pyasn1.type.base.PyAsn1Item` + a PyASN1 object + + Examples + -------- + + .. code-block:: python + + # can also be Set + class MySequence(Sequence): + componentType = NamedTypes( + NamedType('id', OctetString()) + ) + + s = MySequence() + + # returns component #0 with `.isValue` property False + s.getComponentByPosition(0) + + # returns None + s.getComponentByPosition(0, default=None) + + s.clear() + + # returns noValue + s.getComponentByPosition(0, instantiate=False) + + # sets component #0 to OctetString() ASN.1 schema + # object and returns it + s.getComponentByPosition(0, instantiate=True) + + # sets component #0 to ASN.1 value object + s.setComponentByPosition(0, 'ABCD') + + # returns OctetString('ABCD') value object + s.getComponentByPosition(0, instantiate=False) + + s.clear() + + # returns noValue + s.getComponentByPosition(0, instantiate=False) + """ + try: + if self._componentValues is noValue: + componentValue = noValue + + else: + componentValue = self._componentValues[idx] + + except IndexError: + componentValue = noValue + + if not instantiate: + if componentValue is noValue or not componentValue.isValue: + return default + else: + return componentValue + + if componentValue is noValue: + self.setComponentByPosition(idx) + + componentValue = self._componentValues[idx] + + if default is noValue or componentValue.isValue: + return componentValue + else: + return default + + def setComponentByPosition(self, idx, value=noValue, + verifyConstraints=True, + matchTags=True, + matchConstraints=True): + """Assign |ASN.1| type component by position. + + Equivalent to Python sequence item assignment operation (e.g. `[]`). + + Parameters + ---------- + idx : :class:`int` + Component index (zero-based). Must either refer to existing + component (if *componentType* is set) or to N+1 component + otherwise. In the latter case a new component of given ASN.1 + type gets instantiated and appended to |ASN.1| sequence. + + Keyword Args + ------------ + value: :class:`object` or :py:class:`~pyasn1.type.base.PyAsn1Item` derivative + A Python value to initialize |ASN.1| component with (if *componentType* is set) + or ASN.1 value object to assign to |ASN.1| component. + If `value` is not given, schema object will be set as a component. + + verifyConstraints : :class:`bool` + If :obj:`False`, skip constraints validation + + matchTags: :class:`bool` + If :obj:`False`, skip component tags matching + + matchConstraints: :class:`bool` + If :obj:`False`, skip component constraints matching + + Returns + ------- + self + """ + componentType = self.componentType + componentTypeLen = self._componentTypeLen + + if self._componentValues is noValue: + componentValues = [] + + else: + componentValues = self._componentValues + + try: + currentValue = componentValues[idx] + + except IndexError: + currentValue = noValue + if componentTypeLen: + if componentTypeLen < idx: + raise error.PyAsn1Error('component index out of range') + + componentValues = [noValue] * componentTypeLen + + if value is noValue: + if componentTypeLen: + value = componentType.getTypeByPosition(idx) + if isinstance(value, base.ConstructedAsn1Type): + value = value.clone(cloneValueFlag=componentType[idx].isDefaulted) + + elif currentValue is noValue: + raise error.PyAsn1Error('Component type not defined') + + elif not isinstance(value, base.Asn1Item): + if componentTypeLen: + subComponentType = componentType.getTypeByPosition(idx) + if isinstance(subComponentType, base.SimpleAsn1Type): + value = subComponentType.clone(value=value) + + else: + raise error.PyAsn1Error('%s can cast only scalar values' % componentType.__class__.__name__) + + elif currentValue is not noValue and isinstance(currentValue, base.SimpleAsn1Type): + value = currentValue.clone(value=value) + + else: + raise error.PyAsn1Error('%s undefined component type' % componentType.__class__.__name__) + + elif ((verifyConstraints or matchTags or matchConstraints) and + componentTypeLen): + subComponentType = componentType.getTypeByPosition(idx) + if subComponentType is not noValue: + subtypeChecker = (self.strictConstraints and + subComponentType.isSameTypeWith or + subComponentType.isSuperTypeOf) + + if not subtypeChecker(value, verifyConstraints and matchTags, + verifyConstraints and matchConstraints): + if not componentType[idx].openType: + raise error.PyAsn1Error('Component value is tag-incompatible: %r vs %r' % (value, componentType)) + + if componentTypeLen or idx in self._dynamicNames: + componentValues[idx] = value + + elif len(componentValues) == idx: + componentValues.append(value) + self._dynamicNames.addField(idx) + + else: + raise error.PyAsn1Error('Component index out of range') + + self._componentValues = componentValues + + return self + + @property + def isValue(self): + """Indicate that |ASN.1| object represents ASN.1 value. + + If *isValue* is :obj:`False` then this object represents just ASN.1 schema. + + If *isValue* is :obj:`True` then, in addition to its ASN.1 schema features, + this object can also be used like a Python built-in object (e.g. + :class:`int`, :class:`str`, :class:`dict` etc.). + + Returns + ------- + : :class:`bool` + :obj:`False` if object represents just ASN.1 schema. + :obj:`True` if object represents ASN.1 schema and can be used as a + normal value. + + Note + ---- + There is an important distinction between PyASN1 schema and value objects. + The PyASN1 schema objects can only participate in ASN.1 schema-related + operations (e.g. defining or testing the structure of the data). Most + obvious uses of ASN.1 schema is to guide serialisation codecs whilst + encoding/decoding serialised ASN.1 contents. + + The PyASN1 value objects can **additionally** participate in many operations + involving regular Python objects (e.g. arithmetic, comprehension etc). + + It is sufficient for |ASN.1| objects to have all non-optional and non-defaulted + components being value objects to be considered as a value objects as a whole. + In other words, even having one or more optional components not turned into + value objects, |ASN.1| object is still considered as a value object. Defaulted + components are normally value objects by default. + """ + if self._componentValues is noValue: + return False + + componentType = self.componentType + + if componentType: + for idx, subComponentType in enumerate(componentType.namedTypes): + if subComponentType.isDefaulted or subComponentType.isOptional: + continue + + if not self._componentValues: + return False + + componentValue = self._componentValues[idx] + if componentValue is noValue or not componentValue.isValue: + return False + + else: + for componentValue in self._componentValues: + if componentValue is noValue or not componentValue.isValue: + return False + + return True + + @property + def isInconsistent(self): + """Run necessary checks to ensure |ASN.1| object consistency. + + Default action is to verify |ASN.1| object against constraints imposed + by `subtypeSpec`. + + Raises + ------ + :py:class:`~pyasn1.error.PyAsn1tError` on any inconsistencies found + """ + if self.componentType is noValue or not self.subtypeSpec: + return False + + if self._componentValues is noValue: + return True + + mapping = {} + + for idx, value in enumerate(self._componentValues): + # Absent fields are not in the mapping + if value is noValue: + continue + + name = self.componentType.getNameByPosition(idx) + + mapping[name] = value + + try: + # Represent Sequence/Set as a bare dict to constraints chain + self.subtypeSpec(mapping) + + except error.PyAsn1Error: + exc = sys.exc_info()[1] + return exc + + return False + + def prettyPrint(self, scope=0): + """Return an object representation string. + + Returns + ------- + : :class:`str` + Human-friendly object representation. + """ + scope += 1 + representation = self.__class__.__name__ + ':\n' + for idx, componentValue in enumerate(self._componentValues): + if componentValue is not noValue and componentValue.isValue: + representation += ' ' * scope + if self.componentType: + representation += self.componentType.getNameByPosition(idx) + else: + representation += self._dynamicNames.getNameByPosition(idx) + representation = '%s=%s\n' % ( + representation, componentValue.prettyPrint(scope) + ) + return representation + + def prettyPrintType(self, scope=0): + scope += 1 + representation = '%s -> %s {\n' % (self.tagSet, self.__class__.__name__) + for idx, componentType in enumerate(self.componentType.values() or self._componentValues): + representation += ' ' * scope + if self.componentType: + representation += '"%s"' % self.componentType.getNameByPosition(idx) + else: + representation += '"%s"' % self._dynamicNames.getNameByPosition(idx) + representation = '%s = %s\n' % ( + representation, componentType.prettyPrintType(scope) + ) + return representation + '\n' + ' ' * (scope - 1) + '}' + + # backward compatibility + + def setDefaultComponents(self): + return self + + def getComponentType(self): + if self._componentTypeLen: + return self.componentType + + def getNameByPosition(self, idx): + if self._componentTypeLen: + return self.componentType[idx].name + +class Sequence(SequenceAndSetBase): + __doc__ = SequenceAndSetBase.__doc__ + + #: Set (on class, not on instance) or return a + #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s) + #: associated with |ASN.1| type. + tagSet = tag.initTagSet( + tag.Tag(tag.tagClassUniversal, tag.tagFormatConstructed, 0x10) + ) + + #: Set (on class, not on instance) or return a + #: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` object + #: imposing constraints on |ASN.1| type initialization values. + subtypeSpec = constraint.ConstraintsIntersection() + + #: Default collection of ASN.1 types of component (e.g. :py:class:`~pyasn1.type.namedtype.NamedType`) + #: object imposing size constraint on |ASN.1| objects + componentType = namedtype.NamedTypes() + + # Disambiguation ASN.1 types identification + typeId = SequenceAndSetBase.getTypeId() + + # backward compatibility + + def getComponentTagMapNearPosition(self, idx): + if self.componentType: + return self.componentType.getTagMapNearPosition(idx) + + def getComponentPositionNearType(self, tagSet, idx): + if self.componentType: + return self.componentType.getPositionNearType(tagSet, idx) + else: + return idx + + +class Set(SequenceAndSetBase): + __doc__ = SequenceAndSetBase.__doc__ + + #: Set (on class, not on instance) or return a + #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s) + #: associated with |ASN.1| type. + tagSet = tag.initTagSet( + tag.Tag(tag.tagClassUniversal, tag.tagFormatConstructed, 0x11) + ) + + #: Default collection of ASN.1 types of component (e.g. :py:class:`~pyasn1.type.namedtype.NamedType`) + #: object representing ASN.1 type allowed within |ASN.1| type + componentType = namedtype.NamedTypes() + + #: Set (on class, not on instance) or return a + #: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` object + #: imposing constraints on |ASN.1| type initialization values. + subtypeSpec = constraint.ConstraintsIntersection() + + # Disambiguation ASN.1 types identification + typeId = SequenceAndSetBase.getTypeId() + + def getComponent(self, innerFlag=False): + return self + + def getComponentByType(self, tagSet, default=noValue, + instantiate=True, innerFlag=False): + """Returns |ASN.1| type component by ASN.1 tag. + + Parameters + ---------- + tagSet : :py:class:`~pyasn1.type.tag.TagSet` + Object representing ASN.1 tags to identify one of + |ASN.1| object component + + Keyword Args + ------------ + default: :class:`object` + If set and requested component is a schema object, return the `default` + object instead of the requested component. + + instantiate: :class:`bool` + If :obj:`True` (default), inner component will be automatically + instantiated. + If :obj:`False` either existing component or the :class:`noValue` + object will be returned. + + Returns + ------- + : :py:class:`~pyasn1.type.base.PyAsn1Item` + a pyasn1 object + """ + componentValue = self.getComponentByPosition( + self.componentType.getPositionByType(tagSet), + default=default, instantiate=instantiate + ) + if innerFlag and isinstance(componentValue, Set): + # get inner component by inner tagSet + return componentValue.getComponent(innerFlag=True) + else: + # get outer component by inner tagSet + return componentValue + + def setComponentByType(self, tagSet, value=noValue, + verifyConstraints=True, + matchTags=True, + matchConstraints=True, + innerFlag=False): + """Assign |ASN.1| type component by ASN.1 tag. + + Parameters + ---------- + tagSet : :py:class:`~pyasn1.type.tag.TagSet` + Object representing ASN.1 tags to identify one of + |ASN.1| object component + + Keyword Args + ------------ + value: :class:`object` or :py:class:`~pyasn1.type.base.PyAsn1Item` derivative + A Python value to initialize |ASN.1| component with (if *componentType* is set) + or ASN.1 value object to assign to |ASN.1| component. + If `value` is not given, schema object will be set as a component. + + verifyConstraints : :class:`bool` + If :obj:`False`, skip constraints validation + + matchTags: :class:`bool` + If :obj:`False`, skip component tags matching + + matchConstraints: :class:`bool` + If :obj:`False`, skip component constraints matching + + innerFlag: :class:`bool` + If :obj:`True`, search for matching *tagSet* recursively. + + Returns + ------- + self + """ + idx = self.componentType.getPositionByType(tagSet) + + if innerFlag: # set inner component by inner tagSet + componentType = self.componentType.getTypeByPosition(idx) + + if componentType.tagSet: + return self.setComponentByPosition( + idx, value, verifyConstraints, matchTags, matchConstraints + ) + else: + componentType = self.getComponentByPosition(idx) + return componentType.setComponentByType( + tagSet, value, verifyConstraints, matchTags, matchConstraints, innerFlag=innerFlag + ) + else: # set outer component by inner tagSet + return self.setComponentByPosition( + idx, value, verifyConstraints, matchTags, matchConstraints + ) + + @property + def componentTagMap(self): + if self.componentType: + return self.componentType.tagMapUnique + + +class Choice(Set): + """Create |ASN.1| schema or value object. + + |ASN.1| class is based on :class:`~pyasn1.type.base.ConstructedAsn1Type`, + its objects are mutable and duck-type Python :class:`list` objects. + + Keyword Args + ------------ + componentType: :py:class:`~pyasn1.type.namedtype.NamedType` + Object holding named ASN.1 types allowed within this collection + + tagSet: :py:class:`~pyasn1.type.tag.TagSet` + Object representing non-default ASN.1 tag(s) + + subtypeSpec: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` + Object representing non-default ASN.1 subtype constraint(s). Constraints + verification for |ASN.1| type can only occur on explicit + `.isInconsistent` call. + + Examples + -------- + + .. code-block:: python + + class Afters(Choice): + ''' + ASN.1 specification: + + Afters ::= CHOICE { + cheese [0] IA5String, + dessert [1] IA5String + } + ''' + componentType = NamedTypes( + NamedType('cheese', IA5String().subtype( + implicitTag=Tag(tagClassContext, tagFormatSimple, 0) + ), + NamedType('dessert', IA5String().subtype( + implicitTag=Tag(tagClassContext, tagFormatSimple, 1) + ) + ) + + afters = Afters() + afters['cheese'] = 'Mascarpone' + """ + #: Set (on class, not on instance) or return a + #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s) + #: associated with |ASN.1| type. + tagSet = tag.TagSet() # untagged + + #: Default collection of ASN.1 types of component (e.g. :py:class:`~pyasn1.type.namedtype.NamedType`) + #: object representing ASN.1 type allowed within |ASN.1| type + componentType = namedtype.NamedTypes() + + #: Set (on class, not on instance) or return a + #: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` object + #: imposing constraints on |ASN.1| type initialization values. + subtypeSpec = constraint.ConstraintsIntersection( + constraint.ValueSizeConstraint(1, 1) + ) + + # Disambiguation ASN.1 types identification + typeId = Set.getTypeId() + + _currentIdx = None + + def __eq__(self, other): + if self._componentValues: + return self._componentValues[self._currentIdx] == other + return NotImplemented + + def __ne__(self, other): + if self._componentValues: + return self._componentValues[self._currentIdx] != other + return NotImplemented + + def __lt__(self, other): + if self._componentValues: + return self._componentValues[self._currentIdx] < other + return NotImplemented + + def __le__(self, other): + if self._componentValues: + return self._componentValues[self._currentIdx] <= other + return NotImplemented + + def __gt__(self, other): + if self._componentValues: + return self._componentValues[self._currentIdx] > other + return NotImplemented + + def __ge__(self, other): + if self._componentValues: + return self._componentValues[self._currentIdx] >= other + return NotImplemented + + if sys.version_info[0] <= 2: + def __nonzero__(self): + return self._componentValues and True or False + else: + def __bool__(self): + return self._componentValues and True or False + + def __len__(self): + return self._currentIdx is not None and 1 or 0 + + def __contains__(self, key): + if self._currentIdx is None: + return False + return key == self.componentType[self._currentIdx].getName() + + def __iter__(self): + if self._currentIdx is None: + raise StopIteration + yield self.componentType[self._currentIdx].getName() + + # Python dict protocol + + def values(self): + if self._currentIdx is not None: + yield self._componentValues[self._currentIdx] + + def keys(self): + if self._currentIdx is not None: + yield self.componentType[self._currentIdx].getName() + + def items(self): + if self._currentIdx is not None: + yield self.componentType[self._currentIdx].getName(), self[self._currentIdx] + + def checkConsistency(self): + if self._currentIdx is None: + raise error.PyAsn1Error('Component not chosen') + + def _cloneComponentValues(self, myClone, cloneValueFlag): + try: + component = self.getComponent() + except error.PyAsn1Error: + pass + else: + if isinstance(component, Choice): + tagSet = component.effectiveTagSet + else: + tagSet = component.tagSet + if isinstance(component, base.ConstructedAsn1Type): + myClone.setComponentByType( + tagSet, component.clone(cloneValueFlag=cloneValueFlag) + ) + else: + myClone.setComponentByType(tagSet, component.clone()) + + def getComponentByPosition(self, idx, default=noValue, instantiate=True): + __doc__ = Set.__doc__ + + if self._currentIdx is None or self._currentIdx != idx: + return Set.getComponentByPosition(self, idx, default=default, + instantiate=instantiate) + + return self._componentValues[idx] + + def setComponentByPosition(self, idx, value=noValue, + verifyConstraints=True, + matchTags=True, + matchConstraints=True): + """Assign |ASN.1| type component by position. + + Equivalent to Python sequence item assignment operation (e.g. `[]`). + + Parameters + ---------- + idx: :class:`int` + Component index (zero-based). Must either refer to existing + component or to N+1 component. In the latter case a new component + type gets instantiated (if *componentType* is set, or given ASN.1 + object is taken otherwise) and appended to the |ASN.1| sequence. + + Keyword Args + ------------ + value: :class:`object` or :py:class:`~pyasn1.type.base.PyAsn1Item` derivative + A Python value to initialize |ASN.1| component with (if *componentType* is set) + or ASN.1 value object to assign to |ASN.1| component. Once a new value is + set to *idx* component, previous value is dropped. + If `value` is not given, schema object will be set as a component. + + verifyConstraints : :class:`bool` + If :obj:`False`, skip constraints validation + + matchTags: :class:`bool` + If :obj:`False`, skip component tags matching + + matchConstraints: :class:`bool` + If :obj:`False`, skip component constraints matching + + Returns + ------- + self + """ + oldIdx = self._currentIdx + Set.setComponentByPosition(self, idx, value, verifyConstraints, matchTags, matchConstraints) + self._currentIdx = idx + if oldIdx is not None and oldIdx != idx: + self._componentValues[oldIdx] = noValue + return self + + @property + def effectiveTagSet(self): + """Return a :class:`~pyasn1.type.tag.TagSet` object of the currently initialized component or self (if |ASN.1| is tagged).""" + if self.tagSet: + return self.tagSet + else: + component = self.getComponent() + return component.effectiveTagSet + + @property + def tagMap(self): + """"Return a :class:`~pyasn1.type.tagmap.TagMap` object mapping + ASN.1 tags to ASN.1 objects contained within callee. + """ + if self.tagSet: + return Set.tagMap.fget(self) + else: + return self.componentType.tagMapUnique + + def getComponent(self, innerFlag=False): + """Return currently assigned component of the |ASN.1| object. + + Returns + ------- + : :py:class:`~pyasn1.type.base.PyAsn1Item` + a PyASN1 object + """ + if self._currentIdx is None: + raise error.PyAsn1Error('Component not chosen') + else: + c = self._componentValues[self._currentIdx] + if innerFlag and isinstance(c, Choice): + return c.getComponent(innerFlag) + else: + return c + + def getName(self, innerFlag=False): + """Return the name of currently assigned component of the |ASN.1| object. + + Returns + ------- + : :py:class:`str` + |ASN.1| component name + """ + if self._currentIdx is None: + raise error.PyAsn1Error('Component not chosen') + else: + if innerFlag: + c = self._componentValues[self._currentIdx] + if isinstance(c, Choice): + return c.getName(innerFlag) + return self.componentType.getNameByPosition(self._currentIdx) + + @property + def isValue(self): + """Indicate that |ASN.1| object represents ASN.1 value. + + If *isValue* is :obj:`False` then this object represents just ASN.1 schema. + + If *isValue* is :obj:`True` then, in addition to its ASN.1 schema features, + this object can also be used like a Python built-in object (e.g. + :class:`int`, :class:`str`, :class:`dict` etc.). + + Returns + ------- + : :class:`bool` + :obj:`False` if object represents just ASN.1 schema. + :obj:`True` if object represents ASN.1 schema and can be used as a normal + value. + + Note + ---- + There is an important distinction between PyASN1 schema and value objects. + The PyASN1 schema objects can only participate in ASN.1 schema-related + operations (e.g. defining or testing the structure of the data). Most + obvious uses of ASN.1 schema is to guide serialisation codecs whilst + encoding/decoding serialised ASN.1 contents. + + The PyASN1 value objects can **additionally** participate in many operations + involving regular Python objects (e.g. arithmetic, comprehension etc). + """ + if self._currentIdx is None: + return False + + componentValue = self._componentValues[self._currentIdx] + + return componentValue is not noValue and componentValue.isValue + + def clear(self): + self._currentIdx = None + return Set.clear(self) + + # compatibility stubs + + def getMinTagSet(self): + return self.minTagSet + + +class Any(OctetString): + """Create |ASN.1| schema or value object. + + |ASN.1| class is based on :class:`~pyasn1.type.base.SimpleAsn1Type`, + its objects are immutable and duck-type Python 2 :class:`str` or Python 3 + :class:`bytes`. When used in Unicode context, |ASN.1| type assumes + "|encoding|" serialisation. + + Keyword Args + ------------ + value: :class:`unicode`, :class:`str`, :class:`bytes` or |ASN.1| object + :class:`str` (Python 2) or :class:`bytes` (Python 3), alternatively + :class:`unicode` object (Python 2) or :class:`str` (Python 3) + representing character string to be serialised into octets (note + `encoding` parameter) or |ASN.1| object. + If `value` is not given, schema object will be created. + + tagSet: :py:class:`~pyasn1.type.tag.TagSet` + Object representing non-default ASN.1 tag(s) + + subtypeSpec: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` + Object representing non-default ASN.1 subtype constraint(s). Constraints + verification for |ASN.1| type occurs automatically on object + instantiation. + + encoding: :py:class:`str` + Unicode codec ID to encode/decode :class:`unicode` (Python 2) or + :class:`str` (Python 3) the payload when |ASN.1| object is used + in text string context. + + binValue: :py:class:`str` + Binary string initializer to use instead of the *value*. + Example: '10110011'. + + hexValue: :py:class:`str` + Hexadecimal string initializer to use instead of the *value*. + Example: 'DEADBEEF'. + + Raises + ------ + ~pyasn1.error.ValueConstraintError, ~pyasn1.error.PyAsn1Error + On constraint violation or bad initializer. + + Examples + -------- + .. code-block:: python + + class Error(Sequence): + ''' + ASN.1 specification: + + Error ::= SEQUENCE { + code INTEGER, + parameter ANY DEFINED BY code -- Either INTEGER or REAL + } + ''' + componentType=NamedTypes( + NamedType('code', Integer()), + NamedType('parameter', Any(), + openType=OpenType('code', {1: Integer(), + 2: Real()})) + ) + + error = Error() + error['code'] = 1 + error['parameter'] = Integer(1234) + """ + #: Set (on class, not on instance) or return a + #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s) + #: associated with |ASN.1| type. + tagSet = tag.TagSet() # untagged + + #: Set (on class, not on instance) or return a + #: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` object + #: imposing constraints on |ASN.1| type initialization values. + subtypeSpec = constraint.ConstraintsIntersection() + + # Disambiguation ASN.1 types identification + typeId = OctetString.getTypeId() + + @property + def tagMap(self): + """"Return a :class:`~pyasn1.type.tagmap.TagMap` object mapping + ASN.1 tags to ASN.1 objects contained within callee. + """ + try: + return self._tagMap + + except AttributeError: + self._tagMap = tagmap.TagMap( + {self.tagSet: self}, + {eoo.endOfOctets.tagSet: eoo.endOfOctets}, + self + ) + + return self._tagMap + +# XXX +# coercion rules? diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/type/useful.py b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/type/useful.py new file mode 100644 index 00000000..7536b95c --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/pyasn1/type/useful.py @@ -0,0 +1,191 @@ +# +# This file is part of pyasn1 software. +# +# Copyright (c) 2005-2019, Ilya Etingof <etingof@gmail.com> +# License: http://snmplabs.com/pyasn1/license.html +# +import datetime + +from pyasn1 import error +from pyasn1.compat import dateandtime +from pyasn1.compat import string +from pyasn1.type import char +from pyasn1.type import tag +from pyasn1.type import univ + +__all__ = ['ObjectDescriptor', 'GeneralizedTime', 'UTCTime'] + +NoValue = univ.NoValue +noValue = univ.noValue + + +class ObjectDescriptor(char.GraphicString): + __doc__ = char.GraphicString.__doc__ + + #: Default :py:class:`~pyasn1.type.tag.TagSet` object for |ASN.1| objects + tagSet = char.GraphicString.tagSet.tagImplicitly( + tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 7) + ) + + # Optimization for faster codec lookup + typeId = char.GraphicString.getTypeId() + + +class TimeMixIn(object): + + _yearsDigits = 4 + _hasSubsecond = False + _optionalMinutes = False + _shortTZ = False + + class FixedOffset(datetime.tzinfo): + """Fixed offset in minutes east from UTC.""" + + # defaulted arguments required + # https: // docs.python.org / 2.3 / lib / datetime - tzinfo.html + def __init__(self, offset=0, name='UTC'): + self.__offset = datetime.timedelta(minutes=offset) + self.__name = name + + def utcoffset(self, dt): + return self.__offset + + def tzname(self, dt): + return self.__name + + def dst(self, dt): + return datetime.timedelta(0) + + UTC = FixedOffset() + + @property + def asDateTime(self): + """Create :py:class:`datetime.datetime` object from a |ASN.1| object. + + Returns + ------- + : + new instance of :py:class:`datetime.datetime` object + """ + text = str(self) + if text.endswith('Z'): + tzinfo = TimeMixIn.UTC + text = text[:-1] + + elif '-' in text or '+' in text: + if '+' in text: + text, plusminus, tz = string.partition(text, '+') + else: + text, plusminus, tz = string.partition(text, '-') + + if self._shortTZ and len(tz) == 2: + tz += '00' + + if len(tz) != 4: + raise error.PyAsn1Error('malformed time zone offset %s' % tz) + + try: + minutes = int(tz[:2]) * 60 + int(tz[2:]) + if plusminus == '-': + minutes *= -1 + + except ValueError: + raise error.PyAsn1Error('unknown time specification %s' % self) + + tzinfo = TimeMixIn.FixedOffset(minutes, '?') + + else: + tzinfo = None + + if '.' in text or ',' in text: + if '.' in text: + text, _, ms = string.partition(text, '.') + else: + text, _, ms = string.partition(text, ',') + + try: + ms = int(ms) * 1000 + + except ValueError: + raise error.PyAsn1Error('bad sub-second time specification %s' % self) + + else: + ms = 0 + + if self._optionalMinutes and len(text) - self._yearsDigits == 6: + text += '0000' + elif len(text) - self._yearsDigits == 8: + text += '00' + + try: + dt = dateandtime.strptime(text, self._yearsDigits == 4 and '%Y%m%d%H%M%S' or '%y%m%d%H%M%S') + + except ValueError: + raise error.PyAsn1Error('malformed datetime format %s' % self) + + return dt.replace(microsecond=ms, tzinfo=tzinfo) + + @classmethod + def fromDateTime(cls, dt): + """Create |ASN.1| object from a :py:class:`datetime.datetime` object. + + Parameters + ---------- + dt: :py:class:`datetime.datetime` object + The `datetime.datetime` object to initialize the |ASN.1| object + from + + Returns + ------- + : + new instance of |ASN.1| value + """ + text = dt.strftime(cls._yearsDigits == 4 and '%Y%m%d%H%M%S' or '%y%m%d%H%M%S') + if cls._hasSubsecond: + text += '.%d' % (dt.microsecond // 1000) + + if dt.utcoffset(): + seconds = dt.utcoffset().seconds + if seconds < 0: + text += '-' + else: + text += '+' + text += '%.2d%.2d' % (seconds // 3600, seconds % 3600) + else: + text += 'Z' + + return cls(text) + + +class GeneralizedTime(char.VisibleString, TimeMixIn): + __doc__ = char.VisibleString.__doc__ + + #: Default :py:class:`~pyasn1.type.tag.TagSet` object for |ASN.1| objects + tagSet = char.VisibleString.tagSet.tagImplicitly( + tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 24) + ) + + # Optimization for faster codec lookup + typeId = char.VideotexString.getTypeId() + + _yearsDigits = 4 + _hasSubsecond = True + _optionalMinutes = True + _shortTZ = True + + +class UTCTime(char.VisibleString, TimeMixIn): + __doc__ = char.VisibleString.__doc__ + + #: Default :py:class:`~pyasn1.type.tag.TagSet` object for |ASN.1| objects + tagSet = char.VisibleString.tagSet.tagImplicitly( + tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 23) + ) + + # Optimization for faster codec lookup + typeId = char.VideotexString.getTypeId() + + _yearsDigits = 2 + _hasSubsecond = False + _optionalMinutes = False + _shortTZ = False diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/setup.cfg b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/setup.cfg new file mode 100644 index 00000000..b998b2a0 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/setup.cfg @@ -0,0 +1,10 @@ +[bdist_wheel] +universal = 1 + +[metadata] +license_file = LICENSE.rst + +[egg_info] +tag_build = +tag_date = 0 + diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/setup.py b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/setup.py new file mode 100644 index 00000000..fa0a876e --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/setup.py @@ -0,0 +1,121 @@ +#!/usr/bin/env python +# +# This file is part of pyasn1 software. +# +# Copyright (c) 2005-2019, Ilya Etingof <etingof@gmail.com> +# License: http://snmplabs.com/pyasn1/license.html +# +import os +import sys + +classifiers = """\ +Development Status :: 5 - Production/Stable +Environment :: Console +Intended Audience :: Developers +Intended Audience :: Education +Intended Audience :: Information Technology +Intended Audience :: System Administrators +Intended Audience :: Telecommunications Industry +License :: OSI Approved :: BSD License +Natural Language :: English +Operating System :: OS Independent +Programming Language :: Python :: 2 +Programming Language :: Python :: 2.4 +Programming Language :: Python :: 2.5 +Programming Language :: Python :: 2.6 +Programming Language :: Python :: 2.7 +Programming Language :: Python :: 3 +Programming Language :: Python :: 3.2 +Programming Language :: Python :: 3.3 +Programming Language :: Python :: 3.4 +Programming Language :: Python :: 3.5 +Programming Language :: Python :: 3.6 +Programming Language :: Python :: 3.7 +Topic :: Communications +Topic :: Software Development :: Libraries :: Python Modules +""" + + +def howto_install_setuptools(): + print(""" + Error: You need setuptools Python package! + + It's very easy to install it, just type: + + wget https://bootstrap.pypa.io/ez_setup.py + python ez_setup.py + + Then you could make eggs from this package. +""") + + +if sys.version_info[:2] < (2, 4): + print("ERROR: this package requires Python 2.4 or later!") + sys.exit(1) + +try: + from setuptools import setup, Command + + params = { + 'zip_safe': True + } + +except ImportError: + for arg in sys.argv: + if 'egg' in arg: + howto_install_setuptools() + sys.exit(1) + from distutils.core import setup, Command + + params = {} + +params.update({ + 'name': 'pyasn1', + 'version': open(os.path.join('pyasn1', '__init__.py')).read().split('\'')[1], + 'description': 'ASN.1 types and codecs', + 'long_description': 'Pure-Python implementation of ASN.1 types and DER/BER/CER codecs (X.208)', + 'maintainer': 'Ilya Etingof <etingof@gmail.com>', + 'author': 'Ilya Etingof', + 'author_email': 'etingof@gmail.com', + 'url': 'https://github.com/etingof/pyasn1', + 'platforms': ['any'], + 'classifiers': [x for x in classifiers.split('\n') if x], + 'license': 'BSD', + 'packages': ['pyasn1', + 'pyasn1.type', + 'pyasn1.compat', + 'pyasn1.codec', + 'pyasn1.codec.ber', + 'pyasn1.codec.cer', + 'pyasn1.codec.der', + 'pyasn1.codec.native']}) + +# handle unittest discovery feature +try: + import unittest2 as unittest +except ImportError: + import unittest + + +class PyTest(Command): + user_options = [] + + def initialize_options(self): + pass + + def finalize_options(self): + pass + + def run(self): + suite = unittest.TestLoader().loadTestsFromNames( + ['tests.__main__.suite'] + ) + + unittest.TextTestRunner(verbosity=2).run(suite) + +params['cmdclass'] = { + 'test': PyTest, + 'tests': PyTest, +} + +setup(**params) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/tests/__init__.py b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/tests/__init__.py new file mode 100644 index 00000000..8c3066b2 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/tests/__init__.py @@ -0,0 +1 @@ +# This file is necessary to make this directory a package. diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/tests/__main__.py b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/tests/__main__.py new file mode 100644 index 00000000..14ef28aa --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/tests/__main__.py @@ -0,0 +1,22 @@ +# +# This file is part of pyasn1 software. +# +# Copyright (c) 2005-2019, Ilya Etingof <etingof@gmail.com> +# License: http://snmplabs.com/pyasn1/license.html +# +try: + import unittest2 as unittest + +except ImportError: + import unittest + +suite = unittest.TestLoader().loadTestsFromNames( + ['tests.test_debug.suite', + 'tests.type.__main__.suite', + 'tests.codec.__main__.suite', + 'tests.compat.__main__.suite'] +) + + +if __name__ == '__main__': + unittest.TextTestRunner(verbosity=2).run(suite) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/tests/base.py b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/tests/base.py new file mode 100644 index 00000000..07f06dc3 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/tests/base.py @@ -0,0 +1,23 @@ +# +# This file is part of pyasn1 software. +# +# Copyright (c) 2005-2019, Ilya Etingof <etingof@gmail.com> +# License: http://snmplabs.com/pyasn1/license.html +# + +try: + import unittest2 as unittest + +except ImportError: + import unittest + +from pyasn1 import debug + + +class BaseTestCase(unittest.TestCase): + + def setUp(self): + debug.setLogger(debug.Debug('all', printer=lambda *x: None)) + + def tearDown(self): + debug.setLogger(None) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/tests/codec/__init__.py b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/tests/codec/__init__.py new file mode 100644 index 00000000..8c3066b2 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/tests/codec/__init__.py @@ -0,0 +1 @@ +# This file is necessary to make this directory a package. diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/tests/codec/__main__.py b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/tests/codec/__main__.py new file mode 100644 index 00000000..7a4cf207 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/tests/codec/__main__.py @@ -0,0 +1,22 @@ +# +# This file is part of pyasn1 software. +# +# Copyright (c) 2005-2019, Ilya Etingof <etingof@gmail.com> +# License: http://snmplabs.com/pyasn1/license.html +# +try: + import unittest2 as unittest + +except ImportError: + import unittest + +suite = unittest.TestLoader().loadTestsFromNames( + ['tests.codec.ber.__main__.suite', + 'tests.codec.cer.__main__.suite', + 'tests.codec.der.__main__.suite', + 'tests.codec.native.__main__.suite'] +) + + +if __name__ == '__main__': + unittest.TextTestRunner(verbosity=2).run(suite) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/tests/codec/ber/__init__.py b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/tests/codec/ber/__init__.py new file mode 100644 index 00000000..8c3066b2 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/tests/codec/ber/__init__.py @@ -0,0 +1 @@ +# This file is necessary to make this directory a package. diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/tests/codec/ber/__main__.py b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/tests/codec/ber/__main__.py new file mode 100644 index 00000000..59c0c2b1 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/tests/codec/ber/__main__.py @@ -0,0 +1,20 @@ +# +# This file is part of pyasn1 software. +# +# Copyright (c) 2005-2019, Ilya Etingof <etingof@gmail.com> +# License: http://snmplabs.com/pyasn1/license.html +# +try: + import unittest2 as unittest + +except ImportError: + import unittest + +suite = unittest.TestLoader().loadTestsFromNames( + ['tests.codec.ber.test_encoder.suite', + 'tests.codec.ber.test_decoder.suite'] +) + + +if __name__ == '__main__': + unittest.TextTestRunner(verbosity=2).run(suite) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/tests/codec/ber/test_decoder.py b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/tests/codec/ber/test_decoder.py new file mode 100644 index 00000000..e3b74dfd --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/tests/codec/ber/test_decoder.py @@ -0,0 +1,1620 @@ +# +# This file is part of pyasn1 software. +# +# Copyright (c) 2005-2019, Ilya Etingof <etingof@gmail.com> +# License: http://snmplabs.com/pyasn1/license.html +# +import sys + +try: + import unittest2 as unittest + +except ImportError: + import unittest + +from tests.base import BaseTestCase + +from pyasn1.type import tag +from pyasn1.type import namedtype +from pyasn1.type import opentype +from pyasn1.type import univ +from pyasn1.type import char +from pyasn1.codec.ber import decoder +from pyasn1.codec.ber import eoo +from pyasn1.compat.octets import ints2octs, str2octs, null +from pyasn1.error import PyAsn1Error + + +class LargeTagDecoderTestCase(BaseTestCase): + def testLargeTag(self): + assert decoder.decode(ints2octs((127, 141, 245, 182, 253, 47, 3, 2, 1, 1))) == (1, null) + + def testLongTag(self): + assert decoder.decode(ints2octs((0x1f, 2, 1, 0)))[0].tagSet == univ.Integer.tagSet + + def testTagsEquivalence(self): + integer = univ.Integer(2).subtype(implicitTag=tag.Tag(tag.tagClassContext, 0, 0)) + assert decoder.decode(ints2octs((0x9f, 0x80, 0x00, 0x02, 0x01, 0x02)), asn1Spec=integer) == decoder.decode( + ints2octs((0x9f, 0x00, 0x02, 0x01, 0x02)), asn1Spec=integer) + + +class DecoderCacheTestCase(BaseTestCase): + def testCache(self): + assert decoder.decode(ints2octs((0x1f, 2, 1, 0))) == decoder.decode(ints2octs((0x1f, 2, 1, 0))) + + +class IntegerDecoderTestCase(BaseTestCase): + def testPosInt(self): + assert decoder.decode(ints2octs((2, 1, 12))) == (12, null) + + def testNegInt(self): + assert decoder.decode(ints2octs((2, 1, 244))) == (-12, null) + + def testZero(self): + assert decoder.decode(ints2octs((2, 0))) == (0, null) + + def testZeroLong(self): + assert decoder.decode(ints2octs((2, 1, 0))) == (0, null) + + def testMinusOne(self): + assert decoder.decode(ints2octs((2, 1, 255))) == (-1, null) + + def testPosLong(self): + assert decoder.decode( + ints2octs((2, 9, 0, 255, 255, 255, 255, 255, 255, 255, 255)) + ) == (0xffffffffffffffff, null) + + def testNegLong(self): + assert decoder.decode( + ints2octs((2, 9, 255, 0, 0, 0, 0, 0, 0, 0, 1)) + ) == (-0xffffffffffffffff, null) + + def testSpec(self): + try: + decoder.decode( + ints2octs((2, 1, 12)), asn1Spec=univ.Null() + ) == (12, null) + except PyAsn1Error: + pass + else: + assert 0, 'wrong asn1Spec worked out' + assert decoder.decode( + ints2octs((2, 1, 12)), asn1Spec=univ.Integer() + ) == (12, null) + + def testTagFormat(self): + try: + decoder.decode(ints2octs((34, 1, 12))) + except PyAsn1Error: + pass + else: + assert 0, 'wrong tagFormat worked out' + + +class BooleanDecoderTestCase(BaseTestCase): + def testTrue(self): + assert decoder.decode(ints2octs((1, 1, 1))) == (1, null) + + def testTrueNeg(self): + assert decoder.decode(ints2octs((1, 1, 255))) == (1, null) + + def testExtraTrue(self): + assert decoder.decode(ints2octs((1, 1, 1, 0, 120, 50, 50))) == (1, ints2octs((0, 120, 50, 50))) + + def testFalse(self): + assert decoder.decode(ints2octs((1, 1, 0))) == (0, null) + + def testTagFormat(self): + try: + decoder.decode(ints2octs((33, 1, 1))) + except PyAsn1Error: + pass + else: + assert 0, 'wrong tagFormat worked out' + + +class BitStringDecoderTestCase(BaseTestCase): + def testDefMode(self): + assert decoder.decode( + ints2octs((3, 3, 1, 169, 138)) + ) == ((1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1), null) + + def testIndefMode(self): + assert decoder.decode( + ints2octs((3, 3, 1, 169, 138)) + ) == ((1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1), null) + + def testDefModeChunked(self): + assert decoder.decode( + ints2octs((35, 8, 3, 2, 0, 169, 3, 2, 1, 138)) + ) == ((1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1), null) + + def testIndefModeChunked(self): + assert decoder.decode( + ints2octs((35, 128, 3, 2, 0, 169, 3, 2, 1, 138, 0, 0)) + ) == ((1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1), null) + + def testDefModeChunkedSubst(self): + assert decoder.decode( + ints2octs((35, 8, 3, 2, 0, 169, 3, 2, 1, 138)), + substrateFun=lambda a, b, c: (b, b[c:]) + ) == (ints2octs((3, 2, 0, 169, 3, 2, 1, 138)), str2octs('')) + + def testIndefModeChunkedSubst(self): + assert decoder.decode( + ints2octs((35, 128, 3, 2, 0, 169, 3, 2, 1, 138, 0, 0)), + substrateFun=lambda a, b, c: (b, str2octs('')) + ) == (ints2octs((3, 2, 0, 169, 3, 2, 1, 138, 0, 0)), str2octs('')) + + def testTypeChecking(self): + try: + decoder.decode(ints2octs((35, 4, 2, 2, 42, 42))) + except PyAsn1Error: + pass + else: + assert 0, 'accepted mis-encoded bit-string constructed out of an integer' + + +class OctetStringDecoderTestCase(BaseTestCase): + def testDefMode(self): + assert decoder.decode( + ints2octs((4, 15, 81, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 32, 102, 111, 120)) + ) == (str2octs('Quick brown fox'), null) + + def testIndefMode(self): + assert decoder.decode( + ints2octs((36, 128, 4, 15, 81, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 32, 102, 111, 120, 0, 0)) + ) == (str2octs('Quick brown fox'), null) + + def testDefModeChunked(self): + assert decoder.decode( + ints2octs( + (36, 23, 4, 4, 81, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 4, 111, 119, 110, 32, 4, 3, 102, 111, 120)) + ) == (str2octs('Quick brown fox'), null) + + def testIndefModeChunked(self): + assert decoder.decode( + ints2octs((36, 128, 4, 4, 81, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 4, 111, 119, 110, 32, 4, 3, 102, 111, 120, 0, 0)) + ) == (str2octs('Quick brown fox'), null) + + def testDefModeChunkedSubst(self): + assert decoder.decode( + ints2octs( + (36, 23, 4, 4, 81, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 4, 111, 119, 110, 32, 4, 3, 102, 111, 120)), + substrateFun=lambda a, b, c: (b, b[c:]) + ) == (ints2octs((4, 4, 81, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 4, 111, 119, 110, 32, 4, 3, 102, 111, 120)), str2octs('')) + + def testIndefModeChunkedSubst(self): + assert decoder.decode( + ints2octs((36, 128, 4, 4, 81, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 4, 111, 119, 110, 32, 4, 3, 102, 111, + 120, 0, 0)), + substrateFun=lambda a, b, c: (b, str2octs('')) + ) == (ints2octs( + (4, 4, 81, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 4, 111, 119, 110, 32, 4, 3, 102, 111, 120, 0, 0)), str2octs('')) + + +class ExpTaggedOctetStringDecoderTestCase(BaseTestCase): + def setUp(self): + BaseTestCase.setUp(self) + self.o = univ.OctetString( + 'Quick brown fox', + tagSet=univ.OctetString.tagSet.tagExplicitly( + tag.Tag(tag.tagClassApplication, tag.tagFormatSimple, 5) + )) + + def testDefMode(self): + o, r = decoder.decode( + ints2octs((101, 17, 4, 15, 81, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 32, 102, 111, 120)) + ) + assert not r + assert self.o == o + assert self.o.tagSet == o.tagSet + assert self.o.isSameTypeWith(o) + + def testIndefMode(self): + o, r = decoder.decode( + ints2octs((101, 128, 36, 128, 4, 15, 81, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 32, 102, 111, 120, 0, 0, 0, 0)) + ) + assert not r + assert self.o == o + assert self.o.tagSet == o.tagSet + assert self.o.isSameTypeWith(o) + + def testDefModeChunked(self): + o, r = decoder.decode( + ints2octs((101, 25, 36, 23, 4, 4, 81, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 4, 111, 119, 110, 32, 4, 3, 102, 111, 120)) + ) + assert not r + assert self.o == o + assert self.o.tagSet == o.tagSet + assert self.o.isSameTypeWith(o) + + def testIndefModeChunked(self): + o, r = decoder.decode( + ints2octs((101, 128, 36, 128, 4, 4, 81, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 4, 111, 119, 110, 32, 4, 3, 102, 111, 120, 0, 0, 0, 0)) + ) + assert not r + assert self.o == o + assert self.o.tagSet == o.tagSet + assert self.o.isSameTypeWith(o) + + def testDefModeSubst(self): + assert decoder.decode( + ints2octs((101, 17, 4, 15, 81, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 32, 102, 111, 120)), + substrateFun=lambda a, b, c: (b, b[c:]) + ) == (ints2octs((4, 15, 81, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 32, 102, 111, 120)), str2octs('')) + + def testIndefModeSubst(self): + assert decoder.decode( + ints2octs(( + 101, 128, 36, 128, 4, 15, 81, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 32, 102, 111, 120, 0, + 0, 0, 0)), + substrateFun=lambda a, b, c: (b, str2octs('')) + ) == (ints2octs( + (36, 128, 4, 15, 81, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 32, 102, 111, 120, 0, 0, 0, 0)), str2octs('')) + + +class NullDecoderTestCase(BaseTestCase): + def testNull(self): + assert decoder.decode(ints2octs((5, 0))) == (null, null) + + def testTagFormat(self): + try: + decoder.decode(ints2octs((37, 0))) + except PyAsn1Error: + pass + else: + assert 0, 'wrong tagFormat worked out' + + +# Useful analysis of OID encoding issues could be found here: +# https://misc.daniel-marschall.de/asn.1/oid_facts.html +class ObjectIdentifierDecoderTestCase(BaseTestCase): + def testOne(self): + assert decoder.decode( + ints2octs((6, 6, 43, 6, 0, 191, 255, 126)) + ) == ((1, 3, 6, 0, 0xffffe), null) + + def testEdge1(self): + assert decoder.decode( + ints2octs((6, 1, 39)) + ) == ((0, 39), null) + + def testEdge2(self): + assert decoder.decode( + ints2octs((6, 1, 79)) + ) == ((1, 39), null) + + def testEdge3(self): + assert decoder.decode( + ints2octs((6, 1, 120)) + ) == ((2, 40), null) + + def testEdge4(self): + assert decoder.decode( + ints2octs((6, 5, 0x90, 0x80, 0x80, 0x80, 0x4F)) + ) == ((2, 0xffffffff), null) + + def testEdge5(self): + assert decoder.decode( + ints2octs((6, 1, 0x7F)) + ) == ((2, 47), null) + + def testEdge6(self): + assert decoder.decode( + ints2octs((6, 2, 0x81, 0x00)) + ) == ((2, 48), null) + + def testEdge7(self): + assert decoder.decode( + ints2octs((6, 3, 0x81, 0x34, 0x03)) + ) == ((2, 100, 3), null) + + def testEdge8(self): + assert decoder.decode( + ints2octs((6, 2, 133, 0)) + ) == ((2, 560), null) + + def testEdge9(self): + assert decoder.decode( + ints2octs((6, 4, 0x88, 0x84, 0x87, 0x02)) + ) == ((2, 16843570), null) + + def testNonLeading0x80(self): + assert decoder.decode( + ints2octs((6, 5, 85, 4, 129, 128, 0)), + ) == ((2, 5, 4, 16384), null) + + def testLeading0x80Case1(self): + try: + decoder.decode( + ints2octs((6, 5, 85, 4, 128, 129, 0)) + ) + except PyAsn1Error: + pass + else: + assert 0, 'Leading 0x80 tolerated' + + def testLeading0x80Case2(self): + try: + decoder.decode( + ints2octs((6, 7, 1, 0x80, 0x80, 0x80, 0x80, 0x80, 0x7F)) + ) + except PyAsn1Error: + pass + else: + assert 0, 'Leading 0x80 tolerated' + + def testLeading0x80Case3(self): + try: + decoder.decode( + ints2octs((6, 2, 0x80, 1)) + ) + except PyAsn1Error: + pass + else: + assert 0, 'Leading 0x80 tolerated' + + def testLeading0x80Case4(self): + try: + decoder.decode( + ints2octs((6, 2, 0x80, 0x7F)) + ) + except PyAsn1Error: + pass + else: + assert 0, 'Leading 0x80 tolerated' + + def testTagFormat(self): + try: + decoder.decode(ints2octs((38, 1, 239))) + except PyAsn1Error: + pass + else: + assert 0, 'wrong tagFormat worked out' + + def testZeroLength(self): + try: + decoder.decode(ints2octs((6, 0, 0))) + except PyAsn1Error: + pass + else: + assert 0, 'zero length tolerated' + + def testIndefiniteLength(self): + try: + decoder.decode(ints2octs((6, 128, 0))) + except PyAsn1Error: + pass + else: + assert 0, 'indefinite length tolerated' + + def testReservedLength(self): + try: + decoder.decode(ints2octs((6, 255, 0))) + except PyAsn1Error: + pass + else: + assert 0, 'reserved length tolerated' + + def testLarge1(self): + assert decoder.decode( + ints2octs((0x06, 0x11, 0x83, 0xC6, 0xDF, 0xD4, 0xCC, 0xB3, 0xFF, 0xFF, 0xFE, 0xF0, 0xB8, 0xD6, 0xB8, 0xCB, 0xE2, 0xB7, 0x17)) + ) == ((2, 18446744073709551535184467440737095), null) + + def testLarge2(self): + assert decoder.decode( + ints2octs((0x06, 0x13, 0x88, 0x37, 0x83, 0xC6, 0xDF, 0xD4, 0xCC, 0xB3, 0xFF, 0xFF, 0xFE, 0xF0, 0xB8, 0xD6, 0xB8, 0xCB, 0xE2, 0xB6, 0x47)) + ) == ((2, 999, 18446744073709551535184467440737095), null) + + +class RealDecoderTestCase(BaseTestCase): + def testChar(self): + assert decoder.decode( + ints2octs((9, 7, 3, 49, 50, 51, 69, 49, 49)) + ) == (univ.Real((123, 10, 11)), null) + + def testBin1(self): # check base = 2 + assert decoder.decode( # (0.5, 2, 0) encoded with base = 2 + ints2octs((9, 3, 128, 255, 1)) + ) == (univ.Real((1, 2, -1)), null) + + def testBin2(self): # check base = 2 and scale factor + assert decoder.decode( # (3.25, 2, 0) encoded with base = 8 + ints2octs((9, 3, 148, 255, 13)) + ) == (univ.Real((26, 2, -3)), null) + + def testBin3(self): # check base = 16 + assert decoder.decode( # (0.00390625, 2, 0) encoded with base = 16 + ints2octs((9, 3, 160, 254, 1)) + ) == (univ.Real((1, 2, -8)), null) + + def testBin4(self): # check exponent = 0 + assert decoder.decode( # (1, 2, 0) encoded with base = 2 + ints2octs((9, 3, 128, 0, 1)) + ) == (univ.Real((1, 2, 0)), null) + + def testBin5(self): # case of 2 octs for exponent and negative exponent + assert decoder.decode( # (3, 2, -1020) encoded with base = 16 + ints2octs((9, 4, 161, 255, 1, 3)) + ) == (univ.Real((3, 2, -1020)), null) + +# TODO: this requires Real type comparison fix + +# def testBin6(self): +# assert decoder.decode( +# ints2octs((9, 5, 162, 0, 255, 255, 1)) +# ) == (univ.Real((1, 2, 262140)), null) + +# def testBin7(self): +# assert decoder.decode( +# ints2octs((9, 7, 227, 4, 1, 35, 69, 103, 1)) +# ) == (univ.Real((-1, 2, 76354972)), null) + + def testPlusInf(self): + assert decoder.decode( + ints2octs((9, 1, 64)) + ) == (univ.Real('inf'), null) + + def testMinusInf(self): + assert decoder.decode( + ints2octs((9, 1, 65)) + ) == (univ.Real('-inf'), null) + + def testEmpty(self): + assert decoder.decode( + ints2octs((9, 0)) + ) == (univ.Real(0.0), null) + + def testTagFormat(self): + try: + decoder.decode(ints2octs((41, 0))) + except PyAsn1Error: + pass + else: + assert 0, 'wrong tagFormat worked out' + + def testShortEncoding(self): + try: + decoder.decode(ints2octs((9, 1, 131))) + except PyAsn1Error: + pass + else: + assert 0, 'accepted too-short real' + + +if sys.version_info[0:2] > (2, 5): + class UniversalStringDecoderTestCase(BaseTestCase): + def testDecoder(self): + assert decoder.decode(ints2octs((28, 12, 0, 0, 0, 97, 0, 0, 0, 98, 0, 0, 0, 99))) == (char.UniversalString(sys.version_info[0] >= 3 and 'abc' or unicode('abc')), null) + + +class BMPStringDecoderTestCase(BaseTestCase): + def testDecoder(self): + assert decoder.decode(ints2octs((30, 6, 0, 97, 0, 98, 0, 99))) == (char.BMPString(sys.version_info[0] >= 3 and 'abc' or unicode('abc')), null) + + +class UTF8StringDecoderTestCase(BaseTestCase): + def testDecoder(self): + assert decoder.decode(ints2octs((12, 3, 97, 98, 99))) == (char.UTF8String(sys.version_info[0] >= 3 and 'abc' or unicode('abc')), null) + + +class SequenceOfDecoderTestCase(BaseTestCase): + def setUp(self): + BaseTestCase.setUp(self) + + self.s = univ.SequenceOf(componentType=univ.OctetString()) + self.s.setComponentByPosition(0, univ.OctetString('quick brown')) + + def testDefMode(self): + assert decoder.decode( + ints2octs((48, 13, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110)) + ) == (self.s, null) + + def testIndefMode(self): + assert decoder.decode( + ints2octs((48, 128, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 0, 0)) + ) == (self.s, null) + + def testDefModeChunked(self): + assert decoder.decode( + ints2octs((48, 19, 36, 17, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110)) + ) == (self.s, null) + + def testIndefModeChunked(self): + assert decoder.decode( + ints2octs((48, 128, 36, 128, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110, 0, 0, 0, 0)) + ) == (self.s, null) + + def testSchemalessDecoder(self): + assert decoder.decode( + ints2octs((48, 13, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110)), asn1Spec=univ.SequenceOf() + ) == (self.s, null) + + +class ExpTaggedSequenceOfDecoderTestCase(BaseTestCase): + + def testWithSchema(self): + s = univ.SequenceOf().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 3)) + s2, r = decoder.decode( + ints2octs((163, 15, 48, 13, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110)), asn1Spec=s + ) + assert not r + assert s2 == [str2octs('quick brown')] + assert s.tagSet == s2.tagSet + + def testWithoutSchema(self): + s = univ.SequenceOf().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 3)) + s2, r = decoder.decode( + ints2octs((163, 15, 48, 13, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110)) + ) + assert not r + assert s2 == [str2octs('quick brown')] + assert s.tagSet == s2.tagSet + + +class SequenceOfDecoderWithSchemaTestCase(BaseTestCase): + def setUp(self): + BaseTestCase.setUp(self) + self.s = univ.SequenceOf(componentType=univ.OctetString()) + self.s.setComponentByPosition(0, univ.OctetString('quick brown')) + + def testDefMode(self): + assert decoder.decode( + ints2octs((48, 13, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110)), asn1Spec=self.s + ) == (self.s, null) + + def testIndefMode(self): + assert decoder.decode( + ints2octs((48, 128, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 0, 0)), asn1Spec=self.s + ) == (self.s, null) + + def testDefModeChunked(self): + assert decoder.decode( + ints2octs((48, 19, 36, 17, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110)), asn1Spec=self.s + ) == (self.s, null) + + def testIndefModeChunked(self): + assert decoder.decode( + ints2octs((48, 128, 36, 128, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110, 0, 0, 0, 0)), asn1Spec=self.s + ) == (self.s, null) + + +class SetOfDecoderTestCase(BaseTestCase): + def setUp(self): + BaseTestCase.setUp(self) + self.s = univ.SetOf(componentType=univ.OctetString()) + self.s.setComponentByPosition(0, univ.OctetString('quick brown')) + + def testDefMode(self): + assert decoder.decode( + ints2octs((49, 13, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110)) + ) == (self.s, null) + + def testIndefMode(self): + assert decoder.decode( + ints2octs((49, 128, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 0, 0)) + ) == (self.s, null) + + def testDefModeChunked(self): + assert decoder.decode( + ints2octs((49, 19, 36, 17, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110)) + ) == (self.s, null) + + def testIndefModeChunked(self): + assert decoder.decode( + ints2octs((49, 128, 36, 128, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110, 0, 0, 0, 0)) + ) == (self.s, null) + + def testSchemalessDecoder(self): + assert decoder.decode( + ints2octs((49, 13, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110)), asn1Spec=univ.SetOf() + ) == (self.s, null) + + +class SetOfDecoderWithSchemaTestCase(BaseTestCase): + def setUp(self): + BaseTestCase.setUp(self) + self.s = univ.SetOf(componentType=univ.OctetString()) + self.s.setComponentByPosition(0, univ.OctetString('quick brown')) + + def testDefMode(self): + assert decoder.decode( + ints2octs((49, 13, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110)), asn1Spec=self.s + ) == (self.s, null) + + def testIndefMode(self): + assert decoder.decode( + ints2octs((49, 128, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 0, 0)), asn1Spec=self.s + ) == (self.s, null) + + def testDefModeChunked(self): + assert decoder.decode( + ints2octs((49, 19, 36, 17, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110)), asn1Spec=self.s + ) == (self.s, null) + + def testIndefModeChunked(self): + assert decoder.decode( + ints2octs((49, 128, 36, 128, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110, 0, 0, 0, 0)), asn1Spec=self.s + ) == (self.s, null) + + +class SequenceDecoderTestCase(BaseTestCase): + def setUp(self): + BaseTestCase.setUp(self) + self.s = univ.Sequence( + componentType=namedtype.NamedTypes( + namedtype.NamedType('place-holder', univ.Null(null)), + namedtype.NamedType('first-name', univ.OctetString(null)), + namedtype.NamedType('age', univ.Integer(33)) + ) + ) + self.s.setComponentByPosition(0, univ.Null(null)) + self.s.setComponentByPosition(1, univ.OctetString('quick brown')) + self.s.setComponentByPosition(2, univ.Integer(1)) + + def testWithOptionalAndDefaultedDefMode(self): + assert decoder.decode( + ints2octs((48, 18, 5, 0, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 2, 1, 1)) + ) == (self.s, null) + + def testWithOptionalAndDefaultedIndefMode(self): + assert decoder.decode( + ints2octs((48, 128, 5, 0, 36, 128, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 0, 0, 2, 1, 1, 0, 0)) + ) == (self.s, null) + + def testWithOptionalAndDefaultedDefModeChunked(self): + assert decoder.decode( + ints2octs( + (48, 24, 5, 0, 36, 17, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110, 2, 1, 1)) + ) == (self.s, null) + + def testWithOptionalAndDefaultedIndefModeChunked(self): + assert decoder.decode( + ints2octs((48, 128, 5, 0, 36, 128, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110, 0, 0, 2, 1, 1, 0, 0)) + ) == (self.s, null) + + def testWithOptionalAndDefaultedDefModeSubst(self): + assert decoder.decode( + ints2octs((48, 18, 5, 0, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 2, 1, 1)), + substrateFun=lambda a, b, c: (b, b[c:]) + ) == (ints2octs((5, 0, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 2, 1, 1)), str2octs('')) + + def testWithOptionalAndDefaultedIndefModeSubst(self): + assert decoder.decode( + ints2octs((48, 128, 5, 0, 36, 128, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 0, 0, 2, 1, 1, 0, 0)), + substrateFun=lambda a, b, c: (b, str2octs('')) + ) == (ints2octs( + (5, 0, 36, 128, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 0, 0, 2, 1, 1, 0, 0)), str2octs('')) + + def testTagFormat(self): + try: + decoder.decode( + ints2octs((16, 18, 5, 0, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 2, 1, 1)) + ) + except PyAsn1Error: + pass + else: + assert 0, 'wrong tagFormat worked out' + + +class SequenceDecoderWithSchemaTestCase(BaseTestCase): + def setUp(self): + BaseTestCase.setUp(self) + self.s = univ.Sequence( + componentType=namedtype.NamedTypes( + namedtype.NamedType('place-holder', univ.Null(null)), + namedtype.OptionalNamedType('first-name', univ.OctetString()), + namedtype.DefaultedNamedType('age', univ.Integer(33)), + ) + ) + + def __init(self): + self.s.clear() + self.s.setComponentByPosition(0, univ.Null(null)) + + def __initWithOptional(self): + self.s.clear() + self.s.setComponentByPosition(0, univ.Null(null)) + self.s.setComponentByPosition(1, univ.OctetString('quick brown')) + + def __initWithDefaulted(self): + self.s.clear() + self.s.setComponentByPosition(0, univ.Null(null)) + self.s.setComponentByPosition(2, univ.Integer(1)) + + def __initWithOptionalAndDefaulted(self): + self.s.clear() + self.s.setComponentByPosition(0, univ.Null(null)) + self.s.setComponentByPosition(1, univ.OctetString('quick brown')) + self.s.setComponentByPosition(2, univ.Integer(1)) + + def testDefMode(self): + self.__init() + assert decoder.decode( + ints2octs((48, 2, 5, 0)), asn1Spec=self.s + ) == (self.s, null) + + def testIndefMode(self): + self.__init() + assert decoder.decode( + ints2octs((48, 128, 5, 0, 0, 0)), asn1Spec=self.s + ) == (self.s, null) + + def testDefModeChunked(self): + self.__init() + assert decoder.decode( + ints2octs((48, 2, 5, 0)), asn1Spec=self.s + ) == (self.s, null) + + def testIndefModeChunked(self): + self.__init() + assert decoder.decode( + ints2octs((48, 128, 5, 0, 0, 0)), asn1Spec=self.s + ) == (self.s, null) + + def testWithOptionalDefMode(self): + self.__initWithOptional() + assert decoder.decode( + ints2octs((48, 15, 5, 0, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110)), asn1Spec=self.s + ) == (self.s, null) + + def testWithOptionaIndefMode(self): + self.__initWithOptional() + assert decoder.decode( + ints2octs((48, 128, 5, 0, 36, 128, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 0, 0, 0, 0)), + asn1Spec=self.s + ) == (self.s, null) + + def testWithOptionalDefModeChunked(self): + self.__initWithOptional() + assert decoder.decode( + ints2octs((48, 21, 5, 0, 36, 17, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110)), + asn1Spec=self.s + ) == (self.s, null) + + def testWithOptionalIndefModeChunked(self): + self.__initWithOptional() + assert decoder.decode( + ints2octs((48, 128, 5, 0, 36, 128, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110, 0, + 0, 0, 0)), + asn1Spec=self.s + ) == (self.s, null) + + def testWithDefaultedDefMode(self): + self.__initWithDefaulted() + assert decoder.decode( + ints2octs((48, 5, 5, 0, 2, 1, 1)), asn1Spec=self.s + ) == (self.s, null) + + def testWithDefaultedIndefMode(self): + self.__initWithDefaulted() + assert decoder.decode( + ints2octs((48, 128, 5, 0, 2, 1, 1, 0, 0)), asn1Spec=self.s + ) == (self.s, null) + + def testWithDefaultedDefModeChunked(self): + self.__initWithDefaulted() + assert decoder.decode( + ints2octs((48, 5, 5, 0, 2, 1, 1)), asn1Spec=self.s + ) == (self.s, null) + + def testWithDefaultedIndefModeChunked(self): + self.__initWithDefaulted() + assert decoder.decode( + ints2octs((48, 128, 5, 0, 2, 1, 1, 0, 0)), asn1Spec=self.s + ) == (self.s, null) + + def testWithOptionalAndDefaultedDefMode(self): + self.__initWithOptionalAndDefaulted() + assert decoder.decode( + ints2octs((48, 18, 5, 0, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 2, 1, 1)), + asn1Spec=self.s + ) == (self.s, null) + + def testWithOptionalAndDefaultedIndefMode(self): + self.__initWithOptionalAndDefaulted() + assert decoder.decode( + ints2octs((48, 128, 5, 0, 36, 128, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 0, 0, 2, 1, 1, + 0, 0)), asn1Spec=self.s + ) == (self.s, null) + + def testWithOptionalAndDefaultedDefModeChunked(self): + self.__initWithOptionalAndDefaulted() + assert decoder.decode( + ints2octs( + (48, 24, 5, 0, 36, 17, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110, 2, 1, 1)), + asn1Spec=self.s + ) == (self.s, null) + + def testWithOptionalAndDefaultedIndefModeChunked(self): + self.__initWithOptionalAndDefaulted() + assert decoder.decode( + ints2octs((48, 128, 5, 0, 36, 128, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110, 0, + 0, 2, 1, 1, 0, 0)), asn1Spec=self.s + ) == (self.s, null) + + +class SequenceDecoderWithUntaggedOpenTypesTestCase(BaseTestCase): + def setUp(self): + openType = opentype.OpenType( + 'id', + {1: univ.Integer(), + 2: univ.OctetString()} + ) + self.s = univ.Sequence( + componentType=namedtype.NamedTypes( + namedtype.NamedType('id', univ.Integer()), + namedtype.NamedType('blob', univ.Any(), openType=openType) + ) + ) + + def testDecodeOpenTypesChoiceOne(self): + s, r = decoder.decode( + ints2octs((48, 6, 2, 1, 1, 2, 1, 12)), asn1Spec=self.s, + decodeOpenTypes=True + ) + assert not r + assert s[0] == 1 + assert s[1] == 12 + + def testDecodeOpenTypesChoiceTwo(self): + s, r = decoder.decode( + ints2octs((48, 16, 2, 1, 2, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110)), asn1Spec=self.s, + decodeOpenTypes=True + ) + assert not r + assert s[0] == 2 + assert s[1] == univ.OctetString('quick brown') + + def testDecodeOpenTypesUnknownType(self): + try: + s, r = decoder.decode( + ints2octs((48, 6, 2, 1, 2, 6, 1, 39)), asn1Spec=self.s, + decodeOpenTypes=True + ) + + except PyAsn1Error: + pass + + else: + assert False, 'unknown open type tolerated' + + def testDecodeOpenTypesUnknownId(self): + s, r = decoder.decode( + ints2octs((48, 6, 2, 1, 3, 6, 1, 39)), asn1Spec=self.s, + decodeOpenTypes=True + ) + assert not r + assert s[0] == 3 + assert s[1] == univ.OctetString(hexValue='060127') + + def testDontDecodeOpenTypesChoiceOne(self): + s, r = decoder.decode( + ints2octs((48, 6, 2, 1, 1, 2, 1, 12)), asn1Spec=self.s + ) + assert not r + assert s[0] == 1 + assert s[1] == ints2octs((2, 1, 12)) + + def testDontDecodeOpenTypesChoiceTwo(self): + s, r = decoder.decode( + ints2octs((48, 16, 2, 1, 2, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110)), asn1Spec=self.s + ) + assert not r + assert s[0] == 2 + assert s[1] == ints2octs((4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110)) + + +class SequenceDecoderWithImplicitlyTaggedOpenTypesTestCase(BaseTestCase): + def setUp(self): + openType = opentype.OpenType( + 'id', + {1: univ.Integer(), + 2: univ.OctetString()} + ) + self.s = univ.Sequence( + componentType=namedtype.NamedTypes( + namedtype.NamedType('id', univ.Integer()), + namedtype.NamedType( + 'blob', univ.Any().subtype(implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 3)), openType=openType + ) + ) + ) + + def testDecodeOpenTypesChoiceOne(self): + s, r = decoder.decode( + ints2octs((48, 8, 2, 1, 1, 131, 3, 2, 1, 12)), asn1Spec=self.s, decodeOpenTypes=True + ) + assert not r + assert s[0] == 1 + assert s[1] == 12 + + def testDecodeOpenTypesUnknownId(self): + s, r = decoder.decode( + ints2octs((48, 8, 2, 1, 3, 131, 3, 2, 1, 12)), asn1Spec=self.s, decodeOpenTypes=True + ) + assert not r + assert s[0] == 3 + assert s[1] == univ.OctetString(hexValue='02010C') + + +class SequenceDecoderWithExplicitlyTaggedOpenTypesTestCase(BaseTestCase): + def setUp(self): + openType = opentype.OpenType( + 'id', + {1: univ.Integer(), + 2: univ.OctetString()} + ) + self.s = univ.Sequence( + componentType=namedtype.NamedTypes( + namedtype.NamedType('id', univ.Integer()), + namedtype.NamedType( + 'blob', univ.Any().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 3)), openType=openType + ) + ) + ) + + def testDecodeOpenTypesChoiceOne(self): + s, r = decoder.decode( + ints2octs((48, 8, 2, 1, 1, 163, 3, 2, 1, 12)), asn1Spec=self.s, decodeOpenTypes=True + ) + assert not r + assert s[0] == 1 + assert s[1] == 12 + + def testDecodeOpenTypesUnknownId(self): + s, r = decoder.decode( + ints2octs((48, 8, 2, 1, 3, 163, 3, 2, 1, 12)), asn1Spec=self.s, decodeOpenTypes=True + ) + assert not r + assert s[0] == 3 + assert s[1] == univ.OctetString(hexValue='02010C') + + +class SequenceDecoderWithUnaggedSetOfOpenTypesTestCase(BaseTestCase): + def setUp(self): + openType = opentype.OpenType( + 'id', + {1: univ.Integer(), + 2: univ.OctetString()} + ) + self.s = univ.Sequence( + componentType=namedtype.NamedTypes( + namedtype.NamedType('id', univ.Integer()), + namedtype.NamedType('blob', univ.SetOf(componentType=univ.Any()), + openType=openType) + ) + ) + + def testDecodeOpenTypesChoiceOne(self): + s, r = decoder.decode( + ints2octs((48, 8, 2, 1, 1, 49, 3, 2, 1, 12)), asn1Spec=self.s, + decodeOpenTypes=True + ) + assert not r + assert s[0] == 1 + assert s[1][0] == 12 + + def testDecodeOpenTypesChoiceTwo(self): + s, r = decoder.decode( + ints2octs((48, 18, 2, 1, 2, 49, 13, 4, 11, 113, 117, 105, 99, + 107, 32, 98, 114, 111, 119, 110)), asn1Spec=self.s, + decodeOpenTypes=True + ) + assert not r + assert s[0] == 2 + assert s[1][0] == univ.OctetString('quick brown') + + def testDecodeOpenTypesUnknownType(self): + try: + s, r = decoder.decode( + ints2octs((48, 6, 2, 1, 2, 6, 1, 39)), asn1Spec=self.s, + decodeOpenTypes=True + ) + + except PyAsn1Error: + pass + + else: + assert False, 'unknown open type tolerated' + + def testDecodeOpenTypesUnknownId(self): + s, r = decoder.decode( + ints2octs((48, 8, 2, 1, 3, 49, 3, 2, 1, 12)), asn1Spec=self.s, + decodeOpenTypes=True + ) + assert not r + assert s[0] == 3 + assert s[1][0] == univ.OctetString(hexValue='02010c') + + def testDontDecodeOpenTypesChoiceOne(self): + s, r = decoder.decode( + ints2octs((48, 8, 2, 1, 1, 49, 3, 2, 1, 12)), asn1Spec=self.s + ) + assert not r + assert s[0] == 1 + assert s[1][0] == ints2octs((2, 1, 12)) + + def testDontDecodeOpenTypesChoiceTwo(self): + s, r = decoder.decode( + ints2octs((48, 18, 2, 1, 2, 49, 13, 4, 11, 113, 117, 105, 99, + 107, 32, 98, 114, 111, 119, 110)), asn1Spec=self.s + ) + assert not r + assert s[0] == 2 + assert s[1][0] == ints2octs((4, 11, 113, 117, 105, 99, 107, 32, 98, 114, + 111, 119, 110)) + + +class SequenceDecoderWithImplicitlyTaggedSetOfOpenTypesTestCase(BaseTestCase): + def setUp(self): + openType = opentype.OpenType( + 'id', + {1: univ.Integer(), + 2: univ.OctetString()} + ) + self.s = univ.Sequence( + componentType=namedtype.NamedTypes( + namedtype.NamedType('id', univ.Integer()), + namedtype.NamedType( + 'blob', univ.SetOf( + componentType=univ.Any().subtype( + implicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatSimple, 3))), + openType=openType + ) + ) + ) + + def testDecodeOpenTypesChoiceOne(self): + s, r = decoder.decode( + ints2octs((48, 10, 2, 1, 1, 49, 5, 131, 3, 2, 1, 12)), + asn1Spec=self.s, decodeOpenTypes=True + ) + assert not r + assert s[0] == 1 + assert s[1][0] == 12 + + def testDecodeOpenTypesUnknownId(self): + s, r = decoder.decode( + ints2octs((48, 10, 2, 1, 3, 49, 5, 131, 3, 2, 1, 12)), + asn1Spec=self.s, decodeOpenTypes=True + ) + assert not r + assert s[0] == 3 + assert s[1][0] == univ.OctetString(hexValue='02010C') + + +class SequenceDecoderWithExplicitlyTaggedSetOfOpenTypesTestCase(BaseTestCase): + def setUp(self): + openType = opentype.OpenType( + 'id', + {1: univ.Integer(), + 2: univ.OctetString()} + ) + self.s = univ.Sequence( + componentType=namedtype.NamedTypes( + namedtype.NamedType('id', univ.Integer()), + namedtype.NamedType( + 'blob', univ.SetOf( + componentType=univ.Any().subtype( + explicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatSimple, 3))), + openType=openType + ) + ) + ) + + def testDecodeOpenTypesChoiceOne(self): + s, r = decoder.decode( + ints2octs((48, 10, 2, 1, 1, 49, 5, 131, 3, 2, 1, 12)), + asn1Spec=self.s, decodeOpenTypes=True + ) + assert not r + assert s[0] == 1 + assert s[1][0] == 12 + + def testDecodeOpenTypesUnknownId(self): + s, r = decoder.decode( + ints2octs( (48, 10, 2, 1, 3, 49, 5, 131, 3, 2, 1, 12)), + asn1Spec=self.s, decodeOpenTypes=True + ) + assert not r + assert s[0] == 3 + assert s[1][0] == univ.OctetString(hexValue='02010C') + + +class SetDecoderTestCase(BaseTestCase): + def setUp(self): + BaseTestCase.setUp(self) + self.s = univ.Set( + componentType=namedtype.NamedTypes( + namedtype.NamedType('place-holder', univ.Null(null)), + namedtype.NamedType('first-name', univ.OctetString(null)), + namedtype.NamedType('age', univ.Integer(33)) + ) + ) + self.s.setComponentByPosition(0, univ.Null(null)) + self.s.setComponentByPosition(1, univ.OctetString('quick brown')) + self.s.setComponentByPosition(2, univ.Integer(1)) + + def testWithOptionalAndDefaultedDefMode(self): + assert decoder.decode( + ints2octs((49, 18, 5, 0, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 2, 1, 1)) + ) == (self.s, null) + + def testWithOptionalAndDefaultedIndefMode(self): + assert decoder.decode( + ints2octs((49, 128, 5, 0, 36, 128, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 0, 0, 2, 1, 1, 0, 0)) + ) == (self.s, null) + + def testWithOptionalAndDefaultedDefModeChunked(self): + assert decoder.decode( + ints2octs( + (49, 24, 5, 0, 36, 17, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110, 2, 1, 1)) + ) == (self.s, null) + + def testWithOptionalAndDefaultedIndefModeChunked(self): + assert decoder.decode( + ints2octs((49, 128, 5, 0, 36, 128, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110, 0, 0, 2, 1, 1, 0, 0)) + ) == (self.s, null) + + def testWithOptionalAndDefaultedDefModeSubst(self): + assert decoder.decode( + ints2octs((49, 18, 5, 0, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 2, 1, 1)), + substrateFun=lambda a, b, c: (b, b[c:]) + ) == (ints2octs((5, 0, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 2, 1, 1)), str2octs('')) + + def testWithOptionalAndDefaultedIndefModeSubst(self): + assert decoder.decode( + ints2octs((49, 128, 5, 0, 36, 128, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 0, 0, 2, 1, 1, 0, 0)), + substrateFun=lambda a, b, c: (b, str2octs('')) + ) == (ints2octs( + (5, 0, 36, 128, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 0, 0, 2, 1, 1, 0, 0)), str2octs('')) + + def testTagFormat(self): + try: + decoder.decode( + ints2octs((16, 18, 5, 0, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 2, 1, 1)) + ) + except PyAsn1Error: + pass + else: + assert 0, 'wrong tagFormat worked out' + + +class SetDecoderWithSchemaTestCase(BaseTestCase): + def setUp(self): + BaseTestCase.setUp(self) + self.s = univ.Set( + componentType=namedtype.NamedTypes( + namedtype.NamedType('place-holder', univ.Null(null)), + namedtype.OptionalNamedType('first-name', univ.OctetString()), + namedtype.DefaultedNamedType('age', univ.Integer(33)), + ) + ) + + def __init(self): + self.s.clear() + self.s.setComponentByPosition(0, univ.Null(null)) + + def __initWithOptional(self): + self.s.clear() + self.s.setComponentByPosition(0, univ.Null(null)) + self.s.setComponentByPosition(1, univ.OctetString('quick brown')) + + def __initWithDefaulted(self): + self.s.clear() + self.s.setComponentByPosition(0, univ.Null(null)) + self.s.setComponentByPosition(2, univ.Integer(1)) + + def __initWithOptionalAndDefaulted(self): + self.s.clear() + self.s.setComponentByPosition(0, univ.Null(null)) + self.s.setComponentByPosition(1, univ.OctetString('quick brown')) + self.s.setComponentByPosition(2, univ.Integer(1)) + + def testDefMode(self): + self.__init() + assert decoder.decode( + ints2octs((49, 128, 5, 0, 0, 0)), asn1Spec=self.s + ) == (self.s, null) + + def testIndefMode(self): + self.__init() + assert decoder.decode( + ints2octs((49, 128, 5, 0, 0, 0)), asn1Spec=self.s + ) == (self.s, null) + + def testDefModeChunked(self): + self.__init() + assert decoder.decode( + ints2octs((49, 2, 5, 0)), asn1Spec=self.s + ) == (self.s, null) + + def testIndefModeChunked(self): + self.__init() + assert decoder.decode( + ints2octs((49, 128, 5, 0, 0, 0)), asn1Spec=self.s + ) == (self.s, null) + + def testWithOptionalDefMode(self): + self.__initWithOptional() + assert decoder.decode( + ints2octs((49, 15, 5, 0, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110)), asn1Spec=self.s + ) == (self.s, null) + + def testWithOptionalIndefMode(self): + self.__initWithOptional() + assert decoder.decode( + ints2octs((49, 128, 5, 0, 36, 128, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 0, 0, 0, 0)), asn1Spec=self.s + ) == (self.s, null) + + def testWithOptionalDefModeChunked(self): + self.__initWithOptional() + assert decoder.decode( + ints2octs((49, 21, 5, 0, 36, 17, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110)), asn1Spec=self.s + ) == (self.s, null) + + def testWithOptionalIndefModeChunked(self): + self.__initWithOptional() + assert decoder.decode( + ints2octs((49, 128, 5, 0, 36, 128, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110, 0, 0, 0, 0)), asn1Spec=self.s + ) == (self.s, null) + + def testWithDefaultedDefMode(self): + self.__initWithDefaulted() + assert decoder.decode( + ints2octs((49, 5, 5, 0, 2, 1, 1)), asn1Spec=self.s + ) == (self.s, null) + + def testWithDefaultedIndefMode(self): + self.__initWithDefaulted() + assert decoder.decode( + ints2octs((49, 128, 5, 0, 2, 1, 1, 0, 0)), asn1Spec=self.s + ) == (self.s, null) + + def testWithDefaultedDefModeChunked(self): + self.__initWithDefaulted() + assert decoder.decode( + ints2octs((49, 5, 5, 0, 2, 1, 1)), asn1Spec=self.s + ) == (self.s, null) + + def testWithDefaultedIndefModeChunked(self): + self.__initWithDefaulted() + assert decoder.decode( + ints2octs((49, 128, 5, 0, 2, 1, 1, 0, 0)), asn1Spec=self.s + ) == (self.s, null) + + def testWithOptionalAndDefaultedDefMode(self): + self.__initWithOptionalAndDefaulted() + assert decoder.decode( + ints2octs((49, 18, 5, 0, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 2, 1, 1)), asn1Spec=self.s + ) == (self.s, null) + + def testWithOptionalAndDefaultedDefModeReordered(self): + self.__initWithOptionalAndDefaulted() + assert decoder.decode( + ints2octs((49, 18, 2, 1, 1, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 5, 0)), asn1Spec=self.s + ) == (self.s, null) + + def testWithOptionalAndDefaultedIndefMode(self): + self.__initWithOptionalAndDefaulted() + assert decoder.decode( + ints2octs((49, 128, 5, 0, 36, 128, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 0, 0, 2, 1, 1, 0, 0)), asn1Spec=self.s + ) == (self.s, null) + + def testWithOptionalAndDefaultedIndefModeReordered(self): + self.__initWithOptionalAndDefaulted() + assert decoder.decode( + ints2octs((49, 128, 2, 1, 1, 5, 0, 36, 128, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 0, 0, 0, 0)), asn1Spec=self.s + ) == (self.s, null) + + def testWithOptionalAndDefaultedDefModeChunked(self): + self.__initWithOptionalAndDefaulted() + assert decoder.decode( + ints2octs((49, 24, 5, 0, 36, 17, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110, 2, 1, 1)), asn1Spec=self.s + ) == (self.s, null) + + def testWithOptionalAndDefaultedIndefModeChunked(self): + self.__initWithOptionalAndDefaulted() + assert decoder.decode( + ints2octs((49, 128, 5, 0, 36, 128, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110, 0, 0, 2, 1, 1, 0, 0)), asn1Spec=self.s + ) == (self.s, null) + + +class SequenceOfWithExpTaggedOctetStringDecoder(BaseTestCase): + def setUp(self): + BaseTestCase.setUp(self) + self.s = univ.SequenceOf( + componentType=univ.OctetString().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 3)) + ) + self.s.setComponentByPosition(0, 'q') + self.s2 = univ.SequenceOf() + + def testDefModeSchema(self): + s, r = decoder.decode(ints2octs((48, 5, 163, 3, 4, 1, 113)), asn1Spec=self.s) + assert not r + assert s == self.s + assert s.tagSet == self.s.tagSet + + def testIndefModeSchema(self): + s, r = decoder.decode(ints2octs((48, 128, 163, 128, 4, 1, 113, 0, 0, 0, 0)), asn1Spec=self.s) + assert not r + assert s == self.s + assert s.tagSet == self.s.tagSet + + def testDefModeNoComponent(self): + s, r = decoder.decode(ints2octs((48, 5, 163, 3, 4, 1, 113)), asn1Spec=self.s2) + assert not r + assert s == self.s + assert s.tagSet == self.s.tagSet + + def testIndefModeNoComponent(self): + s, r = decoder.decode(ints2octs((48, 128, 163, 128, 4, 1, 113, 0, 0, 0, 0)), asn1Spec=self.s2) + assert not r + assert s == self.s + assert s.tagSet == self.s.tagSet + + def testDefModeSchemaless(self): + s, r = decoder.decode(ints2octs((48, 5, 163, 3, 4, 1, 113))) + assert not r + assert s == self.s + assert s.tagSet == self.s.tagSet + + def testIndefModeSchemaless(self): + s, r = decoder.decode(ints2octs((48, 128, 163, 128, 4, 1, 113, 0, 0, 0, 0))) + assert not r + assert s == self.s + assert s.tagSet == self.s.tagSet + + +class SequenceWithExpTaggedOctetStringDecoder(BaseTestCase): + def setUp(self): + BaseTestCase.setUp(self) + self.s = univ.Sequence( + componentType=namedtype.NamedTypes( + namedtype.NamedType( + 'x', univ.OctetString().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 3)) + ) + ) + ) + self.s.setComponentByPosition(0, 'q') + self.s2 = univ.Sequence() + + def testDefModeSchema(self): + s, r = decoder.decode(ints2octs((48, 5, 163, 3, 4, 1, 113)), asn1Spec=self.s) + assert not r + assert s == self.s + assert s.tagSet == self.s.tagSet + + def testIndefModeSchema(self): + s, r = decoder.decode(ints2octs((48, 128, 163, 128, 4, 1, 113, 0, 0, 0, 0)), asn1Spec=self.s) + assert not r + assert s == self.s + assert s.tagSet == self.s.tagSet + + def testDefModeNoComponent(self): + s, r = decoder.decode(ints2octs((48, 5, 163, 3, 4, 1, 113)), asn1Spec=self.s2) + assert not r + assert s == self.s + assert s.tagSet == self.s.tagSet + + def testIndefModeNoComponent(self): + s, r = decoder.decode(ints2octs((48, 128, 163, 128, 4, 1, 113, 0, 0, 0, 0)), asn1Spec=self.s2) + assert not r + assert s == self.s + assert s.tagSet == self.s.tagSet + + def testDefModeSchemaless(self): + s, r = decoder.decode(ints2octs((48, 5, 163, 3, 4, 1, 113))) + assert not r + assert s == self.s + assert s.tagSet == self.s.tagSet + + def testIndefModeSchemaless(self): + s, r = decoder.decode(ints2octs((48, 128, 163, 128, 4, 1, 113, 0, 0, 0, 0))) + assert not r + assert s == self.s + assert s.tagSet == self.s.tagSet + + +class ChoiceDecoderTestCase(BaseTestCase): + def setUp(self): + BaseTestCase.setUp(self) + self.s = univ.Choice( + componentType=namedtype.NamedTypes( + namedtype.NamedType('place-holder', univ.Null(null)), + namedtype.NamedType('number', univ.Integer(0)), + namedtype.NamedType('string', univ.OctetString()) + ) + ) + + def testBySpec(self): + self.s.setComponentByPosition(0, univ.Null(null)) + assert decoder.decode( + ints2octs((5, 0)), asn1Spec=self.s + ) == (self.s, null) + + def testWithoutSpec(self): + self.s.setComponentByPosition(0, univ.Null(null)) + assert decoder.decode(ints2octs((5, 0))) == (self.s, null) + assert decoder.decode(ints2octs((5, 0))) == (univ.Null(null), null) + + def testUndefLength(self): + self.s.setComponentByPosition(2, univ.OctetString('abcdefgh')) + assert decoder.decode(ints2octs((36, 128, 4, 3, 97, 98, 99, 4, 3, 100, 101, 102, 4, 2, 103, 104, 0, 0)), + asn1Spec=self.s) == (self.s, null) + + def testExplicitTag(self): + s = self.s.subtype(explicitTag=tag.Tag(tag.tagClassContext, + tag.tagFormatConstructed, 4)) + s.setComponentByPosition(0, univ.Null(null)) + assert decoder.decode(ints2octs((164, 2, 5, 0)), asn1Spec=s) == (s, null) + + def testExplicitTagUndefLength(self): + s = self.s.subtype(explicitTag=tag.Tag(tag.tagClassContext, + tag.tagFormatConstructed, 4)) + s.setComponentByPosition(0, univ.Null(null)) + assert decoder.decode(ints2octs((164, 128, 5, 0, 0, 0)), asn1Spec=s) == (s, null) + + +class AnyDecoderTestCase(BaseTestCase): + def setUp(self): + BaseTestCase.setUp(self) + self.s = univ.Any() + + def testByUntagged(self): + assert decoder.decode( + ints2octs((4, 3, 102, 111, 120)), asn1Spec=self.s + ) == (univ.Any('\004\003fox'), null) + + def testTaggedEx(self): + s = univ.Any('\004\003fox').subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 4)) + assert decoder.decode(ints2octs((164, 5, 4, 3, 102, 111, 120)), asn1Spec=s) == (s, null) + + def testTaggedIm(self): + s = univ.Any('\004\003fox').subtype(implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 4)) + assert decoder.decode(ints2octs((132, 5, 4, 3, 102, 111, 120)), asn1Spec=s) == (s, null) + + def testByUntaggedIndefMode(self): + assert decoder.decode( + ints2octs((4, 3, 102, 111, 120)), asn1Spec=self.s + ) == (univ.Any('\004\003fox'), null) + + def testTaggedExIndefMode(self): + s = univ.Any('\004\003fox').subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 4)) + assert decoder.decode(ints2octs((164, 128, 4, 3, 102, 111, 120, 0, 0)), asn1Spec=s) == (s, null) + + def testTaggedImIndefMode(self): + s = univ.Any('\004\003fox').subtype(implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 4)) + assert decoder.decode(ints2octs((164, 128, 4, 3, 102, 111, 120, 0, 0)), asn1Spec=s) == (s, null) + + def testByUntaggedSubst(self): + assert decoder.decode( + ints2octs((4, 3, 102, 111, 120)), + asn1Spec=self.s, + substrateFun=lambda a, b, c: (b, b[c:]) + ) == (ints2octs((4, 3, 102, 111, 120)), str2octs('')) + + def testTaggedExSubst(self): + assert decoder.decode( + ints2octs((164, 5, 4, 3, 102, 111, 120)), + asn1Spec=self.s, + substrateFun=lambda a, b, c: (b, b[c:]) + ) == (ints2octs((164, 5, 4, 3, 102, 111, 120)), str2octs('')) + + +class EndOfOctetsTestCase(BaseTestCase): + def testUnexpectedEoo(self): + try: + decoder.decode(ints2octs((0, 0))) + except PyAsn1Error: + pass + else: + assert 0, 'end-of-contents octets accepted at top level' + + def testExpectedEoo(self): + result, remainder = decoder.decode(ints2octs((0, 0)), allowEoo=True) + assert eoo.endOfOctets.isSameTypeWith(result) and result == eoo.endOfOctets and result is eoo.endOfOctets + assert remainder == null + + def testDefiniteNoEoo(self): + try: + decoder.decode(ints2octs((0x23, 0x02, 0x00, 0x00))) + except PyAsn1Error: + pass + else: + assert 0, 'end-of-contents octets accepted inside definite-length encoding' + + def testIndefiniteEoo(self): + result, remainder = decoder.decode(ints2octs((0x23, 0x80, 0x00, 0x00))) + assert result == () and remainder == null, 'incorrect decoding of indefinite length end-of-octets' + + def testNoLongFormEoo(self): + try: + decoder.decode(ints2octs((0x23, 0x80, 0x00, 0x81, 0x00))) + except PyAsn1Error: + pass + else: + assert 0, 'end-of-contents octets accepted with invalid long-form length' + + def testNoConstructedEoo(self): + try: + decoder.decode(ints2octs((0x23, 0x80, 0x20, 0x00))) + except PyAsn1Error: + pass + else: + assert 0, 'end-of-contents octets accepted with invalid constructed encoding' + + def testNoEooData(self): + try: + decoder.decode(ints2octs((0x23, 0x80, 0x00, 0x01, 0x00))) + except PyAsn1Error: + pass + else: + assert 0, 'end-of-contents octets accepted with unexpected data' + + +class NonStringDecoderTestCase(BaseTestCase): + def setUp(self): + BaseTestCase.setUp(self) + self.s = univ.Sequence( + componentType=namedtype.NamedTypes( + namedtype.NamedType('place-holder', univ.Null(null)), + namedtype.NamedType('first-name', univ.OctetString(null)), + namedtype.NamedType('age', univ.Integer(33)) + ) + ) + self.s.setComponentByPosition(0, univ.Null(null)) + self.s.setComponentByPosition(1, univ.OctetString('quick brown')) + self.s.setComponentByPosition(2, univ.Integer(1)) + + self.substrate = ints2octs([48, 18, 5, 0, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 2, 1, 1]) + + def testOctetString(self): + s, _ = decoder.decode(univ.OctetString(self.substrate), asn1Spec=self.s) + assert self.s == s + + def testAny(self): + s, _ = decoder.decode(univ.Any(self.substrate), asn1Spec=self.s) + assert self.s == s + + +class ErrorOnDecodingTestCase(BaseTestCase): + + def testErrorCondition(self): + decode = decoder.Decoder(decoder.tagMap, decoder.typeMap) + + try: + asn1Object, rest = decode(str2octs('abc')) + + except PyAsn1Error: + exc = sys.exc_info()[1] + assert isinstance(exc, PyAsn1Error), ( + 'Unexpected exception raised %r' % (exc,)) + + else: + assert False, 'Unexpected decoder result %r' % (asn1Object,) + + def testRawDump(self): + decode = decoder.Decoder(decoder.tagMap, decoder.typeMap) + + decode.defaultErrorState = decoder.stDumpRawValue + + asn1Object, rest = decode(ints2octs( + (31, 8, 2, 1, 1, 131, 3, 2, 1, 12))) + + assert isinstance(asn1Object, univ.Any), ( + 'Unexpected raw dump type %r' % (asn1Object,)) + assert asn1Object.asNumbers() == (31, 8, 2, 1, 1), ( + 'Unexpected raw dump value %r' % (asn1Object,)) + assert rest == ints2octs((131, 3, 2, 1, 12)), ( + 'Unexpected rest of substrate after raw dump %r' % rest) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + unittest.TextTestRunner(verbosity=2).run(suite) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/tests/codec/ber/test_encoder.py b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/tests/codec/ber/test_encoder.py new file mode 100644 index 00000000..df82e7b4 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/tests/codec/ber/test_encoder.py @@ -0,0 +1,1503 @@ +# +# This file is part of pyasn1 software. +# +# Copyright (c) 2005-2019, Ilya Etingof <etingof@gmail.com> +# License: http://snmplabs.com/pyasn1/license.html +# +import sys + +try: + import unittest2 as unittest + +except ImportError: + import unittest + +from tests.base import BaseTestCase + +from pyasn1.type import tag +from pyasn1.type import namedtype +from pyasn1.type import opentype +from pyasn1.type import univ +from pyasn1.type import char +from pyasn1.codec.ber import encoder +from pyasn1.compat.octets import ints2octs +from pyasn1.error import PyAsn1Error + + +class LargeTagEncoderTestCase(BaseTestCase): + def setUp(self): + BaseTestCase.setUp(self) + + self.o = univ.Integer().subtype( + value=1, explicitTag=tag.Tag(tag.tagClassApplication, tag.tagFormatSimple, 0xdeadbeaf) + ) + + def testEncoder(self): + assert encoder.encode(self.o) == ints2octs((127, 141, 245, 182, 253, 47, 3, 2, 1, 1)) + + +class IntegerEncoderTestCase(BaseTestCase): + def testPosInt(self): + assert encoder.encode(univ.Integer(12)) == ints2octs((2, 1, 12)) + + def testNegInt(self): + assert encoder.encode(univ.Integer(-12)) == ints2octs((2, 1, 244)) + + def testZero(self): + assert encoder.encode(univ.Integer(0)) == ints2octs((2, 1, 0)) + + def testCompactZero(self): + encoder.IntegerEncoder.supportCompactZero = True + substrate = encoder.encode(univ.Integer(0)) + encoder.IntegerEncoder.supportCompactZero = False + assert substrate == ints2octs((2, 0)) + + def testMinusOne(self): + assert encoder.encode(univ.Integer(-1)) == ints2octs((2, 1, 255)) + + def testPosLong(self): + assert encoder.encode( + univ.Integer(0xffffffffffffffff) + ) == ints2octs((2, 9, 0, 255, 255, 255, 255, 255, 255, 255, 255)) + + def testNegLong(self): + assert encoder.encode( + univ.Integer(-0xffffffffffffffff) + ) == ints2octs((2, 9, 255, 0, 0, 0, 0, 0, 0, 0, 1)) + + +class IntegerEncoderWithSchemaTestCase(BaseTestCase): + def testPosInt(self): + assert encoder.encode(12, asn1Spec=univ.Integer()) == ints2octs((2, 1, 12)) + + def testNegInt(self): + assert encoder.encode(-12, asn1Spec=univ.Integer()) == ints2octs((2, 1, 244)) + + def testZero(self): + assert encoder.encode(0, asn1Spec=univ.Integer()) == ints2octs((2, 1, 0)) + + def testPosLong(self): + assert encoder.encode( + 0xffffffffffffffff, asn1Spec=univ.Integer() + ) == ints2octs((2, 9, 0, 255, 255, 255, 255, 255, 255, 255, 255)) + + +class BooleanEncoderTestCase(BaseTestCase): + def testTrue(self): + assert encoder.encode(univ.Boolean(1)) == ints2octs((1, 1, 1)) + + def testFalse(self): + assert encoder.encode(univ.Boolean(0)) == ints2octs((1, 1, 0)) + + +class BooleanEncoderWithSchemaTestCase(BaseTestCase): + def testTrue(self): + assert encoder.encode(True, asn1Spec=univ.Boolean()) == ints2octs((1, 1, 1)) + + def testFalse(self): + assert encoder.encode(False, asn1Spec=univ.Boolean()) == ints2octs((1, 1, 0)) + + +class BitStringEncoderTestCase(BaseTestCase): + def setUp(self): + BaseTestCase.setUp(self) + self.b = univ.BitString((1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1)) + + def testDefMode(self): + assert encoder.encode(self.b) == ints2octs((3, 3, 1, 169, 138)) + + def testIndefMode(self): + assert encoder.encode( + self.b, defMode=False + ) == ints2octs((3, 3, 1, 169, 138)) + + def testDefModeChunked(self): + assert encoder.encode( + self.b, maxChunkSize=1 + ) == ints2octs((35, 8, 3, 2, 0, 169, 3, 2, 1, 138)) + + def testIndefModeChunked(self): + assert encoder.encode( + self.b, defMode=False, maxChunkSize=1 + ) == ints2octs((35, 128, 3, 2, 0, 169, 3, 2, 1, 138, 0, 0)) + + def testEmptyValue(self): + assert encoder.encode(univ.BitString([])) == ints2octs((3, 1, 0)) + + +class BitStringEncoderWithSchemaTestCase(BaseTestCase): + def setUp(self): + BaseTestCase.setUp(self) + self.b = (1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1) + self.s = univ.BitString() + + def testDefMode(self): + assert encoder.encode(self.b, asn1Spec=self.s) == ints2octs((3, 3, 1, 169, 138)) + + def testIndefMode(self): + assert encoder.encode( + self.b, asn1Spec=self.s, defMode=False + ) == ints2octs((3, 3, 1, 169, 138)) + + def testDefModeChunked(self): + assert encoder.encode( + self.b, asn1Spec=self.s, maxChunkSize=1 + ) == ints2octs((35, 8, 3, 2, 0, 169, 3, 2, 1, 138)) + + def testIndefModeChunked(self): + assert encoder.encode( + self.b, asn1Spec=self.s, defMode=False, maxChunkSize=1 + ) == ints2octs((35, 128, 3, 2, 0, 169, 3, 2, 1, 138, 0, 0)) + + def testEmptyValue(self): + assert encoder.encode([], asn1Spec=self.s) == ints2octs((3, 1, 0)) + + +class OctetStringEncoderTestCase(BaseTestCase): + def setUp(self): + BaseTestCase.setUp(self) + self.o = univ.OctetString('Quick brown fox') + + def testDefMode(self): + assert encoder.encode(self.o) == ints2octs( + (4, 15, 81, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 32, 102, 111, 120)) + + def testIndefMode(self): + assert encoder.encode( + self.o, defMode=False + ) == ints2octs((4, 15, 81, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 32, 102, 111, 120)) + + def testDefModeChunked(self): + assert encoder.encode( + self.o, maxChunkSize=4 + ) == ints2octs((36, 23, 4, 4, 81, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 4, 111, 119, + 110, 32, 4, 3, 102, 111, 120)) + + def testIndefModeChunked(self): + assert encoder.encode( + self.o, defMode=False, maxChunkSize=4 + ) == ints2octs((36, 128, 4, 4, 81, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 4, 111, 119, 110, + 32, 4, 3, 102, 111, 120, 0, 0)) + + +class OctetStringEncoderWithSchemaTestCase(BaseTestCase): + def setUp(self): + BaseTestCase.setUp(self) + self.s = univ.OctetString() + self.o = 'Quick brown fox' + + def testDefMode(self): + assert encoder.encode(self.o, asn1Spec=self.s) == ints2octs( + (4, 15, 81, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 32, 102, 111, 120)) + + def testIndefMode(self): + assert encoder.encode( + self.o, asn1Spec=self.s, defMode=False + ) == ints2octs((4, 15, 81, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 32, 102, 111, 120)) + + def testDefModeChunked(self): + assert encoder.encode( + self.o, asn1Spec=self.s, maxChunkSize=4 + ) == ints2octs((36, 23, 4, 4, 81, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 4, 111, 119, + 110, 32, 4, 3, 102, 111, 120)) + + def testIndefModeChunked(self): + assert encoder.encode( + self.o, asn1Spec=self.s, defMode=False, maxChunkSize=4 + ) == ints2octs((36, 128, 4, 4, 81, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 4, 111, 119, 110, + 32, 4, 3, 102, 111, 120, 0, 0)) + + +class ExpTaggedOctetStringEncoderTestCase(BaseTestCase): + def setUp(self): + BaseTestCase.setUp(self) + self.o = univ.OctetString().subtype( + value='Quick brown fox', + explicitTag=tag.Tag(tag.tagClassApplication, tag.tagFormatSimple, 5) + ) + + def testDefMode(self): + assert encoder.encode(self.o) == ints2octs( + (101, 17, 4, 15, 81, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 32, 102, 111, 120)) + + def testIndefMode(self): + assert encoder.encode( + self.o, defMode=False + ) == ints2octs((101, 128, 4, 15, 81, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 32, 102, 111, 120, 0, 0)) + + def testDefModeChunked(self): + assert encoder.encode( + self.o, defMode=True, maxChunkSize=4 + ) == ints2octs((101, 25, 36, 23, 4, 4, 81, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 4, 111, 119, 110, 32, 4, 3, + 102, 111, 120)) + + def testIndefModeChunked(self): + assert encoder.encode( + self.o, defMode=False, maxChunkSize=4 + ) == ints2octs((101, 128, 36, 128, 4, 4, 81, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 4, 111, 119, 110, 32, 4, 3, 102, 111, 120, 0, 0, 0, 0)) + + +class NullEncoderTestCase(BaseTestCase): + def testNull(self): + assert encoder.encode(univ.Null('')) == ints2octs((5, 0)) + + +class NullEncoderWithSchemaTestCase(BaseTestCase): + def testNull(self): + assert encoder.encode(None, univ.Null()) == ints2octs((5, 0)) + + +class ObjectIdentifierEncoderTestCase(BaseTestCase): + def testOne(self): + assert encoder.encode( + univ.ObjectIdentifier((1, 3, 6, 0, 0xffffe)) + ) == ints2octs((6, 6, 43, 6, 0, 191, 255, 126)) + + def testEdge1(self): + assert encoder.encode( + univ.ObjectIdentifier((0, 39)) + ) == ints2octs((6, 1, 39)) + + def testEdge2(self): + assert encoder.encode( + univ.ObjectIdentifier((1, 39)) + ) == ints2octs((6, 1, 79)) + + def testEdge3(self): + # 01111111 + assert encoder.encode( + univ.ObjectIdentifier((2, 40)) + ) == ints2octs((6, 1, 120)) + + def testEdge4(self): + # 10010000|10000000|10000000|10000000|01001111 + assert encoder.encode( + univ.ObjectIdentifier((2, 0xffffffff)) + ) == ints2octs((6, 5, 0x90, 0x80, 0x80, 0x80, 0x4F)) + + def testEdge5(self): + # 01111111 + assert encoder.encode( + univ.ObjectIdentifier((2, 47)) + ) == ints2octs((6, 1, 0x7F)) + + def testEdge6(self): + # 10000001|00000000 + assert encoder.encode( + univ.ObjectIdentifier((2, 48)) + ) == ints2octs((6, 2, 0x81, 0x00)) + + def testEdge7(self): + # 10000001|00110100|00000003 + assert encoder.encode( + univ.ObjectIdentifier((2, 100, 3)) + ) == ints2octs((6, 3, 0x81, 0x34, 0x03)) + + def testEdge8(self): + # 10000101|00000000 + assert encoder.encode( + univ.ObjectIdentifier((2, 560)) + ) == ints2octs((6, 2, 133, 0)) + + def testEdge9(self): + # 10001000|10000100|10000111|0000010 + assert encoder.encode( + univ.ObjectIdentifier((2, 16843570)) + ) == ints2octs((6, 4, 0x88, 0x84, 0x87, 0x02)) + + def testEdgeA(self): + assert encoder.encode( + univ.ObjectIdentifier((2, 5)) + ) == ints2octs((6, 1, 85)) + + def testImpossible1(self): + try: + encoder.encode(univ.ObjectIdentifier((3, 1, 2))) + except PyAsn1Error: + pass + else: + assert 0, 'impossible leading arc tolerated' + + def testImpossible2(self): + try: + encoder.encode(univ.ObjectIdentifier((0,))) + except PyAsn1Error: + pass + else: + assert 0, 'single arc OID tolerated' + + def testImpossible3(self): + try: + encoder.encode(univ.ObjectIdentifier((0, 40))) + except PyAsn1Error: + pass + else: + assert 0, 'second arc overflow tolerated' + + def testImpossible4(self): + try: + encoder.encode(univ.ObjectIdentifier((1, 40))) + except PyAsn1Error: + pass + else: + assert 0, 'second arc overflow tolerated' + + def testLarge1(self): + assert encoder.encode( + univ.ObjectIdentifier((2, 18446744073709551535184467440737095)) + ) == ints2octs((0x06, 0x11, 0x83, 0xC6, 0xDF, 0xD4, 0xCC, 0xB3, 0xFF, 0xFF, 0xFE, 0xF0, 0xB8, 0xD6, 0xB8, 0xCB, + 0xE2, 0xB7, 0x17)) + + def testLarge2(self): + assert encoder.encode( + univ.ObjectIdentifier((2, 999, 18446744073709551535184467440737095)) + ) == ints2octs((0x06, 0x13, 0x88, 0x37, 0x83, 0xC6, 0xDF, 0xD4, 0xCC, 0xB3, 0xFF, 0xFF, 0xFE, 0xF0, 0xB8, 0xD6, + 0xB8, 0xCB, 0xE2, 0xB6, 0x47)) + + +class ObjectIdentifierWithSchemaEncoderTestCase(BaseTestCase): + def testOne(self): + assert encoder.encode( + (1, 3, 6, 0, 0xffffe), asn1Spec=univ.ObjectIdentifier() + ) == ints2octs((6, 6, 43, 6, 0, 191, 255, 126)) + + +class RealEncoderTestCase(BaseTestCase): + def testChar(self): + assert encoder.encode( + univ.Real((123, 10, 11)) + ) == ints2octs((9, 7, 3, 49, 50, 51, 69, 49, 49)) + + def testBin1(self): + assert encoder.encode( # default binEncBase = 2 + univ.Real((0.5, 2, 0)) # check encbase = 2 and exponent = -1 + ) == ints2octs((9, 3, 128, 255, 1)) + + def testBin2(self): + r = univ.Real((3.25, 2, 0)) + r.binEncBase = 8 # change binEncBase only for this instance of Real + assert encoder.encode( + r # check encbase = 8 + ) == ints2octs((9, 3, 148, 255, 13)) + + def testBin3(self): + # change binEncBase in the RealEncoder instance => for all further Real + binEncBase, encoder.typeMap[univ.Real.typeId].binEncBase = encoder.typeMap[univ.Real.typeId].binEncBase, 16 + assert encoder.encode( + univ.Real((0.00390625, 2, 0)) # check encbase = 16 + ) == ints2octs((9, 3, 160, 254, 1)) + encoder.typeMap[univ.Real.typeId].binEncBase = binEncBase + + def testBin4(self): + # choose binEncBase automatically for all further Real (testBin[4-7]) + binEncBase, encoder.typeMap[univ.Real.typeId].binEncBase = encoder.typeMap[univ.Real.typeId].binEncBase, None + assert encoder.encode( + univ.Real((1, 2, 0)) # check exponent = 0 + ) == ints2octs((9, 3, 128, 0, 1)) + encoder.typeMap[univ.Real.typeId].binEncBase = binEncBase + + def testBin5(self): + assert encoder.encode( + univ.Real((3, 2, -1020)) # case of 2 octs for exponent and + # negative exponent and abs(exponent) is + # all 1's and fills the whole octet(s) + ) == ints2octs((9, 4, 129, 252, 4, 3)) + + def testBin6(self): + assert encoder.encode( + univ.Real((1, 2, 262140)) # case of 3 octs for exponent and + # check that first 9 bits for exponent + # are not all 1's + ) == ints2octs((9, 5, 130, 3, 255, 252, 1)) + + def testBin7(self): + assert encoder.encode( + univ.Real((-1, 2, 76354972)) # case of >3 octs for exponent and + # mantissa < 0 + ) == ints2octs((9, 7, 195, 4, 4, 141, 21, 156, 1)) + + def testPlusInf(self): + assert encoder.encode(univ.Real('inf')) == ints2octs((9, 1, 64)) + + def testMinusInf(self): + assert encoder.encode(univ.Real('-inf')) == ints2octs((9, 1, 65)) + + def testZero(self): + assert encoder.encode(univ.Real(0)) == ints2octs((9, 0)) + + +class RealEncoderWithSchemaTestCase(BaseTestCase): + def testChar(self): + assert encoder.encode( + (123, 10, 11), asn1Spec=univ.Real() + ) == ints2octs((9, 7, 3, 49, 50, 51, 69, 49, 49)) + + +if sys.version_info[0:2] > (2, 5): + class UniversalStringEncoderTestCase(BaseTestCase): + def testEncoding(self): + assert encoder.encode(char.UniversalString(sys.version_info[0] >= 3 and 'abc' or unicode('abc'))) == ints2octs( + (28, 12, 0, 0, 0, 97, 0, 0, 0, 98, 0, 0, 0, 99)), 'Incorrect encoding' + + + class UniversalStringEncoderWithSchemaTestCase(BaseTestCase): + def testEncoding(self): + assert encoder.encode( + sys.version_info[0] >= 3 and 'abc' or unicode('abc'), asn1Spec=char.UniversalString() + ) == ints2octs((28, 12, 0, 0, 0, 97, 0, 0, 0, 98, 0, 0, 0, 99)), 'Incorrect encoding' + + +class BMPStringEncoderTestCase(BaseTestCase): + def testEncoding(self): + assert encoder.encode(char.BMPString(sys.version_info[0] >= 3 and 'abc' or unicode('abc'))) == ints2octs( + (30, 6, 0, 97, 0, 98, 0, 99)), 'Incorrect encoding' + + +class BMPStringEncoderWithSchemaTestCase(BaseTestCase): + def testEncoding(self): + assert encoder.encode( + sys.version_info[0] >= 3 and 'abc' or unicode('abc'), asn1Spec=char.BMPString() + ) == ints2octs((30, 6, 0, 97, 0, 98, 0, 99)), 'Incorrect encoding' + + +class UTF8StringEncoderTestCase(BaseTestCase): + def testEncoding(self): + assert encoder.encode(char.UTF8String(sys.version_info[0] >= 3 and 'abc' or unicode('abc'))) == ints2octs( + (12, 3, 97, 98, 99)), 'Incorrect encoding' + + +class UTF8StringEncoderWithSchemaTestCase(BaseTestCase): + def testEncoding(self): + assert encoder.encode( + sys.version_info[0] >= 3 and 'abc' or unicode('abc'), asn1Spec=char.UTF8String() + ) == ints2octs((12, 3, 97, 98, 99)), 'Incorrect encoding' + + +class SequenceOfEncoderTestCase(BaseTestCase): + def testEmpty(self): + s = univ.SequenceOf() + s.clear() + assert encoder.encode(s) == ints2octs((48, 0)) + + def testDefMode(self): + s = univ.SequenceOf() + s.setComponentByPosition(0, univ.OctetString('quick brown')) + assert encoder.encode(s) == ints2octs((48, 13, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110)) + + def testIndefMode(self): + s = univ.SequenceOf() + s.setComponentByPosition(0, univ.OctetString('quick brown')) + assert encoder.encode( + s, defMode=False + ) == ints2octs((48, 128, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 0, 0)) + + def testDefModeChunked(self): + s = univ.SequenceOf() + s.setComponentByPosition(0, univ.OctetString('quick brown')) + assert encoder.encode( + s, defMode=True, maxChunkSize=4 + ) == ints2octs((48, 19, 36, 17, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110)) + + def testIndefModeChunked(self): + s = univ.SequenceOf() + s.setComponentByPosition(0, univ.OctetString('quick brown')) + assert encoder.encode( + s, defMode=False, maxChunkSize=4 + ) == ints2octs((48, 128, 36, 128, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110, 0, 0, 0, 0)) + + +class SequenceOfEncoderWithSchemaTestCase(BaseTestCase): + def setUp(self): + BaseTestCase.setUp(self) + self.s = univ.SequenceOf(componentType=univ.OctetString()) + self.v = ['quick brown'] + + def testEmpty(self): + assert encoder.encode([], asn1Spec=self.s) == ints2octs((48, 0)) + + def testDefMode(self): + assert encoder.encode( + self.v, asn1Spec=self.s + ) == ints2octs((48, 13, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110)) + + def testIndefMode(self): + assert encoder.encode( + self.v, asn1Spec=self.s, defMode=False + ) == ints2octs((48, 128, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 0, 0)) + + def testDefModeChunked(self): + assert encoder.encode( + self.v, asn1Spec=self.s, defMode=True, maxChunkSize=4 + ) == ints2octs((48, 19, 36, 17, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110)) + + def testIndefModeChunked(self): + assert encoder.encode( + self.v, asn1Spec=self.s, defMode=False, maxChunkSize=4 + ) == ints2octs((48, 128, 36, 128, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110, 0, 0, 0, 0)) + + +class SequenceOfEncoderWithComponentsSchemaTestCase(BaseTestCase): + def setUp(self): + BaseTestCase.setUp(self) + self.s = univ.SequenceOf(componentType=univ.OctetString()) + + def __init(self): + self.s.clear() + self.s.setComponentByPosition(0, 'quick brown') + + def testDefMode(self): + self.__init() + assert encoder.encode(self.s) == ints2octs((48, 13, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110)) + + def testIndefMode(self): + self.__init() + assert encoder.encode( + self.s, defMode=False + ) == ints2octs((48, 128, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 0, 0)) + + def testDefModeChunked(self): + self.__init() + assert encoder.encode( + self.s, defMode=True, maxChunkSize=4 + ) == ints2octs((48, 19, 36, 17, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110)) + + def testIndefModeChunked(self): + self.__init() + assert encoder.encode( + self.s, defMode=False, maxChunkSize=4 + ) == ints2octs((48, 128, 36, 128, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110, 0, 0, 0, 0)) + + +class SetOfEncoderTestCase(BaseTestCase): + def testEmpty(self): + s = univ.SetOf() + s.clear() + assert encoder.encode(s) == ints2octs((49, 0)) + + def testDefMode(self): + s = univ.SetOf() + s.setComponentByPosition(0, univ.OctetString('quick brown')) + assert encoder.encode(s) == ints2octs((49, 13, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110)) + + def testIndefMode(self): + s = univ.SetOf() + s.setComponentByPosition(0, univ.OctetString('quick brown')) + assert encoder.encode( + s, defMode=False + ) == ints2octs((49, 128, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 0, 0)) + + def testDefModeChunked(self): + s = univ.SetOf() + s.setComponentByPosition(0, univ.OctetString('quick brown')) + assert encoder.encode( + s, defMode=True, maxChunkSize=4 + ) == ints2octs((49, 19, 36, 17, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110)) + + def testIndefModeChunked(self): + s = univ.SetOf() + s.setComponentByPosition(0, univ.OctetString('quick brown')) + assert encoder.encode( + s, defMode=False, maxChunkSize=4 + ) == ints2octs((49, 128, 36, 128, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110, 0, 0, 0, 0)) + + +class SetOfEncoderWithSchemaTestCase(BaseTestCase): + def setUp(self): + BaseTestCase.setUp(self) + self.s = univ.SetOf(componentType=univ.OctetString()) + self.v = ['quick brown'] + + def testEmpty(self): + s = univ.SetOf() + assert encoder.encode([], asn1Spec=self.s) == ints2octs((49, 0)) + + def testDefMode(self): + assert encoder.encode( + self.v, asn1Spec=self.s + ) == ints2octs((49, 13, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110)) + + def testIndefMode(self): + assert encoder.encode( + self.v, asn1Spec=self.s, defMode=False + ) == ints2octs((49, 128, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 0, 0)) + + def testDefModeChunked(self): + assert encoder.encode( + self.v, asn1Spec=self.s, defMode=True, maxChunkSize=4 + ) == ints2octs((49, 19, 36, 17, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110)) + + def testIndefModeChunked(self): + assert encoder.encode( + self.v, asn1Spec=self.s, defMode=False, maxChunkSize=4 + ) == ints2octs( + (49, 128, 36, 128, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110, 0, 0, 0, 0)) + + +class SetOfEncoderWithComponentsSchemaTestCase(BaseTestCase): + def setUp(self): + BaseTestCase.setUp(self) + self.s = univ.SetOf(componentType=univ.OctetString()) + + def __init(self): + self.s.clear() + self.s.setComponentByPosition(0, 'quick brown') + + def testDefMode(self): + self.__init() + assert encoder.encode(self.s) == ints2octs((49, 13, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110)) + + def testIndefMode(self): + self.__init() + assert encoder.encode( + self.s, defMode=False + ) == ints2octs((49, 128, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 0, 0)) + + def testDefModeChunked(self): + self.__init() + assert encoder.encode( + self.s, defMode=True, maxChunkSize=4 + ) == ints2octs((49, 19, 36, 17, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110)) + + def testIndefModeChunked(self): + self.__init() + assert encoder.encode( + self.s, defMode=False, maxChunkSize=4 + ) == ints2octs((49, 128, 36, 128, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110, 0, 0, 0, 0)) + + +class SequenceEncoderTestCase(BaseTestCase): + def setUp(self): + BaseTestCase.setUp(self) + self.s = univ.Sequence() + self.s.setComponentByPosition(0, univ.Null('')) + self.s.setComponentByPosition(1, univ.OctetString('quick brown')) + self.s.setComponentByPosition(2, univ.Integer(1)) + + def testDefMode(self): + assert encoder.encode(self.s) == ints2octs((48, 18, 5, 0, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 2, 1, 1)) + + def testIndefMode(self): + assert encoder.encode( + self.s, defMode=False + ) == ints2octs((48, 128, 5, 0, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 2, 1, 1, 0, 0)) + + def testDefModeChunked(self): + assert encoder.encode( + self.s, defMode=True, maxChunkSize=4 + ) == ints2octs((48, 24, 5, 0, 36, 17, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110, 2, 1, 1)) + + def testIndefModeChunked(self): + assert encoder.encode( + self.s, defMode=False, maxChunkSize=4 + ) == ints2octs((48, 128, 5, 0, 36, 128, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110, 0, 0, 2, 1, 1, 0, 0)) + + +class SequenceEncoderWithSchemaTestCase(BaseTestCase): + def setUp(self): + BaseTestCase.setUp(self) + self.s = univ.Sequence( + componentType=namedtype.NamedTypes( + namedtype.NamedType('place-holder', univ.Null()), + namedtype.OptionalNamedType('first-name', univ.OctetString()), + namedtype.DefaultedNamedType('age', univ.Integer(33)), + ) + ) + self.v = { + 'place-holder': None, + 'first-name': 'quick brown', + 'age': 1 + } + + def testEmpty(self): + try: + assert encoder.encode({}, asn1Spec=self.s) + + except PyAsn1Error: + pass + + else: + assert False, 'empty bare sequence tolerated' + + def testDefMode(self): + assert encoder.encode( + self.v, asn1Spec=self.s + ) == ints2octs((48, 18, 5, 0, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 2, 1, 1)) + + def testIndefMode(self): + assert encoder.encode( + self.v, asn1Spec=self.s, defMode=False + ) == ints2octs((48, 128, 5, 0, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 2, 1, 1, 0, 0)) + + def testDefModeChunked(self): + assert encoder.encode( + self.v, asn1Spec=self.s, defMode=True, maxChunkSize=4 + ) == ints2octs((48, 24, 5, 0, 36, 17, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110, 2, 1, 1)) + + def testIndefModeChunked(self): + assert encoder.encode( + self.v, asn1Spec=self.s, defMode=False, maxChunkSize=4 + ) == ints2octs((48, 128, 5, 0, 36, 128, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110, 0, 0, 2, 1, 1, 0, 0)) + + +class SequenceEncoderWithUntaggedOpenTypesTestCase(BaseTestCase): + def setUp(self): + BaseTestCase.setUp(self) + + openType = opentype.OpenType( + 'id', + {1: univ.Integer(), + 2: univ.OctetString()} + ) + self.s = univ.Sequence( + componentType=namedtype.NamedTypes( + namedtype.NamedType('id', univ.Integer()), + namedtype.NamedType('blob', univ.Any(), openType=openType) + ) + ) + + def testEncodeOpenTypeChoiceOne(self): + self.s.clear() + + self.s[0] = 1 + self.s[1] = univ.Integer(12) + + assert encoder.encode(self.s, asn1Spec=self.s) == ints2octs( + (48, 5, 2, 1, 1, 49, 50) + ) + + def testEncodeOpenTypeChoiceTwo(self): + self.s.clear() + + self.s[0] = 2 + self.s[1] = univ.OctetString('quick brown') + + assert encoder.encode(self.s, asn1Spec=self.s) == ints2octs( + (48, 14, 2, 1, 2, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110) + ) + + def testEncodeOpenTypeUnknownId(self): + self.s.clear() + + self.s[0] = 2 + self.s[1] = univ.ObjectIdentifier('1.3.6') + + try: + encoder.encode(self.s, asn1Spec=self.s) + + except PyAsn1Error: + assert False, 'incompatible open type tolerated' + + def testEncodeOpenTypeIncompatibleType(self): + self.s.clear() + + self.s[0] = 2 + self.s[1] = univ.ObjectIdentifier('1.3.6') + + try: + encoder.encode(self.s, asn1Spec=self.s) + + except PyAsn1Error: + assert False, 'incompatible open type tolerated' + + +class SequenceEncoderWithImplicitlyTaggedOpenTypesTestCase(BaseTestCase): + def setUp(self): + BaseTestCase.setUp(self) + + openType = opentype.OpenType( + 'id', + {1: univ.Integer(), + 2: univ.OctetString()} + ) + self.s = univ.Sequence( + componentType=namedtype.NamedTypes( + namedtype.NamedType('id', univ.Integer()), + namedtype.NamedType('blob', univ.Any().subtype(implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 3)), openType=openType) + ) + ) + + def testEncodeOpenTypeChoiceOne(self): + self.s.clear() + + self.s[0] = 1 + self.s[1] = univ.Integer(12) + + assert encoder.encode(self.s, asn1Spec=self.s) == ints2octs( + (48, 9, 2, 1, 1, 131, 4, 131, 2, 49, 50) + ) + + +class SequenceEncoderWithExplicitlyTaggedOpenTypesTestCase(BaseTestCase): + def setUp(self): + BaseTestCase.setUp(self) + + openType = opentype.OpenType( + 'id', + {1: univ.Integer(), + 2: univ.OctetString()} + ) + self.s = univ.Sequence( + componentType=namedtype.NamedTypes( + namedtype.NamedType('id', univ.Integer()), + namedtype.NamedType('blob', univ.Any().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 3)), openType=openType) + ) + ) + + def testEncodeOpenTypeChoiceOne(self): + self.s.clear() + + self.s[0] = 1 + self.s[1] = univ.Integer(12) + + assert encoder.encode(self.s, asn1Spec=self.s) == ints2octs( + (48, 9, 2, 1, 1, 163, 4, 163, 2, 49, 50) + ) + + +class SequenceEncoderWithUntaggedSetOfOpenTypesTestCase(BaseTestCase): + def setUp(self): + BaseTestCase.setUp(self) + + openType = opentype.OpenType( + 'id', + {1: univ.Integer(), + 2: univ.OctetString()} + ) + self.s = univ.Sequence( + componentType=namedtype.NamedTypes( + namedtype.NamedType('id', univ.Integer()), + namedtype.NamedType('blob', univ.SetOf( + componentType=univ.Any()), openType=openType) + ) + ) + + def testEncodeOpenTypeChoiceOne(self): + self.s.clear() + + self.s[0] = 1 + self.s[1].append(univ.Integer(12)) + + assert encoder.encode(self.s, asn1Spec=self.s) == ints2octs( + (48, 7, 2, 1, 1, 49, 2, 49, 50) + ) + + def testEncodeOpenTypeChoiceTwo(self): + self.s.clear() + + self.s[0] = 2 + self.s[1].append(univ.OctetString('quick brown')) + + assert encoder.encode(self.s, asn1Spec=self.s) == ints2octs( + (48, 16, 2, 1, 2, 49, 11, 113, 117, 105, 99, 107, 32, 98, 114, + 111, 119, 110) + ) + + def testEncodeOpenTypeUnknownId(self): + self.s.clear() + + self.s[0] = 2 + self.s[1].append(univ.ObjectIdentifier('1.3.6')) + + try: + encoder.encode(self.s, asn1Spec=self.s) + + except PyAsn1Error: + assert False, 'incompatible open type tolerated' + + def testEncodeOpenTypeIncompatibleType(self): + self.s.clear() + + self.s[0] = 2 + self.s[1].append(univ.ObjectIdentifier('1.3.6')) + + try: + encoder.encode(self.s, asn1Spec=self.s) + + except PyAsn1Error: + assert False, 'incompatible open type tolerated' + + +class SequenceEncoderWithImplicitlyTaggedSetOfOpenTypesTestCase(BaseTestCase): + def setUp(self): + BaseTestCase.setUp(self) + + openType = opentype.OpenType( + 'id', + {1: univ.Integer(), + 2: univ.OctetString()} + ) + self.s = univ.Sequence( + componentType=namedtype.NamedTypes( + namedtype.NamedType('id', univ.Integer()), + namedtype.NamedType('blob', univ.SetOf( + componentType=univ.Any().subtype( + implicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatSimple, 3))), + openType=openType) + ) + ) + + def testEncodeOpenTypeChoiceOne(self): + self.s.clear() + + self.s[0] = 1 + self.s[1].append(univ.Integer(12)) + + assert encoder.encode(self.s, asn1Spec=self.s) == ints2octs( + (48, 11, 2, 1, 1, 49, 6, 131, 4, 131, 2, 49, 50) + ) + + +class SequenceEncoderWithExplicitlyTaggedSetOfOpenTypesTestCase(BaseTestCase): + def setUp(self): + BaseTestCase.setUp(self) + + openType = opentype.OpenType( + 'id', + {1: univ.Integer(), + 2: univ.OctetString()} + ) + self.s = univ.Sequence( + componentType=namedtype.NamedTypes( + namedtype.NamedType('id', univ.Integer()), + namedtype.NamedType('blob', univ.SetOf( + componentType=univ.Any().subtype( + explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 3))), + openType=openType) + ) + ) + + def testEncodeOpenTypeChoiceOne(self): + self.s.clear() + + self.s[0] = 1 + self.s[1].append(univ.Integer(12)) + + assert encoder.encode(self.s, asn1Spec=self.s) == ints2octs( + (48, 11, 2, 1, 1, 49, 6, 163, 4, 163, 2, 49, 50) + ) + + +class SequenceEncoderWithComponentsSchemaTestCase(BaseTestCase): + def setUp(self): + BaseTestCase.setUp(self) + self.s = univ.Sequence( + componentType=namedtype.NamedTypes( + namedtype.NamedType('place-holder', univ.Null()), + namedtype.OptionalNamedType('first-name', univ.OctetString()), + namedtype.DefaultedNamedType('age', univ.Integer(33)), + ) + ) + + def __init(self): + self.s.clear() + self.s.setComponentByPosition(0, '') + + def __initWithOptional(self): + self.s.clear() + self.s.setComponentByPosition(0, '') + self.s.setComponentByPosition(1, 'quick brown') + + def __initWithDefaulted(self): + self.s.clear() + self.s.setComponentByPosition(0, '') + self.s.setComponentByPosition(2, 1) + + def __initWithOptionalAndDefaulted(self): + self.s.clear() + self.s.setComponentByPosition(0, univ.Null('')) + self.s.setComponentByPosition(1, univ.OctetString('quick brown')) + self.s.setComponentByPosition(2, univ.Integer(1)) + + def testDefMode(self): + self.__init() + assert encoder.encode(self.s) == ints2octs((48, 2, 5, 0)) + + def testIndefMode(self): + self.__init() + assert encoder.encode( + self.s, defMode=False + ) == ints2octs((48, 128, 5, 0, 0, 0)) + + def testDefModeChunked(self): + self.__init() + assert encoder.encode( + self.s, defMode=True, maxChunkSize=4 + ) == ints2octs((48, 2, 5, 0)) + + def testIndefModeChunked(self): + self.__init() + assert encoder.encode( + self.s, defMode=False, maxChunkSize=4 + ) == ints2octs((48, 128, 5, 0, 0, 0)) + + def testWithOptionalDefMode(self): + self.__initWithOptional() + assert encoder.encode(self.s) == ints2octs( + (48, 15, 5, 0, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110)) + + def testWithOptionalIndefMode(self): + self.__initWithOptional() + assert encoder.encode( + self.s, defMode=False + ) == ints2octs((48, 128, 5, 0, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 0, 0)) + + def testWithOptionalDefModeChunked(self): + self.__initWithOptional() + assert encoder.encode( + self.s, defMode=True, maxChunkSize=4 + ) == ints2octs((48, 21, 5, 0, 36, 17, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110)) + + def testWithOptionalIndefModeChunked(self): + self.__initWithOptional() + assert encoder.encode( + self.s, defMode=False, maxChunkSize=4 + ) == ints2octs( + (48, 128, 5, 0, 36, 128, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110, 0, 0, 0, 0)) + + def testWithDefaultedDefMode(self): + self.__initWithDefaulted() + assert encoder.encode(self.s) == ints2octs((48, 5, 5, 0, 2, 1, 1)) + + def testWithDefaultedIndefMode(self): + self.__initWithDefaulted() + assert encoder.encode( + self.s, defMode=False + ) == ints2octs((48, 128, 5, 0, 2, 1, 1, 0, 0)) + + def testWithDefaultedDefModeChunked(self): + self.__initWithDefaulted() + assert encoder.encode( + self.s, defMode=True, maxChunkSize=4 + ) == ints2octs((48, 5, 5, 0, 2, 1, 1)) + + def testWithDefaultedIndefModeChunked(self): + self.__initWithDefaulted() + assert encoder.encode( + self.s, defMode=False, maxChunkSize=4 + ) == ints2octs((48, 128, 5, 0, 2, 1, 1, 0, 0)) + + def testWithOptionalAndDefaultedDefMode(self): + self.__initWithOptionalAndDefaulted() + assert encoder.encode(self.s) == ints2octs( + (48, 18, 5, 0, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 2, 1, 1)) + + def testWithOptionalAndDefaultedIndefMode(self): + self.__initWithOptionalAndDefaulted() + assert encoder.encode( + self.s, defMode=False + ) == ints2octs((48, 128, 5, 0, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 2, 1, 1, 0, 0)) + + def testWithOptionalAndDefaultedDefModeChunked(self): + self.__initWithOptionalAndDefaulted() + assert encoder.encode( + self.s, defMode=True, maxChunkSize=4 + ) == ints2octs( + (48, 24, 5, 0, 36, 17, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110, 2, 1, 1)) + + def testWithOptionalAndDefaultedIndefModeChunked(self): + self.__initWithOptionalAndDefaulted() + assert encoder.encode( + self.s, defMode=False, maxChunkSize=4 + ) == ints2octs((48, 128, 5, 0, 36, 128, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110, 0, + 0, 2, 1, 1, 0, 0)) + + +class ExpTaggedSequenceEncoderTestCase(BaseTestCase): + def setUp(self): + BaseTestCase.setUp(self) + s = univ.Sequence( + componentType=namedtype.NamedTypes( + namedtype.NamedType('number', univ.Integer()), + ) + ) + + s = s.subtype( + explicitTag=tag.Tag(tag.tagClassApplication, tag.tagFormatConstructed, 5) + ) + + s[0] = 12 + + self.s = s + + def testDefMode(self): + assert encoder.encode(self.s) == ints2octs((101, 5, 48, 3, 2, 1, 12)) + + def testIndefMode(self): + assert encoder.encode( + self.s, defMode=False + ) == ints2octs((101, 128, 48, 128, 2, 1, 12, 0, 0, 0, 0)) + + +class ExpTaggedSequenceComponentEncoderTestCase(BaseTestCase): + def setUp(self): + BaseTestCase.setUp(self) + self.s = univ.Sequence( + componentType=namedtype.NamedTypes( + namedtype.NamedType('number', univ.Boolean().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0))), + ) + ) + + self.s[0] = True + + def testDefMode(self): + assert encoder.encode(self.s) == ints2octs((48, 5, 160, 3, 1, 1, 1)) + + def testIndefMode(self): + assert encoder.encode( + self.s, defMode=False + ) == ints2octs((48, 128, 160, 3, 1, 1, 1, 0, 0, 0, 0)) + + +class SetEncoderTestCase(BaseTestCase): + def setUp(self): + BaseTestCase.setUp(self) + self.s = univ.Set() + self.s.setComponentByPosition(0, univ.Null('')) + self.s.setComponentByPosition(1, univ.OctetString('quick brown')) + self.s.setComponentByPosition(2, univ.Integer(1)) + + def testDefMode(self): + assert encoder.encode(self.s) == ints2octs((49, 18, 5, 0, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 2, 1, 1)) + + def testIndefMode(self): + assert encoder.encode( + self.s, defMode=False + ) == ints2octs((49, 128, 5, 0, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 2, 1, 1, 0, 0)) + + def testDefModeChunked(self): + assert encoder.encode( + self.s, defMode=True, maxChunkSize=4 + ) == ints2octs((49, 24, 5, 0, 36, 17, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110, 2, 1, 1)) + + def testIndefModeChunked(self): + assert encoder.encode( + self.s, defMode=False, maxChunkSize=4 + ) == ints2octs((49, 128, 5, 0, 36, 128, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110, 0, 0, 2, 1, 1, 0, 0)) + + +class SetEncoderWithSchemaTestCase(BaseTestCase): + def setUp(self): + BaseTestCase.setUp(self) + self.s = univ.Set( + componentType=namedtype.NamedTypes( + namedtype.NamedType('place-holder', univ.Null()), + namedtype.OptionalNamedType('first-name', univ.OctetString()), + namedtype.DefaultedNamedType('age', univ.Integer(33)), + ) + ) + self.v = { + 'place-holder': None, + 'first-name': 'quick brown', + 'age': 1 + } + + def testEmpty(self): + try: + assert encoder.encode({}, asn1Spec=self.s) + + except PyAsn1Error: + pass + + else: + assert False, 'empty bare SET tolerated' + + def testDefMode(self): + assert encoder.encode( + self.v, asn1Spec=self.s + ) == ints2octs((49, 18, 5, 0, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 2, 1, 1)) + + def testIndefMode(self): + assert encoder.encode( + self.v, asn1Spec=self.s, defMode=False + ) == ints2octs((49, 128, 5, 0, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 2, 1, 1, 0, 0)) + + def testDefModeChunked(self): + assert encoder.encode( + self.v, asn1Spec=self.s, defMode=True, maxChunkSize=4 + ) == ints2octs((49, 24, 5, 0, 36, 17, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110, 2, 1, 1)) + + def testIndefModeChunked(self): + assert encoder.encode( + self.v, asn1Spec=self.s, defMode=False, maxChunkSize=4 + ) == ints2octs((49, 128, 5, 0, 36, 128, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110, 0, 0, 2, 1, 1, 0, 0)) + + +class SetEncoderWithComponentsSchemaTestCase(BaseTestCase): + def setUp(self): + BaseTestCase.setUp(self) + self.s = univ.Set( + componentType=namedtype.NamedTypes( + namedtype.NamedType('place-holder', univ.Null()), + namedtype.OptionalNamedType('first-name', univ.OctetString()), + namedtype.DefaultedNamedType('age', univ.Integer(33)), + ) + ) + + def __init(self): + self.s.clear() + self.s.setComponentByPosition(0, '') + + def __initWithOptional(self): + self.s.clear() + self.s.setComponentByPosition(0, '') + self.s.setComponentByPosition(1, 'quick brown') + + def __initWithDefaulted(self): + self.s.clear() + self.s.setComponentByPosition(0, '') + self.s.setComponentByPosition(2, 1) + + def __initWithOptionalAndDefaulted(self): + self.s.clear() + self.s.setComponentByPosition(0, univ.Null('')) + self.s.setComponentByPosition(1, univ.OctetString('quick brown')) + self.s.setComponentByPosition(2, univ.Integer(1)) + + def testDefMode(self): + self.__init() + assert encoder.encode(self.s) == ints2octs((49, 2, 5, 0)) + + def testIndefMode(self): + self.__init() + assert encoder.encode( + self.s, defMode=False + ) == ints2octs((49, 128, 5, 0, 0, 0)) + + def testDefModeChunked(self): + self.__init() + assert encoder.encode( + self.s, defMode=True, maxChunkSize=4 + ) == ints2octs((49, 2, 5, 0)) + + def testIndefModeChunked(self): + self.__init() + assert encoder.encode( + self.s, defMode=False, maxChunkSize=4 + ) == ints2octs((49, 128, 5, 0, 0, 0)) + + def testWithOptionalDefMode(self): + self.__initWithOptional() + assert encoder.encode(self.s) == ints2octs( + (49, 15, 5, 0, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110)) + + def testWithOptionalIndefMode(self): + self.__initWithOptional() + assert encoder.encode( + self.s, defMode=False + ) == ints2octs((49, 128, 5, 0, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 0, 0)) + + def testWithOptionalDefModeChunked(self): + self.__initWithOptional() + assert encoder.encode( + self.s, defMode=True, maxChunkSize=4 + ) == ints2octs((49, 21, 5, 0, 36, 17, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110)) + + def testWithOptionalIndefModeChunked(self): + self.__initWithOptional() + assert encoder.encode( + self.s, defMode=False, maxChunkSize=4 + ) == ints2octs( + (49, 128, 5, 0, 36, 128, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110, 0, 0, 0, 0)) + + def testWithDefaultedDefMode(self): + self.__initWithDefaulted() + assert encoder.encode(self.s) == ints2octs((49, 5, 5, 0, 2, 1, 1)) + + def testWithDefaultedIndefMode(self): + self.__initWithDefaulted() + assert encoder.encode( + self.s, defMode=False + ) == ints2octs((49, 128, 5, 0, 2, 1, 1, 0, 0)) + + def testWithDefaultedDefModeChunked(self): + self.__initWithDefaulted() + assert encoder.encode( + self.s, defMode=True, maxChunkSize=4 + ) == ints2octs((49, 5, 5, 0, 2, 1, 1)) + + def testWithDefaultedIndefModeChunked(self): + self.__initWithDefaulted() + assert encoder.encode( + self.s, defMode=False, maxChunkSize=4 + ) == ints2octs((49, 128, 5, 0, 2, 1, 1, 0, 0)) + + def testWithOptionalAndDefaultedDefMode(self): + self.__initWithOptionalAndDefaulted() + assert encoder.encode(self.s) == ints2octs( + (49, 18, 5, 0, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 2, 1, 1)) + + def testWithOptionalAndDefaultedIndefMode(self): + self.__initWithOptionalAndDefaulted() + assert encoder.encode( + self.s, defMode=False + ) == ints2octs((49, 128, 5, 0, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 2, 1, 1, 0, 0)) + + def testWithOptionalAndDefaultedDefModeChunked(self): + self.__initWithOptionalAndDefaulted() + assert encoder.encode( + self.s, defMode=True, maxChunkSize=4 + ) == ints2octs( + (49, 24, 5, 0, 36, 17, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110, 2, 1, 1)) + + def testWithOptionalAndDefaultedIndefModeChunked(self): + self.__initWithOptionalAndDefaulted() + assert encoder.encode( + self.s, defMode=False, maxChunkSize=4 + ) == ints2octs((49, 128, 5, 0, 36, 128, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110, 0, 0, 2, 1, 1, 0, 0)) + + +class ChoiceEncoderTestCase(BaseTestCase): + + def testEmpty(self): + s = univ.Choice() + try: + encoder.encode(s) + except PyAsn1Error: + pass + else: + assert 0, 'encoded unset choice' + + def testDefModeOptionOne(self): + s = univ.Choice() + s.setComponentByPosition(0, univ.Null('')) + assert encoder.encode(s) == ints2octs((5, 0)) + + def testDefModeOptionTwo(self): + s = univ.Choice() + s.setComponentByPosition(0, univ.OctetString('quick brown')) + assert encoder.encode(s) == ints2octs((4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110)) + + def testIndefMode(self): + s = univ.Choice() + s.setComponentByPosition(0, univ.OctetString('quick brown')) + assert encoder.encode( + s, defMode=False + ) == ints2octs((4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110)) + + def testDefModeChunked(self): + s = univ.Choice() + s.setComponentByPosition(0, univ.OctetString('quick brown')) + assert encoder.encode( + s, defMode=True, maxChunkSize=4 + ) == ints2octs((36, 17, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110)) + + def testIndefModeChunked(self): + s = univ.Choice() + s.setComponentByPosition(0, univ.OctetString('quick brown')) + assert encoder.encode( + s, defMode=False, maxChunkSize=4 + ) == ints2octs((36, 128, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110, 0, 0)) + + +class ChoiceEncoderWithSchemaTestCase(BaseTestCase): + def setUp(self): + BaseTestCase.setUp(self) + self.s = univ.Choice( + componentType=namedtype.NamedTypes( + namedtype.NamedType('place-holder', univ.Null('')), + namedtype.NamedType('number', univ.Integer(0)), + namedtype.NamedType('string', univ.OctetString()) + ) + ) + self.v = { + 'place-holder': None + } + + def testFilled(self): + assert encoder.encode( + self.v, asn1Spec=self.s + ) == ints2octs((5, 0)) + + +class ChoiceEncoderWithComponentsSchemaTestCase(BaseTestCase): + def setUp(self): + BaseTestCase.setUp(self) + self.s = univ.Choice( + componentType=namedtype.NamedTypes( + namedtype.NamedType('place-holder', univ.Null('')), + namedtype.NamedType('number', univ.Integer(0)), + namedtype.NamedType('string', univ.OctetString()) + ) + ) + + def testEmpty(self): + try: + encoder.encode(self.s) + except PyAsn1Error: + pass + else: + assert 0, 'encoded unset choice' + + def testFilled(self): + self.s.setComponentByPosition(0, univ.Null('')) + assert encoder.encode(self.s) == ints2octs((5, 0)) + + def testTagged(self): + s = self.s.subtype( + explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 4) + ) + s.setComponentByPosition(0, univ.Null('')) + assert encoder.encode(s) == ints2octs((164, 2, 5, 0)) + + def testUndefLength(self): + self.s.setComponentByPosition(2, univ.OctetString('abcdefgh')) + assert encoder.encode(self.s, defMode=False, maxChunkSize=3) == ints2octs( + (36, 128, 4, 3, 97, 98, 99, 4, 3, 100, 101, 102, 4, 2, 103, 104, 0, 0)) + + def testTaggedUndefLength(self): + s = self.s.subtype( + explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 4) + ) + s.setComponentByPosition(2, univ.OctetString('abcdefgh')) + assert encoder.encode(s, defMode=False, maxChunkSize=3) == ints2octs( + (164, 128, 36, 128, 4, 3, 97, 98, 99, 4, 3, 100, 101, 102, 4, 2, 103, 104, 0, 0, 0, 0)) + + +class AnyEncoderTestCase(BaseTestCase): + def setUp(self): + BaseTestCase.setUp(self) + self.s = univ.Any(encoder.encode(univ.OctetString('fox'))) + + def testUntagged(self): + assert encoder.encode(self.s) == ints2octs((4, 3, 102, 111, 120)) + + def testTaggedEx(self): + s = self.s.subtype( + explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 4) + ) + assert encoder.encode(s) == ints2octs((164, 5, 4, 3, 102, 111, 120)) + + def testTaggedIm(self): + s = self.s.subtype( + implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 4) + ) + assert encoder.encode(s) == ints2octs((132, 5, 4, 3, 102, 111, 120)) + + +class AnyEncoderWithSchemaTestCase(BaseTestCase): + def setUp(self): + BaseTestCase.setUp(self) + self.s = univ.Any() + self.v = encoder.encode(univ.OctetString('fox')) + + def testUntagged(self): + assert encoder.encode(self.v, asn1Spec=self.s) == ints2octs((4, 3, 102, 111, 120)) + + def testTaggedEx(self): + s = self.s.subtype( + explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 4) + ) + assert encoder.encode(self.v, asn1Spec=s) == ints2octs((164, 5, 4, 3, 102, 111, 120)) + + def testTaggedIm(self): + s = self.s.subtype( + implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 4) + ) + assert encoder.encode(self.v, asn1Spec=s) == ints2octs((132, 5, 4, 3, 102, 111, 120)) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + unittest.TextTestRunner(verbosity=2).run(suite) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/tests/codec/cer/__init__.py b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/tests/codec/cer/__init__.py new file mode 100644 index 00000000..8c3066b2 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/tests/codec/cer/__init__.py @@ -0,0 +1 @@ +# This file is necessary to make this directory a package. diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/tests/codec/cer/__main__.py b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/tests/codec/cer/__main__.py new file mode 100644 index 00000000..e3643a16 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/tests/codec/cer/__main__.py @@ -0,0 +1,20 @@ +# +# This file is part of pyasn1 software. +# +# Copyright (c) 2005-2019, Ilya Etingof <etingof@gmail.com> +# License: http://snmplabs.com/pyasn1/license.html +# +try: + import unittest2 as unittest + +except ImportError: + import unittest + +suite = unittest.TestLoader().loadTestsFromNames( + ['tests.codec.cer.test_encoder.suite', + 'tests.codec.cer.test_decoder.suite'] +) + + +if __name__ == '__main__': + unittest.TextTestRunner(verbosity=2).run(suite) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/tests/codec/cer/test_decoder.py b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/tests/codec/cer/test_decoder.py new file mode 100644 index 00000000..bb5ce93b --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/tests/codec/cer/test_decoder.py @@ -0,0 +1,373 @@ +# +# This file is part of pyasn1 software. +# +# Copyright (c) 2005-2019, Ilya Etingof <etingof@gmail.com> +# License: http://snmplabs.com/pyasn1/license.html +# +import sys + +try: + import unittest2 as unittest +except ImportError: + import unittest + +from tests.base import BaseTestCase + +from pyasn1.type import tag +from pyasn1.type import namedtype +from pyasn1.type import opentype +from pyasn1.type import univ +from pyasn1.codec.cer import decoder +from pyasn1.compat.octets import ints2octs, str2octs, null +from pyasn1.error import PyAsn1Error + + +class BooleanDecoderTestCase(BaseTestCase): + def testTrue(self): + assert decoder.decode(ints2octs((1, 1, 255))) == (1, null) + + def testFalse(self): + assert decoder.decode(ints2octs((1, 1, 0))) == (0, null) + + def testEmpty(self): + try: + decoder.decode(ints2octs((1, 0))) + except PyAsn1Error: + pass + + def testOverflow(self): + try: + decoder.decode(ints2octs((1, 2, 0, 0))) + except PyAsn1Error: + pass + +class BitStringDecoderTestCase(BaseTestCase): + def testShortMode(self): + assert decoder.decode( + ints2octs((3, 3, 6, 170, 128)) + ) == (((1, 0) * 5), null) + + def testLongMode(self): + assert decoder.decode( + ints2octs((3, 127, 6) + (170,) * 125 + (128,)) + ) == (((1, 0) * 501), null) + + # TODO: test failures on short chunked and long unchunked substrate samples + + +class OctetStringDecoderTestCase(BaseTestCase): + def testShortMode(self): + assert decoder.decode( + ints2octs((4, 15, 81, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 32, 102, 111, 120)), + ) == (str2octs('Quick brown fox'), null) + + def testLongMode(self): + assert decoder.decode( + ints2octs((36, 128, 4, 130, 3, 232) + (81,) * 1000 + (4, 1, 81, 0, 0)) + ) == (str2octs('Q' * 1001), null) + + # TODO: test failures on short chunked and long unchunked substrate samples + + +class SequenceDecoderWithUntaggedOpenTypesTestCase(BaseTestCase): + def setUp(self): + openType = opentype.OpenType( + 'id', + {1: univ.Integer(), + 2: univ.OctetString()} + ) + self.s = univ.Sequence( + componentType=namedtype.NamedTypes( + namedtype.NamedType('id', univ.Integer()), + namedtype.NamedType('blob', univ.Any(), openType=openType) + ) + ) + + def testDecodeOpenTypesChoiceOne(self): + s, r = decoder.decode( + ints2octs((48, 128, 2, 1, 1, 2, 1, 12, 0, 0)), + asn1Spec=self.s, + decodeOpenTypes=True + ) + assert not r + assert s[0] == 1 + assert s[1] == 12 + + def testDecodeOpenTypesChoiceTwo(self): + s, r = decoder.decode( + ints2octs((48, 128, 2, 1, 2, 4, 11, 113, 117, 105, 99, 107, 32, 98, + 114, 111, 119, 110, 0, 0)), asn1Spec=self.s, + decodeOpenTypes=True + ) + assert not r + assert s[0] == 2 + assert s[1] == univ.OctetString('quick brown') + + def testDecodeOpenTypesUnknownType(self): + try: + s, r = decoder.decode( + ints2octs((48, 128, 6, 1, 1, 2, 1, 12, 0, 0)), asn1Spec=self.s, + decodeOpenTypes=True + ) + + except PyAsn1Error: + pass + + else: + assert False, 'unknown open type tolerated' + + def testDecodeOpenTypesUnknownId(self): + s, r = decoder.decode( + ints2octs((48, 128, 2, 1, 3, 6, 1, 12, 0, 0)), asn1Spec=self.s, + decodeOpenTypes=True + ) + assert not r + assert s[0] == 3 + assert s[1] == univ.OctetString(hexValue='06010c') + + def testDontDecodeOpenTypesChoiceOne(self): + s, r = decoder.decode( + ints2octs((48, 128, 2, 1, 1, 2, 1, 12, 0, 0)), asn1Spec=self.s + ) + assert not r + assert s[0] == 1 + assert s[1] == ints2octs((2, 1, 12)) + + def testDontDecodeOpenTypesChoiceTwo(self): + s, r = decoder.decode( + ints2octs((48, 128, 2, 1, 2, 4, 11, 113, 117, 105, 99, 107, 32, 98, + 114, 111, 119, 110, 0, 0)), asn1Spec=self.s + ) + assert not r + assert s[0] == 2 + assert s[1] == ints2octs((4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110)) + + +class SequenceDecoderWithImplicitlyTaggedOpenTypesTestCase(BaseTestCase): + def setUp(self): + openType = opentype.OpenType( + 'id', + {1: univ.Integer(), + 2: univ.OctetString()} + ) + self.s = univ.Sequence( + componentType=namedtype.NamedTypes( + namedtype.NamedType('id', univ.Integer()), + namedtype.NamedType( + 'blob', univ.Any().subtype(implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 3)), openType=openType + ) + ) + ) + + def testDecodeOpenTypesChoiceOne(self): + s, r = decoder.decode( + ints2octs((48, 128, 2, 1, 1, 163, 128, 2, 1, 12, 0, 0, 0, 0)), + asn1Spec=self.s, decodeOpenTypes=True + ) + assert not r + assert s[0] == 1 + assert s[1] == 12 + + def testDecodeOpenTypesUnknownId(self): + s, r = decoder.decode( + ints2octs((48, 128, 2, 1, 3, 163, 128, 2, 1, 12, 0, 0, 0, 0)), + asn1Spec=self.s, decodeOpenTypes=True + ) + assert not r + assert s[0] == 3 + assert s[1] == univ.OctetString(hexValue='02010C') + + +class SequenceDecoderWithExplicitlyTaggedOpenTypesTestCase(BaseTestCase): + def setUp(self): + openType = opentype.OpenType( + 'id', + {1: univ.Integer(), + 2: univ.OctetString()} + ) + self.s = univ.Sequence( + componentType=namedtype.NamedTypes( + namedtype.NamedType('id', univ.Integer()), + namedtype.NamedType( + 'blob', univ.Any().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 3)), openType=openType + ) + ) + ) + + def testDecodeOpenTypesChoiceOne(self): + s, r = decoder.decode( + ints2octs((48, 128, 2, 1, 1, 163, 128, 2, 1, 12, 0, 0, 0, 0)), + asn1Spec=self.s, decodeOpenTypes=True + ) + assert not r + assert s[0] == 1 + assert s[1] == 12 + + def testDecodeOpenTypesUnknownId(self): + s, r = decoder.decode( + ints2octs((48, 128, 2, 1, 3, 163, 128, 2, 1, 12, 0, 0, 0, 0)), + asn1Spec=self.s, decodeOpenTypes=True + ) + assert not r + assert s[0] == 3 + assert s[1] == univ.OctetString(hexValue='02010C') + + +class SequenceDecoderWithUntaggedSetOfOpenTypesTestCase(BaseTestCase): + def setUp(self): + openType = opentype.OpenType( + 'id', + {1: univ.Integer(), + 2: univ.OctetString()} + ) + self.s = univ.Sequence( + componentType=namedtype.NamedTypes( + namedtype.NamedType('id', univ.Integer()), + namedtype.NamedType('blob', univ.SetOf(componentType=univ.Any()), + openType=openType) + ) + ) + + def testDecodeOpenTypesChoiceOne(self): + s, r = decoder.decode( + ints2octs((48, 128, 2, 1, 1, 49, 128, 2, 1, 12, 0, 0, 0, 0)), + asn1Spec=self.s, decodeOpenTypes=True + ) + assert not r + assert s[0] == 1 + assert s[1][0] == 12 + + def testDecodeOpenTypesChoiceTwo(self): + s, r = decoder.decode( + ints2octs((48, 128, 2, 1, 2, 49, 128, 4, 11, 113, 117, 105, 99, + 107, 32, 98, 114, 111, 119, 110, 0, 0, 0, 0)), + asn1Spec=self.s, decodeOpenTypes=True + ) + assert not r + assert s[0] == 2 + assert s[1][0] == univ.OctetString('quick brown') + + def testDecodeOpenTypesUnknownType(self): + try: + s, r = decoder.decode( + ints2octs((48, 128, 6, 1, 1, 49, 128, 2, 1, 12, 0, 0, 0, 0)), + asn1Spec=self.s, decodeOpenTypes=True + ) + + except PyAsn1Error: + pass + + else: + assert False, 'unknown open type tolerated' + + def testDecodeOpenTypesUnknownId(self): + s, r = decoder.decode( + ints2octs((48, 128, 2, 1, 3, 49, 128, 2, 1, 12, 0, 0, 0, 0)), + asn1Spec=self.s, decodeOpenTypes=True + ) + assert not r + assert s[0] == 3 + assert s[1][0] == univ.OctetString(hexValue='02010c') + + def testDontDecodeOpenTypesChoiceOne(self): + s, r = decoder.decode( + ints2octs((48, 128, 2, 1, 1, 49, 128, 2, 1, 12, 0, 0, 0, 0)), + asn1Spec=self.s + ) + assert not r + assert s[0] == 1 + assert s[1][0] == ints2octs((2, 1, 12)) + + def testDontDecodeOpenTypesChoiceTwo(self): + s, r = decoder.decode( + ints2octs((48, 128, 2, 1, 2, 49, 128, 4, 11, 113, 117, 105, 99, 107, 32, + 98, 114, 111, 119, 110, 0, 0, 0, 0)), asn1Spec=self.s + ) + assert not r + assert s[0] == 2 + assert s[1][0] == ints2octs((4, 11, 113, 117, 105, 99, 107, 32, 98, 114, + 111, 119, 110)) + + +class SequenceDecoderWithImplicitlyTaggedSetOfOpenTypesTestCase(BaseTestCase): + def setUp(self): + openType = opentype.OpenType( + 'id', + {1: univ.Integer(), + 2: univ.OctetString()} + ) + self.s = univ.Sequence( + componentType=namedtype.NamedTypes( + namedtype.NamedType('id', univ.Integer()), + namedtype.NamedType( + 'blob', univ.SetOf( + componentType=univ.Any().subtype( + implicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatSimple, 3))), + openType=openType + ) + ) + ) + + def testDecodeOpenTypesChoiceOne(self): + s, r = decoder.decode( + ints2octs((48, 10, 2, 1, 1, 49, 5, 131, 3, 2, 1, 12)), + asn1Spec=self.s, decodeOpenTypes=True + ) + assert not r + assert s[0] == 1 + assert s[1][0] == 12 + + def testDecodeOpenTypesUnknownId(self): + s, r = decoder.decode( + ints2octs((48, 10, 2, 1, 3, 49, 5, 131, 3, 2, 1, 12)), + asn1Spec=self.s, decodeOpenTypes=True + ) + assert not r + assert s[0] == 3 + assert s[1][0] == univ.OctetString(hexValue='02010C') + + +class SequenceDecoderWithExplicitlyTaggedSetOfOpenTypesTestCase(BaseTestCase): + def setUp(self): + openType = opentype.OpenType( + 'id', + {1: univ.Integer(), + 2: univ.OctetString()} + ) + self.s = univ.Sequence( + componentType=namedtype.NamedTypes( + namedtype.NamedType('id', univ.Integer()), + namedtype.NamedType( + 'blob', univ.SetOf( + componentType=univ.Any().subtype( + explicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatSimple, 3))), + openType=openType + ) + ) + ) + + def testDecodeOpenTypesChoiceOne(self): + s, r = decoder.decode( + ints2octs((48, 10, 2, 1, 1, 49, 5, 131, 3, 2, 1, 12)), + asn1Spec=self.s, decodeOpenTypes=True + ) + assert not r + assert s[0] == 1 + assert s[1][0] == 12 + + def testDecodeOpenTypesUnknownId(self): + s, r = decoder.decode( + ints2octs( (48, 10, 2, 1, 3, 49, 5, 131, 3, 2, 1, 12)), + asn1Spec=self.s, decodeOpenTypes=True + ) + assert not r + assert s[0] == 3 + assert s[1][0] == univ.OctetString(hexValue='02010C') + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + unittest.TextTestRunner(verbosity=2).run(suite) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/tests/codec/cer/test_encoder.py b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/tests/codec/cer/test_encoder.py new file mode 100644 index 00000000..e155571b --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/tests/codec/cer/test_encoder.py @@ -0,0 +1,961 @@ +# +# This file is part of pyasn1 software. +# +# Copyright (c) 2005-2019, Ilya Etingof <etingof@gmail.com> +# License: http://snmplabs.com/pyasn1/license.html +# +import sys + +try: + import unittest2 as unittest +except ImportError: + import unittest + +from tests.base import BaseTestCase + +from pyasn1.type import tag +from pyasn1.type import namedtype +from pyasn1.type import opentype +from pyasn1.type import univ +from pyasn1.type import useful +from pyasn1.codec.cer import encoder +from pyasn1.compat.octets import ints2octs +from pyasn1.error import PyAsn1Error + + +class BooleanEncoderTestCase(BaseTestCase): + def testTrue(self): + assert encoder.encode(univ.Boolean(1)) == ints2octs((1, 1, 255)) + + def testFalse(self): + assert encoder.encode(univ.Boolean(0)) == ints2octs((1, 1, 0)) + + +class BitStringEncoderTestCase(BaseTestCase): + def testShortMode(self): + assert encoder.encode( + univ.BitString((1, 0) * 5) + ) == ints2octs((3, 3, 6, 170, 128)) + + def testLongMode(self): + assert encoder.encode(univ.BitString((1, 0) * 501)) == ints2octs((3, 127, 6) + (170,) * 125 + (128,)) + + +class OctetStringEncoderTestCase(BaseTestCase): + def testShortMode(self): + assert encoder.encode( + univ.OctetString('Quick brown fox') + ) == ints2octs((4, 15, 81, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 32, 102, 111, 120)) + + def testLongMode(self): + assert encoder.encode( + univ.OctetString('Q' * 1001) + ) == ints2octs((36, 128, 4, 130, 3, 232) + (81,) * 1000 + (4, 1, 81, 0, 0)) + + +class GeneralizedTimeEncoderTestCase(BaseTestCase): + # def testExtraZeroInSeconds(self): + # try: + # assert encoder.encode( + # useful.GeneralizedTime('20150501120112.10Z') + # ) + # except PyAsn1Error: + # pass + # else: + # assert 0, 'Meaningless trailing zero in fraction part tolerated' + + def testLocalTimezone(self): + try: + assert encoder.encode( + useful.GeneralizedTime('20150501120112.1+0200') + ) + except PyAsn1Error: + pass + else: + assert 0, 'Local timezone tolerated' + + def testMissingTimezone(self): + try: + assert encoder.encode( + useful.GeneralizedTime('20150501120112.1') + ) + except PyAsn1Error: + pass + else: + assert 0, 'Missing timezone tolerated' + + + def testDecimalCommaPoint(self): + try: + assert encoder.encode( + useful.GeneralizedTime('20150501120112,1Z') + ) + except PyAsn1Error: + pass + else: + assert 0, 'Decimal comma tolerated' + + def testWithSubseconds(self): + assert encoder.encode( + useful.GeneralizedTime('20170801120112.59Z') + ) == ints2octs((24, 18, 50, 48, 49, 55, 48, 56, 48, 49, 49, 50, 48, 49, 49, 50, 46, 53, 57, 90)) + + def testWithSubsecondsWithZeros(self): + assert encoder.encode( + useful.GeneralizedTime('20170801120112.099Z') + ) == ints2octs((24, 18, 50, 48, 49, 55, 48, 56, 48, 49, 49, 50, 48, 49, 49, 50, 46, 57, 57, 90)) + + def testWithSubsecondsMax(self): + assert encoder.encode( + useful.GeneralizedTime('20170801120112.999Z') + ) == ints2octs((24, 19, 50, 48, 49, 55, 48, 56, 48, 49, 49, 50, 48, 49, 49, 50, 46, 57, 57, 57, 90)) + + def testWithSubsecondsMin(self): + assert encoder.encode( + useful.GeneralizedTime('20170801120112.000Z') + ) == ints2octs((24, 15, 50, 48, 49, 55, 48, 56, 48, 49, 49, 50, 48, 49, 49, 50, 90)) + + def testWithSubsecondsDanglingDot(self): + assert encoder.encode( + useful.GeneralizedTime('20170801120112.Z') + ) == ints2octs((24, 15, 50, 48, 49, 55, 48, 56, 48, 49, 49, 50, 48, 49, 49, 50, 90)) + + def testWithSeconds(self): + assert encoder.encode( + useful.GeneralizedTime('20170801120112Z') + ) == ints2octs((24, 15, 50, 48, 49, 55, 48, 56, 48, 49, 49, 50, 48, 49, 49, 50, 90)) + + def testWithMinutes(self): + assert encoder.encode( + useful.GeneralizedTime('201708011201Z') + ) == ints2octs((24, 13, 50, 48, 49, 55, 48, 56, 48, 49, 49, 50, 48, 49, 90)) + + +class UTCTimeEncoderTestCase(BaseTestCase): + def testFractionOfSecond(self): + try: + assert encoder.encode( + useful.UTCTime('150501120112.10Z') + ) + except PyAsn1Error: + pass + else: + assert 0, 'Decimal point tolerated' + + def testMissingTimezone(self): + try: + assert encoder.encode( + useful.UTCTime('150501120112') + ) == ints2octs((23, 13, 49, 53, 48, 53, 48, 49, 49, 50, 48, 49, 49, 50, 90)) + except PyAsn1Error: + pass + else: + assert 0, 'Missing timezone tolerated' + + def testLocalTimezone(self): + try: + assert encoder.encode( + useful.UTCTime('150501120112+0200') + ) + except PyAsn1Error: + pass + else: + assert 0, 'Local timezone tolerated' + + def testWithSeconds(self): + assert encoder.encode( + useful.UTCTime('990801120112Z') + ) == ints2octs((23, 13, 57, 57, 48, 56, 48, 49, 49, 50, 48, 49, 49, 50, 90)) + + def testWithMinutes(self): + assert encoder.encode( + useful.UTCTime('9908011201Z') + ) == ints2octs((23, 11, 57, 57, 48, 56, 48, 49, 49, 50, 48, 49, 90)) + + +class SequenceOfEncoderTestCase(BaseTestCase): + def testEmpty(self): + s = univ.SequenceOf() + s.clear() + assert encoder.encode(s) == ints2octs((48, 128, 0, 0)) + + def testDefMode1(self): + s = univ.SequenceOf() + s.append(univ.OctetString('a')) + s.append(univ.OctetString('ab')) + assert encoder.encode(s) == ints2octs((48, 128, 4, 1, 97, 4, 2, 97, 98, 0, 0)) + + def testDefMode2(self): + s = univ.SequenceOf() + s.append(univ.OctetString('ab')) + s.append(univ.OctetString('a')) + assert encoder.encode(s) == ints2octs((48, 128, 4, 2, 97, 98, 4, 1, 97, 0, 0)) + + def testDefMode3(self): + s = univ.SequenceOf() + s.append(univ.OctetString('b')) + s.append(univ.OctetString('a')) + assert encoder.encode(s) == ints2octs((48, 128, 4, 1, 98, 4, 1, 97, 0, 0)) + + def testDefMode4(self): + s = univ.SequenceOf() + s.append(univ.OctetString('a')) + s.append(univ.OctetString('b')) + assert encoder.encode(s) == ints2octs((48, 128, 4, 1, 97, 4, 1, 98, 0, 0)) + + +class SequenceOfEncoderWithSchemaTestCase(BaseTestCase): + def setUp(self): + BaseTestCase.setUp(self) + self.s = univ.SequenceOf(componentType=univ.OctetString()) + + def testEmpty(self): + self.s.clear() + assert encoder.encode(self.s) == ints2octs((48, 128, 0, 0)) + + def testIndefMode1(self): + self.s.clear() + self.s.append('a') + self.s.append('ab') + assert encoder.encode(self.s) == ints2octs((48, 128, 4, 1, 97, 4, 2, 97, 98, 0, 0)) + + def testIndefMode2(self): + self.s.clear() + self.s.append('ab') + self.s.append('a') + assert encoder.encode(self.s) == ints2octs((48, 128, 4, 2, 97, 98, 4, 1, 97, 0, 0)) + + def testIndefMode3(self): + self.s.clear() + self.s.append('b') + self.s.append('a') + assert encoder.encode(self.s) == ints2octs((48, 128, 4, 1, 98, 4, 1, 97, 0, 0)) + + def testIndefMode4(self): + self.s.clear() + self.s.append('a') + self.s.append('b') + assert encoder.encode(self.s) == ints2octs((48, 128, 4, 1, 97, 4, 1, 98, 0, 0)) + + +class SetOfEncoderTestCase(BaseTestCase): + def testEmpty(self): + s = univ.SetOf() + s.clear() + assert encoder.encode(s) == ints2octs((49, 128, 0, 0)) + + def testDefMode1(self): + s = univ.SetOf() + s.append(univ.OctetString('a')) + s.append(univ.OctetString('ab')) + assert encoder.encode(s) == ints2octs((49, 128, 4, 1, 97, 4, 2, 97, 98, 0, 0)) + + def testDefMode2(self): + s = univ.SetOf() + s.append(univ.OctetString('ab')) + s.append(univ.OctetString('a')) + assert encoder.encode(s) == ints2octs((49, 128, 4, 1, 97, 4, 2, 97, 98, 0, 0)) + + def testDefMode3(self): + s = univ.SetOf() + s.append(univ.OctetString('b')) + s.append(univ.OctetString('a')) + assert encoder.encode(s) == ints2octs((49, 128, 4, 1, 97, 4, 1, 98, 0, 0)) + + def testDefMode4(self): + s = univ.SetOf() + s.append(univ.OctetString('a')) + s.append(univ.OctetString('b')) + assert encoder.encode(s) == ints2octs((49, 128, 4, 1, 97, 4, 1, 98, 0, 0)) + + +class SetOfEncoderWithSchemaTestCase(BaseTestCase): + def setUp(self): + BaseTestCase.setUp(self) + self.s = univ.SetOf(componentType=univ.OctetString()) + + def testEmpty(self): + self.s.clear() + assert encoder.encode(self.s) == ints2octs((49, 128, 0, 0)) + + def testIndefMode1(self): + self.s.clear() + self.s.append('a') + self.s.append('ab') + + assert encoder.encode(self.s) == ints2octs((49, 128, 4, 1, 97, 4, 2, 97, 98, 0, 0)) + + def testIndefMode2(self): + self.s.clear() + self.s.append('ab') + self.s.append('a') + + assert encoder.encode(self.s) == ints2octs((49, 128, 4, 1, 97, 4, 2, 97, 98, 0, 0)) + + def testIndefMode3(self): + self.s.clear() + self.s.append('b') + self.s.append('a') + + assert encoder.encode(self.s) == ints2octs((49, 128, 4, 1, 97, 4, 1, 98, 0, 0)) + + def testIndefMode4(self): + self.s.clear() + self.s.append('a') + self.s.append('b') + + assert encoder.encode(self.s) == ints2octs((49, 128, 4, 1, 97, 4, 1, 98, 0, 0)) + + +class SetEncoderTestCase(BaseTestCase): + def setUp(self): + BaseTestCase.setUp(self) + self.s = univ.Set() + self.s.setComponentByPosition(0, univ.Null('')) + self.s.setComponentByPosition(1, univ.OctetString('quick brown')) + self.s.setComponentByPosition(2, univ.Integer(1)) + + def testIndefMode(self): + assert encoder.encode(self.s) == ints2octs((49, 128, 2, 1, 1, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 5, 0, 0, 0)) + + def testWithOptionalIndefMode(self): + assert encoder.encode( + self.s + ) == ints2octs((49, 128, 2, 1, 1, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 5, 0, 0, 0)) + + def testWithDefaultedIndefMode(self): + assert encoder.encode( + self.s + ) == ints2octs((49, 128, 2, 1, 1, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 5, 0, 0, 0)) + + def testWithOptionalAndDefaultedIndefMode(self): + assert encoder.encode( + self.s + ) == ints2octs((49, 128, 2, 1, 1, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 5, 0, 0, 0)) + + +class SetEncoderWithSchemaTestCase(BaseTestCase): + def setUp(self): + BaseTestCase.setUp(self) + self.s = univ.Set(componentType=namedtype.NamedTypes( + namedtype.NamedType('place-holder', univ.Null('')), + namedtype.OptionalNamedType('first-name', univ.OctetString()), + namedtype.DefaultedNamedType('age', univ.Integer(33)) + )) + + def __init(self): + self.s.clear() + self.s.setComponentByPosition(0) + + def __initWithOptional(self): + self.s.clear() + self.s.setComponentByPosition(0) + self.s.setComponentByPosition(1, 'quick brown') + + def __initWithDefaulted(self): + self.s.clear() + self.s.setComponentByPosition(0) + self.s.setComponentByPosition(2, 1) + + def __initWithOptionalAndDefaulted(self): + self.s.clear() + self.s.setComponentByPosition(0, univ.Null('')) + self.s.setComponentByPosition(1, univ.OctetString('quick brown')) + self.s.setComponentByPosition(2, univ.Integer(1)) + + def testIndefMode(self): + self.__init() + assert encoder.encode(self.s) == ints2octs((49, 128, 5, 0, 0, 0)) + + def testWithOptionalIndefMode(self): + self.__initWithOptional() + assert encoder.encode( + self.s + ) == ints2octs((49, 128, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 5, 0, 0, 0)) + + def testWithDefaultedIndefMode(self): + self.__initWithDefaulted() + assert encoder.encode( + self.s + ) == ints2octs((49, 128, 2, 1, 1, 5, 0, 0, 0)) + + def testWithOptionalAndDefaultedIndefMode(self): + self.__initWithOptionalAndDefaulted() + assert encoder.encode( + self.s + ) == ints2octs((49, 128, 2, 1, 1, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 5, 0, 0, 0)) + + +class SetEncoderWithChoiceWithSchemaEncoderTestCase(BaseTestCase): + def setUp(self): + BaseTestCase.setUp(self) + c = univ.Choice(componentType=namedtype.NamedTypes( + namedtype.NamedType('actual', univ.Boolean(0)) + )) + self.s = univ.Set(componentType=namedtype.NamedTypes( + namedtype.NamedType('place-holder', univ.Null('')), + namedtype.NamedType('status', c) + )) + + def testIndefMode(self): + self.s.setComponentByPosition(0) + self.s.setComponentByName('status') + self.s.getComponentByName('status').setComponentByPosition(0, 1) + assert encoder.encode(self.s) == ints2octs((49, 128, 1, 1, 255, 5, 0, 0, 0)) + + +class SetEncoderWithTaggedChoiceEncoderTestCase(BaseTestCase): + + def testWithUntaggedChoice(self): + + c = univ.Choice( + componentType=namedtype.NamedTypes( + namedtype.NamedType('premium', univ.Boolean()) + ) + ) + + s = univ.Set( + componentType=namedtype.NamedTypes( + namedtype.NamedType('name', univ.OctetString()), + namedtype.NamedType('customer', c) + ) + ) + + s.setComponentByName('name', 'A') + s.getComponentByName('customer').setComponentByName('premium', True) + + assert encoder.encode(s) == ints2octs((49, 128, 1, 1, 255, 4, 1, 65, 0, 0)) + + def testWithTaggedChoice(self): + + c = univ.Choice( + componentType=namedtype.NamedTypes( + namedtype.NamedType('premium', univ.Boolean()) + ) + ).subtype(implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 7)) + + s = univ.Set( + componentType=namedtype.NamedTypes( + namedtype.NamedType('name', univ.OctetString()), + namedtype.NamedType('customer', c) + ) + ) + + s.setComponentByName('name', 'A') + s.getComponentByName('customer').setComponentByName('premium', True) + + assert encoder.encode(s) == ints2octs((49, 128, 4, 1, 65, 167, 128, 1, 1, 255, 0, 0, 0, 0)) + + +class SequenceEncoderTestCase(BaseTestCase): + def setUp(self): + BaseTestCase.setUp(self) + self.s = univ.Sequence() + self.s.setComponentByPosition(0, univ.Null('')) + self.s.setComponentByPosition(1, univ.OctetString('quick brown')) + self.s.setComponentByPosition(2, univ.Integer(1)) + + def testIndefMode(self): + assert encoder.encode(self.s) == ints2octs((48, 128, 5, 0, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 2, 1, 1, 0, 0)) + + def testWithOptionalIndefMode(self): + assert encoder.encode( + self.s + ) == ints2octs((48, 128, 5, 0, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 2, 1, 1, 0, 0)) + + def testWithDefaultedIndefMode(self): + assert encoder.encode( + self.s + ) == ints2octs((48, 128, 5, 0, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 2, 1, 1, 0, 0)) + + def testWithOptionalAndDefaultedIndefMode(self): + assert encoder.encode( + self.s + ) == ints2octs((48, 128, 5, 0, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 2, 1, 1, 0, 0)) + + +class SequenceEncoderWithSchemaTestCase(BaseTestCase): + def setUp(self): + BaseTestCase.setUp(self) + self.s = univ.Sequence( + componentType=namedtype.NamedTypes( + namedtype.NamedType('place-holder', univ.Null('')), + namedtype.OptionalNamedType('first-name', univ.OctetString()), + namedtype.DefaultedNamedType('age', univ.Integer(33)) + ) + ) + + def __init(self): + self.s.clear() + self.s.setComponentByPosition(0) + + def __initWithOptional(self): + self.s.clear() + self.s.setComponentByPosition(0) + self.s.setComponentByPosition(1, 'quick brown') + + def __initWithDefaulted(self): + self.s.clear() + self.s.setComponentByPosition(0) + self.s.setComponentByPosition(2, 1) + + def __initWithOptionalAndDefaulted(self): + self.s.clear() + self.s.setComponentByPosition(0, univ.Null('')) + self.s.setComponentByPosition(1, univ.OctetString('quick brown')) + self.s.setComponentByPosition(2, univ.Integer(1)) + + def testIndefMode(self): + self.__init() + assert encoder.encode(self.s) == ints2octs((48, 128, 5, 0, 0, 0)) + + def testWithOptionalIndefMode(self): + self.__initWithOptional() + assert encoder.encode( + self.s + ) == ints2octs((48, 128, 5, 0, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 0, 0)) + + def testWithDefaultedIndefMode(self): + self.__initWithDefaulted() + assert encoder.encode( + self.s + ) == ints2octs((48, 128, 5, 0, 2, 1, 1, 0, 0)) + + def testWithOptionalAndDefaultedIndefMode(self): + self.__initWithOptionalAndDefaulted() + assert encoder.encode( + self.s + ) == ints2octs((48, 128, 5, 0, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 2, 1, 1, 0, 0)) + + +class SequenceEncoderWithUntaggedOpenTypesTestCase(BaseTestCase): + def setUp(self): + BaseTestCase.setUp(self) + + openType = opentype.OpenType( + 'id', + {1: univ.Integer(), + 2: univ.OctetString()} + ) + self.s = univ.Sequence( + componentType=namedtype.NamedTypes( + namedtype.NamedType('id', univ.Integer()), + namedtype.NamedType('blob', univ.Any(), openType=openType) + ) + ) + + def testEncodeOpenTypeChoiceOne(self): + self.s.clear() + + self.s[0] = 1 + self.s[1] = univ.Integer(12) + + assert encoder.encode(self.s, asn1Spec=self.s) == ints2octs( + (48, 128, 2, 1, 1, 49, 50, 0, 0) + ) + + def testEncodeOpenTypeChoiceTwo(self): + self.s.clear() + + self.s[0] = 2 + self.s[1] = univ.OctetString('quick brown') + + assert encoder.encode(self.s, asn1Spec=self.s) == ints2octs( + (48, 128, 2, 1, 2, 113, 117, 105, 99, 107, 32, 98, 114, + 111, 119, 110, 0, 0) + ) + + def testEncodeOpenTypeUnknownId(self): + self.s.clear() + + self.s[0] = 2 + self.s[1] = univ.ObjectIdentifier('1.3.6') + + try: + encoder.encode(self.s, asn1Spec=self.s) + + except PyAsn1Error: + assert False, 'incompatible open type tolerated' + + def testEncodeOpenTypeIncompatibleType(self): + self.s.clear() + + self.s[0] = 2 + self.s[1] = univ.ObjectIdentifier('1.3.6') + + try: + encoder.encode(self.s, asn1Spec=self.s) + + except PyAsn1Error: + assert False, 'incompatible open type tolerated' + + +class SequenceEncoderWithImplicitlyTaggedOpenTypesTestCase(BaseTestCase): + def setUp(self): + BaseTestCase.setUp(self) + + openType = opentype.OpenType( + 'id', + {1: univ.Integer(), + 2: univ.OctetString()} + ) + self.s = univ.Sequence( + componentType=namedtype.NamedTypes( + namedtype.NamedType('id', univ.Integer()), + namedtype.NamedType('blob', univ.Any().subtype(implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 3)), openType=openType) + ) + ) + + def testEncodeOpenTypeChoiceOne(self): + self.s.clear() + + self.s[0] = 1 + self.s[1] = univ.Integer(12) + + assert encoder.encode(self.s, asn1Spec=self.s) == ints2octs( + (48, 128, 2, 1, 1, 163, 128, 163, 128, 49, 50, 0, 0, 0, 0, 0, 0) + ) + + +class SequenceEncoderWithExplicitlyTaggedOpenTypesTestCase(BaseTestCase): + def setUp(self): + BaseTestCase.setUp(self) + + openType = opentype.OpenType( + 'id', + {1: univ.Integer(), + 2: univ.OctetString()} + ) + self.s = univ.Sequence( + componentType=namedtype.NamedTypes( + namedtype.NamedType('id', univ.Integer()), + namedtype.NamedType('blob', univ.Any().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 3)), openType=openType) + ) + ) + + def testEncodeOpenTypeChoiceOne(self): + self.s.clear() + + self.s[0] = 1 + self.s[1] = univ.Integer(12) + + assert encoder.encode(self.s, asn1Spec=self.s) == ints2octs( + (48, 128, 2, 1, 1, 163, 128, 163, 128, 49, 50, 0, 0, 0, 0, 0, 0) + ) + + +class SequenceEncoderWithUntaggedSetOfOpenTypesTestCase(BaseTestCase): + def setUp(self): + BaseTestCase.setUp(self) + + openType = opentype.OpenType( + 'id', + {1: univ.Integer(), + 2: univ.OctetString()} + ) + self.s = univ.Sequence( + componentType=namedtype.NamedTypes( + namedtype.NamedType('id', univ.Integer()), + namedtype.NamedType('blob', univ.SetOf( + componentType=univ.Any()), openType=openType) + ) + ) + + def testEncodeOpenTypeChoiceOne(self): + self.s.clear() + + self.s[0] = 1 + self.s[1].append(univ.Integer(12)) + + assert encoder.encode(self.s, asn1Spec=self.s) == ints2octs( + (48, 128, 2, 1, 1, 49, 128, 49, 50, 0, 0, 0, 0) + ) + + def testEncodeOpenTypeChoiceTwo(self): + self.s.clear() + + self.s[0] = 2 + self.s[1].append(univ.OctetString('quick brown')) + + assert encoder.encode(self.s, asn1Spec=self.s) == ints2octs( + (48, 128, 2, 1, 2, 49, 128, 113, 117, 105, 99, 107, 32, 98, 114, + 111, 119, 110, 0, 0, 0, 0) + ) + + def testEncodeOpenTypeUnknownId(self): + self.s.clear() + + self.s[0] = 2 + self.s[1].append(univ.ObjectIdentifier('1.3.6')) + + try: + encoder.encode(self.s, asn1Spec=self.s) + + except PyAsn1Error: + assert False, 'incompatible open type tolerated' + + def testEncodeOpenTypeIncompatibleType(self): + self.s.clear() + + self.s[0] = 2 + self.s[1].append(univ.ObjectIdentifier('1.3.6')) + + try: + encoder.encode(self.s, asn1Spec=self.s) + + except PyAsn1Error: + assert False, 'incompatible open type tolerated' + + +class SequenceEncoderWithImplicitlyTaggedSetOfOpenTypesTestCase(BaseTestCase): + def setUp(self): + BaseTestCase.setUp(self) + + openType = opentype.OpenType( + 'id', + {1: univ.Integer(), + 2: univ.OctetString()} + ) + self.s = univ.Sequence( + componentType=namedtype.NamedTypes( + namedtype.NamedType('id', univ.Integer()), + namedtype.NamedType('blob', univ.SetOf( + componentType=univ.Any().subtype( + implicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatSimple, 3))), + openType=openType) + ) + ) + + def testEncodeOpenTypeChoiceOne(self): + self.s.clear() + + self.s[0] = 1 + self.s[1].append(univ.Integer(12)) + + assert encoder.encode(self.s, asn1Spec=self.s) == ints2octs( + (48, 128, 2, 1, 1, 49, 128, 163, 128, 163, 128, 49, 50, 0, 0, + 0, 0, 0, 0, 0, 0) + ) + + +class SequenceEncoderWithExplicitlyTaggedSetOfOpenTypesTestCase(BaseTestCase): + def setUp(self): + BaseTestCase.setUp(self) + + openType = opentype.OpenType( + 'id', + {1: univ.Integer(), + 2: univ.OctetString()} + ) + self.s = univ.Sequence( + componentType=namedtype.NamedTypes( + namedtype.NamedType('id', univ.Integer()), + namedtype.NamedType('blob', univ.SetOf( + componentType=univ.Any().subtype( + explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 3))), + openType=openType) + ) + ) + + def testEncodeOpenTypeChoiceOne(self): + self.s.clear() + + self.s[0] = 1 + self.s[1].append(univ.Integer(12)) + + assert encoder.encode(self.s, asn1Spec=self.s) == ints2octs( + (48, 128, 2, 1, 1, 49, 128, 163, 128, 163, 128, 49, 50, 0, 0, + 0, 0, 0, 0, 0, 0) + ) + + +class NestedOptionalSequenceEncoderTestCase(BaseTestCase): + def setUp(self): + BaseTestCase.setUp(self) + inner = univ.Sequence( + componentType=namedtype.NamedTypes( + namedtype.OptionalNamedType('first-name', univ.OctetString()), + namedtype.DefaultedNamedType('age', univ.Integer(33)), + ) + ) + + outerWithOptional = univ.Sequence( + componentType=namedtype.NamedTypes( + namedtype.OptionalNamedType('inner', inner), + ) + ) + + outerWithDefault = univ.Sequence( + componentType=namedtype.NamedTypes( + namedtype.DefaultedNamedType('inner', inner), + ) + ) + + self.s1 = outerWithOptional + self.s2 = outerWithDefault + + def __initOptionalWithDefaultAndOptional(self): + self.s1.clear() + self.s1[0][0] = 'test' + self.s1[0][1] = 123 + return self.s1 + + def __initOptionalWithDefault(self): + self.s1.clear() + self.s1[0][1] = 123 + return self.s1 + + def __initOptionalWithOptional(self): + self.s1.clear() + self.s1[0][0] = 'test' + return self.s1 + + def __initOptional(self): + self.s1.clear() + return self.s1 + + def __initDefaultWithDefaultAndOptional(self): + self.s2.clear() + self.s2[0][0] = 'test' + self.s2[0][1] = 123 + return self.s2 + + def __initDefaultWithDefault(self): + self.s2.clear() + self.s2[0][0] = 'test' + return self.s2 + + def __initDefaultWithOptional(self): + self.s2.clear() + self.s2[0][1] = 123 + return self.s2 + + def testOptionalWithDefaultAndOptional(self): + s = self.__initOptionalWithDefaultAndOptional() + assert encoder.encode(s) == ints2octs((48, 128, 48, 128, 4, 4, 116, 101, 115, 116, 2, 1, 123, 0, 0, 0, 0)) + + def testOptionalWithDefault(self): + s = self.__initOptionalWithDefault() + assert encoder.encode(s) == ints2octs((48, 128, 48, 128, 2, 1, 123, 0, 0, 0, 0)) + + def testOptionalWithOptional(self): + s = self.__initOptionalWithOptional() + assert encoder.encode(s) == ints2octs((48, 128, 48, 128, 4, 4, 116, 101, 115, 116, 0, 0, 0, 0)) + + def testOptional(self): + s = self.__initOptional() + assert encoder.encode(s) == ints2octs((48, 128, 0, 0)) + + def testDefaultWithDefaultAndOptional(self): + s = self.__initDefaultWithDefaultAndOptional() + assert encoder.encode(s) == ints2octs((48, 128, 48, 128, 4, 4, 116, 101, 115, 116, 2, 1, 123, 0, 0, 0, 0)) + + def testDefaultWithDefault(self): + s = self.__initDefaultWithDefault() + assert encoder.encode(s) == ints2octs((48, 128, 48, 128, 4, 4, 116, 101, 115, 116, 0, 0, 0, 0)) + + def testDefaultWithOptional(self): + s = self.__initDefaultWithOptional() + assert encoder.encode(s) == ints2octs((48, 128, 48, 128, 2, 1, 123, 0, 0, 0, 0)) + + +class NestedOptionalChoiceEncoderTestCase(BaseTestCase): + def setUp(self): + BaseTestCase.setUp(self) + layer3 = univ.Sequence( + componentType=namedtype.NamedTypes( + namedtype.OptionalNamedType('first-name', univ.OctetString()), + namedtype.DefaultedNamedType('age', univ.Integer(33)), + ) + ) + + layer2 = univ.Choice( + componentType=namedtype.NamedTypes( + namedtype.NamedType('inner', layer3), + namedtype.NamedType('first-name', univ.OctetString()) + ) + ) + + layer1 = univ.Sequence( + componentType=namedtype.NamedTypes( + namedtype.OptionalNamedType('inner', layer2), + ) + ) + + self.s = layer1 + + def __initOptionalWithDefaultAndOptional(self): + self.s.clear() + self.s[0][0][0] = 'test' + self.s[0][0][1] = 123 + return self.s + + def __initOptionalWithDefault(self): + self.s.clear() + self.s[0][0][1] = 123 + return self.s + + def __initOptionalWithOptional(self): + self.s.clear() + self.s[0][0][0] = 'test' + return self.s + + def __initOptional(self): + self.s.clear() + return self.s + + def testOptionalWithDefaultAndOptional(self): + s = self.__initOptionalWithDefaultAndOptional() + assert encoder.encode(s) == ints2octs((48, 128, 48, 128, 4, 4, 116, 101, 115, 116, 2, 1, 123, 0, 0, 0, 0)) + + def testOptionalWithDefault(self): + s = self.__initOptionalWithDefault() + assert encoder.encode(s) == ints2octs((48, 128, 48, 128, 2, 1, 123, 0, 0, 0, 0)) + + def testOptionalWithOptional(self): + s = self.__initOptionalWithOptional() + assert encoder.encode(s) == ints2octs((48, 128, 48, 128, 4, 4, 116, 101, 115, 116, 0, 0, 0, 0)) + + def testOptional(self): + s = self.__initOptional() + assert encoder.encode(s) == ints2octs((48, 128, 0, 0)) + + +class NestedOptionalSequenceOfEncoderTestCase(BaseTestCase): + def setUp(self): + BaseTestCase.setUp(self) + layer2 = univ.SequenceOf( + componentType=univ.OctetString() + ) + + layer1 = univ.Sequence( + componentType=namedtype.NamedTypes( + namedtype.OptionalNamedType('inner', layer2), + ) + ) + + self.s = layer1 + + def __initOptionalWithValue(self): + self.s.clear() + self.s[0][0] = 'test' + return self.s + + def __initOptional(self): + self.s.clear() + return self.s + + def testOptionalWithValue(self): + s = self.__initOptionalWithValue() + assert encoder.encode(s) == ints2octs((48, 128, 48, 128, 4, 4, 116, 101, 115, 116, 0, 0, 0, 0)) + + def testOptional(self): + s = self.__initOptional() + assert encoder.encode(s) == ints2octs((48, 128, 0, 0)) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + unittest.TextTestRunner(verbosity=2).run(suite) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/tests/codec/der/__init__.py b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/tests/codec/der/__init__.py new file mode 100644 index 00000000..8c3066b2 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/tests/codec/der/__init__.py @@ -0,0 +1 @@ +# This file is necessary to make this directory a package. diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/tests/codec/der/__main__.py b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/tests/codec/der/__main__.py new file mode 100644 index 00000000..bfa4ee0a --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/tests/codec/der/__main__.py @@ -0,0 +1,20 @@ +# +# This file is part of pyasn1 software. +# +# Copyright (c) 2005-2019, Ilya Etingof <etingof@gmail.com> +# License: http://snmplabs.com/pyasn1/license.html +# +try: + import unittest2 as unittest + +except ImportError: + import unittest + +suite = unittest.TestLoader().loadTestsFromNames( + ['tests.codec.der.test_encoder.suite', + 'tests.codec.der.test_decoder.suite'] +) + + +if __name__ == '__main__': + unittest.TextTestRunner(verbosity=2).run(suite) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/tests/codec/der/test_decoder.py b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/tests/codec/der/test_decoder.py new file mode 100644 index 00000000..51ce2960 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/tests/codec/der/test_decoder.py @@ -0,0 +1,373 @@ +# +# This file is part of pyasn1 software. +# +# Copyright (c) 2005-2019, Ilya Etingof <etingof@gmail.com> +# License: http://snmplabs.com/pyasn1/license.html +# +import sys + +try: + import unittest2 as unittest + +except ImportError: + import unittest + +from tests.base import BaseTestCase + +from pyasn1.type import tag +from pyasn1.type import namedtype +from pyasn1.type import opentype +from pyasn1.type import univ +from pyasn1.codec.der import decoder +from pyasn1.compat.octets import ints2octs, null +from pyasn1.error import PyAsn1Error + + +class BitStringDecoderTestCase(BaseTestCase): + def testShortMode(self): + assert decoder.decode( + ints2octs((3, 127, 6) + (170,) * 125 + (128,)) + ) == (((1, 0) * 501), null) + + def testIndefMode(self): + try: + decoder.decode( + ints2octs((35, 128, 3, 2, 0, 169, 3, 2, 1, 138, 0, 0)) + ) + except PyAsn1Error: + pass + else: + assert 0, 'indefinite length encoding tolerated' + + def testDefModeChunked(self): + try: + assert decoder.decode( + ints2octs((35, 8, 3, 2, 0, 169, 3, 2, 1, 138)) + ) + except PyAsn1Error: + pass + else: + assert 0, 'chunked encoding tolerated' + + +class OctetStringDecoderTestCase(BaseTestCase): + def testShortMode(self): + assert decoder.decode( + '\004\017Quick brown fox'.encode() + ) == ('Quick brown fox'.encode(), ''.encode()) + + def testIndefMode(self): + try: + decoder.decode( + ints2octs((36, 128, 4, 15, 81, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 32, 102, 111, 120, 0, 0)) + ) + except PyAsn1Error: + pass + else: + assert 0, 'indefinite length encoding tolerated' + + def testChunkedMode(self): + try: + decoder.decode( + ints2octs((36, 23, 4, 2, 81, 117, 4, 2, 105, 99, 4, 2, 107, 32, 4, 2, 98, 114, 4, 2, 111, 119, 4, 1, 110)) + ) + except PyAsn1Error: + pass + else: + assert 0, 'chunked encoding tolerated' + + +class SequenceDecoderWithUntaggedOpenTypesTestCase(BaseTestCase): + def setUp(self): + openType = opentype.OpenType( + 'id', + {1: univ.Integer(), + 2: univ.OctetString()} + ) + self.s = univ.Sequence( + componentType=namedtype.NamedTypes( + namedtype.NamedType('id', univ.Integer()), + namedtype.NamedType('blob', univ.Any(), openType=openType) + ) + ) + + def testDecodeOpenTypesChoiceOne(self): + s, r = decoder.decode( + ints2octs((48, 6, 2, 1, 1, 2, 1, 12)), asn1Spec=self.s, + decodeOpenTypes=True + ) + assert not r + assert s[0] == 1 + assert s[1] == 12 + + def testDecodeOpenTypesChoiceTwo(self): + s, r = decoder.decode( + ints2octs((48, 16, 2, 1, 2, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110)), asn1Spec=self.s, + decodeOpenTypes=True + ) + assert not r + assert s[0] == 2 + assert s[1] == univ.OctetString('quick brown') + + def testDecodeOpenTypesUnknownType(self): + try: + s, r = decoder.decode( + ints2octs((48, 6, 2, 1, 2, 6, 1, 39)), asn1Spec=self.s, + decodeOpenTypes=True + ) + + except PyAsn1Error: + pass + + else: + assert False, 'unknown open type tolerated' + + def testDecodeOpenTypesUnknownId(self): + s, r = decoder.decode( + ints2octs((48, 6, 2, 1, 3, 6, 1, 39)), asn1Spec=self.s, + decodeOpenTypes=True + ) + assert not r + assert s[0] == 3 + assert s[1] == univ.OctetString(hexValue='060127') + + def testDontDecodeOpenTypesChoiceOne(self): + s, r = decoder.decode( + ints2octs((48, 6, 2, 1, 1, 2, 1, 12)), asn1Spec=self.s + ) + assert not r + assert s[0] == 1 + assert s[1] == ints2octs((2, 1, 12)) + + def testDontDecodeOpenTypesChoiceTwo(self): + s, r = decoder.decode( + ints2octs((48, 16, 2, 1, 2, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110)), asn1Spec=self.s + ) + assert not r + assert s[0] == 2 + assert s[1] == ints2octs((4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110)) + + +class SequenceDecoderWithImplicitlyTaggedOpenTypesTestCase(BaseTestCase): + def setUp(self): + openType = opentype.OpenType( + 'id', + {1: univ.Integer(), + 2: univ.OctetString()} + ) + self.s = univ.Sequence( + componentType=namedtype.NamedTypes( + namedtype.NamedType('id', univ.Integer()), + namedtype.NamedType( + 'blob', univ.Any().subtype(implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 3)), openType=openType + ) + ) + ) + + def testDecodeOpenTypesChoiceOne(self): + s, r = decoder.decode( + ints2octs((48, 8, 2, 1, 1, 131, 3, 2, 1, 12)), asn1Spec=self.s, decodeOpenTypes=True + ) + assert not r + assert s[0] == 1 + assert s[1] == 12 + + def testDecodeOpenTypesUnknownId(self): + s, r = decoder.decode( + ints2octs((48, 8, 2, 1, 3, 131, 3, 2, 1, 12)), asn1Spec=self.s, decodeOpenTypes=True + ) + assert not r + assert s[0] == 3 + assert s[1] == univ.OctetString(hexValue='02010C') + + +class SequenceDecoderWithExplicitlyTaggedOpenTypesTestCase(BaseTestCase): + def setUp(self): + openType = opentype.OpenType( + 'id', + {1: univ.Integer(), + 2: univ.OctetString()} + ) + self.s = univ.Sequence( + componentType=namedtype.NamedTypes( + namedtype.NamedType('id', univ.Integer()), + namedtype.NamedType( + 'blob', univ.Any().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 3)), openType=openType + ) + ) + ) + + def testDecodeOpenTypesChoiceOne(self): + s, r = decoder.decode( + ints2octs((48, 8, 2, 1, 1, 163, 3, 2, 1, 12)), asn1Spec=self.s, decodeOpenTypes=True + ) + assert not r + assert s[0] == 1 + assert s[1] == 12 + + def testDecodeOpenTypesUnknownId(self): + s, r = decoder.decode( + ints2octs((48, 8, 2, 1, 3, 163, 3, 2, 1, 12)), asn1Spec=self.s, decodeOpenTypes=True + ) + assert not r + assert s[0] == 3 + assert s[1] == univ.OctetString(hexValue='02010C') + + +class SequenceDecoderWithUnaggedSetOfOpenTypesTestCase(BaseTestCase): + def setUp(self): + openType = opentype.OpenType( + 'id', + {1: univ.Integer(), + 2: univ.OctetString()} + ) + self.s = univ.Sequence( + componentType=namedtype.NamedTypes( + namedtype.NamedType('id', univ.Integer()), + namedtype.NamedType('blob', univ.SetOf(componentType=univ.Any()), + openType=openType) + ) + ) + + def testDecodeOpenTypesChoiceOne(self): + s, r = decoder.decode( + ints2octs((48, 8, 2, 1, 1, 49, 3, 2, 1, 12)), asn1Spec=self.s, + decodeOpenTypes=True + ) + assert not r + assert s[0] == 1 + assert s[1][0] == 12 + + def testDecodeOpenTypesChoiceTwo(self): + s, r = decoder.decode( + ints2octs((48, 18, 2, 1, 2, 49, 13, 4, 11, 113, 117, 105, 99, + 107, 32, 98, 114, 111, 119, 110)), asn1Spec=self.s, + decodeOpenTypes=True + ) + assert not r + assert s[0] == 2 + assert s[1][0] == univ.OctetString('quick brown') + + def testDecodeOpenTypesUnknownType(self): + try: + s, r = decoder.decode( + ints2octs((48, 6, 2, 1, 2, 6, 1, 39)), asn1Spec=self.s, + decodeOpenTypes=True + ) + + except PyAsn1Error: + pass + + else: + assert False, 'unknown open type tolerated' + + def testDecodeOpenTypesUnknownId(self): + s, r = decoder.decode( + ints2octs((48, 8, 2, 1, 3, 49, 3, 2, 1, 12)), asn1Spec=self.s, + decodeOpenTypes=True + ) + assert not r + assert s[0] == 3 + assert s[1][0] == univ.OctetString(hexValue='02010c') + + def testDontDecodeOpenTypesChoiceOne(self): + s, r = decoder.decode( + ints2octs((48, 8, 2, 1, 1, 49, 3, 2, 1, 12)), asn1Spec=self.s + ) + assert not r + assert s[0] == 1 + assert s[1][0] == ints2octs((2, 1, 12)) + + def testDontDecodeOpenTypesChoiceTwo(self): + s, r = decoder.decode( + ints2octs((48, 18, 2, 1, 2, 49, 13, 4, 11, 113, 117, 105, 99, + 107, 32, 98, 114, 111, 119, 110)), asn1Spec=self.s + ) + assert not r + assert s[0] == 2 + assert s[1][0] == ints2octs((4, 11, 113, 117, 105, 99, 107, 32, 98, 114, + 111, 119, 110)) + + +class SequenceDecoderWithImplicitlyTaggedSetOfOpenTypesTestCase(BaseTestCase): + def setUp(self): + openType = opentype.OpenType( + 'id', + {1: univ.Integer(), + 2: univ.OctetString()} + ) + self.s = univ.Sequence( + componentType=namedtype.NamedTypes( + namedtype.NamedType('id', univ.Integer()), + namedtype.NamedType( + 'blob', univ.SetOf( + componentType=univ.Any().subtype( + implicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatSimple, 3))), + openType=openType + ) + ) + ) + + def testDecodeOpenTypesChoiceOne(self): + s, r = decoder.decode( + ints2octs((48, 10, 2, 1, 1, 49, 5, 131, 3, 2, 1, 12)), + asn1Spec=self.s, decodeOpenTypes=True + ) + assert not r + assert s[0] == 1 + assert s[1][0] == 12 + + def testDecodeOpenTypesUnknownId(self): + s, r = decoder.decode( + ints2octs((48, 10, 2, 1, 3, 49, 5, 131, 3, 2, 1, 12)), + asn1Spec=self.s, decodeOpenTypes=True + ) + assert not r + assert s[0] == 3 + assert s[1][0] == univ.OctetString(hexValue='02010C') + + +class SequenceDecoderWithExplicitlyTaggedSetOfOpenTypesTestCase(BaseTestCase): + def setUp(self): + openType = opentype.OpenType( + 'id', + {1: univ.Integer(), + 2: univ.OctetString()} + ) + self.s = univ.Sequence( + componentType=namedtype.NamedTypes( + namedtype.NamedType('id', univ.Integer()), + namedtype.NamedType( + 'blob', univ.SetOf( + componentType=univ.Any().subtype( + explicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatSimple, 3))), + openType=openType + ) + ) + ) + + def testDecodeOpenTypesChoiceOne(self): + s, r = decoder.decode( + ints2octs((48, 10, 2, 1, 1, 49, 5, 131, 3, 2, 1, 12)), + asn1Spec=self.s, decodeOpenTypes=True + ) + assert not r + assert s[0] == 1 + assert s[1][0] == 12 + + def testDecodeOpenTypesUnknownId(self): + s, r = decoder.decode( + ints2octs( (48, 10, 2, 1, 3, 49, 5, 131, 3, 2, 1, 12)), + asn1Spec=self.s, decodeOpenTypes=True + ) + assert not r + assert s[0] == 3 + assert s[1][0] == univ.OctetString(hexValue='02010C') + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + unittest.TextTestRunner(verbosity=2).run(suite) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/tests/codec/der/test_encoder.py b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/tests/codec/der/test_encoder.py new file mode 100644 index 00000000..912e32ca --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/tests/codec/der/test_encoder.py @@ -0,0 +1,650 @@ +# +# This file is part of pyasn1 software. +# +# Copyright (c) 2005-2019, Ilya Etingof <etingof@gmail.com> +# License: http://snmplabs.com/pyasn1/license.html +# +import sys + +try: + import unittest2 as unittest + +except ImportError: + import unittest + +from tests.base import BaseTestCase + +from pyasn1.type import tag +from pyasn1.type import namedtype +from pyasn1.type import opentype +from pyasn1.type import univ +from pyasn1.codec.der import encoder +from pyasn1.compat.octets import ints2octs + + +class OctetStringEncoderTestCase(BaseTestCase): + def testDefModeShort(self): + assert encoder.encode( + univ.OctetString('Quick brown fox') + ) == ints2octs((4, 15, 81, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 32, 102, 111, 120)) + + def testDefModeLong(self): + assert encoder.encode( + univ.OctetString('Q' * 10000) + ) == ints2octs((4, 130, 39, 16) + (81,) * 10000) + + +class BitStringEncoderTestCase(BaseTestCase): + def testDefModeShort(self): + assert encoder.encode( + univ.BitString((1,)) + ) == ints2octs((3, 2, 7, 128)) + + def testDefModeLong(self): + assert encoder.encode( + univ.BitString((1,) * 80000) + ) == ints2octs((3, 130, 39, 17, 0) + (255,) * 10000) + + +class SetOfEncoderTestCase(BaseTestCase): + def setUp(self): + BaseTestCase.setUp(self) + + self.s = univ.SetOf(componentType=univ.OctetString()) + + def testDefMode1(self): + self.s.clear() + self.s.append('a') + self.s.append('ab') + + assert encoder.encode(self.s) == ints2octs((49, 7, 4, 1, 97, 4, 2, 97, 98)) + + def testDefMode2(self): + self.s.clear() + self.s.append('ab') + self.s.append('a') + + assert encoder.encode(self.s) == ints2octs((49, 7, 4, 1, 97, 4, 2, 97, 98)) + + def testDefMode3(self): + self.s.clear() + self.s.append('b') + self.s.append('a') + + assert encoder.encode(self.s) == ints2octs((49, 6, 4, 1, 97, 4, 1, 98)) + + def testDefMode4(self): + self.s.clear() + self.s.append('a') + self.s.append('b') + + assert encoder.encode(self.s) == ints2octs((49, 6, 4, 1, 97, 4, 1, 98)) + + +class SetWithAlternatingChoiceEncoderTestCase(BaseTestCase): + def setUp(self): + BaseTestCase.setUp(self) + + c = univ.Choice(componentType=namedtype.NamedTypes( + namedtype.NamedType('name', univ.OctetString()), + namedtype.NamedType('amount', univ.Boolean())) + ) + + self.s = univ.Set(componentType=namedtype.NamedTypes( + namedtype.NamedType('value', univ.Integer(5)), + namedtype.NamedType('status', c)) + ) + + def testComponentsOrdering1(self): + self.s.setComponentByName('status') + self.s.getComponentByName('status').setComponentByPosition(0, 'A') + assert encoder.encode(self.s) == ints2octs((49, 6, 2, 1, 5, 4, 1, 65)) + + def testComponentsOrdering2(self): + self.s.setComponentByName('status') + self.s.getComponentByName('status').setComponentByPosition(1, True) + assert encoder.encode(self.s) == ints2octs((49, 6, 1, 1, 255, 2, 1, 5)) + + +class SetWithTaggedChoiceEncoderTestCase(BaseTestCase): + + def testWithUntaggedChoice(self): + + c = univ.Choice( + componentType=namedtype.NamedTypes( + namedtype.NamedType('premium', univ.Boolean()) + ) + ) + + s = univ.Set( + componentType=namedtype.NamedTypes( + namedtype.NamedType('name', univ.OctetString()), + namedtype.NamedType('customer', c) + ) + ) + + s.setComponentByName('name', 'A') + s.getComponentByName('customer').setComponentByName('premium', True) + + assert encoder.encode(s) == ints2octs((49, 6, 1, 1, 255, 4, 1, 65)) + + def testWithTaggedChoice(self): + + c = univ.Choice( + componentType=namedtype.NamedTypes( + namedtype.NamedType('premium', univ.Boolean()) + ) + ).subtype(implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 7)) + + s = univ.Set( + componentType=namedtype.NamedTypes( + namedtype.NamedType('name', univ.OctetString()), + namedtype.NamedType('customer', c) + ) + ) + + s.setComponentByName('name', 'A') + s.getComponentByName('customer').setComponentByName('premium', True) + + assert encoder.encode(s) == ints2octs((49, 8, 4, 1, 65, 167, 3, 1, 1, 255)) + + +class SequenceEncoderWithUntaggedOpenTypesTestCase(BaseTestCase): + def setUp(self): + BaseTestCase.setUp(self) + + openType = opentype.OpenType( + 'id', + {1: univ.Integer(), + 2: univ.OctetString()} + ) + self.s = univ.Sequence( + componentType=namedtype.NamedTypes( + namedtype.NamedType('id', univ.Integer()), + namedtype.NamedType('blob', univ.Any(), openType=openType) + ) + ) + + def testEncodeOpenTypeChoiceOne(self): + self.s.clear() + + self.s[0] = 1 + self.s[1] = univ.Integer(12) + + assert encoder.encode(self.s, asn1Spec=self.s) == ints2octs( + (48, 5, 2, 1, 1, 49, 50) + ) + + def testEncodeOpenTypeChoiceTwo(self): + self.s.clear() + + self.s[0] = 2 + self.s[1] = univ.OctetString('quick brown') + + assert encoder.encode(self.s, asn1Spec=self.s) == ints2octs( + (48, 14, 2, 1, 2, 113, 117, 105, 99, 107, 32, + 98, 114, 111, 119, 110) + ) + + def testEncodeOpenTypeUnknownId(self): + self.s.clear() + + self.s[0] = 2 + self.s[1] = univ.ObjectIdentifier('1.3.6') + + try: + encoder.encode(self.s, asn1Spec=self.s) + + except PyAsn1Error: + assert False, 'incompatible open type tolerated' + + def testEncodeOpenTypeIncompatibleType(self): + self.s.clear() + + self.s[0] = 2 + self.s[1] = univ.ObjectIdentifier('1.3.6') + + try: + encoder.encode(self.s, asn1Spec=self.s) + + except PyAsn1Error: + assert False, 'incompatible open type tolerated' + + +class SequenceEncoderWithImplicitlyTaggedOpenTypesTestCase(BaseTestCase): + def setUp(self): + BaseTestCase.setUp(self) + + openType = opentype.OpenType( + 'id', + {1: univ.Integer(), + 2: univ.OctetString()} + ) + self.s = univ.Sequence( + componentType=namedtype.NamedTypes( + namedtype.NamedType('id', univ.Integer()), + namedtype.NamedType('blob', univ.Any().subtype(implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 3)), openType=openType) + ) + ) + + def testEncodeOpenTypeChoiceOne(self): + self.s.clear() + + self.s[0] = 1 + self.s[1] = univ.Integer(12) + + assert encoder.encode(self.s, asn1Spec=self.s) == ints2octs( + (48, 9, 2, 1, 1, 131, 4, 131, 2, 49, 50) + ) + + +class SequenceEncoderWithExplicitlyTaggedOpenTypesTestCase(BaseTestCase): + def setUp(self): + BaseTestCase.setUp(self) + + openType = opentype.OpenType( + 'id', + {1: univ.Integer(), + 2: univ.OctetString()} + ) + self.s = univ.Sequence( + componentType=namedtype.NamedTypes( + namedtype.NamedType('id', univ.Integer()), + namedtype.NamedType('blob', univ.Any().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 3)), openType=openType) + ) + ) + + def testEncodeOpenTypeChoiceOne(self): + self.s.clear() + + self.s[0] = 1 + self.s[1] = univ.Integer(12) + + assert encoder.encode(self.s, asn1Spec=self.s) == ints2octs( + (48, 9, 2, 1, 1, 163, 4, 163, 2, 49, 50) + ) + + +class SequenceEncoderWithUntaggedSetOfOpenTypesTestCase(BaseTestCase): + def setUp(self): + BaseTestCase.setUp(self) + + openType = opentype.OpenType( + 'id', + {1: univ.Integer(), + 2: univ.OctetString()} + ) + self.s = univ.Sequence( + componentType=namedtype.NamedTypes( + namedtype.NamedType('id', univ.Integer()), + namedtype.NamedType('blob', univ.SetOf( + componentType=univ.Any()), openType=openType) + ) + ) + + def testEncodeOpenTypeChoiceOne(self): + self.s.clear() + + self.s[0] = 1 + self.s[1].append(univ.Integer(12)) + + assert encoder.encode(self.s, asn1Spec=self.s) == ints2octs( + (48, 7, 2, 1, 1, 49, 2, 49, 50) + ) + + def testEncodeOpenTypeChoiceTwo(self): + self.s.clear() + + self.s[0] = 2 + self.s[1].append(univ.OctetString('quick brown')) + + assert encoder.encode(self.s, asn1Spec=self.s) == ints2octs( + (48, 16, 2, 1, 2, 49, 11, 113, 117, 105, 99, 107, 32, 98, 114, + 111, 119, 110) + ) + + def testEncodeOpenTypeUnknownId(self): + self.s.clear() + + self.s[0] = 2 + self.s[1].append(univ.ObjectIdentifier('1.3.6')) + + try: + encoder.encode(self.s, asn1Spec=self.s) + + except PyAsn1Error: + assert False, 'incompatible open type tolerated' + + def testEncodeOpenTypeIncompatibleType(self): + self.s.clear() + + self.s[0] = 2 + self.s[1].append(univ.ObjectIdentifier('1.3.6')) + + try: + encoder.encode(self.s, asn1Spec=self.s) + + except PyAsn1Error: + assert False, 'incompatible open type tolerated' + + +class SequenceEncoderWithImplicitlyTaggedSetOfOpenTypesTestCase(BaseTestCase): + def setUp(self): + BaseTestCase.setUp(self) + + openType = opentype.OpenType( + 'id', + {1: univ.Integer(), + 2: univ.OctetString()} + ) + self.s = univ.Sequence( + componentType=namedtype.NamedTypes( + namedtype.NamedType('id', univ.Integer()), + namedtype.NamedType('blob', univ.SetOf( + componentType=univ.Any().subtype( + implicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatSimple, 3))), + openType=openType) + ) + ) + + def testEncodeOpenTypeChoiceOne(self): + self.s.clear() + + self.s[0] = 1 + self.s[1].append(univ.Integer(12)) + + assert encoder.encode(self.s, asn1Spec=self.s) == ints2octs( + (48, 11, 2, 1, 1, 49, 6, 131, 4, 131, 2, 49, 50) + ) + + +class SequenceEncoderWithExplicitlyTaggedSetOfOpenTypesTestCase(BaseTestCase): + def setUp(self): + BaseTestCase.setUp(self) + + openType = opentype.OpenType( + 'id', + {1: univ.Integer(), + 2: univ.OctetString()} + ) + self.s = univ.Sequence( + componentType=namedtype.NamedTypes( + namedtype.NamedType('id', univ.Integer()), + namedtype.NamedType('blob', univ.SetOf( + componentType=univ.Any().subtype( + explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 3))), + openType=openType) + ) + ) + + def testEncodeOpenTypeChoiceOne(self): + self.s.clear() + + self.s[0] = 1 + self.s[1].append(univ.Integer(12)) + + assert encoder.encode(self.s, asn1Spec=self.s) == ints2octs( + (48, 11, 2, 1, 1, 49, 6, 163, 4, 163, 2, 49, 50) + ) + + +class NestedOptionalSequenceEncoderTestCase(BaseTestCase): + def setUp(self): + BaseTestCase.setUp(self) + + inner = univ.Sequence( + componentType=namedtype.NamedTypes( + namedtype.OptionalNamedType('first-name', univ.OctetString()), + namedtype.DefaultedNamedType('age', univ.Integer(33)), + ) + ) + + outerWithOptional = univ.Sequence( + componentType=namedtype.NamedTypes( + namedtype.OptionalNamedType('inner', inner), + ) + ) + + outerWithDefault = univ.Sequence( + componentType=namedtype.NamedTypes( + namedtype.DefaultedNamedType('inner', inner), + ) + ) + + self.s1 = outerWithOptional + self.s2 = outerWithDefault + + def __initOptionalWithDefaultAndOptional(self): + self.s1.clear() + self.s1[0][0] = 'test' + self.s1[0][1] = 123 + return self.s1 + + def __initOptionalWithDefault(self): + self.s1.clear() + self.s1[0][1] = 123 + return self.s1 + + def __initOptionalWithOptional(self): + self.s1.clear() + self.s1[0][0] = 'test' + return self.s1 + + def __initOptional(self): + self.s1.clear() + return self.s1 + + def __initDefaultWithDefaultAndOptional(self): + self.s2.clear() + self.s2[0][0] = 'test' + self.s2[0][1] = 123 + return self.s2 + + def __initDefaultWithDefault(self): + self.s2.clear() + self.s2[0][0] = 'test' + return self.s2 + + def __initDefaultWithOptional(self): + self.s2.clear() + self.s2[0][1] = 123 + return self.s2 + + def testDefModeOptionalWithDefaultAndOptional(self): + s = self.__initOptionalWithDefaultAndOptional() + assert encoder.encode(s) == ints2octs((48, 11, 48, 9, 4, 4, 116, 101, 115, 116, 2, 1, 123)) + + def testDefModeOptionalWithDefault(self): + s = self.__initOptionalWithDefault() + assert encoder.encode(s) == ints2octs((48, 5, 48, 3, 2, 1, 123)) + + def testDefModeOptionalWithOptional(self): + s = self.__initOptionalWithOptional() + assert encoder.encode(s) == ints2octs((48, 8, 48, 6, 4, 4, 116, 101, 115, 116)) + + def testDefModeOptional(self): + s = self.__initOptional() + assert encoder.encode(s) == ints2octs((48, 0)) + + def testDefModeDefaultWithDefaultAndOptional(self): + s = self.__initDefaultWithDefaultAndOptional() + assert encoder.encode(s) == ints2octs((48, 11, 48, 9, 4, 4, 116, 101, 115, 116, 2, 1, 123)) + + def testDefModeDefaultWithDefault(self): + s = self.__initDefaultWithDefault() + assert encoder.encode(s) == ints2octs((48, 8, 48, 6, 4, 4, 116, 101, 115, 116)) + + def testDefModeDefaultWithOptional(self): + s = self.__initDefaultWithOptional() + assert encoder.encode(s) == ints2octs((48, 5, 48, 3, 2, 1, 123)) + + +class NestedOptionalChoiceEncoderTestCase(BaseTestCase): + def setUp(self): + BaseTestCase.setUp(self) + + layer3 = univ.Sequence( + componentType=namedtype.NamedTypes( + namedtype.OptionalNamedType('first-name', univ.OctetString()), + namedtype.DefaultedNamedType('age', univ.Integer(33)), + ) + ) + + layer2 = univ.Choice( + componentType=namedtype.NamedTypes( + namedtype.NamedType('inner', layer3), + namedtype.NamedType('first-name', univ.OctetString()) + ) + ) + + layer1 = univ.Sequence( + componentType=namedtype.NamedTypes( + namedtype.OptionalNamedType('inner', layer2), + ) + ) + + self.s = layer1 + + def __initOptionalWithDefaultAndOptional(self): + self.s.clear() + self.s[0][0][0] = 'test' + self.s[0][0][1] = 123 + return self.s + + def __initOptionalWithDefault(self): + self.s.clear() + self.s[0][0][1] = 123 + return self.s + + def __initOptionalWithOptional(self): + self.s.clear() + self.s[0][0][0] = 'test' + return self.s + + def __initOptional(self): + self.s.clear() + return self.s + + def testDefModeOptionalWithDefaultAndOptional(self): + s = self.__initOptionalWithDefaultAndOptional() + assert encoder.encode(s) == ints2octs((48, 11, 48, 9, 4, 4, 116, 101, 115, 116, 2, 1, 123)) + + def testDefModeOptionalWithDefault(self): + s = self.__initOptionalWithDefault() + assert encoder.encode(s) == ints2octs((48, 5, 48, 3, 2, 1, 123)) + + def testDefModeOptionalWithOptional(self): + s = self.__initOptionalWithOptional() + assert encoder.encode(s) == ints2octs((48, 8, 48, 6, 4, 4, 116, 101, 115, 116)) + + def testDefModeOptional(self): + s = self.__initOptional() + assert encoder.encode(s) == ints2octs((48, 0)) + + +class NestedOptionalSequenceOfEncoderTestCase(BaseTestCase): + def setUp(self): + BaseTestCase.setUp(self) + + layer2 = univ.SequenceOf( + componentType=univ.OctetString() + ) + + layer1 = univ.Sequence( + componentType=namedtype.NamedTypes( + namedtype.OptionalNamedType('inner', layer2), + ) + ) + + self.s = layer1 + + def __initOptionalWithValue(self): + self.s.clear() + self.s[0][0] = 'test' + return self.s + + def __initOptional(self): + self.s.clear() + return self.s + + def testDefModeOptionalWithValue(self): + s = self.__initOptionalWithValue() + assert encoder.encode(s) == ints2octs((48, 8, 48, 6, 4, 4, 116, 101, 115, 116)) + + def testDefModeOptional(self): + s = self.__initOptional() + assert encoder.encode(s) == ints2octs((48, 0)) + + +class EmptyInnerFieldOfSequenceEncoderTestCase(BaseTestCase): + + def testInitializedOptionalNullIsEncoded(self): + self.s = univ.Sequence( + componentType=namedtype.NamedTypes( + namedtype.OptionalNamedType('null', univ.Null()) + ) + ) + + self.s.clear() + self.s[0] = '' + assert encoder.encode(self.s) == ints2octs((48, 2, 5, 0)) + + def testUninitializedOptionalNullIsNotEncoded(self): + self.s = univ.Sequence( + componentType=namedtype.NamedTypes( + namedtype.OptionalNamedType('null', univ.Null()) + ) + ) + + self.s.clear() + assert encoder.encode(self.s) == ints2octs((48, 0)) + + def testInitializedDefaultNullIsNotEncoded(self): + self.s = univ.Sequence( + componentType=namedtype.NamedTypes( + namedtype.DefaultedNamedType('null', univ.Null('')) + ) + ) + + self.s.clear() + self.s[0] = '' + assert encoder.encode(self.s) == ints2octs((48, 0)) + + def testInitializedOptionalOctetStringIsEncoded(self): + self.s = univ.Sequence( + componentType=namedtype.NamedTypes( + namedtype.OptionalNamedType('str', univ.OctetString()) + ) + ) + + self.s.clear() + self.s[0] = '' + assert encoder.encode(self.s) == ints2octs((48, 2, 4, 0)) + + def testUninitializedOptionalOctetStringIsNotEncoded(self): + self.s = univ.Sequence( + componentType=namedtype.NamedTypes( + namedtype.OptionalNamedType('str', univ.OctetString()) + ) + ) + + self.s.clear() + assert encoder.encode(self.s) == ints2octs((48, 0)) + + def testInitializedDefaultOctetStringIsNotEncoded(self): + self.s = univ.Sequence( + componentType=namedtype.NamedTypes( + namedtype.DefaultedNamedType('str', univ.OctetString('')) + ) + ) + + self.s.clear() + self.s[0] = '' + assert encoder.encode(self.s) == ints2octs((48, 0)) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + unittest.TextTestRunner(verbosity=2).run(suite) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/tests/codec/native/__init__.py b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/tests/codec/native/__init__.py new file mode 100644 index 00000000..8c3066b2 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/tests/codec/native/__init__.py @@ -0,0 +1 @@ +# This file is necessary to make this directory a package. diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/tests/codec/native/__main__.py b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/tests/codec/native/__main__.py new file mode 100644 index 00000000..640f5863 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/tests/codec/native/__main__.py @@ -0,0 +1,19 @@ +# +# This file is part of pyasn1 software. +# +# Copyright (c) 2005-2019, Ilya Etingof <etingof@gmail.com> +# License: http://snmplabs.com/pyasn1/license.html +# +try: + import unittest2 as unittest + +except ImportError: + import unittest + +suite = unittest.TestLoader().loadTestsFromNames( + ['tests.codec.native.test_encoder.suite', + 'tests.codec.native.test_decoder.suite'] +) + +if __name__ == '__main__': + unittest.TextTestRunner(verbosity=2).run(suite) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/tests/codec/native/test_decoder.py b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/tests/codec/native/test_decoder.py new file mode 100644 index 00000000..654e2cce --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/tests/codec/native/test_decoder.py @@ -0,0 +1,125 @@ +# +# This file is part of pyasn1 software. +# +# Copyright (c) 2005-2019, Ilya Etingof <etingof@gmail.com> +# License: http://snmplabs.com/pyasn1/license.html +# +import sys + +try: + import unittest2 as unittest + +except ImportError: + import unittest + +from tests.base import BaseTestCase + +from pyasn1.type import namedtype +from pyasn1.type import univ +from pyasn1.codec.native import decoder +from pyasn1.error import PyAsn1Error + + +class BadAsn1SpecTestCase(BaseTestCase): + def testBadSpec(self): + try: + decoder.decode('', asn1Spec='not an Asn1Item') + except PyAsn1Error: + pass + else: + assert 0, 'Invalid asn1Spec accepted' + + +class IntegerDecoderTestCase(BaseTestCase): + def testPosInt(self): + assert decoder.decode(12, asn1Spec=univ.Integer()) == univ.Integer(12) + + def testNegInt(self): + assert decoder.decode(-12, asn1Spec=univ.Integer()) == univ.Integer(-12) + + +class BooleanDecoderTestCase(BaseTestCase): + def testTrue(self): + assert decoder.decode(True, asn1Spec=univ.Boolean()) == univ.Boolean(True) + + def testTrueNeg(self): + assert decoder.decode(False, asn1Spec=univ.Boolean()) == univ.Boolean(False) + + +class BitStringDecoderTestCase(BaseTestCase): + def testSimple(self): + assert decoder.decode('11111111', asn1Spec=univ.BitString()) == univ.BitString(hexValue='ff') + + +class OctetStringDecoderTestCase(BaseTestCase): + def testSimple(self): + assert decoder.decode('Quick brown fox', asn1Spec=univ.OctetString()) == univ.OctetString('Quick brown fox') + + +class NullDecoderTestCase(BaseTestCase): + def testNull(self): + assert decoder.decode(None, asn1Spec=univ.Null()) == univ.Null('') + + +class ObjectIdentifierDecoderTestCase(BaseTestCase): + def testOne(self): + assert decoder.decode('1.3.6.11', asn1Spec=univ.ObjectIdentifier()) == univ.ObjectIdentifier('1.3.6.11') + + +class RealDecoderTestCase(BaseTestCase): + def testSimple(self): + assert decoder.decode(1.33, asn1Spec=univ.Real()) == univ.Real(1.33) + + +class SequenceDecoderTestCase(BaseTestCase): + def setUp(self): + BaseTestCase.setUp(self) + + self.s = univ.Sequence( + componentType=namedtype.NamedTypes( + namedtype.NamedType('place-holder', univ.Null()), + namedtype.NamedType('first-name', univ.OctetString()), + namedtype.NamedType('age', univ.Integer(33)) + ) + ) + + def testSimple(self): + s = self.s.clone() + s[0] = univ.Null('') + s[1] = univ.OctetString('xx') + s[2] = univ.Integer(33) + assert decoder.decode({'place-holder': None, 'first-name': 'xx', 'age': 33}, asn1Spec=self.s) == s + + +class ChoiceDecoderTestCase(BaseTestCase): + def setUp(self): + BaseTestCase.setUp(self) + + self.s = univ.Choice( + componentType=namedtype.NamedTypes( + namedtype.NamedType('place-holder', univ.Null()), + namedtype.NamedType('first-name', univ.OctetString()), + namedtype.NamedType('age', univ.Integer(33)) + ) + ) + + def testSimple(self): + s = self.s.clone() + s[1] = univ.OctetString('xx') + assert decoder.decode({'first-name': 'xx'}, asn1Spec=self.s) == s + + +class AnyDecoderTestCase(BaseTestCase): + def setUp(self): + BaseTestCase.setUp(self) + + self.s = univ.Any() + + def testSimple(self): + assert decoder.decode('fox', asn1Spec=univ.Any()) == univ.Any('fox') + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + unittest.TextTestRunner(verbosity=2).run(suite) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/tests/codec/native/test_encoder.py b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/tests/codec/native/test_encoder.py new file mode 100644 index 00000000..25c99797 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/tests/codec/native/test_encoder.py @@ -0,0 +1,146 @@ +# +# This file is part of pyasn1 software. +# +# Copyright (c) 2005-2019, Ilya Etingof <etingof@gmail.com> +# License: http://snmplabs.com/pyasn1/license.html +# +import sys + +try: + import unittest2 as unittest + +except ImportError: + import unittest + +from tests.base import BaseTestCase + +from pyasn1.type import namedtype +from pyasn1.type import univ +from pyasn1.codec.native import encoder +from pyasn1.compat.octets import str2octs +from pyasn1.error import PyAsn1Error + + +class BadAsn1SpecTestCase(BaseTestCase): + def testBadValueType(self): + try: + encoder.encode('not an Asn1Item') + + except PyAsn1Error: + pass + + else: + assert 0, 'Invalid value type accepted' + + +class IntegerEncoderTestCase(BaseTestCase): + def testPosInt(self): + assert encoder.encode(univ.Integer(12)) == 12 + + def testNegInt(self): + assert encoder.encode(univ.Integer(-12)) == -12 + + +class BooleanEncoderTestCase(BaseTestCase): + def testTrue(self): + assert encoder.encode(univ.Boolean(1)) is True + + def testFalse(self): + assert encoder.encode(univ.Boolean(0)) is False + + +class BitStringEncoderTestCase(BaseTestCase): + def setUp(self): + BaseTestCase.setUp(self) + self.b = univ.BitString((1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1)) + + def testValue(self): + assert encoder.encode(self.b) == '101010011000101' + + +class OctetStringEncoderTestCase(BaseTestCase): + def setUp(self): + BaseTestCase.setUp(self) + self.o = univ.OctetString('Quick brown fox') + + def testValue(self): + assert encoder.encode(self.o) == str2octs('Quick brown fox') + + +class NullEncoderTestCase(BaseTestCase): + def testNull(self): + assert encoder.encode(univ.Null('')) is None + + +class ObjectIdentifierEncoderTestCase(BaseTestCase): + def testOne(self): + assert encoder.encode(univ.ObjectIdentifier((1, 3, 6, 0, 12345))) == '1.3.6.0.12345' + + +class RealEncoderTestCase(BaseTestCase): + def testChar(self): + assert encoder.encode(univ.Real((123, 10, 11))) == 1.23e+13 + + def testPlusInf(self): + assert encoder.encode(univ.Real('inf')) == float('inf') + + def testMinusInf(self): + assert encoder.encode(univ.Real('-inf')) == float('-inf') + + +class SequenceEncoderTestCase(BaseTestCase): + def setUp(self): + BaseTestCase.setUp(self) + + self.s = univ.Sequence(componentType=namedtype.NamedTypes( + namedtype.NamedType('place-holder', univ.Null('')), + namedtype.OptionalNamedType('first-name', univ.OctetString('')), + namedtype.DefaultedNamedType('age', univ.Integer(33)), + )) + + def testSimple(self): + s = self.s.clone() + s[0] = univ.Null('') + s[1] = 'abc' + s[2] = 123 + assert encoder.encode(s) == {'place-holder': None, 'first-name': str2octs('abc'), 'age': 123} + + +class ChoiceEncoderTestCase(BaseTestCase): + def setUp(self): + BaseTestCase.setUp(self) + + self.s = univ.Choice( + componentType=namedtype.NamedTypes( + namedtype.NamedType('place-holder', univ.Null('')), + namedtype.NamedType('number', univ.Integer(0)), + namedtype.NamedType('string', univ.OctetString()) + ) + ) + + def testEmpty(self): + try: + encoder.encode(self.s) + except PyAsn1Error: + pass + else: + assert False, 'encoded unset choice' + + def testFilled(self): + self.s.setComponentByPosition(0, univ.Null('')) + assert encoder.encode(self.s) == {'place-holder': None} + + +class AnyEncoderTestCase(BaseTestCase): + def setUp(self): + BaseTestCase.setUp(self) + self.s = univ.Any(encoder.encode(univ.OctetString('fox'))) + + def testSimple(self): + assert encoder.encode(self.s) == str2octs('fox') + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + unittest.TextTestRunner(verbosity=2).run(suite) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/tests/compat/__init__.py b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/tests/compat/__init__.py new file mode 100644 index 00000000..8c3066b2 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/tests/compat/__init__.py @@ -0,0 +1 @@ +# This file is necessary to make this directory a package. diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/tests/compat/__main__.py b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/tests/compat/__main__.py new file mode 100644 index 00000000..296d70c9 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/tests/compat/__main__.py @@ -0,0 +1,21 @@ +# +# This file is part of pyasn1 software. +# +# Copyright (c) 2005-2019, Ilya Etingof <etingof@gmail.com> +# License: http://snmplabs.com/pyasn1/license.html +# +try: + import unittest2 as unittest + +except ImportError: + import unittest + +suite = unittest.TestLoader().loadTestsFromNames( + ['tests.compat.test_binary.suite', + 'tests.compat.test_integer.suite', + 'tests.compat.test_octets.suite'] +) + + +if __name__ == '__main__': + unittest.TextTestRunner(verbosity=2).run(suite) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/tests/compat/test_binary.py b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/tests/compat/test_binary.py new file mode 100644 index 00000000..3e0949f2 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/tests/compat/test_binary.py @@ -0,0 +1,56 @@ +# +# This file is part of pyasn1 software. +# +# Copyright (c) 2005-2019, Ilya Etingof <etingof@gmail.com> +# License: http://snmplabs.com/pyasn1/license.html +# +import sys + +try: + import unittest2 as unittest +except ImportError: + import unittest + +from tests.base import BaseTestCase + +from pyasn1.compat import binary + + +class BinaryTestCase(BaseTestCase): + + def test_bin_zero(self): + assert '0b0' == binary.bin(0) + + + def test_bin_noarg(self): + try: + binary.bin() + + except TypeError: + pass + + except: + assert 0, 'bin() tolerates no arguments' + + + def test_bin_allones(self): + assert '0b1111111111111111111111111111111111111111111111111111111111111111' == binary.bin(0xffffffffffffffff) + + + def test_bin_allzeros(self): + assert '0b0' == binary.bin(0x0000000) + + + + def test_bin_pos(self): + assert '0b1000000010000000100000001' == binary.bin(0x01010101) + + + def test_bin_neg(self): + assert '-0b1000000010000000100000001' == binary.bin(-0x01010101) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + unittest.TextTestRunner(verbosity=2).run(suite) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/tests/compat/test_integer.py b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/tests/compat/test_integer.py new file mode 100644 index 00000000..04fd86ab --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/tests/compat/test_integer.py @@ -0,0 +1,53 @@ +# +# This file is part of pyasn1 software. +# +# Copyright (c) 2005-2019, Ilya Etingof <etingof@gmail.com> +# License: http://snmplabs.com/pyasn1/license.html +# +import sys + +try: + import unittest2 as unittest +except ImportError: + import unittest + +from tests.base import BaseTestCase + +from pyasn1.compat import integer + + +class IntegerTestCase(BaseTestCase): + + if sys.version_info[0] > 2: + + def test_from_bytes_zero(self): + assert 0 == integer.from_bytes(bytes([0]), signed=False) + + def test_from_bytes_unsigned(self): + assert -66051 == integer.from_bytes(bytes([254, 253, 253]), signed=True) + + def test_from_bytes_signed(self): + assert 66051 == integer.from_bytes(bytes([0, 1, 2, 3]), signed=False) + + def test_from_bytes_empty(self): + assert 0 == integer.from_bytes(bytes([])) + + else: + + def test_from_bytes_zero(self): + assert 0 == integer.from_bytes('\x00', signed=False) + + def test_from_bytes_unsigned(self): + assert -66051 == integer.from_bytes('\xfe\xfd\xfd', signed=True) + + def test_from_bytes_signed(self): + assert 66051 == integer.from_bytes('\x01\x02\x03', signed=False) + + def test_from_bytes_empty(self): + assert 0 == integer.from_bytes('') + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + unittest.TextTestRunner(verbosity=2).run(suite) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/tests/compat/test_octets.py b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/tests/compat/test_octets.py new file mode 100644 index 00000000..5a9bc7c3 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/tests/compat/test_octets.py @@ -0,0 +1,117 @@ +# +# This file is part of pyasn1 software. +# +# Copyright (c) 2005-2019, Ilya Etingof <etingof@gmail.com> +# License: http://snmplabs.com/pyasn1/license.html +# +import sys + +try: + import unittest2 as unittest +except ImportError: + import unittest + +from tests.base import BaseTestCase + +from pyasn1.compat import octets + + +class OctetsTestCase(BaseTestCase): + + if sys.version_info[0] > 2: + + def test_ints2octs(self): + assert [1, 2, 3] == list(octets.ints2octs([1, 2, 3])) + + def test_ints2octs_empty(self): + assert not octets.ints2octs([]) + + def test_int2oct(self): + assert [12] == list(octets.int2oct(12)) + + def test_octs2ints(self): + assert [1, 2, 3] == list(octets.octs2ints(bytes([1, 2, 3]))) + + def test_octs2ints_empty(self): + assert not octets.octs2ints(bytes([])) + + def test_oct2int(self): + assert 12 == octets.oct2int(bytes([12]))[0] + + def test_str2octs(self): + assert bytes([1, 2, 3]) == octets.str2octs('\x01\x02\x03') + + def test_str2octs_empty(self): + assert not octets.str2octs('') + + def test_octs2str(self): + assert '\x01\x02\x03' == octets.octs2str(bytes([1, 2, 3])) + + def test_octs2str_empty(self): + assert not octets.octs2str(bytes([])) + + def test_isOctetsType(self): + assert octets.isOctetsType('abc') == False + assert octets.isOctetsType(123) == False + assert octets.isOctetsType(bytes()) == True + + def test_isStringType(self): + assert octets.isStringType('abc') == True + assert octets.isStringType(123) == False + assert octets.isStringType(bytes()) == False + + def test_ensureString(self): + assert 'abc'.encode() == octets.ensureString('abc'.encode()) + assert bytes([1, 2, 3]) == octets.ensureString([1, 2, 3]) + + else: + + def test_ints2octs(self): + assert '\x01\x02\x03' == octets.ints2octs([1, 2, 3]) + + def test_ints2octs_empty(self): + assert not octets.ints2octs([]) + + def test_int2oct(self): + assert '\x0c' == octets.int2oct(12) + + def test_octs2ints(self): + assert [1, 2, 3] == octets.octs2ints('\x01\x02\x03') + + def test_octs2ints_empty(self): + assert not octets.octs2ints('') + + def test_oct2int(self): + assert 12 == octets.oct2int('\x0c') + + def test_str2octs(self): + assert '\x01\x02\x03' == octets.str2octs('\x01\x02\x03') + + def test_str2octs_empty(self): + assert not octets.str2octs('') + + def test_octs2str(self): + assert '\x01\x02\x03' == octets.octs2str('\x01\x02\x03') + + def test_octs2str_empty(self): + assert not octets.octs2str('') + + def test_isOctetsType(self): + assert octets.isOctetsType('abc') == True + assert octets.isOctetsType(123) == False + assert octets.isOctetsType(unicode('abc')) == False + + def test_isStringType(self): + assert octets.isStringType('abc') == True + assert octets.isStringType(123) == False + assert octets.isStringType(unicode('abc')) == True + + def test_ensureString(self): + assert 'abc' == octets.ensureString('abc') + assert '123' == octets.ensureString(123) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + unittest.TextTestRunner(verbosity=2).run(suite) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/tests/test_debug.py b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/tests/test_debug.py new file mode 100644 index 00000000..9e33f930 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/tests/test_debug.py @@ -0,0 +1,42 @@ +# +# This file is part of pyasn1 software. +# +# Copyright (c) 2005-2019, Ilya Etingof <etingof@gmail.com> +# License: http://snmplabs.com/pyasn1/license.html +# +import sys + +try: + import unittest2 as unittest + +except ImportError: + import unittest + +from tests.base import BaseTestCase + +from pyasn1 import debug +from pyasn1 import error + +class DebugCaseBase(BaseTestCase): + def testKnownFlags(self): + debug.setLogger(0) + debug.setLogger(debug.Debug('all', 'encoder', 'decoder')) + debug.setLogger(0) + + def testUnknownFlags(self): + try: + debug.setLogger(debug.Debug('all', 'unknown', loggerName='xxx')) + + except error.PyAsn1Error: + debug.setLogger(0) + return + + else: + debug.setLogger(0) + assert 0, 'unknown debug flag tolerated' + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + unittest.TextTestRunner(verbosity=2).run(suite) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/tests/type/__init__.py b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/tests/type/__init__.py new file mode 100644 index 00000000..8c3066b2 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/tests/type/__init__.py @@ -0,0 +1 @@ +# This file is necessary to make this directory a package. diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/tests/type/__main__.py b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/tests/type/__main__.py new file mode 100644 index 00000000..fcc66e78 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/tests/type/__main__.py @@ -0,0 +1,26 @@ +# +# This file is part of pyasn1 software. +# +# Copyright (c) 2005-2019, Ilya Etingof <etingof@gmail.com> +# License: http://snmplabs.com/pyasn1/license.html +# +try: + import unittest2 as unittest + +except ImportError: + import unittest + +suite = unittest.TestLoader().loadTestsFromNames( + ['tests.type.test_constraint.suite', + 'tests.type.test_opentype.suite', + 'tests.type.test_namedtype.suite', + 'tests.type.test_namedval.suite', + 'tests.type.test_tag.suite', + 'tests.type.test_univ.suite', + 'tests.type.test_char.suite', + 'tests.type.test_useful.suite'] +) + + +if __name__ == '__main__': + unittest.TextTestRunner(verbosity=2).run(suite) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/tests/type/test_char.py b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/tests/type/test_char.py new file mode 100644 index 00000000..8540a3e9 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/tests/type/test_char.py @@ -0,0 +1,175 @@ +# +# This file is part of pyasn1 software. +# +# Copyright (c) 2005-2019, Ilya Etingof <etingof@gmail.com> +# License: http://snmplabs.com/pyasn1/license.html +# +import pickle +import sys + +try: + import unittest2 as unittest + +except ImportError: + import unittest + +from tests.base import BaseTestCase + +from pyasn1.type import char +from pyasn1.type import univ +from pyasn1.type import constraint +from pyasn1.compat.octets import ints2octs +from pyasn1.error import PyAsn1Error + + +class AbstractStringTestCase(object): + + initializer = () + encoding = 'us-ascii' + asn1Type = None + + def setUp(self): + BaseTestCase.setUp(self) + + self.asn1String = self.asn1Type(ints2octs(self.initializer), encoding=self.encoding) + self.pythonString = ints2octs(self.initializer).decode(self.encoding) + + def testUnicode(self): + assert self.asn1String == self.pythonString, 'unicode init fails' + + def testLength(self): + assert len(self.asn1String) == len(self.pythonString), 'unicode len() fails' + + def testSizeConstraint(self): + asn1Spec = self.asn1Type(subtypeSpec=constraint.ValueSizeConstraint(1, 1)) + + try: + asn1Spec.clone(self.pythonString) + except PyAsn1Error: + pass + else: + assert False, 'Size constraint tolerated' + + try: + asn1Spec.clone(self.pythonString[0]) + except PyAsn1Error: + assert False, 'Size constraint failed' + + def testSerialised(self): + if sys.version_info[0] < 3: + assert str(self.asn1String) == self.pythonString.encode(self.encoding), '__str__() fails' + else: + assert bytes(self.asn1String) == self.pythonString.encode(self.encoding), '__str__() fails' + + def testPrintable(self): + if sys.version_info[0] < 3: + assert unicode(self.asn1String) == self.pythonString, '__str__() fails' + else: + assert str(self.asn1String) == self.pythonString, '__str__() fails' + + def testInit(self): + assert self.asn1Type(self.pythonString) == self.pythonString + assert self.asn1Type(self.pythonString.encode(self.encoding)) == self.pythonString + assert self.asn1Type(univ.OctetString(self.pythonString.encode(self.encoding))) == self.pythonString + assert self.asn1Type(self.asn1Type(self.pythonString)) == self.pythonString + assert self.asn1Type(self.initializer, encoding=self.encoding) == self.pythonString + + def testInitFromAsn1(self): + assert self.asn1Type(self.asn1Type(self.pythonString)) == self.pythonString + assert self.asn1Type(univ.OctetString(self.pythonString.encode(self.encoding), encoding=self.encoding)) == self.pythonString + + def testAsOctets(self): + assert self.asn1String.asOctets() == self.pythonString.encode(self.encoding), 'testAsOctets() fails' + + def testAsNumbers(self): + assert self.asn1String.asNumbers() == self.initializer, 'testAsNumbers() fails' + + def testSeq(self): + assert self.asn1String[0] == self.pythonString[0], '__getitem__() fails' + + def testEmpty(self): + try: + str(self.asn1Type()) + except PyAsn1Error: + pass + else: + assert 0, 'Value operation on ASN1 type tolerated' + + def testAdd(self): + assert self.asn1String + self.pythonString.encode(self.encoding) == self.pythonString + self.pythonString, '__add__() fails' + + def testRadd(self): + assert self.pythonString.encode(self.encoding) + self.asn1String == self.pythonString + self.pythonString, '__radd__() fails' + + def testMul(self): + assert self.asn1String * 2 == self.pythonString * 2, '__mul__() fails' + + def testRmul(self): + assert 2 * self.asn1String == 2 * self.pythonString, '__rmul__() fails' + + def testContains(self): + assert self.pythonString in self.asn1String + assert self.pythonString + self.pythonString not in self.asn1String + + if sys.version_info[:2] > (2, 4): + def testReverse(self): + assert list(reversed(self.asn1String)) == list(reversed(self.pythonString)) + + def testSchemaPickling(self): + old_asn1 = self.asn1Type() + serialised = pickle.dumps(old_asn1) + assert serialised + new_asn1 = pickle.loads(serialised) + assert type(new_asn1) == self.asn1Type + assert old_asn1.isSameTypeWith(new_asn1) + + def testValuePickling(self): + old_asn1 = self.asn1String + serialised = pickle.dumps(old_asn1) + assert serialised + new_asn1 = pickle.loads(serialised) + assert new_asn1 == self.asn1String + + +class VisibleStringTestCase(AbstractStringTestCase, BaseTestCase): + + initializer = (97, 102) + encoding = 'us-ascii' + asn1Type = char.VisibleString + + +class GeneralStringTestCase(AbstractStringTestCase, BaseTestCase): + + initializer = (169, 174) + encoding = 'iso-8859-1' + asn1Type = char.GeneralString + + +class UTF8StringTestCase(AbstractStringTestCase, BaseTestCase): + + initializer = (209, 132, 208, 176) + encoding = 'utf-8' + asn1Type = char.UTF8String + + +class BMPStringTestCase(AbstractStringTestCase, BaseTestCase): + + initializer = (4, 48, 4, 68) + encoding = 'utf-16-be' + asn1Type = char.BMPString + + +if sys.version_info[0] > 2: + + # Somehow comparison of UTF-32 encoded strings does not work in Py2 + + class UniversalStringTestCase(AbstractStringTestCase, BaseTestCase): + initializer = (0, 0, 4, 48, 0, 0, 4, 68) + encoding = 'utf-32-be' + asn1Type = char.UniversalString + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + unittest.TextTestRunner(verbosity=2).run(suite) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/tests/type/test_constraint.py b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/tests/type/test_constraint.py new file mode 100644 index 00000000..7ef62937 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/tests/type/test_constraint.py @@ -0,0 +1,425 @@ +# +# This file is part of pyasn1 software. +# +# Copyright (c) 2005-2019, Ilya Etingof <etingof@gmail.com> +# License: http://snmplabs.com/pyasn1/license.html +# +import sys + +try: + import unittest2 as unittest + +except ImportError: + import unittest + +from tests.base import BaseTestCase + +from pyasn1.type import constraint +from pyasn1.type import error + + +class SingleValueConstraintTestCase(BaseTestCase): + def setUp(self): + BaseTestCase.setUp(self) + self.v1 = 1, 2 + self.v2 = 3, 4 + self.c1 = constraint.SingleValueConstraint(*self.v1) + self.c2 = constraint.SingleValueConstraint(*self.v2) + + def testCmp(self): + assert self.c1 == self.c1, 'comparison fails' + + def testHash(self): + assert hash(self.c1) != hash(self.c2), 'hash() fails' + + def testGoodVal(self): + try: + self.c1(1) + + except error.ValueConstraintError: + assert 0, 'constraint check fails' + + def testBadVal(self): + try: + self.c1(4) + except error.ValueConstraintError: + pass + else: + assert 0, 'constraint check fails' + + def testContains(self): + for v in self.v1: + assert v in self.c1 + assert v not in self.c2 + + for v in self.v2: + assert v in self.c2 + assert v not in self.c1 + + def testIter(self): + assert set(self.v1) == set(self.c1) + assert set(self.v2) == set(self.c2) + + def testSub(self): + subconst = self.c1 - constraint.SingleValueConstraint(self.v1[0]) + assert list(subconst) == [self.v1[1]] + + def testAdd(self): + superconst = self.c1 + self.c2 + assert set(superconst) == set(self.v1 + self.v2) + + +class ContainedSubtypeConstraintTestCase(BaseTestCase): + def setUp(self): + BaseTestCase.setUp(self) + self.c1 = constraint.ContainedSubtypeConstraint( + constraint.SingleValueConstraint(12) + ) + + def testGoodVal(self): + try: + self.c1(12) + except error.ValueConstraintError: + assert 0, 'constraint check fails' + + def testBadVal(self): + try: + self.c1(4) + except error.ValueConstraintError: + pass + else: + assert 0, 'constraint check fails' + + +class ValueRangeConstraintTestCase(BaseTestCase): + def setUp(self): + BaseTestCase.setUp(self) + self.c1 = constraint.ValueRangeConstraint(1, 4) + + def testGoodVal(self): + try: + self.c1(1) + except error.ValueConstraintError: + assert 0, 'constraint check fails' + + def testBadVal(self): + try: + self.c1(-5) + except error.ValueConstraintError: + pass + else: + assert 0, 'constraint check fails' + + +class ValueSizeConstraintTestCase(BaseTestCase): + def setUp(self): + BaseTestCase.setUp(self) + self.c1 = constraint.ValueSizeConstraint(1, 2) + + def testGoodVal(self): + try: + self.c1('a') + except error.ValueConstraintError: + assert 0, 'constraint check fails' + + def testBadVal(self): + try: + self.c1('abc') + except error.ValueConstraintError: + pass + else: + assert 0, 'constraint check fails' + + +class PermittedAlphabetConstraintTestCase(SingleValueConstraintTestCase): + def setUp(self): + self.v1 = 'A', 'B' + self.v2 = 'C', 'D' + self.c1 = constraint.PermittedAlphabetConstraint(*self.v1) + self.c2 = constraint.PermittedAlphabetConstraint(*self.v2) + + def testGoodVal(self): + try: + self.c1('A') + + except error.ValueConstraintError: + assert 0, 'constraint check fails' + + def testBadVal(self): + try: + self.c1('E') + + except error.ValueConstraintError: + pass + + else: + assert 0, 'constraint check fails' + + +class WithComponentsConstraintTestCase(BaseTestCase): + + def testGoodVal(self): + c = constraint.WithComponentsConstraint( + ('A', constraint.ComponentPresentConstraint()), + ('B', constraint.ComponentAbsentConstraint())) + + try: + c({'A': 1}) + + except error.ValueConstraintError: + assert 0, 'constraint check fails' + + def testGoodValWithExtraFields(self): + c = constraint.WithComponentsConstraint( + ('A', constraint.ComponentPresentConstraint()), + ('B', constraint.ComponentAbsentConstraint()) + ) + + try: + c({'A': 1, 'C': 2}) + + except error.ValueConstraintError: + assert 0, 'constraint check fails' + + def testEmptyConstraint(self): + c = constraint.WithComponentsConstraint() + + try: + c({'A': 1}) + + except error.ValueConstraintError: + assert 0, 'constraint check fails' + + def testBadVal(self): + c = constraint.WithComponentsConstraint( + ('A', constraint.ComponentPresentConstraint()) + ) + + try: + c({'B': 2}) + + except error.ValueConstraintError: + pass + + else: + assert 0, 'constraint check fails' + + def testBadValExtraFields(self): + c = constraint.WithComponentsConstraint( + ('A', constraint.ComponentPresentConstraint()) + ) + + try: + c({'B': 2, 'C': 3}) + + except error.ValueConstraintError: + pass + + else: + assert 0, 'constraint check fails' + + +class ConstraintsIntersectionTestCase(BaseTestCase): + def setUp(self): + BaseTestCase.setUp(self) + self.c1 = constraint.ConstraintsIntersection( + constraint.SingleValueConstraint(4), + constraint.ValueRangeConstraint(2, 4) + ) + + def testCmp1(self): + assert constraint.SingleValueConstraint(4) in self.c1, '__cmp__() fails' + + def testCmp2(self): + assert constraint.SingleValueConstraint(5) not in self.c1, \ + '__cmp__() fails' + + def testCmp3(self): + c = constraint.ConstraintsUnion(constraint.ConstraintsIntersection( + constraint.SingleValueConstraint(4), + constraint.ValueRangeConstraint(2, 4)) + ) + assert self.c1 in c, '__cmp__() fails' + + def testCmp4(self): + c = constraint.ConstraintsUnion( + constraint.ConstraintsIntersection(constraint.SingleValueConstraint(5)) + ) + assert self.c1 not in c, '__cmp__() fails' + + def testGoodVal(self): + try: + self.c1(4) + except error.ValueConstraintError: + assert 0, 'constraint check fails' + + def testBadVal(self): + try: + self.c1(-5) + except error.ValueConstraintError: + pass + else: + assert 0, 'constraint check fails' + + +class InnerTypeConstraintTestCase(BaseTestCase): + def testConst1(self): + c = constraint.InnerTypeConstraint( + constraint.SingleValueConstraint(4) + ) + try: + c(4, 32) + except error.ValueConstraintError: + assert 0, 'constraint check fails' + try: + c(5, 32) + except error.ValueConstraintError: + pass + else: + assert 0, 'constraint check fails' + + def testConst2(self): + c = constraint.InnerTypeConstraint( + (0, constraint.SingleValueConstraint(4), 'PRESENT'), + (1, constraint.SingleValueConstraint(4), 'ABSENT') + ) + try: + c(4, 0) + except error.ValueConstraintError: + assert 0, 'constraint check fails' + try: + c(4, 1) + except error.ValueConstraintError: + pass + else: + assert 0, 'constraint check fails' + try: + c(3, 0) + except error.ValueConstraintError: + pass + else: + assert 0, 'constraint check fails' + + # Constraints compositions + + +class ConstraintsIntersectionRangeTestCase(BaseTestCase): + def setUp(self): + BaseTestCase.setUp(self) + self.c1 = constraint.ConstraintsIntersection( + constraint.ValueRangeConstraint(1, 9), + constraint.ValueRangeConstraint(2, 5) + ) + + def testGoodVal(self): + try: + self.c1(3) + except error.ValueConstraintError: + assert 0, 'constraint check fails' + + def testBadVal(self): + try: + self.c1(0) + except error.ValueConstraintError: + pass + else: + assert 0, 'constraint check fails' + + +class ConstraintsUnionTestCase(BaseTestCase): + def setUp(self): + BaseTestCase.setUp(self) + self.c1 = constraint.ConstraintsUnion( + constraint.SingleValueConstraint(5), + constraint.ValueRangeConstraint(1, 3) + ) + + def testGoodVal(self): + try: + self.c1(2) + self.c1(5) + except error.ValueConstraintError: + assert 0, 'constraint check fails' + + def testBadVal(self): + try: + self.c1(-5) + except error.ValueConstraintError: + pass + else: + assert 0, 'constraint check fails' + + +class ConstraintsExclusionTestCase(BaseTestCase): + def setUp(self): + BaseTestCase.setUp(self) + self.c1 = constraint.ConstraintsExclusion( + constraint.ValueRangeConstraint(2, 4) + ) + + def testGoodVal(self): + try: + self.c1(6) + except error.ValueConstraintError: + assert 0, 'constraint check fails' + + def testBadVal(self): + try: + self.c1(2) + except error.ValueConstraintError: + pass + else: + assert 0, 'constraint check fails' + + +# Constraints derivations + +class DirectDerivationTestCase(BaseTestCase): + def setUp(self): + BaseTestCase.setUp(self) + + self.c1 = constraint.SingleValueConstraint(5) + + self.c2 = constraint.ConstraintsUnion( + self.c1, constraint.ValueRangeConstraint(1, 3) + ) + + def testGoodVal(self): + assert self.c1.isSuperTypeOf(self.c2), 'isSuperTypeOf failed' + assert not self.c1.isSubTypeOf(self.c2), 'isSubTypeOf failed' + + def testBadVal(self): + assert not self.c2.isSuperTypeOf(self.c1), 'isSuperTypeOf failed' + assert self.c2.isSubTypeOf(self.c1), 'isSubTypeOf failed' + + +class IndirectDerivationTestCase(BaseTestCase): + def setUp(self): + BaseTestCase.setUp(self) + + self.c1 = constraint.ConstraintsIntersection( + constraint.ValueRangeConstraint(1, 30) + ) + + self.c2 = constraint.ConstraintsIntersection( + self.c1, constraint.ValueRangeConstraint(1, 20) + ) + + self.c2 = constraint.ConstraintsIntersection( + self.c2, constraint.ValueRangeConstraint(1, 10) + ) + + def testGoodVal(self): + assert self.c1.isSuperTypeOf(self.c2), 'isSuperTypeOf failed' + assert not self.c1.isSubTypeOf(self.c2), 'isSubTypeOf failed' + + def testBadVal(self): + assert not self.c2.isSuperTypeOf(self.c1), 'isSuperTypeOf failed' + assert self.c2.isSubTypeOf(self.c1), 'isSubTypeOf failed' + +# TODO: how to apply size constraints to constructed types? + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + unittest.TextTestRunner(verbosity=2).run(suite) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/tests/type/test_namedtype.py b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/tests/type/test_namedtype.py new file mode 100644 index 00000000..7cff45ea --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/tests/type/test_namedtype.py @@ -0,0 +1,140 @@ +# +# This file is part of pyasn1 software. +# +# Copyright (c) 2005-2019, Ilya Etingof <etingof@gmail.com> +# License: http://snmplabs.com/pyasn1/license.html +# +import sys + +try: + import unittest2 as unittest + +except ImportError: + import unittest + +from tests.base import BaseTestCase + +from pyasn1.type import namedtype +from pyasn1.type import univ +from pyasn1.error import PyAsn1Error + + +class NamedTypeCaseBase(BaseTestCase): + def setUp(self): + BaseTestCase.setUp(self) + self.e = namedtype.NamedType('age', univ.Integer(0)) + + def testIter(self): + n, t = self.e + assert n == 'age' or t == univ.Integer(), 'unpack fails' + + def testRepr(self): + assert 'age' in repr(self.e) + + +class NamedTypesCaseBase(BaseTestCase): + def setUp(self): + BaseTestCase.setUp(self) + + self.e = namedtype.NamedTypes( + namedtype.NamedType('first-name', univ.OctetString('')), + namedtype.OptionalNamedType('age', univ.Integer(0)), + namedtype.NamedType('family-name', univ.OctetString('')) + ) + + def testRepr(self): + assert 'first-name' in repr(self.e) + + def testContains(self): + assert 'first-name' in self.e + assert '<missing>' not in self.e + + # noinspection PyUnusedLocal + def testGetItem(self): + assert self.e[0] == namedtype.NamedType('first-name', univ.OctetString('')) + + def testIter(self): + assert list(self.e) == ['first-name', 'age', 'family-name'] + + def testGetTypeByPosition(self): + assert self.e.getTypeByPosition(0) == univ.OctetString(''), \ + 'getTypeByPosition() fails' + + def testGetNameByPosition(self): + assert self.e.getNameByPosition(0) == 'first-name', \ + 'getNameByPosition() fails' + + def testGetPositionByName(self): + assert self.e.getPositionByName('first-name') == 0, \ + 'getPositionByName() fails' + + def testGetTypesNearPosition(self): + assert self.e.getTagMapNearPosition(0).presentTypes == { + univ.OctetString.tagSet: univ.OctetString('') + } + assert self.e.getTagMapNearPosition(1).presentTypes == { + univ.Integer.tagSet: univ.Integer(0), + univ.OctetString.tagSet: univ.OctetString('') + } + assert self.e.getTagMapNearPosition(2).presentTypes == { + univ.OctetString.tagSet: univ.OctetString('') + } + + def testGetTagMap(self): + assert self.e.tagMap.presentTypes == { + univ.OctetString.tagSet: univ.OctetString(''), + univ.Integer.tagSet: univ.Integer(0) + } + + def testStrTagMap(self): + assert 'TagMap' in str(self.e.tagMap) + assert 'OctetString' in str(self.e.tagMap) + assert 'Integer' in str(self.e.tagMap) + + def testReprTagMap(self): + assert 'TagMap' in repr(self.e.tagMap) + assert 'OctetString' in repr(self.e.tagMap) + assert 'Integer' in repr(self.e.tagMap) + + def testGetTagMapWithDups(self): + try: + self.e.tagMapUnique[0] + except PyAsn1Error: + pass + else: + assert 0, 'Duped types not noticed' + + def testGetPositionNearType(self): + assert self.e.getPositionNearType(univ.OctetString.tagSet, 0) == 0 + assert self.e.getPositionNearType(univ.Integer.tagSet, 1) == 1 + assert self.e.getPositionNearType(univ.OctetString.tagSet, 2) == 2 + + +class OrderedNamedTypesCaseBase(BaseTestCase): + def setUp(self): + BaseTestCase.setUp(self) + + self.e = namedtype.NamedTypes( + namedtype.NamedType('first-name', univ.OctetString('')), + namedtype.NamedType('age', univ.Integer(0)) + ) + + def testGetTypeByPosition(self): + assert self.e.getTypeByPosition(0) == univ.OctetString(''), \ + 'getTypeByPosition() fails' + + +class DuplicateNamedTypesCaseBase(BaseTestCase): + def testDuplicateDefaultTags(self): + nt = namedtype.NamedTypes( + namedtype.NamedType('first-name', univ.Any()), + namedtype.NamedType('age', univ.Any()) + ) + + assert isinstance(nt.tagMap, namedtype.NamedTypes.PostponedError) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + unittest.TextTestRunner(verbosity=2).run(suite) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/tests/type/test_namedval.py b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/tests/type/test_namedval.py new file mode 100644 index 00000000..4ac08cf9 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/tests/type/test_namedval.py @@ -0,0 +1,58 @@ +# +# This file is part of pyasn1 software. +# +# Copyright (c) 2005-2019, Ilya Etingof <etingof@gmail.com> +# License: http://snmplabs.com/pyasn1/license.html +# +import sys + +try: + import unittest2 as unittest + +except ImportError: + import unittest + +from tests.base import BaseTestCase + +from pyasn1.type import namedval + + +class NamedValuesCaseBase(BaseTestCase): + def setUp(self): + BaseTestCase.setUp(self) + self.e = namedval.NamedValues(('off', 0), ('on', 1)) + + def testDict(self): + assert set(self.e.items()) == set([('off', 0), ('on', 1)]) + assert set(self.e.keys()) == set(['off', 'on']) + assert set(self.e) == set(['off', 'on']) + assert set(self.e.values()) == set([0, 1]) + assert 'on' in self.e and 'off' in self.e and 'xxx' not in self.e + assert 0 in self.e and 1 in self.e and 2 not in self.e + + def testInit(self): + assert namedval.NamedValues(off=0, on=1) == {'off': 0, 'on': 1} + assert namedval.NamedValues('off', 'on') == {'off': 0, 'on': 1} + assert namedval.NamedValues(('c', 0)) == {'c': 0} + assert namedval.NamedValues('a', 'b', ('c', 0), d=1) == {'c': 0, 'd': 1, 'a': 2, 'b': 3} + + def testLen(self): + assert len(self.e) == 2 + assert len(namedval.NamedValues()) == 0 + + def testAdd(self): + assert namedval.NamedValues(off=0) + namedval.NamedValues(on=1) == {'off': 0, 'on': 1} + + def testClone(self): + assert namedval.NamedValues(off=0).clone(('on', 1)) == {'off': 0, 'on': 1} + assert namedval.NamedValues(off=0).clone(on=1) == {'off': 0, 'on': 1} + + def testStrRepr(self): + assert str(self.e) + assert repr(self.e) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + unittest.TextTestRunner(verbosity=2).run(suite) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/tests/type/test_opentype.py b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/tests/type/test_opentype.py new file mode 100644 index 00000000..ff6788fc --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/tests/type/test_opentype.py @@ -0,0 +1,106 @@ +# +# This file is part of pyasn1 software. +# +# Copyright (c) 2005-2019, Ilya Etingof <etingof@gmail.com> +# License: http://snmplabs.com/pyasn1/license.html +# +import sys + +try: + import unittest2 as unittest + +except ImportError: + import unittest + +from tests.base import BaseTestCase + +from pyasn1.type import univ +from pyasn1.type import tag +from pyasn1.type import namedtype +from pyasn1.type import opentype +from pyasn1.compat.octets import str2octs +from pyasn1.error import PyAsn1Error + + +class UntaggedAnyTestCase(BaseTestCase): + + def setUp(self): + BaseTestCase.setUp(self) + + class Sequence(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('id', univ.Integer()), + namedtype.NamedType('blob', univ.Any()) + ) + + self.s = Sequence() + + def testTypeCheckOnAssignment(self): + + self.s.clear() + + self.s['blob'] = univ.Any(str2octs('xxx')) + + # this should succeed because Any is untagged and unconstrained + self.s['blob'] = univ.Integer(123) + + +class TaggedAnyTestCase(BaseTestCase): + + def setUp(self): + BaseTestCase.setUp(self) + + self.taggedAny = univ.Any().subtype(implicitTag=tag.Tag(tag.tagClassPrivate, tag.tagFormatSimple, 20)) + + class Sequence(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('id', univ.Integer()), + namedtype.NamedType('blob', self.taggedAny) + ) + + self.s = Sequence() + + def testTypeCheckOnAssignment(self): + + self.s.clear() + + self.s['blob'] = self.taggedAny.clone('xxx') + + try: + self.s.setComponentByName('blob', univ.Integer(123)) + + except PyAsn1Error: + pass + + else: + assert False, 'non-open type assignment tolerated' + + +class TaggedAnyOpenTypeTestCase(BaseTestCase): + + def setUp(self): + BaseTestCase.setUp(self) + + self.taggedAny = univ.Any().subtype(implicitTag=tag.Tag(tag.tagClassPrivate, tag.tagFormatSimple, 20)) + + class Sequence(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('id', univ.Integer()), + namedtype.NamedType('blob', self.taggedAny, openType=opentype.OpenType(name='id')) + ) + + self.s = Sequence() + + def testTypeCheckOnAssignment(self): + + self.s.clear() + + self.s['blob'] = univ.Any(str2octs('xxx')) + self.s['blob'] = univ.Integer(123) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + + +if __name__ == '__main__': + unittest.TextTestRunner(verbosity=2).run(suite) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/tests/type/test_tag.py b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/tests/type/test_tag.py new file mode 100644 index 00000000..e8dd7a35 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/tests/type/test_tag.py @@ -0,0 +1,138 @@ +# +# This file is part of pyasn1 software. +# +# Copyright (c) 2005-2019, Ilya Etingof <etingof@gmail.com> +# License: http://snmplabs.com/pyasn1/license.html +# +import sys + +try: + import unittest2 as unittest + +except ImportError: + import unittest + +from tests.base import BaseTestCase + +from pyasn1.type import tag + + +class TagTestCaseBase(BaseTestCase): + def setUp(self): + BaseTestCase.setUp(self) + self.t1 = tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 3) + self.t2 = tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 3) + + +class TagReprTestCase(TagTestCaseBase): + def testRepr(self): + assert 'Tag' in repr(self.t1) + + +class TagCmpTestCase(TagTestCaseBase): + def testCmp(self): + assert self.t1 == self.t2, 'tag comparison fails' + + def testHash(self): + assert hash(self.t1) == hash(self.t2), 'tag hash comparison fails' + + def testSequence(self): + assert self.t1[0] == self.t2[0] and \ + self.t1[1] == self.t2[1] and \ + self.t1[2] == self.t2[2], 'tag sequence protocol fails' + + +class TagSetTestCaseBase(BaseTestCase): + def setUp(self): + BaseTestCase.setUp(self) + + self.ts1 = tag.initTagSet( + tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 12) + ) + + self.ts2 = tag.initTagSet( + tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 12) + ) + + +class TagSetReprTestCase(TagSetTestCaseBase): + def testRepr(self): + assert 'TagSet' in repr(self.ts1) + + +class TagSetCmpTestCase(TagSetTestCaseBase): + def testCmp(self): + assert self.ts1 == self.ts2, 'tag set comparison fails' + + def testHash(self): + assert hash(self.ts1) == hash(self.ts2), 'tag set hash comp. fails' + + def testLen(self): + assert len(self.ts1) == len(self.ts2), 'tag length comparison fails' + + +class TaggingTestSuite(TagSetTestCaseBase): + def testImplicitTag(self): + t = self.ts1.tagImplicitly( + tag.Tag(tag.tagClassApplication, tag.tagFormatSimple, 14) + ) + assert t == tag.TagSet( + tag.Tag(tag.tagClassApplication, tag.tagFormatSimple, 12), + tag.Tag(tag.tagClassApplication, tag.tagFormatSimple, 14) + ), 'implicit tagging went wrong' + + def testExplicitTag(self): + t = self.ts1.tagExplicitly( + tag.Tag(tag.tagClassPrivate, tag.tagFormatSimple, 32) + ) + assert t == tag.TagSet( + tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 12), + tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 12), + tag.Tag(tag.tagClassPrivate, tag.tagFormatConstructed, 32) + ), 'explicit tagging went wrong' + + +class TagSetAddTestSuite(TagSetTestCaseBase): + def testAdd(self): + t = self.ts1 + tag.Tag(tag.tagClassApplication, tag.tagFormatSimple, 2) + assert t == tag.TagSet( + tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 12), + tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 12), + tag.Tag(tag.tagClassApplication, tag.tagFormatSimple, 2) + ), 'TagSet.__add__() fails' + + def testRadd(self): + t = tag.Tag(tag.tagClassApplication, tag.tagFormatSimple, 2) + self.ts1 + assert t == tag.TagSet( + tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 12), + tag.Tag(tag.tagClassApplication, tag.tagFormatSimple, 2), + tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 12) + ), 'TagSet.__radd__() fails' + + +class SuperTagSetTestCase(TagSetTestCaseBase): + def testSuperTagCheck1(self): + assert self.ts1.isSuperTagSetOf( + tag.TagSet( + tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 12), + tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 12) + )), 'isSuperTagSetOf() fails' + + def testSuperTagCheck2(self): + assert not self.ts1.isSuperTagSetOf( + tag.TagSet( + tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 12), + tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 13) + )), 'isSuperTagSetOf() fails' + + def testSuperTagCheck3(self): + assert self.ts1.isSuperTagSetOf( + tag.TagSet((), tag.Tag(tag.tagClassUniversal, + tag.tagFormatSimple, 12)) + ), 'isSuperTagSetOf() fails' + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + unittest.TextTestRunner(verbosity=2).run(suite) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/tests/type/test_univ.py b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/tests/type/test_univ.py new file mode 100644 index 00000000..124e5e99 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/tests/type/test_univ.py @@ -0,0 +1,2208 @@ +# +# This file is part of pyasn1 software. +# +# Copyright (c) 2005-2019, Ilya Etingof <etingof@gmail.com> +# License: http://snmplabs.com/pyasn1/license.html +# +import math +import pickle +import sys + +try: + import unittest2 as unittest + +except ImportError: + import unittest + +from tests.base import BaseTestCase + +from pyasn1.type import univ +from pyasn1.type import tag +from pyasn1.type import constraint +from pyasn1.type import namedtype +from pyasn1.type import namedval +from pyasn1.type import error +from pyasn1.compat.octets import str2octs, ints2octs, octs2ints, octs2str +from pyasn1.error import PyAsn1Error +from pyasn1.error import PyAsn1UnicodeEncodeError, PyAsn1UnicodeDecodeError + + +class NoValueTestCase(BaseTestCase): + def testSingleton(self): + assert univ.NoValue() is univ.NoValue(), 'NoValue is not a singleton' + + def testRepr(self): + try: + repr(univ.noValue) + + except PyAsn1Error: + assert False, 'repr() on NoValue object fails' + + def testIsInstance(self): + try: + assert isinstance(univ.noValue, univ.NoValue), 'isinstance() on NoValue() object fails' + + except PyAsn1Error: + assert False, 'isinstance() on NoValue object fails' + + def testStr(self): + try: + str(univ.noValue) + + except PyAsn1Error: + pass + + else: + assert False, 'str() works for NoValue object' + + def testLen(self): + try: + len(univ.noValue) + + except PyAsn1Error: + pass + + else: + assert False, 'len() works for NoValue object' + + def testCmp(self): + try: + univ.noValue == 1 + + except PyAsn1Error: + pass + + else: + assert False, 'comparison works for NoValue object' + + def testSubs(self): + try: + univ.noValue[0] + + except PyAsn1Error: + pass + + else: + assert False, '__getitem__() works for NoValue object' + + def testKey(self): + try: + univ.noValue['key'] + + except PyAsn1Error: + pass + + else: + assert False, '__getitem__() works for NoValue object' + + def testKeyAssignment(self): + try: + univ.noValue['key'] = 123 + + except PyAsn1Error: + pass + + else: + assert False, '__setitem__() works for NoValue object' + + def testInt(self): + try: + int(univ.noValue) + + except PyAsn1Error: + pass + + else: + assert False, 'integer conversion works for NoValue object' + + def testAdd(self): + try: + univ.noValue + univ.noValue + + except PyAsn1Error: + pass + + else: + assert False, 'addition works for NoValue object' + + def testBitShift(self): + try: + univ.noValue << 1 + + except PyAsn1Error: + pass + + else: + assert False, 'bitshift works for NoValue object' + + def testBooleanEvaluation(self): + try: + if univ.noValue: + pass + + except PyAsn1Error: + pass + + else: + assert False, 'boolean evaluation works for NoValue object' + + def testSizeOf(self): + try: + if hasattr(sys, 'getsizeof'): + sys.getsizeof(univ.noValue) + + # TODO: remove when Py2.5 support is gone + elif sys.version_info > (2, 6): + raise unittest.SkipTest("no sys.getsizeof() method") + + except PyAsn1Error: + assert False, 'sizeof failed for NoValue object' + + except TypeError: + # TODO: remove when Py2.5 support is gone + if sys.version_info > (2, 6): + raise unittest.SkipTest("sys.getsizeof() raises TypeError") + + +class IntegerTestCase(BaseTestCase): + def testStr(self): + assert str(univ.Integer(1)) in ('1', '1L'), 'str() fails' + + def testRepr(self): + assert '123' in repr(univ.Integer(123)) + + def testAnd(self): + assert univ.Integer(1) & 0 == 0, '__and__() fails' + + def testOr(self): + assert univ.Integer(1) | 0 == 1, '__or__() fails' + + def testXor(self): + assert univ.Integer(1) ^ 0 == 1, '__xor__() fails' + + def testRand(self): + assert 0 & univ.Integer(1) == 0, '__rand__() fails' + + def testRor(self): + assert 0 | univ.Integer(1) == 1, '__ror__() fails' + + def testRxor(self): + assert 0 ^ univ.Integer(1) == 1, '__rxor__() fails' + + def testAdd(self): + assert univ.Integer(-4) + 6 == 2, '__add__() fails' + + def testRadd(self): + assert 4 + univ.Integer(5) == 9, '__radd__() fails' + + def testSub(self): + assert univ.Integer(3) - 6 == -3, '__sub__() fails' + + def testRsub(self): + assert 6 - univ.Integer(3) == 3, '__rsub__() fails' + + def testMul(self): + assert univ.Integer(3) * -3 == -9, '__mul__() fails' + + def testRmul(self): + assert 2 * univ.Integer(3) == 6, '__rmul__() fails' + + def testDivInt(self): + assert univ.Integer(4) / 2 == 2, '__div__() fails' + + if sys.version_info[0] > 2: + def testDivFloat(self): + assert univ.Integer(3) / 2 == 1.5, '__div__() fails' + + def testRdivFloat(self): + assert 3 / univ.Integer(2) == 1.5, '__rdiv__() fails' + else: + def testDivFloat(self): + assert univ.Integer(3) / 2 == 1, '__div__() fails' + + def testRdivFloat(self): + assert 3 / univ.Integer(2) == 1, '__rdiv__() fails' + + def testRdivInt(self): + assert 6 / univ.Integer(3) == 2, '__rdiv__() fails' + + if sys.version_info[0] > 2: + def testTrueDiv(self): + assert univ.Integer(3) / univ.Integer(2) == 1.5, '__truediv__() fails' + + def testFloorDiv(self): + assert univ.Integer(3) // univ.Integer(2) == 1, '__floordiv__() fails' + + def testMod(self): + assert univ.Integer(3) % 2 == 1, '__mod__() fails' + + def testRmod(self): + assert 4 % univ.Integer(3) == 1, '__rmod__() fails' + + def testPow(self): + assert univ.Integer(3) ** 2 == 9, '__pow__() fails' + + def testRpow(self): + assert 2 ** univ.Integer(2) == 4, '__rpow__() fails' + + def testLshift(self): + assert univ.Integer(1) << 1 == 2, '<< fails' + + def testRshift(self): + assert univ.Integer(2) >> 1 == 1, '>> fails' + + def testInt(self): + assert int(univ.Integer(3)) == 3, '__int__() fails' + + def testLong(self): + assert int(univ.Integer(8)) == 8, '__long__() fails' + + def testFloat(self): + assert float(univ.Integer(4)) == 4.0, '__float__() fails' + + def testPos(self): + assert +univ.Integer(1) == 1, '__pos__() fails' + + def testNeg(self): + assert -univ.Integer(1) == -1, '__neg__() fails' + + def testInvert(self): + assert ~univ.Integer(1) == -2, '__invert__() fails' + + def testRound(self): + assert round(univ.Integer(1), 3) == 1.0, '__round__() fails' + + def testFloor(self): + assert math.floor(univ.Integer(1)) == 1, '__floor__() fails' + + def testCeil(self): + assert math.ceil(univ.Integer(1)) == 1, '__ceil__() fails' + + if sys.version_info[0:2] > (2, 5): + def testTrunc(self): + assert math.trunc(univ.Integer(1)) == 1, '__trunc__() fails' + + def testPrettyIn(self): + assert univ.Integer('3') == 3, 'prettyIn() fails' + + def testTag(self): + assert univ.Integer().tagSet == tag.TagSet( + (), + tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 0x02) + ) + + def testNamedVals(self): + + class Integer(univ.Integer): + namedValues = univ.Integer.namedValues.clone(('asn1', 1)) + + assert Integer('asn1') == 1, 'named val fails' + assert int(Integer('asn1')) == 1, 'named val fails' + assert str(Integer('asn1')) == 'asn1', 'named val __str__() fails' + + def testSubtype(self): + assert univ.Integer().subtype( + value=1, + implicitTag=tag.Tag(tag.tagClassPrivate, tag.tagFormatSimple, 2), + subtypeSpec=constraint.SingleValueConstraint(1, 3) + ) == univ.Integer( + value=1, + tagSet=tag.TagSet(tag.Tag(tag.tagClassPrivate, + tag.tagFormatSimple, 2)), + subtypeSpec=constraint.ConstraintsIntersection(constraint.SingleValueConstraint(1, 3)) + ) + + +class IntegerPicklingTestCase(unittest.TestCase): + + def testSchemaPickling(self): + old_asn1 = univ.Integer() + serialised = pickle.dumps(old_asn1) + assert serialised + new_asn1 = pickle.loads(serialised) + assert type(new_asn1) == univ.Integer + assert old_asn1.isSameTypeWith(new_asn1) + + def testValuePickling(self): + old_asn1 = univ.Integer(-123) + serialised = pickle.dumps(old_asn1) + assert serialised + new_asn1 = pickle.loads(serialised) + assert new_asn1 == -123 + + +class BooleanTestCase(BaseTestCase): + def testTruth(self): + assert univ.Boolean(True) and univ.Boolean(1), 'Truth initializer fails' + + def testFalse(self): + assert not univ.Boolean(False) and not univ.Boolean(0), 'False initializer fails' + + def testStr(self): + assert str(univ.Boolean(1)) == 'True', 'str() fails' + + def testInt(self): + assert int(univ.Boolean(1)) == 1, 'int() fails' + + def testRepr(self): + assert 'Boolean' in repr(univ.Boolean(1)) + + def testTag(self): + assert univ.Boolean().tagSet == tag.TagSet( + (), + tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 0x01) + ) + + def testConstraints(self): + + class Boolean(univ.Boolean): + pass + + try: + Boolean(2) + except error.ValueConstraintError: + pass + else: + assert 0, 'constraint fail' + + +class BooleanPicklingTestCase(unittest.TestCase): + + def testSchemaPickling(self): + old_asn1 = univ.Boolean() + serialised = pickle.dumps(old_asn1) + assert serialised + new_asn1 = pickle.loads(serialised) + assert type(new_asn1) == univ.Boolean + assert old_asn1.isSameTypeWith(new_asn1) + + def testValuePickling(self): + old_asn1 = univ.Boolean(True) + serialised = pickle.dumps(old_asn1) + assert serialised + new_asn1 = pickle.loads(serialised) + assert new_asn1 == True + + +class BitStringTestCase(BaseTestCase): + def setUp(self): + BaseTestCase.setUp(self) + + self.b = univ.BitString( + namedValues=namedval.NamedValues(('Active', 0), ('Urgent', 1)) + ) + + def testBinDefault(self): + + class BinDefault(univ.BitString): + defaultBinValue = '1010100110001010' + + assert BinDefault() == univ.BitString(binValue='1010100110001010') + + def testHexDefault(self): + + class HexDefault(univ.BitString): + defaultHexValue = 'A98A' + + assert HexDefault() == univ.BitString(hexValue='A98A') + + def testSet(self): + assert self.b.clone('Active') == (1,) + assert self.b.clone('Urgent') == (0, 1) + assert self.b.clone('Urgent, Active') == (1, 1) + assert self.b.clone("'1010100110001010'B") == (1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0) + assert self.b.clone("'A98A'H") == (1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0) + assert self.b.clone(binValue='1010100110001010') == (1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0) + assert self.b.clone(hexValue='A98A') == (1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0) + assert self.b.clone('1010100110001010') == (1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0) + assert self.b.clone((1, 0, 1)) == (1, 0, 1) + + def testStr(self): + assert str(self.b.clone('Urgent')) == '01' + + def testRepr(self): + assert 'BitString' in repr(self.b.clone('Urgent,Active')) + + def testTag(self): + assert univ.BitString().tagSet == tag.TagSet( + (), + tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 0x03) + ) + + def testLen(self): + assert len(self.b.clone("'A98A'H")) == 16 + + def testGetItem(self): + assert self.b.clone("'A98A'H")[0] == 1 + assert self.b.clone("'A98A'H")[1] == 0 + assert self.b.clone("'A98A'H")[2] == 1 + + if sys.version_info[:2] > (2, 4): + def testReverse(self): + assert list(reversed(univ.BitString([0, 0, 1]))) == list(univ.BitString([1, 0, 0])) + + def testAsOctets(self): + assert self.b.clone(hexValue='A98A').asOctets() == ints2octs((0xa9, 0x8a)), 'testAsOctets() fails' + + def testAsInts(self): + assert self.b.clone(hexValue='A98A').asNumbers() == (0xa9, 0x8a), 'testAsNumbers() fails' + + def testMultipleOfEightPadding(self): + assert self.b.clone((1, 0, 1)).asNumbers() == (5,) + + def testAsInteger(self): + assert self.b.clone('11000000011001').asInteger() == 12313 + assert self.b.clone('1100110011011111').asInteger() == 52447 + + def testStaticDef(self): + + class BitString(univ.BitString): + pass + + assert BitString('11000000011001').asInteger() == 12313 + + +class BitStringPicklingTestCase(unittest.TestCase): + + def testSchemaPickling(self): + old_asn1 = univ.BitString() + serialised = pickle.dumps(old_asn1) + assert serialised + new_asn1 = pickle.loads(serialised) + assert type(new_asn1) == univ.BitString + assert old_asn1.isSameTypeWith(new_asn1) + + def testValuePickling(self): + old_asn1 = univ.BitString((1, 0, 1, 0)) + serialised = pickle.dumps(old_asn1) + assert serialised + new_asn1 = pickle.loads(serialised) + assert new_asn1 == (1, 0, 1, 0) + + +class OctetStringWithUnicodeMixIn(object): + + initializer = () + encoding = 'us-ascii' + + def setUp(self): + self.pythonString = ints2octs(self.initializer).decode(self.encoding) + self.encodedPythonString = self.pythonString.encode(self.encoding) + self.numbersString = tuple(octs2ints(self.encodedPythonString)) + + def testInit(self): + assert univ.OctetString(self.encodedPythonString) == self.encodedPythonString, '__init__() fails' + + def testInitFromAsn1(self): + assert univ.OctetString(univ.OctetString(self.encodedPythonString)) == self.encodedPythonString + assert univ.OctetString(univ.Integer(123)) == univ.OctetString('123') + + def testSerialised(self): + if sys.version_info[0] < 3: + assert str(univ.OctetString(self.encodedPythonString, encoding=self.encoding)) == self.encodedPythonString, '__str__() fails' + else: + assert bytes(univ.OctetString(self.encodedPythonString, encoding=self.encoding)) == self.encodedPythonString, '__str__() fails' + + def testPrintable(self): + if sys.version_info[0] < 3: + assert str(univ.OctetString(self.encodedPythonString, encoding=self.encoding)) == self.encodedPythonString, '__str__() fails' + assert unicode(univ.OctetString(self.pythonString, encoding=self.encoding)) == self.pythonString, 'unicode init fails' + else: + assert str(univ.OctetString(self.pythonString, encoding=self.encoding)) == self.pythonString, 'unicode init fails' + + def testSeq(self): + assert univ.OctetString(self.encodedPythonString)[0] == self.encodedPythonString[0], '__getitem__() fails' + + def testRepr(self): + assert 'abc' in repr(univ.OctetString('abc')) + + def testAsOctets(self): + assert univ.OctetString(self.encodedPythonString).asOctets() == self.encodedPythonString, 'testAsOctets() fails' + + def testAsInts(self): + assert univ.OctetString(self.encodedPythonString).asNumbers() == self.numbersString, 'testAsNumbers() fails' + + def testAdd(self): + assert univ.OctetString(self.encodedPythonString) + self.encodedPythonString == self.encodedPythonString + self.encodedPythonString, '__add__() fails' + + def testRadd(self): + assert self.encodedPythonString + univ.OctetString(self.encodedPythonString) == self.encodedPythonString + self.encodedPythonString, '__radd__() fails' + + def testMul(self): + assert univ.OctetString(self.encodedPythonString) * 2 == self.encodedPythonString * 2, '__mul__() fails' + + def testRmul(self): + assert 2 * univ.OctetString(self.encodedPythonString) == 2 * self.encodedPythonString, '__rmul__() fails' + + def testContains(self): + s = univ.OctetString(self.encodedPythonString) + assert self.encodedPythonString in s + assert self.encodedPythonString * 2 not in s + + if sys.version_info[:2] > (2, 4): + def testReverse(self): + assert list(reversed(univ.OctetString(self.encodedPythonString))) == list(reversed(self.encodedPythonString)) + + +class OctetStringWithAsciiTestCase(OctetStringWithUnicodeMixIn, BaseTestCase): + initializer = (97, 102) + encoding = 'us-ascii' + + +class OctetStringUnicodeErrorTestCase(BaseTestCase): + def testEncodeError(self): + serialized = ints2octs((0xff, 0xfe)) + + if sys.version_info < (3, 0): + text = serialized.decode('iso-8859-1') + + else: + text = octs2str(serialized) + + try: + univ.OctetString(text, encoding='us-ascii') + + except PyAsn1UnicodeEncodeError: + pass + + # TODO: remove when Py2.5 support is gone + else: + if sys.version_info > (2, 6): + assert False, 'Unicode encoding error not caught' + + def testDecodeError(self): + serialized = ints2octs((0xff, 0xfe)) + + octetString = univ.OctetString(serialized, encoding='us-ascii') + + try: + if sys.version_info < (3, 0): + unicode(octetString) + + else: + str(octetString) + + except PyAsn1UnicodeDecodeError: + pass + + # TODO: remove when Py2.5 support is gone + else: + if sys.version_info > (2, 6): + assert False, 'Unicode decoding error not caught' + + +class OctetStringWithUtf8TestCase(OctetStringWithUnicodeMixIn, BaseTestCase): + initializer = (208, 176, 208, 177, 208, 178) + encoding = 'utf-8' + + +class OctetStringWithUtf16TestCase(OctetStringWithUnicodeMixIn, BaseTestCase): + initializer = (4, 48, 4, 49, 4, 50) + encoding = 'utf-16-be' + + +if sys.version_info[0] > 2: + + # Somehow comparison of UTF-32 encoded strings does not work in Py2 + + class OctetStringWithUtf32TestCase(OctetStringWithUnicodeMixIn, BaseTestCase): + initializer = (0, 0, 4, 48, 0, 0, 4, 49, 0, 0, 4, 50) + encoding = 'utf-32-be' + + +class OctetStringTestCase(BaseTestCase): + + def testBinDefault(self): + + class BinDefault(univ.OctetString): + defaultBinValue = '1000010111101110101111000000111011' + + assert BinDefault() == univ.OctetString(binValue='1000010111101110101111000000111011') + + def testHexDefault(self): + + class HexDefault(univ.OctetString): + defaultHexValue = 'FA9823C43E43510DE3422' + + assert HexDefault() == univ.OctetString(hexValue='FA9823C43E43510DE3422') + + def testBinStr(self): + assert univ.OctetString(binValue="1000010111101110101111000000111011") == ints2octs((133, 238, 188, 14, 192)), 'bin init fails' + + def testHexStr(self): + assert univ.OctetString(hexValue="FA9823C43E43510DE3422") == ints2octs((250, 152, 35, 196, 62, 67, 81, 13, 227, 66, 32)), 'hex init fails' + + def testTuple(self): + assert univ.OctetString((1, 2, 3, 4, 5)) == ints2octs((1, 2, 3, 4, 5)), 'tuple init failed' + + def testRepr(self): + assert 'abc' in repr(univ.OctetString('abc')) + + def testEmpty(self): + try: + str(univ.OctetString()) + except PyAsn1Error: + pass + else: + assert 0, 'empty OctetString() not reported' + + def testTag(self): + assert univ.OctetString().tagSet == tag.TagSet( + (), + tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 0x04) + ) + + def testStaticDef(self): + + class OctetString(univ.OctetString): + pass + + assert OctetString(hexValue="FA9823C43E43510DE3422") == ints2octs((250, 152, 35, 196, 62, 67, 81, 13, 227, 66, 32)) + + +class OctetStringPicklingTestCase(unittest.TestCase): + + def testSchemaPickling(self): + old_asn1 = univ.BitString() + serialised = pickle.dumps(old_asn1) + assert serialised + new_asn1 = pickle.loads(serialised) + assert type(new_asn1) == univ.BitString + assert old_asn1.isSameTypeWith(new_asn1) + + def testValuePickling(self): + old_asn1 = univ.BitString((1, 0, 1, 0)) + serialised = pickle.dumps(old_asn1) + assert serialised + new_asn1 = pickle.loads(serialised) + assert new_asn1 == (1, 0, 1, 0) + + +class Null(BaseTestCase): + + def testInit(self): + assert not univ.Null().isValue + assert univ.Null(0) == str2octs('') + assert univ.Null(False) == str2octs('') + assert univ.Null('') == str2octs('') + assert univ.Null(None) == str2octs('') + + try: + assert univ.Null(True) + + except PyAsn1Error: + pass + + try: + assert univ.Null('xxx') + + except PyAsn1Error: + pass + + def testStr(self): + assert str(univ.Null('')) == '', 'str() fails' + + def testRepr(self): + assert 'Null' in repr(univ.Null('')) + + def testTag(self): + assert univ.Null().tagSet == tag.TagSet( + (), + tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 0x05) + ) + + def testConstraints(self): + try: + univ.Null(2) + except error.ValueConstraintError: + pass + else: + assert 0, 'constraint fail' + + def testStaticDef(self): + + class Null(univ.Null): + pass + + assert not Null('') + + +class NullPicklingTestCase(unittest.TestCase): + + def testSchemaPickling(self): + old_asn1 = univ.Null() + serialised = pickle.dumps(old_asn1) + assert serialised + new_asn1 = pickle.loads(serialised) + assert type(new_asn1) == univ.Null + assert old_asn1.isSameTypeWith(new_asn1) + + def testValuePickling(self): + old_asn1 = univ.Null('') + serialised = pickle.dumps(old_asn1) + assert serialised + new_asn1 = pickle.loads(serialised) + assert not new_asn1 + + +class RealTestCase(BaseTestCase): + def testFloat4BinEnc(self): + assert univ.Real((0.25, 2, 3)) == 2.0, 'float initializer for binary encoding fails' + + def testStr(self): + assert str(univ.Real(1.0)) == '1.0', 'str() fails' + + def testRepr(self): + assert 'Real' in repr(univ.Real(-4.1)) + assert 'Real' in repr(univ.Real(-4.1)) + assert 'inf' in repr(univ.Real('inf')) + assert '-inf' in repr(univ.Real('-inf')) + + def testAdd(self): + assert univ.Real(-4.1) + 1.4 == -2.7, '__add__() fails' + + def testRadd(self): + assert 4 + univ.Real(0.5) == 4.5, '__radd__() fails' + + def testSub(self): + assert univ.Real(3.9) - 1.7 == 2.2, '__sub__() fails' + + def testRsub(self): + assert 6.1 - univ.Real(0.1) == 6, '__rsub__() fails' + + def testMul(self): + assert univ.Real(3.0) * -3 == -9, '__mul__() fails' + + def testRmul(self): + assert 2 * univ.Real(3.0) == 6, '__rmul__() fails' + + def testDiv(self): + assert univ.Real(3.0) / 2 == 1.5, '__div__() fails' + + def testRdiv(self): + assert 6 / univ.Real(3.0) == 2, '__rdiv__() fails' + + def testMod(self): + assert univ.Real(3.0) % 2 == 1, '__mod__() fails' + + def testRmod(self): + assert 4 % univ.Real(3.0) == 1, '__rmod__() fails' + + def testPow(self): + assert univ.Real(3.0) ** 2 == 9, '__pow__() fails' + + def testRpow(self): + assert 2 ** univ.Real(2.0) == 4, '__rpow__() fails' + + def testInt(self): + assert int(univ.Real(3.0)) == 3, '__int__() fails' + + def testLong(self): + assert int(univ.Real(8.0)) == 8, '__long__() fails' + + def testFloat(self): + assert float(univ.Real(4.0)) == 4.0, '__float__() fails' + + def testPrettyIn(self): + assert univ.Real((3, 10, 0)) == 3, 'prettyIn() fails' + + # infinite float values + def testStrInf(self): + assert str(univ.Real('inf')) == 'inf', 'str() fails' + + def testAddInf(self): + assert univ.Real('inf') + 1 == float('inf'), '__add__() fails' + + def testRaddInf(self): + assert 1 + univ.Real('inf') == float('inf'), '__radd__() fails' + + def testIntInf(self): + try: + assert int(univ.Real('inf')) + except OverflowError: + pass + else: + assert 0, '__int__() fails' + + def testLongInf(self): + try: + assert int(univ.Real('inf')) + except OverflowError: + pass + else: + assert 0, '__long__() fails' + assert int(univ.Real(8.0)) == 8, '__long__() fails' + + def testFloatInf(self): + assert float(univ.Real('-inf')) == float('-inf'), '__float__() fails' + + def testPrettyInInf(self): + assert univ.Real(float('inf')) == float('inf'), 'prettyIn() fails' + + def testPlusInf(self): + assert univ.Real('inf').isPlusInf, 'isPlusInfinity failed' + + def testMinusInf(self): + assert univ.Real('-inf').isMinusInf, 'isMinusInfinity failed' + + def testPos(self): + assert +univ.Real(1.0) == 1.0, '__pos__() fails' + + def testNeg(self): + assert -univ.Real(1.0) == -1.0, '__neg__() fails' + + def testRound(self): + assert round(univ.Real(1.123), 2) == 1.12, '__round__() fails' + + def testFloor(self): + assert math.floor(univ.Real(1.6)) == 1.0, '__floor__() fails' + + def testCeil(self): + assert math.ceil(univ.Real(1.2)) == 2.0, '__ceil__() fails' + + if sys.version_info[0:2] > (2, 5): + def testTrunc(self): + assert math.trunc(univ.Real(1.1)) == 1.0, '__trunc__() fails' + + def testTag(self): + assert univ.Real().tagSet == tag.TagSet( + (), + tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 0x09) + ) + + def testStaticDef(self): + + class Real(univ.Real): + pass + + assert Real(1.0) == 1.0 + + +class RealPicklingTestCase(unittest.TestCase): + + def testSchemaPickling(self): + old_asn1 = univ.Real() + serialised = pickle.dumps(old_asn1) + assert serialised + new_asn1 = pickle.loads(serialised) + assert type(new_asn1) == univ.Real + assert old_asn1.isSameTypeWith(new_asn1) + + def testValuePickling(self): + old_asn1 = univ.Real((1, 10, 3)) + serialised = pickle.dumps(old_asn1) + assert serialised + new_asn1 = pickle.loads(serialised) + assert new_asn1 == 1000 + + +class ObjectIdentifier(BaseTestCase): + def testStr(self): + assert str(univ.ObjectIdentifier((1, 3, 6))) == '1.3.6', 'str() fails' + + def testRepr(self): + assert '1.3.6' in repr(univ.ObjectIdentifier('1.3.6')) + + def testEq(self): + assert univ.ObjectIdentifier((1, 3, 6)) == (1, 3, 6), '__cmp__() fails' + + def testAdd(self): + assert univ.ObjectIdentifier((1, 3)) + (6,) == (1, 3, 6), '__add__() fails' + + def testRadd(self): + assert (1,) + univ.ObjectIdentifier((3, 6)) == (1, 3, 6), '__radd__() fails' + + def testLen(self): + assert len(univ.ObjectIdentifier((1, 3))) == 2, '__len__() fails' + + def testPrefix(self): + o = univ.ObjectIdentifier('1.3.6') + assert o.isPrefixOf((1, 3, 6)), 'isPrefixOf() fails' + assert o.isPrefixOf((1, 3, 6, 1)), 'isPrefixOf() fails' + assert not o.isPrefixOf((1, 3)), 'isPrefixOf() fails' + + def testInput1(self): + assert univ.ObjectIdentifier('1.3.6') == (1, 3, 6), 'prettyIn() fails' + + def testInput2(self): + assert univ.ObjectIdentifier((1, 3, 6)) == (1, 3, 6), 'prettyIn() fails' + + def testInput3(self): + assert univ.ObjectIdentifier(univ.ObjectIdentifier('1.3') + (6,)) == (1, 3, 6), 'prettyIn() fails' + + def testUnicode(self): + s = '1.3.6' + if sys.version_info[0] < 3: + s = s.decode() + assert univ.ObjectIdentifier(s) == (1, 3, 6), 'unicode init fails' + + def testTag(self): + assert univ.ObjectIdentifier().tagSet == tag.TagSet( + (), + tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 0x06) + ) + + def testContains(self): + s = univ.ObjectIdentifier('1.3.6.1234.99999') + assert 1234 in s + assert 4321 not in s + + def testStaticDef(self): + + class ObjectIdentifier(univ.ObjectIdentifier): + pass + + assert str(ObjectIdentifier((1, 3, 6))) == '1.3.6' + + +class ObjectIdentifierPicklingTestCase(unittest.TestCase): + + def testSchemaPickling(self): + old_asn1 = univ.ObjectIdentifier() + serialised = pickle.dumps(old_asn1) + assert serialised + new_asn1 = pickle.loads(serialised) + assert type(new_asn1) == univ.ObjectIdentifier + assert old_asn1.isSameTypeWith(new_asn1) + + def testValuePickling(self): + old_asn1 = univ.ObjectIdentifier('2.3.1.1.2') + serialised = pickle.dumps(old_asn1) + assert serialised + new_asn1 = pickle.loads(serialised) + assert new_asn1 == (2, 3, 1, 1, 2) + + +class SequenceOf(BaseTestCase): + def setUp(self): + BaseTestCase.setUp(self) + self.s1 = univ.SequenceOf( + componentType=univ.OctetString('') + ) + self.s2 = self.s1.clone() + + def testRepr(self): + assert 'a' in repr(self.s1.clone().setComponents('a', 'b')) + + def testTag(self): + assert self.s1.tagSet == tag.TagSet( + (), + tag.Tag(tag.tagClassUniversal, tag.tagFormatConstructed, 0x10) + ), 'wrong tagSet' + + def testSeq(self): + self.s1.setComponentByPosition(0, univ.OctetString('abc')) + assert self.s1[0] == str2octs('abc'), 'set by idx fails' + self.s1[0] = 'cba' + assert self.s1[0] == str2octs('cba'), 'set by idx fails' + + def testCmp(self): + self.s1.clear() + self.s1.setComponentByPosition(0, 'abc') + self.s2.clear() + self.s2.setComponentByPosition(0, univ.OctetString('abc')) + assert self.s1 == self.s2, '__cmp__() fails' + + def testSubtypeSpec(self): + s = self.s1.clone( + componentType=univ.OctetString().subtype( + subtypeSpec=constraint.SingleValueConstraint(str2octs('abc')))) + try: + s.setComponentByPosition( + 0, univ.OctetString().subtype( + 'abc', subtypeSpec=constraint.SingleValueConstraint(str2octs('abc')))) + except PyAsn1Error: + assert 0, 'constraint fails' + try: + s.setComponentByPosition(1, univ.OctetString('Abc')) + except PyAsn1Error: + try: + s.setComponentByPosition(1, univ.OctetString('Abc'), + verifyConstraints=False) + except PyAsn1Error: + assert 0, 'constraint fails with verifyConstraints=False' + else: + assert 0, 'constraint fails' + + def testComponentTagsMatching(self): + s = self.s1.clone() + s.strictConstraints = True # This requires types equality + o = univ.OctetString('abc').subtype(explicitTag=tag.Tag(tag.tagClassPrivate, tag.tagFormatSimple, 12)) + try: + s.setComponentByPosition(0, o) + except PyAsn1Error: + pass + else: + assert 0, 'inner supertype tag allowed' + + def testComponentConstraintsMatching(self): + s = self.s1.clone() + o = univ.OctetString().subtype( + subtypeSpec=constraint.ConstraintsUnion(constraint.SingleValueConstraint(str2octs('cba')))) + s.strictConstraints = True # This requires types equality + try: + s.setComponentByPosition(0, o.clone('cba')) + except PyAsn1Error: + pass + else: + assert 0, 'inner supertype constraint allowed' + s.strictConstraints = False # This requires subtype relationships + try: + s.setComponentByPosition(0, o.clone('cba')) + except PyAsn1Error: + assert 0, 'inner supertype constraint disallowed' + else: + pass + + def testConsistency(self): + s = self.s1.clone(subtypeSpec=constraint.ConstraintsUnion( + constraint.ValueSizeConstraint(1, 1) + )) + s.setComponentByPosition(0, univ.OctetString('abc')) + assert not s.isInconsistent, 'size spec fails' + s.setComponentByPosition(1, univ.OctetString('abc')) + assert s.isInconsistent, 'size spec fails' + + def testGetComponentTagMap(self): + assert self.s1.componentType.tagMap.presentTypes == { + univ.OctetString.tagSet: univ.OctetString('') + } + + def testSubtype(self): + subtype = self.s1.subtype( + implicitTag=tag.Tag(tag.tagClassPrivate, tag.tagFormatSimple, 2), + subtypeSpec=constraint.ValueSizeConstraint(0, 1) + ) + subtype.clear() + clone = self.s1.clone( + tagSet=tag.TagSet(tag.Tag(tag.tagClassPrivate, + tag.tagFormatSimple, 2)), + subtypeSpec=constraint.ValueSizeConstraint(0, 1) + ) + clone.clear() + assert clone == subtype + + def testClone(self): + self.s1.setComponentByPosition(0, univ.OctetString('abc')) + s = self.s1.clone() + s.clear() + assert len(s) == 0 + s = self.s1.clone(cloneValueFlag=1) + assert len(s) == 1 + assert s.getComponentByPosition(0) == self.s1.getComponentByPosition(0) + + def testSetComponents(self): + assert self.s1.clone().setComponents('abc', 'def') == \ + self.s1.setComponentByPosition(0, 'abc').setComponentByPosition(1, 'def') + + def testGetItem(self): + s = self.s1.clone() + s.append('xxx') + assert s[0] + + # this is a deviation from standard sequence protocol + assert not s[2] + + def testGetItemSlice(self): + s = self.s1.clone() + s.extend(['xxx', 'yyy', 'zzz']) + assert s[:1] == [str2octs('xxx')] + assert s[-2:] == [str2octs('yyy'), str2octs('zzz')] + assert s[1:2] == [str2octs('yyy')] + + def testSetItem(self): + s = self.s1.clone() + s.append('xxx') + s[2] = 'yyy' + assert len(s) == 3 + assert s[1] == str2octs('') + + def testSetItemSlice(self): + s = self.s1.clone() + s[:1] = ['xxx'] + assert s == [str2octs('xxx')] + s[-2:] = ['yyy', 'zzz'] + assert s == [str2octs('yyy'), str2octs('zzz')] + s[1:2] = ['yyy'] + assert s == [str2octs('yyy'), str2octs('yyy')] + assert len(s) == 2 + + def testAppend(self): + self.s1.clear() + self.s1.setComponentByPosition(0, univ.OctetString('abc')) + assert len(self.s1) == 1 + self.s1.append('def') + assert len(self.s1) == 2 + assert list(self.s1) == [str2octs(x) for x in ['abc', 'def']] + + def testExtend(self): + self.s1.clear() + self.s1.setComponentByPosition(0, univ.OctetString('abc')) + assert len(self.s1) == 1 + self.s1.extend(['def', 'ghi']) + assert len(self.s1) == 3 + assert list(self.s1) == [str2octs(x) for x in ['abc', 'def', 'ghi']] + + def testCount(self): + self.s1.clear() + for x in ['abc', 'def', 'abc']: + self.s1.append(x) + assert self.s1.count(str2octs('abc')) == 2 + assert self.s1.count(str2octs('def')) == 1 + assert self.s1.count(str2octs('ghi')) == 0 + + def testIndex(self): + self.s1.clear() + for x in ['abc', 'def', 'abc']: + self.s1.append(x) + assert self.s1.index(str2octs('abc')) == 0 + assert self.s1.index(str2octs('def')) == 1 + assert self.s1.index(str2octs('abc'), 1) == 2 + + def testSort(self): + self.s1.clear() + self.s1[0] = 'b' + self.s1[1] = 'a' + assert list(self.s1) == [str2octs('b'), str2octs('a')] + self.s1.sort() + assert list(self.s1) == [str2octs('a'), str2octs('b')] + + def testStaticDef(self): + + class SequenceOf(univ.SequenceOf): + componentType = univ.OctetString('') + + s = SequenceOf() + s[0] = 'abc' + assert len(s) == 1 + assert s == [str2octs('abc')] + + def testUntyped(self): + n = univ.SequenceOf() + + assert not n.isValue + + n[0] = univ.OctetString('fox') + + assert n.isValue + + def testLegacyInitializer(self): + n = univ.SequenceOf( + componentType=univ.OctetString() + ) + o = univ.SequenceOf( + univ.OctetString() # this is the old way + ) + + assert n.isSameTypeWith(o) and o.isSameTypeWith(n) + + n[0] = 'fox' + o[0] = 'fox' + + assert n == o + + def testGetComponentWithDefault(self): + + class SequenceOf(univ.SequenceOf): + componentType = univ.OctetString() + + s = SequenceOf() + assert s.getComponentByPosition(0, default=None, instantiate=False) is None + assert s.getComponentByPosition(0, default=None) is None + s[0] = 'test' + assert s.getComponentByPosition(0, default=None) is not None + assert s.getComponentByPosition(0, default=None) == str2octs('test') + s.clear() + assert s.getComponentByPosition(0, default=None) is None + + def testGetComponentNoInstantiation(self): + + class SequenceOf(univ.SequenceOf): + componentType = univ.OctetString() + + s = SequenceOf() + assert s.getComponentByPosition(0, instantiate=False) is univ.noValue + s[0] = 'test' + assert s.getComponentByPosition(0, instantiate=False) is not univ.noValue + assert s.getComponentByPosition(0, instantiate=False) == str2octs('test') + s.clear() + assert s.getComponentByPosition(0, instantiate=False) is univ.noValue + + def testClear(self): + + class SequenceOf(univ.SequenceOf): + componentType = univ.OctetString() + + s = SequenceOf() + s.setComponentByPosition(0, 'test') + + assert s.getComponentByPosition(0) == str2octs('test') + assert len(s) == 1 + assert s.isValue + + s.clear() + + assert len(s) == 0 + assert s == [] + assert s.isValue + + def testReset(self): + + class SequenceOf(univ.SequenceOf): + componentType = univ.OctetString() + + s = SequenceOf() + s.setComponentByPosition(0, 'test') + + assert s.getComponentByPosition(0) == str2octs('test') + assert s.isValue + + s.reset() + + assert not s.isValue + + def testIsInconsistentSizeConstraint(self): + + class SequenceOf(univ.SequenceOf): + componentType = univ.OctetString() + subtypeSpec = constraint.ValueSizeConstraint(0, 1) + + s = SequenceOf() + + assert s.isInconsistent + + s[0] = 'test' + + assert not s.isInconsistent + + s[0] = 'test' + s[1] = 'test' + + assert s.isInconsistent + + s.clear() + + assert not s.isInconsistent + + s.reset() + + assert s.isInconsistent + + s[1] = 'test' + + assert not s.isInconsistent + + +class SequenceOfPicklingTestCase(unittest.TestCase): + + def testSchemaPickling(self): + old_asn1 = univ.SequenceOf(componentType=univ.OctetString()) + serialised = pickle.dumps(old_asn1) + assert serialised + new_asn1 = pickle.loads(serialised) + assert type(new_asn1) == univ.SequenceOf + assert old_asn1.isSameTypeWith(new_asn1) + + def testValuePickling(self): + old_asn1 = univ.SequenceOf(componentType=univ.OctetString()) + old_asn1[0] = 'test' + serialised = pickle.dumps(old_asn1) + assert serialised + new_asn1 = pickle.loads(serialised) + assert new_asn1 + assert new_asn1 == [str2octs('test')] + + +class Sequence(BaseTestCase): + def setUp(self): + BaseTestCase.setUp(self) + self.s1 = univ.Sequence( + componentType=namedtype.NamedTypes( + namedtype.NamedType('name', univ.OctetString('')), + namedtype.OptionalNamedType('nick', univ.OctetString('')), + namedtype.DefaultedNamedType('age', univ.Integer(34)) + ) + ) + + def testRepr(self): + assert 'name' in repr(self.s1.clone().setComponents('a', 'b')) + + def testTag(self): + assert self.s1.tagSet == tag.TagSet( + (), + tag.Tag(tag.tagClassUniversal, tag.tagFormatConstructed, 0x10) + ), 'wrong tagSet' + + def testById(self): + self.s1.setComponentByName('name', univ.OctetString('abc')) + assert self.s1.getComponentByName('name') == str2octs('abc'), 'set by name fails' + + def testByKey(self): + self.s1['name'] = 'abc' + assert self.s1['name'] == str2octs('abc'), 'set by key fails' + + def testContains(self): + assert 'name' in self.s1 + assert '<missing>' not in self.s1 + + def testGetNearPosition(self): + assert self.s1.componentType.getTagMapNearPosition(1).presentTypes == { + univ.OctetString.tagSet: univ.OctetString(''), + univ.Integer.tagSet: univ.Integer(34) + } + assert self.s1.componentType.getPositionNearType( + univ.OctetString.tagSet, 1 + ) == 1 + + def testSetDefaultComponents(self): + self.s1.clear() + self.s1.setComponentByPosition(0, univ.OctetString('Ping')) + self.s1.setComponentByPosition(1, univ.OctetString('Pong')) + assert self.s1.getComponentByPosition(2) == 34 + + def testClone(self): + self.s1.setComponentByPosition(0, univ.OctetString('abc')) + self.s1.setComponentByPosition(1, univ.OctetString('def')) + self.s1.setComponentByPosition(2, univ.Integer(123)) + s = self.s1.clone() + assert s.getComponentByPosition(0) != self.s1.getComponentByPosition(0) + assert s.getComponentByPosition(1) != self.s1.getComponentByPosition(1) + assert s.getComponentByPosition(2) != self.s1.getComponentByPosition(2) + s = self.s1.clone(cloneValueFlag=1) + assert s.getComponentByPosition(0) == self.s1.getComponentByPosition(0) + assert s.getComponentByPosition(1) == self.s1.getComponentByPosition(1) + assert s.getComponentByPosition(2) == self.s1.getComponentByPosition(2) + + def testComponentTagsMatching(self): + s = self.s1.clone() + s.strictConstraints = True # This requires types equality + o = univ.OctetString('abc').subtype(explicitTag=tag.Tag(tag.tagClassPrivate, tag.tagFormatSimple, 12)) + try: + s.setComponentByName('name', o) + except PyAsn1Error: + pass + else: + assert 0, 'inner supertype tag allowed' + + def testComponentConstraintsMatching(self): + s = self.s1.clone() + o = univ.OctetString().subtype( + subtypeSpec=constraint.ConstraintsUnion(constraint.SingleValueConstraint(str2octs('cba')))) + s.strictConstraints = True # This requires types equality + try: + s.setComponentByName('name', o.clone('cba')) + except PyAsn1Error: + pass + else: + assert 0, 'inner supertype constraint allowed' + s.strictConstraints = False # This requires subtype relationships + try: + s.setComponentByName('name', o.clone('cba')) + except PyAsn1Error: + assert 0, 'inner supertype constraint disallowed' + else: + pass + + def testSetComponents(self): + assert self.s1.clone().setComponents(name='a', nick='b', age=1) == \ + self.s1.setComponentByPosition(0, 'a').setComponentByPosition(1, 'b').setComponentByPosition(2, 1) + + def testSetToDefault(self): + s = self.s1.clone() + s.setComponentByPosition(0, univ.noValue) + s[2] = univ.noValue + assert s[0] == univ.OctetString('') + assert s[2] == univ.Integer(34) + + def testGetItem(self): + s = self.s1.clone() + s['name'] = 'xxx' + assert s['name'] + assert s[0] + + try: + s['xxx'] + + except KeyError: + pass + + else: + assert False, 'KeyError not raised' + + try: + s[100] + + except IndexError: + pass + + else: + assert False, 'IndexError not raised' + + def testSetItem(self): + s = self.s1.clone() + s['name'] = 'xxx' + + try: + + s['xxx'] = 'xxx' + + except KeyError: + pass + + else: + assert False, 'KeyError not raised' + + try: + + s[100] = 'xxx' + + except IndexError: + pass + + else: + assert False, 'IndexError not raised' + + def testIter(self): + assert list(self.s1) == ['name', 'nick', 'age'] + + def testKeys(self): + self.s1.setComponentByPosition(0, univ.OctetString('abc')) + self.s1.setComponentByPosition(1, univ.OctetString('def')) + self.s1.setComponentByPosition(2, univ.Integer(123)) + assert list(self.s1.keys()) == ['name', 'nick', 'age'] + + def testValues(self): + self.s1.setComponentByPosition(0, univ.OctetString('abc')) + self.s1.setComponentByPosition(1, univ.OctetString('def')) + self.s1.setComponentByPosition(2, univ.Integer(123)) + assert list(self.s1.values()) == [str2octs('abc'), str2octs('def'), 123] + + def testItems(self): + self.s1.setComponentByPosition(0, univ.OctetString('abc')) + self.s1.setComponentByPosition(1, univ.OctetString('def')) + self.s1.setComponentByPosition(2, univ.Integer(123)) + assert list(self.s1.items()) == [(x[0], str2octs(x[1])) for x in [('name', 'abc'), ('nick', 'def')]] + [('age', 123)] + + def testUpdate(self): + self.s1.clear() + assert list(self.s1.values()) == [str2octs(''), str2octs(''), 34] + self.s1.update(**{'name': 'abc', 'nick': 'def', 'age': 123}) + assert list(self.s1.items()) == [(x[0], str2octs(x[1])) for x in [('name', 'abc'), ('nick', 'def')]] + [('age', 123)] + self.s1.update(('name', 'ABC')) + assert list(self.s1.items()) == [(x[0], str2octs(x[1])) for x in [('name', 'ABC'), ('nick', 'def')]] + [('age', 123)] + self.s1.update(name='CBA') + assert list(self.s1.items()) == [(x[0], str2octs(x[1])) for x in [('name', 'CBA'), ('nick', 'def')]] + [('age', 123)] + + def testStaticDef(self): + + class Sequence(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('name', univ.OctetString('')), + namedtype.OptionalNamedType('nick', univ.OctetString('')), + namedtype.DefaultedNamedType('age', univ.Integer(34)) + ) + + s = Sequence() + s['name'] = 'abc' + assert s['name'] == str2octs('abc') + + def testGetComponentWithDefault(self): + + class Sequence(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('name', univ.OctetString('')), + namedtype.OptionalNamedType('nick', univ.OctetString()), + ) + + s = Sequence() + + assert s[0] == str2octs('') + assert s.getComponentByPosition(1, default=None, instantiate=False) is None + assert s.getComponentByName('nick', default=None) is None + s[1] = 'test' + assert s.getComponentByPosition(1, default=None) is not None + assert s.getComponentByPosition(1, default=None) == str2octs('test') + s.clear() + assert s.getComponentByPosition(1, default=None) is None + + def testGetComponentWithConstructedDefault(self): + + class Sequence(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('name', univ.OctetString()), + namedtype.DefaultedNamedType('nick', univ.SequenceOf( + componentType=univ.Integer() + ).setComponentByPosition(0, 1)), + ) + + s = Sequence() + + assert s.getComponentByPosition(1, default=None, instantiate=False) is None + assert s.getComponentByPosition(1, instantiate=False) is univ.noValue + assert s.getComponentByPosition(1) == [1] + + def testGetComponentNoInstantiation(self): + + class Sequence(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('name', univ.OctetString('')), + namedtype.OptionalNamedType('nick', univ.OctetString()), + ) + + s = Sequence() + assert s[0] == str2octs('') + assert s.getComponentByPosition(1, instantiate=False) is univ.noValue + assert s.getComponentByName('nick', instantiate=False) is univ.noValue + s[1] = 'test' + assert s.getComponentByPosition(1, instantiate=False) is not univ.noValue + assert s.getComponentByPosition(1, instantiate=False) == str2octs('test') + s.clear() + assert s.getComponentByPosition(1, instantiate=False) is univ.noValue + + def testSchemaWithComponents(self): + + class Sequence(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('name', univ.OctetString()) + ) + + s = Sequence() + + assert not s.isValue + + s[0] = 'test' + + assert s.isValue + + s.clear() + + assert not s.isValue + + s.reset() + + assert not s.isValue + + def testSchemaWithOptionalComponents(self): + + class Sequence(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.OptionalNamedType('name', univ.OctetString()) + ) + + s = Sequence() + + assert s.isValue + + s[0] = 'test' + + assert s.isValue + + s.clear() + + assert s.isValue + + s.reset() + + assert not s.isValue + + def testSchemaWithOptionalComponents(self): + + class Sequence(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.DefaultedNamedType('name', univ.OctetString('')) + ) + + s = Sequence() + + assert s.isValue + + s[0] = 'test' + + assert s.isValue + + s.clear() + + assert s.isValue + + s.reset() + + assert not s.isValue + + def testIsInconsistentWithComponentsConstraint(self): + + class Sequence(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.OptionalNamedType('name', univ.OctetString()), + namedtype.DefaultedNamedType('age', univ.Integer(65)) + ) + subtypeSpec = constraint.WithComponentsConstraint( + ('name', constraint.ComponentPresentConstraint()), + ('age', constraint.ComponentAbsentConstraint()) + ) + + s = Sequence() + + assert s.isInconsistent + + s[0] = 'test' + + assert not s.isInconsistent + + s[0] = 'test' + s[1] = 23 + + assert s.isInconsistent + + s.clear() + + assert s.isInconsistent + + s.reset() + + assert s.isInconsistent + + s[1] = 23 + + assert s.isInconsistent + + def testIsInconsistentSizeConstraint(self): + + class Sequence(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.OptionalNamedType('name', univ.OctetString()), + namedtype.DefaultedNamedType('age', univ.Integer(65)) + ) + subtypeSpec = constraint.ValueSizeConstraint(0, 1) + + s = Sequence() + + assert not s.isInconsistent + + s[0] = 'test' + + assert not s.isInconsistent + + s[0] = 'test' + s[1] = 23 + + assert s.isInconsistent + + s.clear() + + assert not s.isInconsistent + + s.reset() + + assert s.isInconsistent + + s[1] = 23 + + assert not s.isInconsistent + + +class SequenceWithoutSchema(BaseTestCase): + + def testGetItem(self): + s = univ.Sequence() + s.setComponentByPosition(0, univ.OctetString('abc')) + s[0] = 'abc' + assert s['field-0'] + assert s[0] + + try: + s['field-1'] + + except KeyError: + pass + + else: + assert False, 'KeyError not raised' + + def testSetItem(self): + s = univ.Sequence() + s.setComponentByPosition(0, univ.OctetString('abc')) + s['field-0'] = 'xxx' + + try: + + s['field-1'] = 'xxx' + + except KeyError: + pass + + else: + assert False, 'KeyError not raised' + + def testIter(self): + s = univ.Sequence() + s.setComponentByPosition(0, univ.OctetString('abc')) + s.setComponentByPosition(1, univ.Integer(123)) + assert list(s) == ['field-0', 'field-1'] + + def testKeys(self): + s = univ.Sequence() + s.setComponentByPosition(0, univ.OctetString('abc')) + s.setComponentByPosition(1, univ.Integer(123)) + assert list(s.keys()) == ['field-0', 'field-1'] + + def testValues(self): + s = univ.Sequence() + s.setComponentByPosition(0, univ.OctetString('abc')) + s.setComponentByPosition(1, univ.Integer(123)) + assert list(s.values()) == [str2octs('abc'), 123] + + def testItems(self): + s = univ.Sequence() + s.setComponentByPosition(0, univ.OctetString('abc')) + s.setComponentByPosition(1, univ.Integer(123)) + assert list(s.items()) == [('field-0', str2octs('abc')), ('field-1', 123)] + + def testUpdate(self): + s = univ.Sequence().clear() + assert not s + s.setComponentByPosition(0, univ.OctetString('abc')) + s.setComponentByPosition(1, univ.Integer(123)) + assert s + assert list(s.keys()) == ['field-0', 'field-1'] + assert list(s.values()) == [str2octs('abc'), 123] + assert list(s.items()) == [('field-0', str2octs('abc')), ('field-1', 123)] + s['field-0'] = univ.OctetString('def') + assert list(s.values()) == [str2octs('def'), 123] + s['field-1'] = univ.OctetString('ghi') + assert list(s.values()) == [str2octs('def'), str2octs('ghi')] + try: + s['field-2'] = univ.OctetString('xxx') + except KeyError: + pass + else: + assert False, 'unknown field at schema-less object tolerated' + assert 'field-0' in s + s.clear() + assert 'field-0' not in s + + def testSchema(self): + + class Sequence(univ.Sequence): + pass + + s = Sequence() + + assert not s.isValue + + s[0] = univ.OctetString('test') + + assert s.isValue + + s.clear() + + assert s.isValue + + s.reset() + + assert not s.isValue + + +class SequencePicklingTestCase(unittest.TestCase): + + def testSchemaPickling(self): + old_asn1 = univ.Sequence( + componentType=namedtype.NamedTypes( + namedtype.NamedType('name', univ.OctetString()) + ) + ) + serialised = pickle.dumps(old_asn1) + assert serialised + new_asn1 = pickle.loads(serialised) + assert type(new_asn1) == univ.Sequence + assert old_asn1.isSameTypeWith(new_asn1) + + def testValuePickling(self): + old_asn1 = univ.Sequence( + componentType=namedtype.NamedTypes( + namedtype.NamedType('name', univ.OctetString()) + ) + ) + old_asn1['name'] = 'test' + serialised = pickle.dumps(old_asn1) + assert serialised + new_asn1 = pickle.loads(serialised) + assert new_asn1 + assert new_asn1['name'] == str2octs('test') + + +class SetOf(BaseTestCase): + def setUp(self): + BaseTestCase.setUp(self) + self.s1 = univ.SetOf(componentType=univ.OctetString('')) + + def testTag(self): + assert self.s1.tagSet == tag.TagSet( + (), + tag.Tag(tag.tagClassUniversal, tag.tagFormatConstructed, 0x11) + ), 'wrong tagSet' + + def testSeq(self): + self.s1.setComponentByPosition(0, univ.OctetString('abc')) + assert self.s1[0] == str2octs('abc'), 'set by idx fails' + self.s1.setComponentByPosition(0, self.s1[0].clone('cba')) + assert self.s1[0] == str2octs('cba'), 'set by idx fails' + + def testStaticDef(self): + + class SetOf(univ.SequenceOf): + componentType = univ.OctetString('') + + s = SetOf() + s[0] = 'abc' + assert len(s) == 1 + assert s == [str2octs('abc')] + + + +class SetOfPicklingTestCase(unittest.TestCase): + + def testSchemaPickling(self): + old_asn1 = univ.SetOf(componentType=univ.OctetString()) + serialised = pickle.dumps(old_asn1) + assert serialised + new_asn1 = pickle.loads(serialised) + assert type(new_asn1) == univ.SetOf + assert old_asn1.isSameTypeWith(new_asn1) + + def testValuePickling(self): + old_asn1 = univ.SetOf(componentType=univ.OctetString()) + old_asn1[0] = 'test' + serialised = pickle.dumps(old_asn1) + assert serialised + new_asn1 = pickle.loads(serialised) + assert new_asn1 + assert new_asn1 == [str2octs('test')] + + +class Set(BaseTestCase): + def setUp(self): + BaseTestCase.setUp(self) + + self.s1 = univ.Set( + componentType=namedtype.NamedTypes( + namedtype.NamedType('name', univ.OctetString('')), + namedtype.OptionalNamedType('null', univ.Null('')), + namedtype.DefaultedNamedType('age', univ.Integer(34)) + ) + ) + self.s2 = self.s1.clone() + + def testTag(self): + assert self.s1.tagSet == tag.TagSet( + (), + tag.Tag(tag.tagClassUniversal, tag.tagFormatConstructed, 0x11) + ), 'wrong tagSet' + + def testByTypeWithPythonValue(self): + self.s1.setComponentByType(univ.OctetString.tagSet, 'abc') + assert self.s1.getComponentByType( + univ.OctetString.tagSet + ) == str2octs('abc'), 'set by name fails' + + def testByTypeWithInstance(self): + self.s1.setComponentByType(univ.OctetString.tagSet, univ.OctetString('abc')) + assert self.s1.getComponentByType( + univ.OctetString.tagSet + ) == str2octs('abc'), 'set by name fails' + + def testGetTagMap(self): + assert self.s1.tagMap.presentTypes == { + univ.Set.tagSet: univ.Set().clear() + } + + def testGetComponentTagMap(self): + assert self.s1.componentType.tagMapUnique.presentTypes == { + univ.OctetString.tagSet: univ.OctetString(''), + univ.Null.tagSet: univ.Null(''), + univ.Integer.tagSet: univ.Integer(34) + } + + def testGetPositionByType(self): + assert self.s1.componentType.getPositionByType(univ.Null().tagSet) == 1 + + def testSetToDefault(self): + self.s1.setComponentByName('name', univ.noValue) + assert self.s1['name'] == univ.OctetString('') + + def testIter(self): + assert list(self.s1) == ['name', 'null', 'age'] + + def testStaticDef(self): + + class Set(univ.Set): + componentType = namedtype.NamedTypes( + namedtype.NamedType('name', univ.OctetString('')), + namedtype.OptionalNamedType('nick', univ.OctetString('')), + namedtype.DefaultedNamedType('age', univ.Integer(34)) + ) + + s = Set() + s['name'] = 'abc' + assert s['name'] == str2octs('abc') + + def testGetComponentWithDefault(self): + + class Set(univ.Set): + componentType = namedtype.NamedTypes( + namedtype.NamedType('id', univ.Integer(123)), + namedtype.OptionalNamedType('nick', univ.OctetString()), + ) + + s = Set() + assert s[0] == 123 + assert s.getComponentByPosition(1, default=None, instantiate=False) is None + assert s.getComponentByName('nick', default=None) is None + s[1] = 'test' + assert s.getComponentByPosition(1, default=None) is not None + assert s.getComponentByPosition(1, default=None) == str2octs('test') + s.clear() + assert s.getComponentByPosition(1, default=None) is None + + def testGetComponentNoInstantiation(self): + + class Set(univ.Set): + componentType = namedtype.NamedTypes( + namedtype.NamedType('id', univ.Integer(123)), + namedtype.OptionalNamedType('nick', univ.OctetString()), + ) + + s = Set() + assert s[0] == 123 + assert s.getComponentByPosition(1, instantiate=False) is univ.noValue + assert s.getComponentByName('nick', instantiate=False) is univ.noValue + assert s.getComponentByType(univ.OctetString.tagSet, instantiate=False) is univ.noValue + s[1] = 'test' + assert s.getComponentByPosition(1, instantiate=False) is not univ.noValue + assert s.getComponentByPosition(1, instantiate=False) == str2octs('test') + s.clear() + assert s.getComponentByPosition(1, instantiate=False) is univ.noValue + + +class SetPicklingTestCase(unittest.TestCase): + + def testSchemaPickling(self): + old_asn1 = univ.Set( + componentType=namedtype.NamedTypes( + namedtype.NamedType('name', univ.OctetString()) + ) + ) + serialised = pickle.dumps(old_asn1) + assert serialised + new_asn1 = pickle.loads(serialised) + assert type(new_asn1) == univ.Set + assert old_asn1.isSameTypeWith(new_asn1) + + def testValuePickling(self): + old_asn1 = univ.Set( + componentType=namedtype.NamedTypes( + namedtype.NamedType('name', univ.OctetString()) + ) + ) + old_asn1['name'] = 'test' + serialised = pickle.dumps(old_asn1) + assert serialised + new_asn1 = pickle.loads(serialised) + assert new_asn1 + assert new_asn1['name'] == str2octs('test') + + +class Choice(BaseTestCase): + def setUp(self): + BaseTestCase.setUp(self) + + innerComp = univ.Choice( + componentType=namedtype.NamedTypes( + namedtype.NamedType('count', univ.Integer()), + namedtype.NamedType('flag', univ.Boolean()) + ) + ) + self.s1 = univ.Choice( + componentType=namedtype.NamedTypes( + namedtype.NamedType('name', univ.OctetString()), + namedtype.NamedType('sex', innerComp) + ) + ) + + def testTag(self): + assert self.s1.tagSet == tag.TagSet(), 'wrong tagSet' + + def testRepr(self): + assert 'Choice' in repr(self.s1.clone().setComponents('a')) + s = self.s1.clone().setComponents( + sex=self.s1.setComponentByPosition(1).getComponentByPosition(1).clone().setComponents(count=univ.Integer(123)) + ) + assert 'Choice' in repr(s) + + def testContains(self): + self.s1.setComponentByType(univ.OctetString.tagSet, 'abc') + assert 'name' in self.s1 + assert 'sex' not in self.s1 + + self.s1.setComponentByType(univ.Integer.tagSet, 123, innerFlag=True) + assert 'name' not in self.s1 + assert 'sex' in self.s1 + + def testIter(self): + self.s1.setComponentByType(univ.OctetString.tagSet, 'abc') + assert list(self.s1) == ['name'] + self.s1.setComponentByType(univ.Integer.tagSet, 123, innerFlag=True) + assert list(self.s1) == ['sex'] + + def testOuterByTypeWithPythonValue(self): + self.s1.setComponentByType(univ.OctetString.tagSet, 'abc') + assert self.s1.getComponentByType( + univ.OctetString.tagSet + ) == str2octs('abc') + + def testOuterByTypeWithInstanceValue(self): + self.s1.setComponentByType( + univ.OctetString.tagSet, univ.OctetString('abc') + ) + assert self.s1.getComponentByType( + univ.OctetString.tagSet + ) == str2octs('abc') + + def testInnerByTypeWithPythonValue(self): + self.s1.setComponentByType(univ.Integer.tagSet, 123, innerFlag=True) + assert self.s1.getComponentByType( + univ.Integer.tagSet, 1 + ) == 123 + + def testInnerByTypeWithInstanceValue(self): + self.s1.setComponentByType( + univ.Integer.tagSet, univ.Integer(123), innerFlag=True + ) + assert self.s1.getComponentByType( + univ.Integer.tagSet, 1 + ) == 123 + + def testCmp(self): + self.s1.setComponentByName('name', univ.OctetString('abc')) + assert self.s1 == str2octs('abc'), '__cmp__() fails' + + def testGetComponent(self): + self.s1.setComponentByType(univ.OctetString.tagSet, 'abc') + assert self.s1.getComponent() == str2octs('abc'), 'getComponent() fails' + + def testGetName(self): + self.s1.setComponentByType(univ.OctetString.tagSet, 'abc') + assert self.s1.getName() == 'name', 'getName() fails' + + def testSetComponentByPosition(self): + self.s1.setComponentByPosition(0, univ.OctetString('Jim')) + assert self.s1 == str2octs('Jim') + + def testClone(self): + self.s1.setComponentByPosition(0, univ.OctetString('abc')) + s = self.s1.clone() + assert len(s) == 0 + s = self.s1.clone(cloneValueFlag=1) + assert len(s) == 1 + assert s.getComponentByPosition(0) == self.s1.getComponentByPosition(0) + + def testSetToDefault(self): + s = self.s1.clone() + s.setComponentByName('sex', univ.noValue) + assert s['sex'] is not univ.noValue + + def testStaticDef(self): + + class InnerChoice(univ.Choice): + componentType = namedtype.NamedTypes( + namedtype.NamedType('count', univ.Integer()), + namedtype.NamedType('flag', univ.Boolean()) + ) + + class OuterChoice(univ.Choice): + componentType = namedtype.NamedTypes( + namedtype.NamedType('name', univ.OctetString()), + namedtype.NamedType('sex', InnerChoice()) + ) + + c = OuterChoice() + + c.setComponentByType(univ.OctetString.tagSet, 'abc') + assert c.getName() == 'name' + + def testGetComponentWithDefault(self): + + s = univ.Choice( + componentType=namedtype.NamedTypes( + namedtype.NamedType('name', univ.OctetString()), + namedtype.NamedType('id', univ.Integer()) + ) + ) + + assert s.getComponentByPosition(0, default=None, instantiate=False) is None + assert s.getComponentByPosition(1, default=None, instantiate=False) is None + assert s.getComponentByName('name', default=None, instantiate=False) is None + assert s.getComponentByName('id', default=None, instantiate=False) is None + assert s.getComponentByType(univ.OctetString.tagSet, default=None) is None + assert s.getComponentByType(univ.Integer.tagSet, default=None) is None + s[1] = 123 + assert s.getComponentByPosition(1, default=None) is not None + assert s.getComponentByPosition(1, univ.noValue) == 123 + s.clear() + assert s.getComponentByPosition(1, default=None, instantiate=False) is None + + def testGetComponentNoInstantiation(self): + + s = univ.Choice( + componentType=namedtype.NamedTypes( + namedtype.NamedType('name', univ.OctetString()), + namedtype.NamedType('id', univ.Integer()) + ) + ) + + assert s.getComponentByPosition(0, instantiate=False) is univ.noValue + assert s.getComponentByPosition(1, instantiate=False) is univ.noValue + assert s.getComponentByName('name', instantiate=False) is univ.noValue + assert s.getComponentByName('id', instantiate=False) is univ.noValue + assert s.getComponentByType(univ.OctetString.tagSet, instantiate=False) is univ.noValue + assert s.getComponentByType(univ.Integer.tagSet, instantiate=False) is univ.noValue + s[1] = 123 + assert s.getComponentByPosition(1, instantiate=False) is not univ.noValue + assert s.getComponentByPosition(1, instantiate=False) == 123 + s.clear() + assert s.getComponentByPosition(1, instantiate=False) is univ.noValue + + +class ChoicePicklingTestCase(unittest.TestCase): + + def testSchemaPickling(self): + old_asn1 = univ.Choice( + componentType=namedtype.NamedTypes( + namedtype.NamedType('name', univ.OctetString()), + namedtype.NamedType('id', univ.Integer()) + ) + ) + serialised = pickle.dumps(old_asn1) + assert serialised + new_asn1 = pickle.loads(serialised) + assert type(new_asn1) == univ.Choice + assert old_asn1.isSameTypeWith(new_asn1) + + def testValuePickling(self): + old_asn1 = univ.Choice( + componentType=namedtype.NamedTypes( + namedtype.NamedType('name', univ.OctetString()), + namedtype.NamedType('id', univ.Integer()) + ) + ) + old_asn1['name'] = 'test' + serialised = pickle.dumps(old_asn1) + assert serialised + new_asn1 = pickle.loads(serialised) + assert new_asn1 + assert new_asn1['name'] == str2octs('test') + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + unittest.TextTestRunner(verbosity=2).run(suite) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/tests/type/test_useful.py b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/tests/type/test_useful.py new file mode 100644 index 00000000..8a5ab308 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/pyasn1/tests/type/test_useful.py @@ -0,0 +1,143 @@ +# +# This file is part of pyasn1 software. +# +# Copyright (c) 2005-2019, Ilya Etingof <etingof@gmail.com> +# License: http://snmplabs.com/pyasn1/license.html +# +import datetime +import pickle +import sys +from copy import deepcopy + +try: + import unittest2 as unittest + +except ImportError: + import unittest + +from tests.base import BaseTestCase + +from pyasn1.type import useful + + +class FixedOffset(datetime.tzinfo): + def __init__(self, offset, name): + self.__offset = datetime.timedelta(minutes=offset) + self.__name = name + + def utcoffset(self, dt): + return self.__offset + + def tzname(self, dt): + return self.__name + + def dst(self, dt): + return datetime.timedelta(0) + + +UTC = FixedOffset(0, 'UTC') +UTC2 = FixedOffset(120, 'UTC') + + +class ObjectDescriptorTestCase(BaseTestCase): + pass + + +class GeneralizedTimeTestCase(BaseTestCase): + + def testFromDateTime(self): + assert useful.GeneralizedTime.fromDateTime(datetime.datetime(2017, 7, 11, 0, 1, 2, 3000, tzinfo=UTC)) == '20170711000102.3Z' + + def testToDateTime0(self): + assert datetime.datetime(2017, 7, 11, 0, 1, 2) == useful.GeneralizedTime('20170711000102').asDateTime + + def testToDateTime1(self): + assert datetime.datetime(2017, 7, 11, 0, 1, 2, tzinfo=UTC) == useful.GeneralizedTime('20170711000102Z').asDateTime + + def testToDateTime2(self): + assert datetime.datetime(2017, 7, 11, 0, 1, 2, 3000, tzinfo=UTC) == useful.GeneralizedTime('20170711000102.3Z').asDateTime + + def testToDateTime3(self): + assert datetime.datetime(2017, 7, 11, 0, 1, 2, 3000, tzinfo=UTC) == useful.GeneralizedTime('20170711000102,3Z').asDateTime + + def testToDateTime4(self): + assert datetime.datetime(2017, 7, 11, 0, 1, 2, 3000, tzinfo=UTC) == useful.GeneralizedTime('20170711000102.3+0000').asDateTime + + def testToDateTime5(self): + assert datetime.datetime(2017, 7, 11, 0, 1, 2, 3000, tzinfo=UTC2) == useful.GeneralizedTime('20170711000102.3+0200').asDateTime + + def testToDateTime6(self): + assert datetime.datetime(2017, 7, 11, 0, 1, 2, 3000, tzinfo=UTC2) == useful.GeneralizedTime('20170711000102.3+02').asDateTime + + def testToDateTime7(self): + assert datetime.datetime(2017, 7, 11, 0, 1) == useful.GeneralizedTime('201707110001').asDateTime + + def testToDateTime8(self): + assert datetime.datetime(2017, 7, 11, 0) == useful.GeneralizedTime('2017071100').asDateTime + + def testCopy(self): + dt = useful.GeneralizedTime("20170916234254+0130").asDateTime + assert dt == deepcopy(dt) + + +class GeneralizedTimePicklingTestCase(unittest.TestCase): + + def testSchemaPickling(self): + old_asn1 = useful.GeneralizedTime() + serialised = pickle.dumps(old_asn1) + assert serialised + new_asn1 = pickle.loads(serialised) + assert type(new_asn1) == useful.GeneralizedTime + assert old_asn1.isSameTypeWith(new_asn1) + + def testValuePickling(self): + old_asn1 = useful.GeneralizedTime("20170916234254+0130") + serialised = pickle.dumps(old_asn1) + assert serialised + new_asn1 = pickle.loads(serialised) + assert new_asn1 == old_asn1 + + +class UTCTimeTestCase(BaseTestCase): + + def testFromDateTime(self): + assert useful.UTCTime.fromDateTime(datetime.datetime(2017, 7, 11, 0, 1, 2, tzinfo=UTC)) == '170711000102Z' + + def testToDateTime0(self): + assert datetime.datetime(2017, 7, 11, 0, 1, 2) == useful.UTCTime('170711000102').asDateTime + + def testToDateTime1(self): + assert datetime.datetime(2017, 7, 11, 0, 1, 2, tzinfo=UTC) == useful.UTCTime('170711000102Z').asDateTime + + def testToDateTime2(self): + assert datetime.datetime(2017, 7, 11, 0, 1, 2, tzinfo=UTC) == useful.UTCTime('170711000102+0000').asDateTime + + def testToDateTime3(self): + assert datetime.datetime(2017, 7, 11, 0, 1, 2, tzinfo=UTC2) == useful.UTCTime('170711000102+0200').asDateTime + + def testToDateTime4(self): + assert datetime.datetime(2017, 7, 11, 0, 1) == useful.UTCTime('1707110001').asDateTime + + +class UTCTimePicklingTestCase(unittest.TestCase): + + def testSchemaPickling(self): + old_asn1 = useful.UTCTime() + serialised = pickle.dumps(old_asn1) + assert serialised + new_asn1 = pickle.loads(serialised) + assert type(new_asn1) == useful.UTCTime + assert old_asn1.isSameTypeWith(new_asn1) + + def testValuePickling(self): + old_asn1 = useful.UTCTime("170711000102") + serialised = pickle.dumps(old_asn1) + assert serialised + new_asn1 = pickle.loads(serialised) + assert new_asn1 == old_asn1 + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + unittest.TextTestRunner(verbosity=2).run(suite) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/rsa/CHANGELOG.md b/arch-config/.config/calibre/plugins/DeACSM/modules/rsa/CHANGELOG.md new file mode 100644 index 00000000..3781be98 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/rsa/CHANGELOG.md @@ -0,0 +1,235 @@ +# Python-RSA changelog + +## Version 4.8 - in development + +- Switch to [Poetry](https://python-poetry.org/) for dependency and release management. +- Compatibility with Python 3.10. +- Chain exceptions using `raise new_exception from old_exception` + ([#157](https://github.com/sybrenstuvel/python-rsa/pull/157)) +- Added marker file for PEP 561. This will allow type checking tools in dependent projects + to use type annotations from Python-RSA + ([#136](https://github.com/sybrenstuvel/python-rsa/pull/136)). +- Use the Chinese Remainder Theorem when decrypting with a private key. This + makes decryption 2-4x faster + ([#163](https://github.com/sybrenstuvel/python-rsa/pull/163)). + +## Version 4.7.2 - released 2021-02-24 + +- Fix picking/unpickling issue introduced in 4.7 + ([#173](https://github.com/sybrenstuvel/python-rsa/issues/173)) + +## Version 4.7.1 - released 2021-02-15 + +- Fix threading issue introduced in 4.7 + ([#173](https://github.com/sybrenstuvel/python-rsa/issues/173)) + +## Version 4.7 - released 2021-01-10 + +- Fix [#165](https://github.com/sybrenstuvel/python-rsa/issues/165): + CVE-2020-25658 - Bleichenbacher-style timing oracle in PKCS#1 v1.5 decryption + code +- Add padding length check as described by PKCS#1 v1.5 (Fixes + [#164](https://github.com/sybrenstuvel/python-rsa/issues/164)) +- Reuse of blinding factors to speed up blinding operations. + Fixes [#162](https://github.com/sybrenstuvel/python-rsa/issues/162). +- Declare & test support for Python 3.9 + + +## Version 4.4 & 4.6 - released 2020-06-12 + +Version 4.4 and 4.6 are almost a re-tagged release of version 4.2. It requires +Python 3.5+. To avoid older Python installations from trying to upgrade to RSA +4.4, this is now made explicit in the `python_requires` argument in `setup.py`. +There was a mistake releasing 4.4 as "3.5+ only", which made it necessary to +retag 4.4 as 4.6 as well. + +No functional changes compared to version 4.2. + + +## Version 4.3 & 4.5 - released 2020-06-12 + +Version 4.3 and 4.5 are almost a re-tagged release of version 4.0. It is the +last to support Python 2.7. This is now made explicit in the `python_requires` +argument in `setup.py`. Python 3.4 is not supported by this release. There was a +mistake releasing 4.4 as "3.5+ only", which made it necessary to retag 4.3 as +4.5 as well. + +Two security fixes have also been backported, so 4.3 = 4.0 + these two fixes. + +- Choose blinding factor relatively prime to N. Thanks Christian Heimes for pointing this out. +- Reject cyphertexts (when decrypting) and signatures (when verifying) that have + been modified by prepending zero bytes. This resolves CVE-2020-13757. Thanks + Carnil for pointing this out. + + +## Version 4.2 - released 2020-06-10 + +- Rolled back the switch to Poetry, and reverted back to using Pipenv + setup.py + for dependency management. There apparently is an issue no-binary installs of + packages build with Poetry. This fixes + [#148](https://github.com/sybrenstuvel/python-rsa/issues/148) +- Limited SHA3 support to those Python versions (3.6+) that support it natively. + The third-party library that adds support for this to Python 3.5 is a binary + package, and thus breaks the pure-Python nature of Python-RSA. + This should fix [#147](https://github.com/sybrenstuvel/python-rsa/issues/147). + + +## Version 4.1 - released 2020-06-10 + +- Added support for Python 3.8. +- Dropped support for Python 2 and 3.4. +- Added type annotations to the source code. This will make Python-RSA easier to use in + your IDE, and allows better type checking. +- Added static type checking via [MyPy](http://mypy-lang.org/). +- Fix [#129](https://github.com/sybrenstuvel/python-rsa/issues/129) Installing from source + gives UnicodeDecodeError. +- Switched to using [Poetry](https://poetry.eustace.io/) for package + management. +- Added support for SHA3 hashing: SHA3-256, SHA3-384, SHA3-512. This + is natively supported by Python 3.6+ and supported via a third-party + library on Python 3.5. +- Choose blinding factor relatively prime to N. Thanks Christian Heimes for pointing this out. +- Reject cyphertexts (when decrypting) and signatures (when verifying) that have + been modified by prepending zero bytes. This resolves CVE-2020-13757. Thanks + Adelapie for pointing this out. + + +## Version 4.0 - released 2018-09-16 + +- Removed deprecated modules: + - rsa.varblock + - rsa.bigfile + - rsa._version133 + - rsa._version200 +- Removed CLI commands that use the VARBLOCK/bigfile format. +- Ensured that PublicKey.save_pkcs1() and PrivateKey.save_pkcs1() always return bytes. +- Dropped support for Python 2.6 and 3.3. +- Dropped support for Psyco. +- Miller-Rabin iterations determined by bitsize of key. + [#58](https://github.com/sybrenstuvel/python-rsa/pull/58) +- Added function `rsa.find_signature_hash()` to return the name of the hashing + algorithm used to sign a message. `rsa.verify()` now also returns that name, + instead of always returning `True`. + [#78](https://github.com/sybrenstuvel/python-rsa/issues/13) +- Add support for SHA-224 for PKCS1 signatures. + [#104](https://github.com/sybrenstuvel/python-rsa/pull/104) +- Transitioned from `requirements.txt` to Pipenv for package management. + + +## Version 3.4.2 - released 2016-03-29 + +- Fixed dates in CHANGELOG.txt + + +## Version 3.4.1 - released 2016-03-26 + +- Included tests/private.pem in MANIFEST.in +- Included README.md and CHANGELOG.txt in MANIFEST.in + + +## Version 3.4 - released 2016-03-17 + +- Moved development to GitHub: https://github.com/sybrenstuvel/python-rsa +- Solved side-channel vulnerability by implementing blinding, fixes #19 +- Deprecated the VARBLOCK format and rsa.bigfile module due to security issues, see + https://github.com/sybrenstuvel/python-rsa/issues/13 +- Integration with Travis-CI [1], Coveralls [2] and Code Climate [3] +- Deprecated the old rsa._version133 and rsa._version200 submodules, they will be + completely removed in version 4.0. +- Add an 'exponent' argument to key.newkeys() +- Switched from Solovay-Strassen to Miller-Rabin primality testing, to + comply with NIST FIPS 186-4 [4] as probabilistic primality test + (Appendix C, subsection C.3): +- Fixed bugs #12, #14, #27, #30, #49 + +[1] https://travis-ci.org/sybrenstuvel/python-rsa +[2] https://coveralls.io/github/sybrenstuvel/python-rsa +[3] https://codeclimate.com/github/sybrenstuvel/python-rsa +[4] http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf + + +## Version 3.3 - released 2016-01-13 + +- Thanks to Filippo Valsorda: Fix BB'06 attack in verify() by + switching from parsing to comparison. See [1] for more information. +- Simplified Tox configuration and dropped Python 3.2 support. The + coverage package uses a u'' prefix, which was reintroduced in 3.3 + for ease of porting. + +[1] https://blog.filippo.io/bleichenbacher-06-signature-forgery-in-python-rsa/ + + +## Version 3.2.3 - released 2015-11-05 + +- Added character encoding markers for Python 2.x + + +## Version 3.2.1 - released 2015-11-05 + +- Added per-file licenses +- Added support for wheel packages +- Made example code more consistent and up to date with Python 3.4 + + +## Version 3.2 - released 2015-07-29 + +- Mentioned support for Python 3 in setup.py + + +## Version 3.1.4 - released 2014-02-22 + +- Fixed some bugs + + +## Version 3.1.3 - released 2014-02-02 + +- Dropped support for Python 2.5 + + +## Version 3.1.2 - released 2013-09-15 + +- Added Python 3.3 to the test environment. +- Removed dependency on Distribute +- Added support for loading public keys from OpenSSL + + +## Version 3.1.1 - released 2012-06-18 + +- Fixed doctests for Python 2.7 +- Removed obsolete unittest so all tests run fine on Python 3.2 + +## Version 3.1 - released 2012-06-17 + +- Big, big credits to Yesudeep Mangalapilly for all the changes listed + below! +- Added ability to generate keys on multiple cores simultaneously. +- Massive speedup +- Partial Python 3.2 compatibility (core functionality works, but + saving or loading keys doesn't, for that the pyasn1 package needs to + be ported to Python 3 first) +- Lots of bug fixes + + + +## Version 3.0.1 - released 2011-08-07 + +- Removed unused import of abc module + + +## Version 3.0 - released 2011-08-05 + +- Changed the meaning of the keysize to mean the size of ``n`` rather than + the size of both ``p`` and ``q``. This is the common interpretation of + RSA keysize. To get the old behaviour, double the keysize when generating a + new key. +- Added a lot of doctests +- Added random-padded encryption and decryption using PKCS#1 version 1.5 +- Added hash-based signatures and verification using PKCS#1v1.5 +- Modeling private and public key as real objects rather than dicts. +- Support for saving and loading keys as PEM and DER files. +- Ability to extract a public key from a private key (PEM+DER) + + +## Version 2.0 + +- Security improvements by Barry Mead. diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/rsa/LICENSE b/arch-config/.config/calibre/plugins/DeACSM/modules/rsa/LICENSE new file mode 100644 index 00000000..67589cbb --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/rsa/LICENSE @@ -0,0 +1,13 @@ +Copyright 2011 Sybren A. Stüvel <sybren@stuvel.eu> + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/rsa/PKG-INFO b/arch-config/.config/calibre/plugins/DeACSM/modules/rsa/PKG-INFO new file mode 100644 index 00000000..e3e5a7c6 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/rsa/PKG-INFO @@ -0,0 +1,72 @@ +Metadata-Version: 2.1 +Name: rsa +Version: 4.8 +Summary: Pure-Python RSA implementation +Home-page: https://stuvel.eu/rsa +License: Apache-2.0 +Author: Sybren A. Stüvel +Author-email: sybren@stuvel.eu +Requires-Python: >=3.6,<4 +Classifier: Development Status :: 5 - Production/Stable +Classifier: Intended Audience :: Developers +Classifier: Intended Audience :: Education +Classifier: Intended Audience :: Information Technology +Classifier: License :: OSI Approved :: Apache Software License +Classifier: Operating System :: OS Independent +Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3.10 +Classifier: Programming Language :: Python :: 3.6 +Classifier: Programming Language :: Python :: 3.7 +Classifier: Programming Language :: Python :: 3.8 +Classifier: Programming Language :: Python :: 3.9 +Classifier: Programming Language :: Python :: Implementation :: CPython +Classifier: Programming Language :: Python :: Implementation :: PyPy +Classifier: Topic :: Security :: Cryptography +Requires-Dist: pyasn1 (>=0.1.3) +Description-Content-Type: text/markdown + +# Pure Python RSA implementation + +[![PyPI](https://img.shields.io/pypi/v/rsa.svg)](https://pypi.org/project/rsa/) +[![Build Status](https://travis-ci.org/sybrenstuvel/python-rsa.svg?branch=master)](https://travis-ci.org/sybrenstuvel/python-rsa) +[![Coverage Status](https://coveralls.io/repos/github/sybrenstuvel/python-rsa/badge.svg?branch=master)](https://coveralls.io/github/sybrenstuvel/python-rsa?branch=master) +[![Code Climate](https://api.codeclimate.com/v1/badges/a99a88d28ad37a79dbf6/maintainability)](https://codeclimate.com/github/codeclimate/codeclimate/maintainability) + +[Python-RSA](https://stuvel.eu/rsa) is a pure-Python RSA implementation. It supports +encryption and decryption, signing and verifying signatures, and key +generation according to PKCS#1 version 1.5. It can be used as a Python +library as well as on the commandline. The code was mostly written by +Sybren A. Stüvel. + +Documentation can be found at the [Python-RSA homepage](https://stuvel.eu/rsa). For all changes, check [the changelog](https://github.com/sybrenstuvel/python-rsa/blob/master/CHANGELOG.md). + +Download and install using: + + pip install rsa + +or download it from the [Python Package Index](https://pypi.org/project/rsa/). + +The source code is maintained at [GitHub](https://github.com/sybrenstuvel/python-rsa/) and is +licensed under the [Apache License, version 2.0](https://www.apache.org/licenses/LICENSE-2.0) + +## Security + +Because of how Python internally stores numbers, it is very hard (if not impossible) to make a pure-Python program secure against timing attacks. This library is no exception, so use it with care. See https://securitypitfalls.wordpress.com/2018/08/03/constant-time-compare-in-python/ for more info. + +## Setup of Development Environment + +``` +python3 -m venv .venv +. ./.venv/bin/activate +pip install poetry +poetry install +``` + +## Publishing a New Release + +``` +. ./.venv/bin/activate +poetry publish --build +``` + diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/rsa/README.md b/arch-config/.config/calibre/plugins/DeACSM/modules/rsa/README.md new file mode 100644 index 00000000..02761da7 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/rsa/README.md @@ -0,0 +1,43 @@ +# Pure Python RSA implementation + +[![PyPI](https://img.shields.io/pypi/v/rsa.svg)](https://pypi.org/project/rsa/) +[![Build Status](https://travis-ci.org/sybrenstuvel/python-rsa.svg?branch=master)](https://travis-ci.org/sybrenstuvel/python-rsa) +[![Coverage Status](https://coveralls.io/repos/github/sybrenstuvel/python-rsa/badge.svg?branch=master)](https://coveralls.io/github/sybrenstuvel/python-rsa?branch=master) +[![Code Climate](https://api.codeclimate.com/v1/badges/a99a88d28ad37a79dbf6/maintainability)](https://codeclimate.com/github/codeclimate/codeclimate/maintainability) + +[Python-RSA](https://stuvel.eu/rsa) is a pure-Python RSA implementation. It supports +encryption and decryption, signing and verifying signatures, and key +generation according to PKCS#1 version 1.5. It can be used as a Python +library as well as on the commandline. The code was mostly written by +Sybren A. Stüvel. + +Documentation can be found at the [Python-RSA homepage](https://stuvel.eu/rsa). For all changes, check [the changelog](https://github.com/sybrenstuvel/python-rsa/blob/master/CHANGELOG.md). + +Download and install using: + + pip install rsa + +or download it from the [Python Package Index](https://pypi.org/project/rsa/). + +The source code is maintained at [GitHub](https://github.com/sybrenstuvel/python-rsa/) and is +licensed under the [Apache License, version 2.0](https://www.apache.org/licenses/LICENSE-2.0) + +## Security + +Because of how Python internally stores numbers, it is very hard (if not impossible) to make a pure-Python program secure against timing attacks. This library is no exception, so use it with care. See https://securitypitfalls.wordpress.com/2018/08/03/constant-time-compare-in-python/ for more info. + +## Setup of Development Environment + +``` +python3 -m venv .venv +. ./.venv/bin/activate +pip install poetry +poetry install +``` + +## Publishing a New Release + +``` +. ./.venv/bin/activate +poetry publish --build +``` diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/rsa/pyproject.toml b/arch-config/.config/calibre/plugins/DeACSM/modules/rsa/pyproject.toml new file mode 100644 index 00000000..c5b183bc --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/rsa/pyproject.toml @@ -0,0 +1,57 @@ +[tool.poetry] +name = "rsa" +version = "4.8" +license = "Apache-2.0" +description = "Pure-Python RSA implementation" +readme = "README.md" +authors = ["Sybren A. Stüvel <sybren@stuvel.eu>"] +homepage = "https://stuvel.eu/rsa" +classifiers = [ + "Development Status :: 5 - Production/Stable", + "Intended Audience :: Developers", + "Intended Audience :: Education", + "Intended Audience :: Information Technology", + "License :: OSI Approved :: Apache Software License", + "Operating System :: OS Independent", + "Programming Language :: Python", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.6", + "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: Implementation :: CPython", + "Programming Language :: Python :: Implementation :: PyPy", + "Topic :: Security :: Cryptography", +] +include = [ + "LICENSE", "README.md", "CHANGELOG.md", +] + +[tool.poetry.dependencies] +python = ">=3.6, <4" +pyasn1 = ">=0.1.3" + +[tool.poetry.dev-dependencies] +coveralls = "^3.0.0" +Sphinx = "^3.5.1" +pytest = "^6.2.2" +pytest-cov = "^2.11.1" +tox = "^3.22.0" +mypy = "^0.910" +flake8 = "^3.8.4" + +[build-system] +requires = ["poetry-core>=1.0.0"] +build-backend = "poetry.core.masonry.api" + +[tool.poetry.scripts] +"pyrsa-priv2pub" = "rsa.util:private_to_public" +"pyrsa-keygen" = "rsa.cli:keygen" +"pyrsa-encrypt" = "rsa.cli:encrypt" +"pyrsa-decrypt" = "rsa.cli:decrypt" +"pyrsa-sign" = "rsa.cli:sign" +"pyrsa-verify" = "rsa.cli:verify" + +[tool.black] +line-length = 100 diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/rsa/rsa/__init__.py b/arch-config/.config/calibre/plugins/DeACSM/modules/rsa/rsa/__init__.py new file mode 100644 index 00000000..57030234 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/rsa/rsa/__init__.py @@ -0,0 +1,60 @@ +# Copyright 2011 Sybren A. Stüvel <sybren@stuvel.eu> +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""RSA module + +Module for calculating large primes, and RSA encryption, decryption, signing +and verification. Includes generating public and private keys. + +WARNING: this implementation does not use compression of the cleartext input to +prevent repetitions, or other common security improvements. Use with care. + +""" + +from rsa.key import newkeys, PrivateKey, PublicKey +from rsa.pkcs1 import ( + encrypt, + decrypt, + sign, + verify, + DecryptionError, + VerificationError, + find_signature_hash, + sign_hash, + compute_hash, +) + +__author__ = "Sybren Stuvel, Barry Mead and Yesudeep Mangalapilly" +__date__ = "2021-11-24" +__version__ = "4.8" + +# Do doctest if we're run directly +if __name__ == "__main__": + import doctest + + doctest.testmod() + +__all__ = [ + "newkeys", + "encrypt", + "decrypt", + "sign", + "verify", + "PublicKey", + "PrivateKey", + "DecryptionError", + "VerificationError", + "find_signature_hash", + "compute_hash", + "sign_hash", +] diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/rsa/rsa/__pycache__/__init__.cpython-310.pyc b/arch-config/.config/calibre/plugins/DeACSM/modules/rsa/rsa/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 00000000..d51d3c84 Binary files /dev/null and b/arch-config/.config/calibre/plugins/DeACSM/modules/rsa/rsa/__pycache__/__init__.cpython-310.pyc differ diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/rsa/rsa/__pycache__/common.cpython-310.pyc b/arch-config/.config/calibre/plugins/DeACSM/modules/rsa/rsa/__pycache__/common.cpython-310.pyc new file mode 100644 index 00000000..3a9cad92 Binary files /dev/null and b/arch-config/.config/calibre/plugins/DeACSM/modules/rsa/rsa/__pycache__/common.cpython-310.pyc differ diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/rsa/rsa/__pycache__/core.cpython-310.pyc b/arch-config/.config/calibre/plugins/DeACSM/modules/rsa/rsa/__pycache__/core.cpython-310.pyc new file mode 100644 index 00000000..d2f7fbda Binary files /dev/null and b/arch-config/.config/calibre/plugins/DeACSM/modules/rsa/rsa/__pycache__/core.cpython-310.pyc differ diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/rsa/rsa/__pycache__/key.cpython-310.pyc b/arch-config/.config/calibre/plugins/DeACSM/modules/rsa/rsa/__pycache__/key.cpython-310.pyc new file mode 100644 index 00000000..bae2286a Binary files /dev/null and b/arch-config/.config/calibre/plugins/DeACSM/modules/rsa/rsa/__pycache__/key.cpython-310.pyc differ diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/rsa/rsa/__pycache__/pem.cpython-310.pyc b/arch-config/.config/calibre/plugins/DeACSM/modules/rsa/rsa/__pycache__/pem.cpython-310.pyc new file mode 100644 index 00000000..07091f39 Binary files /dev/null and b/arch-config/.config/calibre/plugins/DeACSM/modules/rsa/rsa/__pycache__/pem.cpython-310.pyc differ diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/rsa/rsa/__pycache__/pkcs1.cpython-310.pyc b/arch-config/.config/calibre/plugins/DeACSM/modules/rsa/rsa/__pycache__/pkcs1.cpython-310.pyc new file mode 100644 index 00000000..f01bd989 Binary files /dev/null and b/arch-config/.config/calibre/plugins/DeACSM/modules/rsa/rsa/__pycache__/pkcs1.cpython-310.pyc differ diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/rsa/rsa/__pycache__/prime.cpython-310.pyc b/arch-config/.config/calibre/plugins/DeACSM/modules/rsa/rsa/__pycache__/prime.cpython-310.pyc new file mode 100644 index 00000000..ea4ea29f Binary files /dev/null and b/arch-config/.config/calibre/plugins/DeACSM/modules/rsa/rsa/__pycache__/prime.cpython-310.pyc differ diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/rsa/rsa/__pycache__/randnum.cpython-310.pyc b/arch-config/.config/calibre/plugins/DeACSM/modules/rsa/rsa/__pycache__/randnum.cpython-310.pyc new file mode 100644 index 00000000..942b7399 Binary files /dev/null and b/arch-config/.config/calibre/plugins/DeACSM/modules/rsa/rsa/__pycache__/randnum.cpython-310.pyc differ diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/rsa/rsa/__pycache__/transform.cpython-310.pyc b/arch-config/.config/calibre/plugins/DeACSM/modules/rsa/rsa/__pycache__/transform.cpython-310.pyc new file mode 100644 index 00000000..c3f425de Binary files /dev/null and b/arch-config/.config/calibre/plugins/DeACSM/modules/rsa/rsa/__pycache__/transform.cpython-310.pyc differ diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/rsa/rsa/_compat.py b/arch-config/.config/calibre/plugins/DeACSM/modules/rsa/rsa/_compat.py new file mode 100644 index 00000000..050e81b9 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/rsa/rsa/_compat.py @@ -0,0 +1,48 @@ +# Copyright 2011 Sybren A. Stüvel <sybren@stuvel.eu> +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Python compatibility wrappers.""" + +from struct import pack + + +def byte(num: int) -> bytes: + """ + Converts a number between 0 and 255 (both inclusive) to a base-256 (byte) + representation. + + :param num: + An unsigned integer between 0 and 255 (both inclusive). + :returns: + A single byte. + """ + return pack("B", num) + + +def xor_bytes(b1: bytes, b2: bytes) -> bytes: + """ + Returns the bitwise XOR result between two bytes objects, b1 ^ b2. + + Bitwise XOR operation is commutative, so order of parameters doesn't + generate different results. If parameters have different length, extra + length of the largest one is ignored. + + :param b1: + First bytes object. + :param b2: + Second bytes object. + :returns: + Bytes object, result of XOR operation. + """ + return bytes(x ^ y for x, y in zip(b1, b2)) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/rsa/rsa/asn1.py b/arch-config/.config/calibre/plugins/DeACSM/modules/rsa/rsa/asn1.py new file mode 100644 index 00000000..4cc4dd35 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/rsa/rsa/asn1.py @@ -0,0 +1,52 @@ +# Copyright 2011 Sybren A. Stüvel <sybren@stuvel.eu> +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""ASN.1 definitions. + +Not all ASN.1-handling code use these definitions, but when it does, they should be here. +""" + +from pyasn1.type import univ, namedtype, tag + + +class PubKeyHeader(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType("oid", univ.ObjectIdentifier()), + namedtype.NamedType("parameters", univ.Null()), + ) + + +class OpenSSLPubKey(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType("header", PubKeyHeader()), + # This little hack (the implicit tag) allows us to get a Bit String as Octet String + namedtype.NamedType( + "key", + univ.OctetString().subtype(implicitTag=tag.Tag(tagClass=0, tagFormat=0, tagId=3)), + ), + ) + + +class AsnPubKey(univ.Sequence): + """ASN.1 contents of DER encoded public key: + + RSAPublicKey ::= SEQUENCE { + modulus INTEGER, -- n + publicExponent INTEGER, -- e + """ + + componentType = namedtype.NamedTypes( + namedtype.NamedType("modulus", univ.Integer()), + namedtype.NamedType("publicExponent", univ.Integer()), + ) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/rsa/rsa/cli.py b/arch-config/.config/calibre/plugins/DeACSM/modules/rsa/rsa/cli.py new file mode 100644 index 00000000..4db3f0b5 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/rsa/rsa/cli.py @@ -0,0 +1,321 @@ +# Copyright 2011 Sybren A. Stüvel <sybren@stuvel.eu> +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Commandline scripts. + +These scripts are called by the executables defined in setup.py. +""" + +import abc +import sys +import typing +import optparse + +import rsa +import rsa.key +import rsa.pkcs1 + +HASH_METHODS = sorted(rsa.pkcs1.HASH_METHODS.keys()) +Indexable = typing.Union[typing.Tuple, typing.List[str]] + + +def keygen() -> None: + """Key generator.""" + + # Parse the CLI options + parser = optparse.OptionParser( + usage="usage: %prog [options] keysize", + description='Generates a new RSA key pair of "keysize" bits.', + ) + + parser.add_option( + "--pubout", + type="string", + help="Output filename for the public key. The public key is " + "not saved if this option is not present. You can use " + "pyrsa-priv2pub to create the public key file later.", + ) + + parser.add_option( + "-o", + "--out", + type="string", + help="Output filename for the private key. The key is " + "written to stdout if this option is not present.", + ) + + parser.add_option( + "--form", + help="key format of the private and public keys - default PEM", + choices=("PEM", "DER"), + default="PEM", + ) + + (cli, cli_args) = parser.parse_args(sys.argv[1:]) + + if len(cli_args) != 1: + parser.print_help() + raise SystemExit(1) + + try: + keysize = int(cli_args[0]) + except ValueError as ex: + parser.print_help() + print("Not a valid number: %s" % cli_args[0], file=sys.stderr) + raise SystemExit(1) from ex + + print("Generating %i-bit key" % keysize, file=sys.stderr) + (pub_key, priv_key) = rsa.newkeys(keysize) + + # Save public key + if cli.pubout: + print("Writing public key to %s" % cli.pubout, file=sys.stderr) + data = pub_key.save_pkcs1(format=cli.form) + with open(cli.pubout, "wb") as outfile: + outfile.write(data) + + # Save private key + data = priv_key.save_pkcs1(format=cli.form) + + if cli.out: + print("Writing private key to %s" % cli.out, file=sys.stderr) + with open(cli.out, "wb") as outfile: + outfile.write(data) + else: + print("Writing private key to stdout", file=sys.stderr) + sys.stdout.buffer.write(data) + + +class CryptoOperation(metaclass=abc.ABCMeta): + """CLI callable that operates with input, output, and a key.""" + + keyname = "public" # or 'private' + usage = "usage: %%prog [options] %(keyname)s_key" + description = "" + operation = "decrypt" + operation_past = "decrypted" + operation_progressive = "decrypting" + input_help = "Name of the file to %(operation)s. Reads from stdin if " "not specified." + output_help = ( + "Name of the file to write the %(operation_past)s file " + "to. Written to stdout if this option is not present." + ) + expected_cli_args = 1 + has_output = True + + key_class = rsa.PublicKey # type: typing.Type[rsa.key.AbstractKey] + + def __init__(self) -> None: + self.usage = self.usage % self.__class__.__dict__ + self.input_help = self.input_help % self.__class__.__dict__ + self.output_help = self.output_help % self.__class__.__dict__ + + @abc.abstractmethod + def perform_operation( + self, indata: bytes, key: rsa.key.AbstractKey, cli_args: Indexable + ) -> typing.Any: + """Performs the program's operation. + + Implement in a subclass. + + :returns: the data to write to the output. + """ + + def __call__(self) -> None: + """Runs the program.""" + + (cli, cli_args) = self.parse_cli() + + key = self.read_key(cli_args[0], cli.keyform) + + indata = self.read_infile(cli.input) + + print(self.operation_progressive.title(), file=sys.stderr) + outdata = self.perform_operation(indata, key, cli_args) + + if self.has_output: + self.write_outfile(outdata, cli.output) + + def parse_cli(self) -> typing.Tuple[optparse.Values, typing.List[str]]: + """Parse the CLI options + + :returns: (cli_opts, cli_args) + """ + + parser = optparse.OptionParser(usage=self.usage, description=self.description) + + parser.add_option("-i", "--input", type="string", help=self.input_help) + + if self.has_output: + parser.add_option("-o", "--output", type="string", help=self.output_help) + + parser.add_option( + "--keyform", + help="Key format of the %s key - default PEM" % self.keyname, + choices=("PEM", "DER"), + default="PEM", + ) + + (cli, cli_args) = parser.parse_args(sys.argv[1:]) + + if len(cli_args) != self.expected_cli_args: + parser.print_help() + raise SystemExit(1) + + return cli, cli_args + + def read_key(self, filename: str, keyform: str) -> rsa.key.AbstractKey: + """Reads a public or private key.""" + + print("Reading %s key from %s" % (self.keyname, filename), file=sys.stderr) + with open(filename, "rb") as keyfile: + keydata = keyfile.read() + + return self.key_class.load_pkcs1(keydata, keyform) + + def read_infile(self, inname: str) -> bytes: + """Read the input file""" + + if inname: + print("Reading input from %s" % inname, file=sys.stderr) + with open(inname, "rb") as infile: + return infile.read() + + print("Reading input from stdin", file=sys.stderr) + return sys.stdin.buffer.read() + + def write_outfile(self, outdata: bytes, outname: str) -> None: + """Write the output file""" + + if outname: + print("Writing output to %s" % outname, file=sys.stderr) + with open(outname, "wb") as outfile: + outfile.write(outdata) + else: + print("Writing output to stdout", file=sys.stderr) + sys.stdout.buffer.write(outdata) + + +class EncryptOperation(CryptoOperation): + """Encrypts a file.""" + + keyname = "public" + description = ( + "Encrypts a file. The file must be shorter than the key " "length in order to be encrypted." + ) + operation = "encrypt" + operation_past = "encrypted" + operation_progressive = "encrypting" + + def perform_operation( + self, indata: bytes, pub_key: rsa.key.AbstractKey, cli_args: Indexable = () + ) -> bytes: + """Encrypts files.""" + assert isinstance(pub_key, rsa.key.PublicKey) + return rsa.encrypt(indata, pub_key) + + +class DecryptOperation(CryptoOperation): + """Decrypts a file.""" + + keyname = "private" + description = ( + "Decrypts a file. The original file must be shorter than " + "the key length in order to have been encrypted." + ) + operation = "decrypt" + operation_past = "decrypted" + operation_progressive = "decrypting" + key_class = rsa.PrivateKey + + def perform_operation( + self, indata: bytes, priv_key: rsa.key.AbstractKey, cli_args: Indexable = () + ) -> bytes: + """Decrypts files.""" + assert isinstance(priv_key, rsa.key.PrivateKey) + return rsa.decrypt(indata, priv_key) + + +class SignOperation(CryptoOperation): + """Signs a file.""" + + keyname = "private" + usage = "usage: %%prog [options] private_key hash_method" + description = ( + "Signs a file, outputs the signature. Choose the hash " + "method from %s" % ", ".join(HASH_METHODS) + ) + operation = "sign" + operation_past = "signature" + operation_progressive = "Signing" + key_class = rsa.PrivateKey + expected_cli_args = 2 + + output_help = ( + "Name of the file to write the signature to. Written " + "to stdout if this option is not present." + ) + + def perform_operation( + self, indata: bytes, priv_key: rsa.key.AbstractKey, cli_args: Indexable + ) -> bytes: + """Signs files.""" + assert isinstance(priv_key, rsa.key.PrivateKey) + + hash_method = cli_args[1] + if hash_method not in HASH_METHODS: + raise SystemExit("Invalid hash method, choose one of %s" % ", ".join(HASH_METHODS)) + + return rsa.sign(indata, priv_key, hash_method) + + +class VerifyOperation(CryptoOperation): + """Verify a signature.""" + + keyname = "public" + usage = "usage: %%prog [options] public_key signature_file" + description = ( + "Verifies a signature, exits with status 0 upon success, " + "prints an error message and exits with status 1 upon error." + ) + operation = "verify" + operation_past = "verified" + operation_progressive = "Verifying" + key_class = rsa.PublicKey + expected_cli_args = 2 + has_output = False + + def perform_operation( + self, indata: bytes, pub_key: rsa.key.AbstractKey, cli_args: Indexable + ) -> None: + """Verifies files.""" + assert isinstance(pub_key, rsa.key.PublicKey) + + signature_file = cli_args[1] + + with open(signature_file, "rb") as sigfile: + signature = sigfile.read() + + try: + rsa.verify(indata, signature, pub_key) + except rsa.VerificationError as ex: + raise SystemExit("Verification failed.") from ex + + print("Verification OK", file=sys.stderr) + + +encrypt = EncryptOperation() +decrypt = DecryptOperation() +sign = SignOperation() +verify = VerifyOperation() diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/rsa/rsa/common.py b/arch-config/.config/calibre/plugins/DeACSM/modules/rsa/rsa/common.py new file mode 100644 index 00000000..ca732e58 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/rsa/rsa/common.py @@ -0,0 +1,184 @@ +# Copyright 2011 Sybren A. Stüvel <sybren@stuvel.eu> +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Common functionality shared by several modules.""" + +import typing + + +class NotRelativePrimeError(ValueError): + def __init__(self, a: int, b: int, d: int, msg: str = "") -> None: + super().__init__(msg or "%d and %d are not relatively prime, divider=%i" % (a, b, d)) + self.a = a + self.b = b + self.d = d + + +def bit_size(num: int) -> int: + """ + Number of bits needed to represent a integer excluding any prefix + 0 bits. + + Usage:: + + >>> bit_size(1023) + 10 + >>> bit_size(1024) + 11 + >>> bit_size(1025) + 11 + + :param num: + Integer value. If num is 0, returns 0. Only the absolute value of the + number is considered. Therefore, signed integers will be abs(num) + before the number's bit length is determined. + :returns: + Returns the number of bits in the integer. + """ + + try: + return num.bit_length() + except AttributeError as ex: + raise TypeError("bit_size(num) only supports integers, not %r" % type(num)) from ex + + +def byte_size(number: int) -> int: + """ + Returns the number of bytes required to hold a specific long number. + + The number of bytes is rounded up. + + Usage:: + + >>> byte_size(1 << 1023) + 128 + >>> byte_size((1 << 1024) - 1) + 128 + >>> byte_size(1 << 1024) + 129 + + :param number: + An unsigned integer + :returns: + The number of bytes required to hold a specific long number. + """ + if number == 0: + return 1 + return ceil_div(bit_size(number), 8) + + +def ceil_div(num: int, div: int) -> int: + """ + Returns the ceiling function of a division between `num` and `div`. + + Usage:: + + >>> ceil_div(100, 7) + 15 + >>> ceil_div(100, 10) + 10 + >>> ceil_div(1, 4) + 1 + + :param num: Division's numerator, a number + :param div: Division's divisor, a number + + :return: Rounded up result of the division between the parameters. + """ + quanta, mod = divmod(num, div) + if mod: + quanta += 1 + return quanta + + +def extended_gcd(a: int, b: int) -> typing.Tuple[int, int, int]: + """Returns a tuple (r, i, j) such that r = gcd(a, b) = ia + jb""" + # r = gcd(a,b) i = multiplicitive inverse of a mod b + # or j = multiplicitive inverse of b mod a + # Neg return values for i or j are made positive mod b or a respectively + # Iterateive Version is faster and uses much less stack space + x = 0 + y = 1 + lx = 1 + ly = 0 + oa = a # Remember original a/b to remove + ob = b # negative values from return results + while b != 0: + q = a // b + (a, b) = (b, a % b) + (x, lx) = ((lx - (q * x)), x) + (y, ly) = ((ly - (q * y)), y) + if lx < 0: + lx += ob # If neg wrap modulo original b + if ly < 0: + ly += oa # If neg wrap modulo original a + return a, lx, ly # Return only positive values + + +def inverse(x: int, n: int) -> int: + """Returns the inverse of x % n under multiplication, a.k.a x^-1 (mod n) + + >>> inverse(7, 4) + 3 + >>> (inverse(143, 4) * 143) % 4 + 1 + """ + + (divider, inv, _) = extended_gcd(x, n) + + if divider != 1: + raise NotRelativePrimeError(x, n, divider) + + return inv + + +def crt(a_values: typing.Iterable[int], modulo_values: typing.Iterable[int]) -> int: + """Chinese Remainder Theorem. + + Calculates x such that x = a[i] (mod m[i]) for each i. + + :param a_values: the a-values of the above equation + :param modulo_values: the m-values of the above equation + :returns: x such that x = a[i] (mod m[i]) for each i + + + >>> crt([2, 3], [3, 5]) + 8 + + >>> crt([2, 3, 2], [3, 5, 7]) + 23 + + >>> crt([2, 3, 0], [7, 11, 15]) + 135 + """ + + m = 1 + x = 0 + + for modulo in modulo_values: + m *= modulo + + for (m_i, a_i) in zip(modulo_values, a_values): + M_i = m // m_i + inv = inverse(M_i, m_i) + + x = (x + a_i * M_i * inv) % m + + return x + + +if __name__ == "__main__": + import doctest + + doctest.testmod() diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/rsa/rsa/core.py b/arch-config/.config/calibre/plugins/DeACSM/modules/rsa/rsa/core.py new file mode 100644 index 00000000..84ed3f88 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/rsa/rsa/core.py @@ -0,0 +1,53 @@ +# Copyright 2011 Sybren A. Stüvel <sybren@stuvel.eu> +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Core mathematical operations. + +This is the actual core RSA implementation, which is only defined +mathematically on integers. +""" + + +def assert_int(var: int, name: str) -> None: + if isinstance(var, int): + return + + raise TypeError("%s should be an integer, not %s" % (name, var.__class__)) + + +def encrypt_int(message: int, ekey: int, n: int) -> int: + """Encrypts a message using encryption key 'ekey', working modulo n""" + + assert_int(message, "message") + assert_int(ekey, "ekey") + assert_int(n, "n") + + if message < 0: + raise ValueError("Only non-negative numbers are supported") + + if message > n: + raise OverflowError("The message %i is too long for n=%i" % (message, n)) + + return pow(message, ekey, n) + + +def decrypt_int(cyphertext: int, dkey: int, n: int) -> int: + """Decrypts a cypher text using the decryption key 'dkey', working modulo n""" + + assert_int(cyphertext, "cyphertext") + assert_int(dkey, "dkey") + assert_int(n, "n") + + message = pow(cyphertext, dkey, n) + return message diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/rsa/rsa/key.py b/arch-config/.config/calibre/plugins/DeACSM/modules/rsa/rsa/key.py new file mode 100644 index 00000000..1284ffc3 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/rsa/rsa/key.py @@ -0,0 +1,859 @@ +# Copyright 2011 Sybren A. Stüvel <sybren@stuvel.eu> +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""RSA key generation code. + +Create new keys with the newkeys() function. It will give you a PublicKey and a +PrivateKey object. + +Loading and saving keys requires the pyasn1 module. This module is imported as +late as possible, such that other functionality will remain working in absence +of pyasn1. + +.. note:: + + Storing public and private keys via the `pickle` module is possible. + However, it is insecure to load a key from an untrusted source. + The pickle module is not secure against erroneous or maliciously + constructed data. Never unpickle data received from an untrusted + or unauthenticated source. + +""" + +import logging +import threading +import typing +import warnings + +import rsa.prime +import rsa.pem +import rsa.common +import rsa.randnum +import rsa.core + + +log = logging.getLogger(__name__) +DEFAULT_EXPONENT = 65537 + + +class AbstractKey: + """Abstract superclass for private and public keys.""" + + __slots__ = ("n", "e", "blindfac", "blindfac_inverse", "mutex") + + def __init__(self, n: int, e: int) -> None: + self.n = n + self.e = e + + # These will be computed properly on the first call to blind(). + self.blindfac = self.blindfac_inverse = -1 + + # Used to protect updates to the blinding factor in multi-threaded + # environments. + self.mutex = threading.Lock() + + @classmethod + def _load_pkcs1_pem(cls, keyfile: bytes) -> "AbstractKey": + """Loads a key in PKCS#1 PEM format, implement in a subclass. + + :param keyfile: contents of a PEM-encoded file that contains + the public key. + :type keyfile: bytes + + :return: the loaded key + :rtype: AbstractKey + """ + + @classmethod + def _load_pkcs1_der(cls, keyfile: bytes) -> "AbstractKey": + """Loads a key in PKCS#1 PEM format, implement in a subclass. + + :param keyfile: contents of a DER-encoded file that contains + the public key. + :type keyfile: bytes + + :return: the loaded key + :rtype: AbstractKey + """ + + def _save_pkcs1_pem(self) -> bytes: + """Saves the key in PKCS#1 PEM format, implement in a subclass. + + :returns: the PEM-encoded key. + :rtype: bytes + """ + + def _save_pkcs1_der(self) -> bytes: + """Saves the key in PKCS#1 DER format, implement in a subclass. + + :returns: the DER-encoded key. + :rtype: bytes + """ + + @classmethod + def load_pkcs1(cls, keyfile: bytes, format: str = "PEM") -> "AbstractKey": + """Loads a key in PKCS#1 DER or PEM format. + + :param keyfile: contents of a DER- or PEM-encoded file that contains + the key. + :type keyfile: bytes + :param format: the format of the file to load; 'PEM' or 'DER' + :type format: str + + :return: the loaded key + :rtype: AbstractKey + """ + + methods = { + "PEM": cls._load_pkcs1_pem, + "DER": cls._load_pkcs1_der, + } + + method = cls._assert_format_exists(format, methods) + return method(keyfile) + + @staticmethod + def _assert_format_exists( + file_format: str, methods: typing.Mapping[str, typing.Callable] + ) -> typing.Callable: + """Checks whether the given file format exists in 'methods'.""" + + try: + return methods[file_format] + except KeyError as ex: + formats = ", ".join(sorted(methods.keys())) + raise ValueError( + "Unsupported format: %r, try one of %s" % (file_format, formats) + ) from ex + + def save_pkcs1(self, format: str = "PEM") -> bytes: + """Saves the key in PKCS#1 DER or PEM format. + + :param format: the format to save; 'PEM' or 'DER' + :type format: str + :returns: the DER- or PEM-encoded key. + :rtype: bytes + """ + + methods = { + "PEM": self._save_pkcs1_pem, + "DER": self._save_pkcs1_der, + } + + method = self._assert_format_exists(format, methods) + return method() + + def blind(self, message: int) -> typing.Tuple[int, int]: + """Performs blinding on the message. + + :param message: the message, as integer, to blind. + :param r: the random number to blind with. + :return: tuple (the blinded message, the inverse of the used blinding factor) + + The blinding is such that message = unblind(decrypt(blind(encrypt(message))). + + See https://en.wikipedia.org/wiki/Blinding_%28cryptography%29 + """ + blindfac, blindfac_inverse = self._update_blinding_factor() + blinded = (message * pow(blindfac, self.e, self.n)) % self.n + return blinded, blindfac_inverse + + def unblind(self, blinded: int, blindfac_inverse: int) -> int: + """Performs blinding on the message using random number 'blindfac_inverse'. + + :param blinded: the blinded message, as integer, to unblind. + :param blindfac: the factor to unblind with. + :return: the original message. + + The blinding is such that message = unblind(decrypt(blind(encrypt(message))). + + See https://en.wikipedia.org/wiki/Blinding_%28cryptography%29 + """ + return (blindfac_inverse * blinded) % self.n + + def _initial_blinding_factor(self) -> int: + for _ in range(1000): + blind_r = rsa.randnum.randint(self.n - 1) + if rsa.prime.are_relatively_prime(self.n, blind_r): + return blind_r + raise RuntimeError("unable to find blinding factor") + + def _update_blinding_factor(self) -> typing.Tuple[int, int]: + """Update blinding factors. + + Computing a blinding factor is expensive, so instead this function + does this once, then updates the blinding factor as per section 9 + of 'A Timing Attack against RSA with the Chinese Remainder Theorem' + by Werner Schindler. + See https://tls.mbed.org/public/WSchindler-RSA_Timing_Attack.pdf + + :return: the new blinding factor and its inverse. + """ + + with self.mutex: + if self.blindfac < 0: + # Compute initial blinding factor, which is rather slow to do. + self.blindfac = self._initial_blinding_factor() + self.blindfac_inverse = rsa.common.inverse(self.blindfac, self.n) + else: + # Reuse previous blinding factor. + self.blindfac = pow(self.blindfac, 2, self.n) + self.blindfac_inverse = pow(self.blindfac_inverse, 2, self.n) + + return self.blindfac, self.blindfac_inverse + + +class PublicKey(AbstractKey): + """Represents a public RSA key. + + This key is also known as the 'encryption key'. It contains the 'n' and 'e' + values. + + Supports attributes as well as dictionary-like access. Attribute access is + faster, though. + + >>> PublicKey(5, 3) + PublicKey(5, 3) + + >>> key = PublicKey(5, 3) + >>> key.n + 5 + >>> key['n'] + 5 + >>> key.e + 3 + >>> key['e'] + 3 + + """ + + __slots__ = ("n", "e") + + def __getitem__(self, key: str) -> int: + return getattr(self, key) + + def __repr__(self) -> str: + return "PublicKey(%i, %i)" % (self.n, self.e) + + def __getstate__(self) -> typing.Tuple[int, int]: + """Returns the key as tuple for pickling.""" + return self.n, self.e + + def __setstate__(self, state: typing.Tuple[int, int]) -> None: + """Sets the key from tuple.""" + self.n, self.e = state + AbstractKey.__init__(self, self.n, self.e) + + def __eq__(self, other: typing.Any) -> bool: + if other is None: + return False + + if not isinstance(other, PublicKey): + return False + + return self.n == other.n and self.e == other.e + + def __ne__(self, other: typing.Any) -> bool: + return not (self == other) + + def __hash__(self) -> int: + return hash((self.n, self.e)) + + @classmethod + def _load_pkcs1_der(cls, keyfile: bytes) -> "PublicKey": + """Loads a key in PKCS#1 DER format. + + :param keyfile: contents of a DER-encoded file that contains the public + key. + :return: a PublicKey object + + First let's construct a DER encoded key: + + >>> import base64 + >>> b64der = 'MAwCBQCNGmYtAgMBAAE=' + >>> der = base64.standard_b64decode(b64der) + + This loads the file: + + >>> PublicKey._load_pkcs1_der(der) + PublicKey(2367317549, 65537) + + """ + + from pyasn1.codec.der import decoder + from rsa.asn1 import AsnPubKey + + (priv, _) = decoder.decode(keyfile, asn1Spec=AsnPubKey()) + return cls(n=int(priv["modulus"]), e=int(priv["publicExponent"])) + + def _save_pkcs1_der(self) -> bytes: + """Saves the public key in PKCS#1 DER format. + + :returns: the DER-encoded public key. + :rtype: bytes + """ + + from pyasn1.codec.der import encoder + from rsa.asn1 import AsnPubKey + + # Create the ASN object + asn_key = AsnPubKey() + asn_key.setComponentByName("modulus", self.n) + asn_key.setComponentByName("publicExponent", self.e) + + return encoder.encode(asn_key) + + @classmethod + def _load_pkcs1_pem(cls, keyfile: bytes) -> "PublicKey": + """Loads a PKCS#1 PEM-encoded public key file. + + The contents of the file before the "-----BEGIN RSA PUBLIC KEY-----" and + after the "-----END RSA PUBLIC KEY-----" lines is ignored. + + :param keyfile: contents of a PEM-encoded file that contains the public + key. + :return: a PublicKey object + """ + + der = rsa.pem.load_pem(keyfile, "RSA PUBLIC KEY") + return cls._load_pkcs1_der(der) + + def _save_pkcs1_pem(self) -> bytes: + """Saves a PKCS#1 PEM-encoded public key file. + + :return: contents of a PEM-encoded file that contains the public key. + :rtype: bytes + """ + + der = self._save_pkcs1_der() + return rsa.pem.save_pem(der, "RSA PUBLIC KEY") + + @classmethod + def load_pkcs1_openssl_pem(cls, keyfile: bytes) -> "PublicKey": + """Loads a PKCS#1.5 PEM-encoded public key file from OpenSSL. + + These files can be recognised in that they start with BEGIN PUBLIC KEY + rather than BEGIN RSA PUBLIC KEY. + + The contents of the file before the "-----BEGIN PUBLIC KEY-----" and + after the "-----END PUBLIC KEY-----" lines is ignored. + + :param keyfile: contents of a PEM-encoded file that contains the public + key, from OpenSSL. + :type keyfile: bytes + :return: a PublicKey object + """ + + der = rsa.pem.load_pem(keyfile, "PUBLIC KEY") + return cls.load_pkcs1_openssl_der(der) + + @classmethod + def load_pkcs1_openssl_der(cls, keyfile: bytes) -> "PublicKey": + """Loads a PKCS#1 DER-encoded public key file from OpenSSL. + + :param keyfile: contents of a DER-encoded file that contains the public + key, from OpenSSL. + :return: a PublicKey object + """ + + from rsa.asn1 import OpenSSLPubKey + from pyasn1.codec.der import decoder + from pyasn1.type import univ + + (keyinfo, _) = decoder.decode(keyfile, asn1Spec=OpenSSLPubKey()) + + if keyinfo["header"]["oid"] != univ.ObjectIdentifier("1.2.840.113549.1.1.1"): + raise TypeError("This is not a DER-encoded OpenSSL-compatible public key") + + return cls._load_pkcs1_der(keyinfo["key"][1:]) + + +class PrivateKey(AbstractKey): + """Represents a private RSA key. + + This key is also known as the 'decryption key'. It contains the 'n', 'e', + 'd', 'p', 'q' and other values. + + Supports attributes as well as dictionary-like access. Attribute access is + faster, though. + + >>> PrivateKey(3247, 65537, 833, 191, 17) + PrivateKey(3247, 65537, 833, 191, 17) + + exp1, exp2 and coef will be calculated: + + >>> pk = PrivateKey(3727264081, 65537, 3349121513, 65063, 57287) + >>> pk.exp1 + 55063 + >>> pk.exp2 + 10095 + >>> pk.coef + 50797 + + """ + + __slots__ = ("n", "e", "d", "p", "q", "exp1", "exp2", "coef") + + def __init__(self, n: int, e: int, d: int, p: int, q: int) -> None: + AbstractKey.__init__(self, n, e) + self.d = d + self.p = p + self.q = q + + # Calculate exponents and coefficient. + self.exp1 = int(d % (p - 1)) + self.exp2 = int(d % (q - 1)) + self.coef = rsa.common.inverse(q, p) + + def __getitem__(self, key: str) -> int: + return getattr(self, key) + + def __repr__(self) -> str: + return "PrivateKey(%i, %i, %i, %i, %i)" % ( + self.n, + self.e, + self.d, + self.p, + self.q, + ) + + def __getstate__(self) -> typing.Tuple[int, int, int, int, int, int, int, int]: + """Returns the key as tuple for pickling.""" + return self.n, self.e, self.d, self.p, self.q, self.exp1, self.exp2, self.coef + + def __setstate__(self, state: typing.Tuple[int, int, int, int, int, int, int, int]) -> None: + """Sets the key from tuple.""" + self.n, self.e, self.d, self.p, self.q, self.exp1, self.exp2, self.coef = state + AbstractKey.__init__(self, self.n, self.e) + + def __eq__(self, other: typing.Any) -> bool: + if other is None: + return False + + if not isinstance(other, PrivateKey): + return False + + return ( + self.n == other.n + and self.e == other.e + and self.d == other.d + and self.p == other.p + and self.q == other.q + and self.exp1 == other.exp1 + and self.exp2 == other.exp2 + and self.coef == other.coef + ) + + def __ne__(self, other: typing.Any) -> bool: + return not (self == other) + + def __hash__(self) -> int: + return hash((self.n, self.e, self.d, self.p, self.q, self.exp1, self.exp2, self.coef)) + + def blinded_decrypt(self, encrypted: int) -> int: + """Decrypts the message using blinding to prevent side-channel attacks. + + :param encrypted: the encrypted message + :type encrypted: int + + :returns: the decrypted message + :rtype: int + """ + + # Blinding and un-blinding should be using the same factor + blinded, blindfac_inverse = self.blind(encrypted) + + # Instead of using the core functionality, use the Chinese Remainder + # Theorem and be 2-4x faster. This the same as: + # + # decrypted = rsa.core.decrypt_int(blinded, self.d, self.n) + s1 = pow(blinded, self.exp1, self.p) + s2 = pow(blinded, self.exp2, self.q) + h = ((s1 - s2) * self.coef) % self.p + decrypted = s2 + self.q * h + + return self.unblind(decrypted, blindfac_inverse) + + def blinded_encrypt(self, message: int) -> int: + """Encrypts the message using blinding to prevent side-channel attacks. + + :param message: the message to encrypt + :type message: int + + :returns: the encrypted message + :rtype: int + """ + + blinded, blindfac_inverse = self.blind(message) + encrypted = rsa.core.encrypt_int(blinded, self.d, self.n) + return self.unblind(encrypted, blindfac_inverse) + + @classmethod + def _load_pkcs1_der(cls, keyfile: bytes) -> "PrivateKey": + """Loads a key in PKCS#1 DER format. + + :param keyfile: contents of a DER-encoded file that contains the private + key. + :type keyfile: bytes + :return: a PrivateKey object + + First let's construct a DER encoded key: + + >>> import base64 + >>> b64der = 'MC4CAQACBQDeKYlRAgMBAAECBQDHn4npAgMA/icCAwDfxwIDANcXAgInbwIDAMZt' + >>> der = base64.standard_b64decode(b64der) + + This loads the file: + + >>> PrivateKey._load_pkcs1_der(der) + PrivateKey(3727264081, 65537, 3349121513, 65063, 57287) + + """ + + from pyasn1.codec.der import decoder + + (priv, _) = decoder.decode(keyfile) + + # ASN.1 contents of DER encoded private key: + # + # RSAPrivateKey ::= SEQUENCE { + # version Version, + # modulus INTEGER, -- n + # publicExponent INTEGER, -- e + # privateExponent INTEGER, -- d + # prime1 INTEGER, -- p + # prime2 INTEGER, -- q + # exponent1 INTEGER, -- d mod (p-1) + # exponent2 INTEGER, -- d mod (q-1) + # coefficient INTEGER, -- (inverse of q) mod p + # otherPrimeInfos OtherPrimeInfos OPTIONAL + # } + + if priv[0] != 0: + raise ValueError("Unable to read this file, version %s != 0" % priv[0]) + + as_ints = map(int, priv[1:6]) + key = cls(*as_ints) + + exp1, exp2, coef = map(int, priv[6:9]) + + if (key.exp1, key.exp2, key.coef) != (exp1, exp2, coef): + warnings.warn( + "You have provided a malformed keyfile. Either the exponents " + "or the coefficient are incorrect. Using the correct values " + "instead.", + UserWarning, + ) + + return key + + def _save_pkcs1_der(self) -> bytes: + """Saves the private key in PKCS#1 DER format. + + :returns: the DER-encoded private key. + :rtype: bytes + """ + + from pyasn1.type import univ, namedtype + from pyasn1.codec.der import encoder + + class AsnPrivKey(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType("version", univ.Integer()), + namedtype.NamedType("modulus", univ.Integer()), + namedtype.NamedType("publicExponent", univ.Integer()), + namedtype.NamedType("privateExponent", univ.Integer()), + namedtype.NamedType("prime1", univ.Integer()), + namedtype.NamedType("prime2", univ.Integer()), + namedtype.NamedType("exponent1", univ.Integer()), + namedtype.NamedType("exponent2", univ.Integer()), + namedtype.NamedType("coefficient", univ.Integer()), + ) + + # Create the ASN object + asn_key = AsnPrivKey() + asn_key.setComponentByName("version", 0) + asn_key.setComponentByName("modulus", self.n) + asn_key.setComponentByName("publicExponent", self.e) + asn_key.setComponentByName("privateExponent", self.d) + asn_key.setComponentByName("prime1", self.p) + asn_key.setComponentByName("prime2", self.q) + asn_key.setComponentByName("exponent1", self.exp1) + asn_key.setComponentByName("exponent2", self.exp2) + asn_key.setComponentByName("coefficient", self.coef) + + return encoder.encode(asn_key) + + @classmethod + def _load_pkcs1_pem(cls, keyfile: bytes) -> "PrivateKey": + """Loads a PKCS#1 PEM-encoded private key file. + + The contents of the file before the "-----BEGIN RSA PRIVATE KEY-----" and + after the "-----END RSA PRIVATE KEY-----" lines is ignored. + + :param keyfile: contents of a PEM-encoded file that contains the private + key. + :type keyfile: bytes + :return: a PrivateKey object + """ + + der = rsa.pem.load_pem(keyfile, b"RSA PRIVATE KEY") + return cls._load_pkcs1_der(der) + + def _save_pkcs1_pem(self) -> bytes: + """Saves a PKCS#1 PEM-encoded private key file. + + :return: contents of a PEM-encoded file that contains the private key. + :rtype: bytes + """ + + der = self._save_pkcs1_der() + return rsa.pem.save_pem(der, b"RSA PRIVATE KEY") + + +def find_p_q( + nbits: int, + getprime_func: typing.Callable[[int], int] = rsa.prime.getprime, + accurate: bool = True, +) -> typing.Tuple[int, int]: + """Returns a tuple of two different primes of nbits bits each. + + The resulting p * q has exactly 2 * nbits bits, and the returned p and q + will not be equal. + + :param nbits: the number of bits in each of p and q. + :param getprime_func: the getprime function, defaults to + :py:func:`rsa.prime.getprime`. + + *Introduced in Python-RSA 3.1* + + :param accurate: whether to enable accurate mode or not. + :returns: (p, q), where p > q + + >>> (p, q) = find_p_q(128) + >>> from rsa import common + >>> common.bit_size(p * q) + 256 + + When not in accurate mode, the number of bits can be slightly less + + >>> (p, q) = find_p_q(128, accurate=False) + >>> from rsa import common + >>> common.bit_size(p * q) <= 256 + True + >>> common.bit_size(p * q) > 240 + True + + """ + + total_bits = nbits * 2 + + # Make sure that p and q aren't too close or the factoring programs can + # factor n. + shift = nbits // 16 + pbits = nbits + shift + qbits = nbits - shift + + # Choose the two initial primes + log.debug("find_p_q(%i): Finding p", nbits) + p = getprime_func(pbits) + log.debug("find_p_q(%i): Finding q", nbits) + q = getprime_func(qbits) + + def is_acceptable(p: int, q: int) -> bool: + """Returns True iff p and q are acceptable: + + - p and q differ + - (p * q) has the right nr of bits (when accurate=True) + """ + + if p == q: + return False + + if not accurate: + return True + + # Make sure we have just the right amount of bits + found_size = rsa.common.bit_size(p * q) + return total_bits == found_size + + # Keep choosing other primes until they match our requirements. + change_p = False + while not is_acceptable(p, q): + # Change p on one iteration and q on the other + if change_p: + p = getprime_func(pbits) + else: + q = getprime_func(qbits) + + change_p = not change_p + + # We want p > q as described on + # http://www.di-mgt.com.au/rsa_alg.html#crt + return max(p, q), min(p, q) + + +def calculate_keys_custom_exponent(p: int, q: int, exponent: int) -> typing.Tuple[int, int]: + """Calculates an encryption and a decryption key given p, q and an exponent, + and returns them as a tuple (e, d) + + :param p: the first large prime + :param q: the second large prime + :param exponent: the exponent for the key; only change this if you know + what you're doing, as the exponent influences how difficult your + private key can be cracked. A very common choice for e is 65537. + :type exponent: int + + """ + + phi_n = (p - 1) * (q - 1) + + try: + d = rsa.common.inverse(exponent, phi_n) + except rsa.common.NotRelativePrimeError as ex: + raise rsa.common.NotRelativePrimeError( + exponent, + phi_n, + ex.d, + msg="e (%d) and phi_n (%d) are not relatively prime (divider=%i)" + % (exponent, phi_n, ex.d), + ) from ex + + if (exponent * d) % phi_n != 1: + raise ValueError( + "e (%d) and d (%d) are not mult. inv. modulo " "phi_n (%d)" % (exponent, d, phi_n) + ) + + return exponent, d + + +def calculate_keys(p: int, q: int) -> typing.Tuple[int, int]: + """Calculates an encryption and a decryption key given p and q, and + returns them as a tuple (e, d) + + :param p: the first large prime + :param q: the second large prime + + :return: tuple (e, d) with the encryption and decryption exponents. + """ + + return calculate_keys_custom_exponent(p, q, DEFAULT_EXPONENT) + + +def gen_keys( + nbits: int, + getprime_func: typing.Callable[[int], int], + accurate: bool = True, + exponent: int = DEFAULT_EXPONENT, +) -> typing.Tuple[int, int, int, int]: + """Generate RSA keys of nbits bits. Returns (p, q, e, d). + + Note: this can take a long time, depending on the key size. + + :param nbits: the total number of bits in ``p`` and ``q``. Both ``p`` and + ``q`` will use ``nbits/2`` bits. + :param getprime_func: either :py:func:`rsa.prime.getprime` or a function + with similar signature. + :param exponent: the exponent for the key; only change this if you know + what you're doing, as the exponent influences how difficult your + private key can be cracked. A very common choice for e is 65537. + :type exponent: int + """ + + # Regenerate p and q values, until calculate_keys doesn't raise a + # ValueError. + while True: + (p, q) = find_p_q(nbits // 2, getprime_func, accurate) + try: + (e, d) = calculate_keys_custom_exponent(p, q, exponent=exponent) + break + except ValueError: + pass + + return p, q, e, d + + +def newkeys( + nbits: int, + accurate: bool = True, + poolsize: int = 1, + exponent: int = DEFAULT_EXPONENT, +) -> typing.Tuple[PublicKey, PrivateKey]: + """Generates public and private keys, and returns them as (pub, priv). + + The public key is also known as the 'encryption key', and is a + :py:class:`rsa.PublicKey` object. The private key is also known as the + 'decryption key' and is a :py:class:`rsa.PrivateKey` object. + + :param nbits: the number of bits required to store ``n = p*q``. + :param accurate: when True, ``n`` will have exactly the number of bits you + asked for. However, this makes key generation much slower. When False, + `n`` may have slightly less bits. + :param poolsize: the number of processes to use to generate the prime + numbers. If set to a number > 1, a parallel algorithm will be used. + This requires Python 2.6 or newer. + :param exponent: the exponent for the key; only change this if you know + what you're doing, as the exponent influences how difficult your + private key can be cracked. A very common choice for e is 65537. + :type exponent: int + + :returns: a tuple (:py:class:`rsa.PublicKey`, :py:class:`rsa.PrivateKey`) + + The ``poolsize`` parameter was added in *Python-RSA 3.1* and requires + Python 2.6 or newer. + + """ + + if nbits < 16: + raise ValueError("Key too small") + + if poolsize < 1: + raise ValueError("Pool size (%i) should be >= 1" % poolsize) + + # Determine which getprime function to use + if poolsize > 1: + from rsa import parallel + + def getprime_func(nbits: int) -> int: + return parallel.getprime(nbits, poolsize=poolsize) + + else: + getprime_func = rsa.prime.getprime + + # Generate the key components + (p, q, e, d) = gen_keys(nbits, getprime_func, accurate=accurate, exponent=exponent) + + # Create the key objects + n = p * q + + return (PublicKey(n, e), PrivateKey(n, e, d, p, q)) + + +__all__ = ["PublicKey", "PrivateKey", "newkeys"] + +if __name__ == "__main__": + import doctest + + try: + for count in range(100): + (failures, tests) = doctest.testmod() + if failures: + break + + if (count % 10 == 0 and count) or count == 1: + print("%i times" % count) + except KeyboardInterrupt: + print("Aborted") + else: + print("Doctests done") diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/rsa/rsa/parallel.py b/arch-config/.config/calibre/plugins/DeACSM/modules/rsa/rsa/parallel.py new file mode 100644 index 00000000..5020edbc --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/rsa/rsa/parallel.py @@ -0,0 +1,96 @@ +# Copyright 2011 Sybren A. Stüvel <sybren@stuvel.eu> +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Functions for parallel computation on multiple cores. + +Introduced in Python-RSA 3.1. + +.. note:: + + Requires Python 2.6 or newer. + +""" + +import multiprocessing as mp +from multiprocessing.connection import Connection + +import rsa.prime +import rsa.randnum + + +def _find_prime(nbits: int, pipe: Connection) -> None: + while True: + integer = rsa.randnum.read_random_odd_int(nbits) + + # Test for primeness + if rsa.prime.is_prime(integer): + pipe.send(integer) + return + + +def getprime(nbits: int, poolsize: int) -> int: + """Returns a prime number that can be stored in 'nbits' bits. + + Works in multiple threads at the same time. + + >>> p = getprime(128, 3) + >>> rsa.prime.is_prime(p-1) + False + >>> rsa.prime.is_prime(p) + True + >>> rsa.prime.is_prime(p+1) + False + + >>> from rsa import common + >>> common.bit_size(p) == 128 + True + + """ + + (pipe_recv, pipe_send) = mp.Pipe(duplex=False) + + # Create processes + try: + procs = [mp.Process(target=_find_prime, args=(nbits, pipe_send)) for _ in range(poolsize)] + # Start processes + for p in procs: + p.start() + + result = pipe_recv.recv() + finally: + pipe_recv.close() + pipe_send.close() + + # Terminate processes + for p in procs: + p.terminate() + + return result + + +__all__ = ["getprime"] + +if __name__ == "__main__": + print("Running doctests 1000x or until failure") + import doctest + + for count in range(100): + (failures, tests) = doctest.testmod() + if failures: + break + + if count % 10 == 0 and count: + print("%i times" % count) + + print("Doctests done") diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/rsa/rsa/pem.py b/arch-config/.config/calibre/plugins/DeACSM/modules/rsa/rsa/pem.py new file mode 100644 index 00000000..5d26e6ed --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/rsa/rsa/pem.py @@ -0,0 +1,134 @@ +# Copyright 2011 Sybren A. Stüvel <sybren@stuvel.eu> +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Functions that load and write PEM-encoded files.""" + +import base64 +import typing + +# Should either be ASCII strings or bytes. +FlexiText = typing.Union[str, bytes] + + +def _markers(pem_marker: FlexiText) -> typing.Tuple[bytes, bytes]: + """ + Returns the start and end PEM markers, as bytes. + """ + + if not isinstance(pem_marker, bytes): + pem_marker = pem_marker.encode("ascii") + + return ( + b"-----BEGIN " + pem_marker + b"-----", + b"-----END " + pem_marker + b"-----", + ) + + +def _pem_lines(contents: bytes, pem_start: bytes, pem_end: bytes) -> typing.Iterator[bytes]: + """Generator over PEM lines between pem_start and pem_end.""" + + in_pem_part = False + seen_pem_start = False + + for line in contents.splitlines(): + line = line.strip() + + # Skip empty lines + if not line: + continue + + # Handle start marker + if line == pem_start: + if in_pem_part: + raise ValueError('Seen start marker "%r" twice' % pem_start) + + in_pem_part = True + seen_pem_start = True + continue + + # Skip stuff before first marker + if not in_pem_part: + continue + + # Handle end marker + if in_pem_part and line == pem_end: + in_pem_part = False + break + + # Load fields + if b":" in line: + continue + + yield line + + # Do some sanity checks + if not seen_pem_start: + raise ValueError('No PEM start marker "%r" found' % pem_start) + + if in_pem_part: + raise ValueError('No PEM end marker "%r" found' % pem_end) + + +def load_pem(contents: FlexiText, pem_marker: FlexiText) -> bytes: + """Loads a PEM file. + + :param contents: the contents of the file to interpret + :param pem_marker: the marker of the PEM content, such as 'RSA PRIVATE KEY' + when your file has '-----BEGIN RSA PRIVATE KEY-----' and + '-----END RSA PRIVATE KEY-----' markers. + + :return: the base64-decoded content between the start and end markers. + + @raise ValueError: when the content is invalid, for example when the start + marker cannot be found. + + """ + + # We want bytes, not text. If it's text, it can be converted to ASCII bytes. + if not isinstance(contents, bytes): + contents = contents.encode("ascii") + + (pem_start, pem_end) = _markers(pem_marker) + pem_lines = [line for line in _pem_lines(contents, pem_start, pem_end)] + + # Base64-decode the contents + pem = b"".join(pem_lines) + return base64.standard_b64decode(pem) + + +def save_pem(contents: bytes, pem_marker: FlexiText) -> bytes: + """Saves a PEM file. + + :param contents: the contents to encode in PEM format + :param pem_marker: the marker of the PEM content, such as 'RSA PRIVATE KEY' + when your file has '-----BEGIN RSA PRIVATE KEY-----' and + '-----END RSA PRIVATE KEY-----' markers. + + :return: the base64-encoded content between the start and end markers, as bytes. + + """ + + (pem_start, pem_end) = _markers(pem_marker) + + b64 = base64.standard_b64encode(contents).replace(b"\n", b"") + pem_lines = [pem_start] + + for block_start in range(0, len(b64), 64): + block = b64[block_start : block_start + 64] + pem_lines.append(block) + + pem_lines.append(pem_end) + pem_lines.append(b"") + + return b"\n".join(pem_lines) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/rsa/rsa/pkcs1.py b/arch-config/.config/calibre/plugins/DeACSM/modules/rsa/rsa/pkcs1.py new file mode 100644 index 00000000..3837a69b --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/rsa/rsa/pkcs1.py @@ -0,0 +1,484 @@ +# Copyright 2011 Sybren A. Stüvel <sybren@stuvel.eu> +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Functions for PKCS#1 version 1.5 encryption and signing + +This module implements certain functionality from PKCS#1 version 1.5. For a +very clear example, read http://www.di-mgt.com.au/rsa_alg.html#pkcs1schemes + +At least 8 bytes of random padding is used when encrypting a message. This makes +these methods much more secure than the ones in the ``rsa`` module. + +WARNING: this module leaks information when decryption fails. The exceptions +that are raised contain the Python traceback information, which can be used to +deduce where in the process the failure occurred. DO NOT PASS SUCH INFORMATION +to your users. +""" + +import hashlib +import os +import sys +import typing +from hmac import compare_digest + +from . import common, transform, core, key + +if typing.TYPE_CHECKING: + HashType = hashlib._Hash +else: + HashType = typing.Any + +# ASN.1 codes that describe the hash algorithm used. +HASH_ASN1 = { + "MD5": b"\x30\x20\x30\x0c\x06\x08\x2a\x86\x48\x86\xf7\x0d\x02\x05\x05\x00\x04\x10", + "SHA-1": b"\x30\x21\x30\x09\x06\x05\x2b\x0e\x03\x02\x1a\x05\x00\x04\x14", + "SHA-224": b"\x30\x2d\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x04\x05\x00\x04\x1c", + "SHA-256": b"\x30\x31\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x01\x05\x00\x04\x20", + "SHA-384": b"\x30\x41\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x02\x05\x00\x04\x30", + "SHA-512": b"\x30\x51\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x03\x05\x00\x04\x40", +} + +HASH_METHODS: typing.Dict[str, typing.Callable[[], HashType]] = { + "MD5": hashlib.md5, + "SHA-1": hashlib.sha1, + "SHA-224": hashlib.sha224, + "SHA-256": hashlib.sha256, + "SHA-384": hashlib.sha384, + "SHA-512": hashlib.sha512, +} + + +if sys.version_info >= (3, 6): + # Python 3.6 introduced SHA3 support. + HASH_ASN1.update( + { + "SHA3-256": b"\x30\x31\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x08\x05\x00\x04\x20", + "SHA3-384": b"\x30\x41\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x09\x05\x00\x04\x30", + "SHA3-512": b"\x30\x51\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x0a\x05\x00\x04\x40", + } + ) + + HASH_METHODS.update( + { + "SHA3-256": hashlib.sha3_256, + "SHA3-384": hashlib.sha3_384, + "SHA3-512": hashlib.sha3_512, + } + ) + + +class CryptoError(Exception): + """Base class for all exceptions in this module.""" + + +class DecryptionError(CryptoError): + """Raised when decryption fails.""" + + +class VerificationError(CryptoError): + """Raised when verification fails.""" + + +def _pad_for_encryption(message: bytes, target_length: int) -> bytes: + r"""Pads the message for encryption, returning the padded message. + + :return: 00 02 RANDOM_DATA 00 MESSAGE + + >>> block = _pad_for_encryption(b'hello', 16) + >>> len(block) + 16 + >>> block[0:2] + b'\x00\x02' + >>> block[-6:] + b'\x00hello' + + """ + + max_msglength = target_length - 11 + msglength = len(message) + + if msglength > max_msglength: + raise OverflowError( + "%i bytes needed for message, but there is only" + " space for %i" % (msglength, max_msglength) + ) + + # Get random padding + padding = b"" + padding_length = target_length - msglength - 3 + + # We remove 0-bytes, so we'll end up with less padding than we've asked for, + # so keep adding data until we're at the correct length. + while len(padding) < padding_length: + needed_bytes = padding_length - len(padding) + + # Always read at least 8 bytes more than we need, and trim off the rest + # after removing the 0-bytes. This increases the chance of getting + # enough bytes, especially when needed_bytes is small + new_padding = os.urandom(needed_bytes + 5) + new_padding = new_padding.replace(b"\x00", b"") + padding = padding + new_padding[:needed_bytes] + + assert len(padding) == padding_length + + return b"".join([b"\x00\x02", padding, b"\x00", message]) + + +def _pad_for_signing(message: bytes, target_length: int) -> bytes: + r"""Pads the message for signing, returning the padded message. + + The padding is always a repetition of FF bytes. + + :return: 00 01 PADDING 00 MESSAGE + + >>> block = _pad_for_signing(b'hello', 16) + >>> len(block) + 16 + >>> block[0:2] + b'\x00\x01' + >>> block[-6:] + b'\x00hello' + >>> block[2:-6] + b'\xff\xff\xff\xff\xff\xff\xff\xff' + + """ + + max_msglength = target_length - 11 + msglength = len(message) + + if msglength > max_msglength: + raise OverflowError( + "%i bytes needed for message, but there is only" + " space for %i" % (msglength, max_msglength) + ) + + padding_length = target_length - msglength - 3 + + return b"".join([b"\x00\x01", padding_length * b"\xff", b"\x00", message]) + + +def encrypt(message: bytes, pub_key: key.PublicKey) -> bytes: + """Encrypts the given message using PKCS#1 v1.5 + + :param message: the message to encrypt. Must be a byte string no longer than + ``k-11`` bytes, where ``k`` is the number of bytes needed to encode + the ``n`` component of the public key. + :param pub_key: the :py:class:`rsa.PublicKey` to encrypt with. + :raise OverflowError: when the message is too large to fit in the padded + block. + + >>> from rsa import key, common + >>> (pub_key, priv_key) = key.newkeys(256) + >>> message = b'hello' + >>> crypto = encrypt(message, pub_key) + + The crypto text should be just as long as the public key 'n' component: + + >>> len(crypto) == common.byte_size(pub_key.n) + True + + """ + + keylength = common.byte_size(pub_key.n) + padded = _pad_for_encryption(message, keylength) + + payload = transform.bytes2int(padded) + encrypted = core.encrypt_int(payload, pub_key.e, pub_key.n) + block = transform.int2bytes(encrypted, keylength) + + return block + + +def decrypt(crypto: bytes, priv_key: key.PrivateKey) -> bytes: + r"""Decrypts the given message using PKCS#1 v1.5 + + The decryption is considered 'failed' when the resulting cleartext doesn't + start with the bytes 00 02, or when the 00 byte between the padding and + the message cannot be found. + + :param crypto: the crypto text as returned by :py:func:`rsa.encrypt` + :param priv_key: the :py:class:`rsa.PrivateKey` to decrypt with. + :raise DecryptionError: when the decryption fails. No details are given as + to why the code thinks the decryption fails, as this would leak + information about the private key. + + + >>> import rsa + >>> (pub_key, priv_key) = rsa.newkeys(256) + + It works with strings: + + >>> crypto = encrypt(b'hello', pub_key) + >>> decrypt(crypto, priv_key) + b'hello' + + And with binary data: + + >>> crypto = encrypt(b'\x00\x00\x00\x00\x01', pub_key) + >>> decrypt(crypto, priv_key) + b'\x00\x00\x00\x00\x01' + + Altering the encrypted information will *likely* cause a + :py:class:`rsa.pkcs1.DecryptionError`. If you want to be *sure*, use + :py:func:`rsa.sign`. + + + .. warning:: + + Never display the stack trace of a + :py:class:`rsa.pkcs1.DecryptionError` exception. It shows where in the + code the exception occurred, and thus leaks information about the key. + It's only a tiny bit of information, but every bit makes cracking the + keys easier. + + >>> crypto = encrypt(b'hello', pub_key) + >>> crypto = crypto[0:5] + b'X' + crypto[6:] # change a byte + >>> decrypt(crypto, priv_key) + Traceback (most recent call last): + ... + rsa.pkcs1.DecryptionError: Decryption failed + + """ + + blocksize = common.byte_size(priv_key.n) + encrypted = transform.bytes2int(crypto) + decrypted = priv_key.blinded_decrypt(encrypted) + cleartext = transform.int2bytes(decrypted, blocksize) + + # Detect leading zeroes in the crypto. These are not reflected in the + # encrypted value (as leading zeroes do not influence the value of an + # integer). This fixes CVE-2020-13757. + if len(crypto) > blocksize: + # This is operating on public information, so doesn't need to be constant-time. + raise DecryptionError("Decryption failed") + + # If we can't find the cleartext marker, decryption failed. + cleartext_marker_bad = not compare_digest(cleartext[:2], b"\x00\x02") + + # Find the 00 separator between the padding and the message + sep_idx = cleartext.find(b"\x00", 2) + + # sep_idx indicates the position of the `\x00` separator that separates the + # padding from the actual message. The padding should be at least 8 bytes + # long (see https://tools.ietf.org/html/rfc8017#section-7.2.2 step 3), which + # means the separator should be at least at index 10 (because of the + # `\x00\x02` marker that precedes it). + sep_idx_bad = sep_idx < 10 + + anything_bad = cleartext_marker_bad | sep_idx_bad + if anything_bad: + raise DecryptionError("Decryption failed") + + return cleartext[sep_idx + 1 :] + + +def sign_hash(hash_value: bytes, priv_key: key.PrivateKey, hash_method: str) -> bytes: + """Signs a precomputed hash with the private key. + + Hashes the message, then signs the hash with the given key. This is known + as a "detached signature", because the message itself isn't altered. + + :param hash_value: A precomputed hash to sign (ignores message). + :param priv_key: the :py:class:`rsa.PrivateKey` to sign with + :param hash_method: the hash method used on the message. Use 'MD5', 'SHA-1', + 'SHA-224', SHA-256', 'SHA-384' or 'SHA-512'. + :return: a message signature block. + :raise OverflowError: if the private key is too small to contain the + requested hash. + + """ + + # Get the ASN1 code for this hash method + if hash_method not in HASH_ASN1: + raise ValueError("Invalid hash method: %s" % hash_method) + asn1code = HASH_ASN1[hash_method] + + # Encrypt the hash with the private key + cleartext = asn1code + hash_value + keylength = common.byte_size(priv_key.n) + padded = _pad_for_signing(cleartext, keylength) + + payload = transform.bytes2int(padded) + encrypted = priv_key.blinded_encrypt(payload) + block = transform.int2bytes(encrypted, keylength) + + return block + + +def sign(message: bytes, priv_key: key.PrivateKey, hash_method: str) -> bytes: + """Signs the message with the private key. + + Hashes the message, then signs the hash with the given key. This is known + as a "detached signature", because the message itself isn't altered. + + :param message: the message to sign. Can be an 8-bit string or a file-like + object. If ``message`` has a ``read()`` method, it is assumed to be a + file-like object. + :param priv_key: the :py:class:`rsa.PrivateKey` to sign with + :param hash_method: the hash method used on the message. Use 'MD5', 'SHA-1', + 'SHA-224', SHA-256', 'SHA-384' or 'SHA-512'. + :return: a message signature block. + :raise OverflowError: if the private key is too small to contain the + requested hash. + + """ + + msg_hash = compute_hash(message, hash_method) + return sign_hash(msg_hash, priv_key, hash_method) + + +def verify(message: bytes, signature: bytes, pub_key: key.PublicKey) -> str: + """Verifies that the signature matches the message. + + The hash method is detected automatically from the signature. + + :param message: the signed message. Can be an 8-bit string or a file-like + object. If ``message`` has a ``read()`` method, it is assumed to be a + file-like object. + :param signature: the signature block, as created with :py:func:`rsa.sign`. + :param pub_key: the :py:class:`rsa.PublicKey` of the person signing the message. + :raise VerificationError: when the signature doesn't match the message. + :returns: the name of the used hash. + + """ + + keylength = common.byte_size(pub_key.n) + encrypted = transform.bytes2int(signature) + decrypted = core.decrypt_int(encrypted, pub_key.e, pub_key.n) + clearsig = transform.int2bytes(decrypted, keylength) + + # Get the hash method + method_name = _find_method_hash(clearsig) + message_hash = compute_hash(message, method_name) + + # Reconstruct the expected padded hash + cleartext = HASH_ASN1[method_name] + message_hash + expected = _pad_for_signing(cleartext, keylength) + + if len(signature) != keylength: + raise VerificationError("Verification failed") + + # Compare with the signed one + if expected != clearsig: + raise VerificationError("Verification failed") + + return method_name + + +def find_signature_hash(signature: bytes, pub_key: key.PublicKey) -> str: + """Returns the hash name detected from the signature. + + If you also want to verify the message, use :py:func:`rsa.verify()` instead. + It also returns the name of the used hash. + + :param signature: the signature block, as created with :py:func:`rsa.sign`. + :param pub_key: the :py:class:`rsa.PublicKey` of the person signing the message. + :returns: the name of the used hash. + """ + + keylength = common.byte_size(pub_key.n) + encrypted = transform.bytes2int(signature) + decrypted = core.decrypt_int(encrypted, pub_key.e, pub_key.n) + clearsig = transform.int2bytes(decrypted, keylength) + + return _find_method_hash(clearsig) + + +def yield_fixedblocks(infile: typing.BinaryIO, blocksize: int) -> typing.Iterator[bytes]: + """Generator, yields each block of ``blocksize`` bytes in the input file. + + :param infile: file to read and separate in blocks. + :param blocksize: block size in bytes. + :returns: a generator that yields the contents of each block + """ + + while True: + block = infile.read(blocksize) + + read_bytes = len(block) + if read_bytes == 0: + break + + yield block + + if read_bytes < blocksize: + break + + +def compute_hash(message: typing.Union[bytes, typing.BinaryIO], method_name: str) -> bytes: + """Returns the message digest. + + :param message: the signed message. Can be an 8-bit string or a file-like + object. If ``message`` has a ``read()`` method, it is assumed to be a + file-like object. + :param method_name: the hash method, must be a key of + :py:const:`HASH_METHODS`. + + """ + + if method_name not in HASH_METHODS: + raise ValueError("Invalid hash method: %s" % method_name) + + method = HASH_METHODS[method_name] + hasher = method() + + if isinstance(message, bytes): + hasher.update(message) + else: + assert hasattr(message, "read") and hasattr(message.read, "__call__") + # read as 1K blocks + for block in yield_fixedblocks(message, 1024): + hasher.update(block) + + return hasher.digest() + + +def _find_method_hash(clearsig: bytes) -> str: + """Finds the hash method. + + :param clearsig: full padded ASN1 and hash. + :return: the used hash method. + :raise VerificationFailed: when the hash method cannot be found + """ + + for (hashname, asn1code) in HASH_ASN1.items(): + if asn1code in clearsig: + return hashname + + raise VerificationError("Verification failed") + + +__all__ = [ + "encrypt", + "decrypt", + "sign", + "verify", + "DecryptionError", + "VerificationError", + "CryptoError", +] + +if __name__ == "__main__": + print("Running doctests 1000x or until failure") + import doctest + + for count in range(1000): + (failures, tests) = doctest.testmod() + if failures: + break + + if count % 100 == 0 and count: + print("%i times" % count) + + print("Doctests done") diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/rsa/rsa/pkcs1_v2.py b/arch-config/.config/calibre/plugins/DeACSM/modules/rsa/rsa/pkcs1_v2.py new file mode 100644 index 00000000..d68b9077 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/rsa/rsa/pkcs1_v2.py @@ -0,0 +1,100 @@ +# Copyright 2011 Sybren A. Stüvel <sybren@stuvel.eu> +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Functions for PKCS#1 version 2 encryption and signing + +This module implements certain functionality from PKCS#1 version 2. Main +documentation is RFC 2437: https://tools.ietf.org/html/rfc2437 +""" + +from rsa import ( + common, + pkcs1, + transform, +) + + +def mgf1(seed: bytes, length: int, hasher: str = "SHA-1") -> bytes: + """ + MGF1 is a Mask Generation Function based on a hash function. + + A mask generation function takes an octet string of variable length and a + desired output length as input, and outputs an octet string of the desired + length. The plaintext-awareness of RSAES-OAEP relies on the random nature of + the output of the mask generation function, which in turn relies on the + random nature of the underlying hash. + + :param bytes seed: seed from which mask is generated, an octet string + :param int length: intended length in octets of the mask, at most 2^32(hLen) + :param str hasher: hash function (hLen denotes the length in octets of the hash + function output) + + :return: mask, an octet string of length `length` + :rtype: bytes + + :raise OverflowError: when `length` is too large for the specified `hasher` + :raise ValueError: when specified `hasher` is invalid + """ + + try: + hash_length = pkcs1.HASH_METHODS[hasher]().digest_size + except KeyError as ex: + raise ValueError( + "Invalid `hasher` specified. Please select one of: {hash_list}".format( + hash_list=", ".join(sorted(pkcs1.HASH_METHODS.keys())) + ) + ) from ex + + # If l > 2^32(hLen), output "mask too long" and stop. + if length > (2 ** 32 * hash_length): + raise OverflowError( + "Desired length should be at most 2**32 times the hasher's output " + "length ({hash_length} for {hasher} function)".format( + hash_length=hash_length, + hasher=hasher, + ) + ) + + # Looping `counter` from 0 to ceil(l / hLen)-1, build `output` based on the + # hashes formed by (`seed` + C), being `C` an octet string of length 4 + # generated by converting `counter` with the primitive I2OSP + output = b"".join( + pkcs1.compute_hash( + seed + transform.int2bytes(counter, fill_size=4), + method_name=hasher, + ) + for counter in range(common.ceil_div(length, hash_length) + 1) + ) + + # Output the leading `length` octets of `output` as the octet string mask. + return output[:length] + + +__all__ = [ + "mgf1", +] + +if __name__ == "__main__": + print("Running doctests 1000x or until failure") + import doctest + + for count in range(1000): + (failures, tests) = doctest.testmod() + if failures: + break + + if count % 100 == 0 and count: + print("%i times" % count) + + print("Doctests done") diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/rsa/rsa/prime.py b/arch-config/.config/calibre/plugins/DeACSM/modules/rsa/rsa/prime.py new file mode 100644 index 00000000..ec486bcc --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/rsa/rsa/prime.py @@ -0,0 +1,198 @@ +# Copyright 2011 Sybren A. Stüvel <sybren@stuvel.eu> +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Numerical functions related to primes. + +Implementation based on the book Algorithm Design by Michael T. Goodrich and +Roberto Tamassia, 2002. +""" + +import rsa.common +import rsa.randnum + +__all__ = ["getprime", "are_relatively_prime"] + + +def gcd(p: int, q: int) -> int: + """Returns the greatest common divisor of p and q + + >>> gcd(48, 180) + 12 + """ + + while q != 0: + (p, q) = (q, p % q) + return p + + +def get_primality_testing_rounds(number: int) -> int: + """Returns minimum number of rounds for Miller-Rabing primality testing, + based on number bitsize. + + According to NIST FIPS 186-4, Appendix C, Table C.3, minimum number of + rounds of M-R testing, using an error probability of 2 ** (-100), for + different p, q bitsizes are: + * p, q bitsize: 512; rounds: 7 + * p, q bitsize: 1024; rounds: 4 + * p, q bitsize: 1536; rounds: 3 + See: http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf + """ + + # Calculate number bitsize. + bitsize = rsa.common.bit_size(number) + # Set number of rounds. + if bitsize >= 1536: + return 3 + if bitsize >= 1024: + return 4 + if bitsize >= 512: + return 7 + # For smaller bitsizes, set arbitrary number of rounds. + return 10 + + +def miller_rabin_primality_testing(n: int, k: int) -> bool: + """Calculates whether n is composite (which is always correct) or prime + (which theoretically is incorrect with error probability 4**-k), by + applying Miller-Rabin primality testing. + + For reference and implementation example, see: + https://en.wikipedia.org/wiki/Miller%E2%80%93Rabin_primality_test + + :param n: Integer to be tested for primality. + :type n: int + :param k: Number of rounds (witnesses) of Miller-Rabin testing. + :type k: int + :return: False if the number is composite, True if it's probably prime. + :rtype: bool + """ + + # prevent potential infinite loop when d = 0 + if n < 2: + return False + + # Decompose (n - 1) to write it as (2 ** r) * d + # While d is even, divide it by 2 and increase the exponent. + d = n - 1 + r = 0 + + while not (d & 1): + r += 1 + d >>= 1 + + # Test k witnesses. + for _ in range(k): + # Generate random integer a, where 2 <= a <= (n - 2) + a = rsa.randnum.randint(n - 3) + 1 + + x = pow(a, d, n) + if x == 1 or x == n - 1: + continue + + for _ in range(r - 1): + x = pow(x, 2, n) + if x == 1: + # n is composite. + return False + if x == n - 1: + # Exit inner loop and continue with next witness. + break + else: + # If loop doesn't break, n is composite. + return False + + return True + + +def is_prime(number: int) -> bool: + """Returns True if the number is prime, and False otherwise. + + >>> is_prime(2) + True + >>> is_prime(42) + False + >>> is_prime(41) + True + """ + + # Check for small numbers. + if number < 10: + return number in {2, 3, 5, 7} + + # Check for even numbers. + if not (number & 1): + return False + + # Calculate minimum number of rounds. + k = get_primality_testing_rounds(number) + + # Run primality testing with (minimum + 1) rounds. + return miller_rabin_primality_testing(number, k + 1) + + +def getprime(nbits: int) -> int: + """Returns a prime number that can be stored in 'nbits' bits. + + >>> p = getprime(128) + >>> is_prime(p-1) + False + >>> is_prime(p) + True + >>> is_prime(p+1) + False + + >>> from rsa import common + >>> common.bit_size(p) == 128 + True + """ + + assert nbits > 3 # the loop will hang on too small numbers + + while True: + integer = rsa.randnum.read_random_odd_int(nbits) + + # Test for primeness + if is_prime(integer): + return integer + + # Retry if not prime + + +def are_relatively_prime(a: int, b: int) -> bool: + """Returns True if a and b are relatively prime, and False if they + are not. + + >>> are_relatively_prime(2, 3) + True + >>> are_relatively_prime(2, 4) + False + """ + + d = gcd(a, b) + return d == 1 + + +if __name__ == "__main__": + print("Running doctests 1000x or until failure") + import doctest + + for count in range(1000): + (failures, tests) = doctest.testmod() + if failures: + break + + if count % 100 == 0 and count: + print("%i times" % count) + + print("Doctests done") diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/rsa/rsa/py.typed b/arch-config/.config/calibre/plugins/DeACSM/modules/rsa/rsa/py.typed new file mode 100644 index 00000000..6c27071a --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/rsa/rsa/py.typed @@ -0,0 +1 @@ +# Marker file for PEP 561. The rsa package uses inline types. diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/rsa/rsa/randnum.py b/arch-config/.config/calibre/plugins/DeACSM/modules/rsa/rsa/randnum.py new file mode 100644 index 00000000..c65facdd --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/rsa/rsa/randnum.py @@ -0,0 +1,95 @@ +# Copyright 2011 Sybren A. Stüvel <sybren@stuvel.eu> +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Functions for generating random numbers.""" + +# Source inspired by code by Yesudeep Mangalapilly <yesudeep@gmail.com> + +import os +import struct + +from rsa import common, transform + + +def read_random_bits(nbits: int) -> bytes: + """Reads 'nbits' random bits. + + If nbits isn't a whole number of bytes, an extra byte will be appended with + only the lower bits set. + """ + + nbytes, rbits = divmod(nbits, 8) + + # Get the random bytes + randomdata = os.urandom(nbytes) + + # Add the remaining random bits + if rbits > 0: + randomvalue = ord(os.urandom(1)) + randomvalue >>= 8 - rbits + randomdata = struct.pack("B", randomvalue) + randomdata + + return randomdata + + +def read_random_int(nbits: int) -> int: + """Reads a random integer of approximately nbits bits.""" + + randomdata = read_random_bits(nbits) + value = transform.bytes2int(randomdata) + + # Ensure that the number is large enough to just fill out the required + # number of bits. + value |= 1 << (nbits - 1) + + return value + + +def read_random_odd_int(nbits: int) -> int: + """Reads a random odd integer of approximately nbits bits. + + >>> read_random_odd_int(512) & 1 + 1 + """ + + value = read_random_int(nbits) + + # Make sure it's odd + return value | 1 + + +def randint(maxvalue: int) -> int: + """Returns a random integer x with 1 <= x <= maxvalue + + May take a very long time in specific situations. If maxvalue needs N bits + to store, the closer maxvalue is to (2 ** N) - 1, the faster this function + is. + """ + + bit_size = common.bit_size(maxvalue) + + tries = 0 + while True: + value = read_random_int(bit_size) + if value <= maxvalue: + break + + if tries % 10 == 0 and tries: + # After a lot of tries to get the right number of bits but still + # smaller than maxvalue, decrease the number of bits by 1. That'll + # dramatically increase the chances to get a large enough number. + bit_size -= 1 + tries += 1 + + return value diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/rsa/rsa/transform.py b/arch-config/.config/calibre/plugins/DeACSM/modules/rsa/rsa/transform.py new file mode 100644 index 00000000..c609b65f --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/rsa/rsa/transform.py @@ -0,0 +1,72 @@ +# Copyright 2011 Sybren A. Stüvel <sybren@stuvel.eu> +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Data transformation functions. + +From bytes to a number, number to bytes, etc. +""" + +import math + + +def bytes2int(raw_bytes: bytes) -> int: + r"""Converts a list of bytes or an 8-bit string to an integer. + + When using unicode strings, encode it to some encoding like UTF8 first. + + >>> (((128 * 256) + 64) * 256) + 15 + 8405007 + >>> bytes2int(b'\x80@\x0f') + 8405007 + + """ + return int.from_bytes(raw_bytes, "big", signed=False) + + +def int2bytes(number: int, fill_size: int = 0) -> bytes: + """ + Convert an unsigned integer to bytes (big-endian):: + + Does not preserve leading zeros if you don't specify a fill size. + + :param number: + Integer value + :param fill_size: + If the optional fill size is given the length of the resulting + byte string is expected to be the fill size and will be padded + with prefix zero bytes to satisfy that length. + :returns: + Raw bytes (base-256 representation). + :raises: + ``OverflowError`` when fill_size is given and the number takes up more + bytes than fit into the block. This requires the ``overflow`` + argument to this function to be set to ``False`` otherwise, no + error will be raised. + """ + + if number < 0: + raise ValueError("Number must be an unsigned integer: %d" % number) + + bytes_required = max(1, math.ceil(number.bit_length() / 8)) + + if fill_size > 0: + return number.to_bytes(fill_size, "big") + + return number.to_bytes(bytes_required, "big") + + +if __name__ == "__main__": + import doctest + + doctest.testmod() diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/rsa/rsa/util.py b/arch-config/.config/calibre/plugins/DeACSM/modules/rsa/rsa/util.py new file mode 100644 index 00000000..087caf8d --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/rsa/rsa/util.py @@ -0,0 +1,97 @@ +# Copyright 2011 Sybren A. Stüvel <sybren@stuvel.eu> +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Utility functions.""" + +import sys +from optparse import OptionParser + +import rsa.key + + +def private_to_public() -> None: + """Reads a private key and outputs the corresponding public key.""" + + # Parse the CLI options + parser = OptionParser( + usage="usage: %prog [options]", + description="Reads a private key and outputs the " + "corresponding public key. Both private and public keys use " + "the format described in PKCS#1 v1.5", + ) + + parser.add_option( + "-i", + "--input", + dest="infilename", + type="string", + help="Input filename. Reads from stdin if not specified", + ) + parser.add_option( + "-o", + "--output", + dest="outfilename", + type="string", + help="Output filename. Writes to stdout of not specified", + ) + + parser.add_option( + "--inform", + dest="inform", + help="key format of input - default PEM", + choices=("PEM", "DER"), + default="PEM", + ) + + parser.add_option( + "--outform", + dest="outform", + help="key format of output - default PEM", + choices=("PEM", "DER"), + default="PEM", + ) + + (cli, cli_args) = parser.parse_args(sys.argv) + + # Read the input data + if cli.infilename: + print( + "Reading private key from %s in %s format" % (cli.infilename, cli.inform), + file=sys.stderr, + ) + with open(cli.infilename, "rb") as infile: + in_data = infile.read() + else: + print("Reading private key from stdin in %s format" % cli.inform, file=sys.stderr) + in_data = sys.stdin.read().encode("ascii") + + assert type(in_data) == bytes, type(in_data) + + # Take the public fields and create a public key + priv_key = rsa.key.PrivateKey.load_pkcs1(in_data, cli.inform) + pub_key = rsa.key.PublicKey(priv_key.n, priv_key.e) + + # Save to the output file + out_data = pub_key.save_pkcs1(cli.outform) + + if cli.outfilename: + print( + "Writing public key to %s in %s format" % (cli.outfilename, cli.outform), + file=sys.stderr, + ) + with open(cli.outfilename, "wb") as outfile: + outfile.write(out_data) + else: + print("Writing public key to stdout in %s format" % cli.outform, file=sys.stderr) + sys.stdout.write(out_data.decode("ascii")) diff --git a/arch-config/.config/calibre/plugins/DeACSM/modules/rsa/setup.py b/arch-config/.config/calibre/plugins/DeACSM/modules/rsa/setup.py new file mode 100644 index 00000000..d3a1c2c9 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeACSM/modules/rsa/setup.py @@ -0,0 +1,39 @@ +# -*- coding: utf-8 -*- +from setuptools import setup + +packages = \ +['rsa'] + +package_data = \ +{'': ['*']} + +install_requires = \ +['pyasn1>=0.1.3'] + +entry_points = \ +{'console_scripts': ['pyrsa-decrypt = rsa.cli:decrypt', + 'pyrsa-encrypt = rsa.cli:encrypt', + 'pyrsa-keygen = rsa.cli:keygen', + 'pyrsa-priv2pub = rsa.util:private_to_public', + 'pyrsa-sign = rsa.cli:sign', + 'pyrsa-verify = rsa.cli:verify']} + +setup_kwargs = { + 'name': 'rsa', + 'version': '4.8', + 'description': 'Pure-Python RSA implementation', + 'long_description': '# Pure Python RSA implementation\n\n[![PyPI](https://img.shields.io/pypi/v/rsa.svg)](https://pypi.org/project/rsa/)\n[![Build Status](https://travis-ci.org/sybrenstuvel/python-rsa.svg?branch=master)](https://travis-ci.org/sybrenstuvel/python-rsa)\n[![Coverage Status](https://coveralls.io/repos/github/sybrenstuvel/python-rsa/badge.svg?branch=master)](https://coveralls.io/github/sybrenstuvel/python-rsa?branch=master)\n[![Code Climate](https://api.codeclimate.com/v1/badges/a99a88d28ad37a79dbf6/maintainability)](https://codeclimate.com/github/codeclimate/codeclimate/maintainability)\n\n[Python-RSA](https://stuvel.eu/rsa) is a pure-Python RSA implementation. It supports\nencryption and decryption, signing and verifying signatures, and key\ngeneration according to PKCS#1 version 1.5. It can be used as a Python\nlibrary as well as on the commandline. The code was mostly written by\nSybren A. Stüvel.\n\nDocumentation can be found at the [Python-RSA homepage](https://stuvel.eu/rsa). For all changes, check [the changelog](https://github.com/sybrenstuvel/python-rsa/blob/master/CHANGELOG.md).\n\nDownload and install using:\n\n pip install rsa\n\nor download it from the [Python Package Index](https://pypi.org/project/rsa/).\n\nThe source code is maintained at [GitHub](https://github.com/sybrenstuvel/python-rsa/) and is\nlicensed under the [Apache License, version 2.0](https://www.apache.org/licenses/LICENSE-2.0)\n\n## Security\n\nBecause of how Python internally stores numbers, it is very hard (if not impossible) to make a pure-Python program secure against timing attacks. This library is no exception, so use it with care. See https://securitypitfalls.wordpress.com/2018/08/03/constant-time-compare-in-python/ for more info.\n\n## Setup of Development Environment\n\n```\npython3 -m venv .venv\n. ./.venv/bin/activate\npip install poetry\npoetry install\n```\n\n## Publishing a New Release\n\n```\n. ./.venv/bin/activate\npoetry publish --build\n```\n', + 'author': 'Sybren A. Stüvel', + 'author_email': 'sybren@stuvel.eu', + 'maintainer': None, + 'maintainer_email': None, + 'url': 'https://stuvel.eu/rsa', + 'packages': packages, + 'package_data': package_data, + 'install_requires': install_requires, + 'entry_points': entry_points, + 'python_requires': '>=3.6,<4', +} + + +setup(**setup_kwargs) diff --git a/arch-config/.config/calibre/plugins/DeDRM.zip b/arch-config/.config/calibre/plugins/DeDRM.zip new file mode 100644 index 00000000..5f21b264 Binary files /dev/null and b/arch-config/.config/calibre/plugins/DeDRM.zip differ diff --git a/arch-config/.config/calibre/plugins/DeDRM/help/DeDRM_Adobe Digital Editions Key_Help.htm b/arch-config/.config/calibre/plugins/DeDRM/help/DeDRM_Adobe Digital Editions Key_Help.htm new file mode 100644 index 00000000..762070a7 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeDRM/help/DeDRM_Adobe Digital Editions Key_Help.htm @@ -0,0 +1,60 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" + "http://www.w3.org/TR/html4/strict.dtd"> + +<html> + +<head> +<meta http-equiv="content-type" content="text/html; charset=utf-8"> +<title>Managing Adobe Digital Editions Keys + + + + + +

Managing Adobe Digital Editions Keys

+ + +

If you have upgraded from an earlier version of the plugin, any existing Adobe Digital Editions keys will have been automatically imported, so you might not need to do any more configuration. In addition, on Windows and Mac, the default Adobe Digital Editions key is added the first time the plugin is run. Continue reading for key generation and management instructions.

+ +

Creating New Keys:

+ +

On the right-hand side of the plugin’s customization dialog, you will see a button with an icon that looks like a green plus sign (+). Clicking this button will open a new dialog prompting you to enter a key name for the default Adobe Digital Editions key.

+ + +

Click the OK button to create and store the Adobe Digital Editions key for the current installation of Adobe Digital Editions. Or Cancel if you don’t want to create the key.

+

New keys are checked against the current list of keys before being added, and duplicates are discarded.

+ +

Deleting Keys:

+ +

On the right-hand side of the plugin’s customization dialog, you will see a button with an icon that looks like a red "X". Clicking this button will delete the highlighted key in the list. You will be prompted once to be sure that’s what you truly mean to do. Once gone, it’s permanently gone.

+ +

Renaming Keys:

+ +

On the right-hand side of the plugin’s customization dialog, you will see a button with an icon that looks like a sheet of paper. Clicking this button will prompt you to enter a new name for the highlighted key in the list. Enter the new name for the encryption key and click the OK button to use the new name, or Cancel to revert to the old name..

+ +

Exporting Keys:

+ +

On the right-hand side of the plugin’s customization dialog, you will see a button with an icon that looks like a computer’s hard-drive. Use this button to export the highlighted key to a file (with a ‘.der’ file name extension). Used for backup purposes or to migrate key data to other computers/calibre installations. The dialog will prompt you for a place to save the file.

+ +

Linux Users: WINEPREFIX

+ +

Under the list of keys, Linux users will see a text field labeled "WINEPREFIX". If you are use Adobe Digital Editions under Wine, and your wine installation containing Adobe Digital Editions isn't the default Wine installation, you may enter the full path to the correct Wine installation here. Leave blank if you are unsure.

+ +

Importing Existing Keyfiles:

+ +

At the bottom-left of the plugin’s customization dialog, you will see a button labeled "Import Existing Keyfiles". Use this button to import existing ‘.der’ key files. Key files might come from being exported from this or older plugins, or may have been generated using the adobekey.pyw script running under Wine on Linux systems.

+ +

Once done creating/deleting/renaming/importing decryption keys, click Close to exit the customization dialogue. Your changes will only be saved permanently when you click OK in the main configuration dialog.

+ + + + + diff --git a/arch-config/.config/calibre/plugins/DeDRM/help/DeDRM_Help.htm b/arch-config/.config/calibre/plugins/DeDRM/help/DeDRM_Help.htm new file mode 100644 index 00000000..5d851592 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeDRM/help/DeDRM_Help.htm @@ -0,0 +1,79 @@ + + + + + + +DeDRM Plugin Configuration + + + + + +

DeDRM Plugin (v10.0.3)

+ +

This plugin removes DRM from ebooks when they are imported into calibre. If you already have DRMed ebooks in your calibre library, you will need to remove them and import them again.

+ +

It is a forked version created by NoDRM, based on the original plugin by Apprentice Alf and Apprentice Harper.

+ +

Installation

+

You have obviously managed to install the plugin, as otherwise you wouldn’t be reading this help file. However, you should also delete any older DRM removal plugins, as this DeDRM plugin replaces the five older plugins: Kindle and Mobipocket DeDRM (K4MobiDeDRM), Ignoble Epub DeDRM (ignobleepub), Inept Epub DeDRM (ineptepub), Inept PDF DeDRM (ineptepub) and eReader PDB 2 PML (eReaderPDB2PML).

+ +

Configuration

+

On Windows and Mac, the keys for ebooks downloaded for Kindle for Mac/PC and Adobe Digital Editions are automatically generated. If all your DRMed ebooks can be opened and read in Kindle for Mac/PC and/or Adobe Digital Editions on the same computer on which you are running calibre, you do not need to do any configuration of this plugin. On Linux, keys for Kindle for PC and Adobe Digital Editions need to be generated separately (see the Linux section below).

+ +

If you are using the DeACSM / ACSM Input Plugin for Calibre, the keys will also automatically be dumped for you.

+ +

If you have other DRMed ebooks, you will need to enter extra configuration information. The buttons in this dialog will open individual configuration dialogs that will allow you to enter the needed information, depending on the type and source of your DRMed eBooks. Additional help on the information required is available in each of the the dialogs.

+ +

If you have used previous versions of the various DeDRM plugins on this machine, you may find that some of the configuration dialogs already contain the information you entered through those previous plugins.

+ +

When you have finished entering your configuration information, you must click the OK button to save it. If you click the Cancel button, all your changes in all the configuration dialogs will be lost.

+ +

Troubleshooting:

+ +

If you find that it’s not working for you , you can save a lot of time by trying to add the ebook to Calibre in debug mode. This will print out a lot of helpful info that can be copied into any online help requests.

+ +

Open a command prompt (terminal window) and type "calibre-debug -g" (without the quotes). Calibre will launch, and you can can add the problem ebook the usual way. The debug info will be output to the original command prompt (terminal window). Copy the resulting output and paste it into the comment you make at my blog.

+

Note: The Mac version of Calibre doesn’t install the command line tools by default. If you go to the ‘Preferences’ page and click on the miscellaneous button, you’ll find the option to install the command line tools.

+ +

Credits:

+ + +

For additional help read the FAQs at NoDRM's GitHub repository (or the corresponding FAQs at Apprentice Harpers’s GitHub repository). You can open issue reportsrelated to this fork at NoDRM's GitHub repository.

+ + +

Linux Systems Only

+

Generating decryption keys for Adobe Digital Editions and Kindle for PC

+

If you install Kindle for PC and/or Adobe Digital Editions in Wine, you will be able to download DRMed ebooks to them under Wine. To be able to remove the DRM, you will need to generate key files and add them in the plugin's customisation dialogs.

+ +

To generate the key files you will need to install Python and PyCrypto under the same Wine setup as your Kindle for PC and/or Adobe Digital Editions installations. (Kindle for PC, Python and Pycrypto installation instructions in the ReadMe.)

+ +

Once everything's installed under Wine, you'll need to run the adobekey.pyw script (for Adobe Digital Editions) and kindlekey.pyw (For Kindle for PC) using the python installation in your Wine system. The scripts can be found in Other_Tools/Key_Retrieval_Scripts.

+ +

Each script will create a key file in the same folder as the script. Copy the key files to your Linux system and then load the key files using the Adobe Digital Editions ebooks dialog and the Kindle for Mac/PC ebooks dialog.

+ + + + + diff --git a/arch-config/.config/calibre/plugins/DeDRM/help/DeDRM_Kindle for Mac and PC Key_Help.htm b/arch-config/.config/calibre/plugins/DeDRM/help/DeDRM_Kindle for Mac and PC Key_Help.htm new file mode 100644 index 00000000..77f6136f --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeDRM/help/DeDRM_Kindle for Mac and PC Key_Help.htm @@ -0,0 +1,59 @@ + + + + + + +Managing Kindle for Mac/PC Keys + + + + + +

Managing Kindle for Mac/PC Keys

+ + +

If you have upgraded from an earlier version of the plugin, any existing Kindle for Mac/PC keys will have been automatically imported, so you might not need to do any more configuration. In addition, on Windows and Mac, the default Kindle for Mac/PC key is added the first time the plugin is run. Continue reading for key generation and management instructions.

+ +

Creating New Keys:

+ +

On the right-hand side of the plugin’s customization dialog, you will see a button with an icon that looks like a green plus sign (+). Clicking this button will open a new dialog prompting you to enter a key name for the default Kindle for Mac/PC key.

+ + +

Click the OK button to create and store the Kindle for Mac/PC key for the current installation of Kindle for Mac/PC. Or Cancel if you don’t want to create the key.

+

New keys are checked against the current list of keys before being added, and duplicates are discarded.

+ +

Deleting Keys:

+ +

On the right-hand side of the plugin’s customization dialog, you will see a button with an icon that looks like a red "X". Clicking this button will delete the highlighted key in the list. You will be prompted once to be sure that’s what you truly mean to do. Once gone, it’s permanently gone.

+ +

Renaming Keys:

+ +

On the right-hand side of the plugin’s customization dialog, you will see a button with an icon that looks like a sheet of paper. Clicking this button will prompt you to enter a new name for the highlighted key in the list. Enter the new name for the encryption key and click the OK button to use the new name, or Cancel to revert to the old name..

+ +

Exporting Keys:

+ +

On the right-hand side of the plugin’s customization dialog, you will see a button with an icon that looks like a computer’s hard-drive. Use this button to export the highlighted key to a file (with a ‘.der’ file name extension). Used for backup purposes or to migrate key data to other computers/calibre installations. The dialog will prompt you for a place to save the file.

+ +

Linux Users: WINEPREFIX

+ +

Under the list of keys, Linux users will see a text field labeled "WINEPREFIX". If you are using the Kindle for PC under Wine, and your wine installation containing Kindle for PC isn't the default Wine installation, you may enter the full path to the correct Wine installation here. Leave blank if you are unsure.

+ +

Importing Existing Keyfiles:

+ +

At the bottom-left of the plugin’s customization dialog, you will see a button labeled "Import Existing Keyfiles". Use this button to import existing ‘.k4i’ key files. Key files might come from being exported from this plugin, or may have been generated using the kindlekey.pyw script running under Wine on Linux systems.

+ +

Once done creating/deleting/renaming/importing decryption keys, click Close to exit the customization dialogue. Your changes wil only be saved permanently when you click OK in the main configuration dialog.

+ + + + diff --git a/arch-config/.config/calibre/plugins/DeDRM/libraryfiles/adobekey.py b/arch-config/.config/calibre/plugins/DeDRM/libraryfiles/adobekey.py new file mode 100644 index 00000000..50e2c713 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeDRM/libraryfiles/adobekey.py @@ -0,0 +1,626 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +# adobekey.pyw, version 7.4 +# Copyright © 2009-2022 i♥cabbages, Apprentice Harper et al. + +# Released under the terms of the GNU General Public Licence, version 3 +# + +# Revision history: +# 1 - Initial release, for Adobe Digital Editions 1.7 +# 2 - Better algorithm for finding pLK; improved error handling +# 3 - Rename to INEPT +# 4 - Series of changes by joblack (and others?) -- +# 4.1 - quick beta fix for ADE 1.7.2 (anon) +# 4.2 - added old 1.7.1 processing +# 4.3 - better key search +# 4.4 - Make it working on 64-bit Python +# 5 - Clean up and improve 4.x changes; +# Clean up and merge OS X support by unknown +# 5.1 - add support for using OpenSSL on Windows in place of PyCrypto +# 5.2 - added support for output of key to a particular file +# 5.3 - On Windows try PyCrypto first, OpenSSL next +# 5.4 - Modify interface to allow use of import +# 5.5 - Fix for potential problem with PyCrypto +# 5.6 - Revised to allow use in Plugins to eliminate need for duplicate code +# 5.7 - Unicode support added, renamed adobekey from ineptkey +# 5.8 - Added getkey interface for Windows DeDRM application +# 5.9 - moved unicode_argv call inside main for Windows DeDRM compatibility +# 6.0 - Work if TkInter is missing +# 7.0 - Python 3 for calibre 5 +# 7.1 - Fix "failed to decrypt user key key" error (read username from registry) +# 7.2 - Fix decryption error on Python2 if there's unicode in the username +# 7.3 - Fix OpenSSL in Wine +# 7.4 - Remove OpenSSL support to only support PyCryptodome + +""" +Retrieve Adobe ADEPT user key. +""" + +__license__ = 'GPL v3' +__version__ = '7.4' + +import sys, os, struct, getopt +from base64 import b64decode + + +# Wrap a stream so that output gets flushed immediately +# and also make sure that any unicode strings get +# encoded using "replace" before writing them. +class SafeUnbuffered: + def __init__(self, stream): + self.stream = stream + self.encoding = stream.encoding + if self.encoding == None: + self.encoding = "utf-8" + def write(self, data): + if isinstance(data,str) or isinstance(data,unicode): + # str for Python3, unicode for Python2 + data = data.encode(self.encoding,"replace") + try: + buffer = getattr(self.stream, 'buffer', self.stream) + # self.stream.buffer for Python3, self.stream for Python2 + buffer.write(data) + buffer.flush() + except: + # We can do nothing if a write fails + raise + def __getattr__(self, attr): + return getattr(self.stream, attr) + +try: + from calibre.constants import iswindows, isosx +except: + iswindows = sys.platform.startswith('win') + isosx = sys.platform.startswith('darwin') + +def unicode_argv(): + if iswindows: + # Uses shell32.GetCommandLineArgvW to get sys.argv as a list of Unicode + # strings. + + # Versions 2.x of Python don't support Unicode in sys.argv on + # Windows, with the underlying Windows API instead replacing multi-byte + # characters with '?'. So use shell32.GetCommandLineArgvW to get sys.argv + # as a list of Unicode strings and encode them as utf-8 + + from ctypes import POINTER, byref, cdll, c_int, windll + from ctypes.wintypes import LPCWSTR, LPWSTR + + GetCommandLineW = cdll.kernel32.GetCommandLineW + GetCommandLineW.argtypes = [] + GetCommandLineW.restype = LPCWSTR + + CommandLineToArgvW = windll.shell32.CommandLineToArgvW + CommandLineToArgvW.argtypes = [LPCWSTR, POINTER(c_int)] + CommandLineToArgvW.restype = POINTER(LPWSTR) + + cmd = GetCommandLineW() + argc = c_int(0) + argv = CommandLineToArgvW(cmd, byref(argc)) + if argc.value > 0: + # Remove Python executable and commands if present + start = argc.value - len(sys.argv) + return [argv[i] for i in + range(start, argc.value)] + # if we don't have any arguments at all, just pass back script name + # this should never happen + return ["adobekey.py"] + else: + argvencoding = sys.stdin.encoding or "utf-8" + return [arg if (isinstance(arg, str) or isinstance(arg,unicode)) else str(arg, argvencoding) for arg in sys.argv] + +class ADEPTError(Exception): + pass + +if iswindows: + from ctypes import windll, c_char_p, c_wchar_p, c_uint, POINTER, byref, \ + create_unicode_buffer, create_string_buffer, CFUNCTYPE, addressof, \ + string_at, Structure, c_void_p, cast, c_size_t, memmove, CDLL, c_int, \ + c_long, c_ulong + + from ctypes.wintypes import LPVOID, DWORD, BOOL + try: + import winreg + except ImportError: + import _winreg as winreg + + try: + from Cryptodome.Cipher import AES + except ImportError: + from Crypto.Cipher import AES + + def unpad(data, padding=16): + if sys.version_info[0] == 2: + pad_len = ord(data[-1]) + else: + pad_len = data[-1] + + return data[:-pad_len] + + DEVICE_KEY_PATH = r'Software\Adobe\Adept\Device' + PRIVATE_LICENCE_KEY_PATH = r'Software\Adobe\Adept\Activation' + + MAX_PATH = 255 + + kernel32 = windll.kernel32 + advapi32 = windll.advapi32 + crypt32 = windll.crypt32 + + def GetSystemDirectory(): + GetSystemDirectoryW = kernel32.GetSystemDirectoryW + GetSystemDirectoryW.argtypes = [c_wchar_p, c_uint] + GetSystemDirectoryW.restype = c_uint + def GetSystemDirectory(): + buffer = create_unicode_buffer(MAX_PATH + 1) + GetSystemDirectoryW(buffer, len(buffer)) + return buffer.value + return GetSystemDirectory + GetSystemDirectory = GetSystemDirectory() + + def GetVolumeSerialNumber(): + GetVolumeInformationW = kernel32.GetVolumeInformationW + GetVolumeInformationW.argtypes = [c_wchar_p, c_wchar_p, c_uint, + POINTER(c_uint), POINTER(c_uint), + POINTER(c_uint), c_wchar_p, c_uint] + GetVolumeInformationW.restype = c_uint + def GetVolumeSerialNumber(path): + vsn = c_uint(0) + GetVolumeInformationW( + path, None, 0, byref(vsn), None, None, None, 0) + return vsn.value + return GetVolumeSerialNumber + GetVolumeSerialNumber = GetVolumeSerialNumber() + + def GetUserName(): + GetUserNameW = advapi32.GetUserNameW + GetUserNameW.argtypes = [c_wchar_p, POINTER(c_uint)] + GetUserNameW.restype = c_uint + def GetUserName(): + buffer = create_unicode_buffer(32) + size = c_uint(len(buffer)) + while not GetUserNameW(buffer, byref(size)): + buffer = create_unicode_buffer(len(buffer) * 2) + size.value = len(buffer) + return buffer.value.encode('utf-16-le')[::2] + return GetUserName + GetUserName = GetUserName() + + def GetUserName2(): + try: + from winreg import OpenKey, QueryValueEx, HKEY_CURRENT_USER + except ImportError: + # We're on Python 2 + try: + # The default _winreg on Python2 isn't unicode-safe. + # Check if we have winreg_unicode, a unicode-safe alternative. + # Without winreg_unicode, this will fail with Unicode chars in the username. + from adobekey_winreg_unicode import OpenKey, QueryValueEx, HKEY_CURRENT_USER + except: + from _winreg import OpenKey, QueryValueEx, HKEY_CURRENT_USER + + try: + DEVICE_KEY_PATH = r'Software\Adobe\Adept\Device' + regkey = OpenKey(HKEY_CURRENT_USER, DEVICE_KEY_PATH) + userREG = QueryValueEx(regkey, 'username')[0].encode('utf-16-le')[::2] + return userREG + except: + return None + + PAGE_EXECUTE_READWRITE = 0x40 + MEM_COMMIT = 0x1000 + MEM_RESERVE = 0x2000 + + def VirtualAlloc(): + _VirtualAlloc = kernel32.VirtualAlloc + _VirtualAlloc.argtypes = [LPVOID, c_size_t, DWORD, DWORD] + _VirtualAlloc.restype = LPVOID + def VirtualAlloc(addr, size, alloctype=(MEM_COMMIT | MEM_RESERVE), + protect=PAGE_EXECUTE_READWRITE): + return _VirtualAlloc(addr, size, alloctype, protect) + return VirtualAlloc + VirtualAlloc = VirtualAlloc() + + MEM_RELEASE = 0x8000 + + def VirtualFree(): + _VirtualFree = kernel32.VirtualFree + _VirtualFree.argtypes = [LPVOID, c_size_t, DWORD] + _VirtualFree.restype = BOOL + def VirtualFree(addr, size=0, freetype=MEM_RELEASE): + return _VirtualFree(addr, size, freetype) + return VirtualFree + VirtualFree = VirtualFree() + + class NativeFunction(object): + def __init__(self, restype, argtypes, insns): + self._buf = buf = VirtualAlloc(None, len(insns)) + memmove(buf, insns, len(insns)) + ftype = CFUNCTYPE(restype, *argtypes) + self._native = ftype(buf) + + def __call__(self, *args): + return self._native(*args) + + def __del__(self): + if self._buf is not None: + try: + VirtualFree(self._buf) + self._buf = None + except TypeError: + # Apparently this sometimes gets cleared on application exit + # Causes a useless exception in the log, so let's just catch and ignore that. + pass + + if struct.calcsize("P") == 4: + CPUID0_INSNS = ( + b"\x53" # push %ebx + b"\x31\xc0" # xor %eax,%eax + b"\x0f\xa2" # cpuid + b"\x8b\x44\x24\x08" # mov 0x8(%esp),%eax + b"\x89\x18" # mov %ebx,0x0(%eax) + b"\x89\x50\x04" # mov %edx,0x4(%eax) + b"\x89\x48\x08" # mov %ecx,0x8(%eax) + b"\x5b" # pop %ebx + b"\xc3" # ret + ) + CPUID1_INSNS = ( + b"\x53" # push %ebx + b"\x31\xc0" # xor %eax,%eax + b"\x40" # inc %eax + b"\x0f\xa2" # cpuid + b"\x5b" # pop %ebx + b"\xc3" # ret + ) + else: + CPUID0_INSNS = ( + b"\x49\x89\xd8" # mov %rbx,%r8 + b"\x49\x89\xc9" # mov %rcx,%r9 + b"\x48\x31\xc0" # xor %rax,%rax + b"\x0f\xa2" # cpuid + b"\x4c\x89\xc8" # mov %r9,%rax + b"\x89\x18" # mov %ebx,0x0(%rax) + b"\x89\x50\x04" # mov %edx,0x4(%rax) + b"\x89\x48\x08" # mov %ecx,0x8(%rax) + b"\x4c\x89\xc3" # mov %r8,%rbx + b"\xc3" # retq + ) + CPUID1_INSNS = ( + b"\x53" # push %rbx + b"\x48\x31\xc0" # xor %rax,%rax + b"\x48\xff\xc0" # inc %rax + b"\x0f\xa2" # cpuid + b"\x5b" # pop %rbx + b"\xc3" # retq + ) + + def cpuid0(): + _cpuid0 = NativeFunction(None, [c_char_p], CPUID0_INSNS) + buf = create_string_buffer(12) + def cpuid0(): + _cpuid0(buf) + return buf.raw + return cpuid0 + cpuid0 = cpuid0() + + cpuid1 = NativeFunction(c_uint, [], CPUID1_INSNS) + + class DataBlob(Structure): + _fields_ = [('cbData', c_uint), + ('pbData', c_void_p)] + DataBlob_p = POINTER(DataBlob) + + def CryptUnprotectData(): + _CryptUnprotectData = crypt32.CryptUnprotectData + _CryptUnprotectData.argtypes = [DataBlob_p, c_wchar_p, DataBlob_p, + c_void_p, c_void_p, c_uint, DataBlob_p] + _CryptUnprotectData.restype = c_uint + def CryptUnprotectData(indata, entropy): + indatab = create_string_buffer(indata) + indata = DataBlob(len(indata), cast(indatab, c_void_p)) + entropyb = create_string_buffer(entropy) + entropy = DataBlob(len(entropy), cast(entropyb, c_void_p)) + outdata = DataBlob() + if not _CryptUnprotectData(byref(indata), None, byref(entropy), + None, None, 0, byref(outdata)): + raise ADEPTError("Failed to decrypt user key key (sic)") + return string_at(outdata.pbData, outdata.cbData) + return CryptUnprotectData + CryptUnprotectData = CryptUnprotectData() + + def adeptkeys(): + root = GetSystemDirectory().split('\\')[0] + '\\' + serial = GetVolumeSerialNumber(root) + vendor = cpuid0() + signature = struct.pack('>I', cpuid1())[1:] + user = GetUserName2() + if user is None: + user = GetUserName() + entropy = struct.pack('>I12s3s13s', serial, vendor, signature, user) + cuser = winreg.HKEY_CURRENT_USER + try: + regkey = winreg.OpenKey(cuser, DEVICE_KEY_PATH) + device = winreg.QueryValueEx(regkey, 'key')[0] + except (WindowsError, FileNotFoundError): + raise ADEPTError("Adobe Digital Editions not activated") + keykey = CryptUnprotectData(device, entropy) + userkey = None + keys = [] + names = [] + try: + plkroot = winreg.OpenKey(cuser, PRIVATE_LICENCE_KEY_PATH) + except (WindowsError, FileNotFoundError): + raise ADEPTError("Could not locate ADE activation") + + i = -1 + while True: + i = i + 1 # start with 0 + try: + plkparent = winreg.OpenKey(plkroot, "%04d" % (i,)) + except: + # No more keys + break + + ktype = winreg.QueryValueEx(plkparent, None)[0] + if ktype != 'credentials': + continue + uuid_name = "" + for j in range(0, 16): + try: + plkkey = winreg.OpenKey(plkparent, "%04d" % (j,)) + except (WindowsError, FileNotFoundError): + break + ktype = winreg.QueryValueEx(plkkey, None)[0] + if ktype == 'user': + # Add Adobe UUID to key name + uuid_name = uuid_name + winreg.QueryValueEx(plkkey, 'value')[0][9:] + "_" + if ktype == 'username': + # Add account type & email to key name, if present + try: + uuid_name = uuid_name + winreg.QueryValueEx(plkkey, 'method')[0] + "_" + except: + pass + try: + uuid_name = uuid_name + winreg.QueryValueEx(plkkey, 'value')[0] + "_" + except: + pass + if ktype == 'privateLicenseKey': + userkey = winreg.QueryValueEx(plkkey, 'value')[0] + userkey = unpad(AES.new(keykey, AES.MODE_CBC, b'\x00'*16).decrypt(b64decode(userkey)))[26:] + # print ("found " + uuid_name + " key: " + str(userkey)) + keys.append(userkey) + + if uuid_name == "": + names.append("Unknown") + else: + names.append(uuid_name[:-1]) + + if len(keys) == 0: + raise ADEPTError('Could not locate privateLicenseKey') + print("Found {0:d} keys".format(len(keys))) + return keys, names + + +elif isosx: + import xml.etree.ElementTree as etree + import subprocess + + NSMAP = {'adept': 'http://ns.adobe.com/adept', + 'enc': 'http://www.w3.org/2001/04/xmlenc#'} + + def findActivationDat(): + import warnings + warnings.filterwarnings('ignore', category=FutureWarning) + + home = os.getenv('HOME') + cmdline = 'find "' + home + '/Library/Application Support/Adobe/Digital Editions" -name "activation.dat"' + cmdline = cmdline.encode(sys.getfilesystemencoding()) + p2 = subprocess.Popen(cmdline, shell=True, stdin=None, stdout=subprocess.PIPE, stderr=subprocess.PIPE, close_fds=False) + out1, out2 = p2.communicate() + reslst = out1.split(b'\n') + cnt = len(reslst) + ActDatPath = b"activation.dat" + for j in range(cnt): + resline = reslst[j] + pp = resline.find(b'activation.dat') + if pp >= 0: + ActDatPath = resline + break + if os.path.exists(ActDatPath): + return ActDatPath + return None + + def adeptkeys(): + # TODO: All the code to support extracting multiple activation keys + # TODO: seems to be Windows-only currently, still needs to be added for Mac. + actpath = findActivationDat() + if actpath is None: + raise ADEPTError("Could not find ADE activation.dat file.") + tree = etree.parse(actpath) + adept = lambda tag: '{%s}%s' % (NSMAP['adept'], tag) + expr = '//%s/%s' % (adept('credentials'), adept('privateLicenseKey')) + userkey = tree.findtext(expr) + + exprUUID = '//%s/%s' % (adept('credentials'), adept('user')) + keyName = "" + try: + keyName = tree.findtext(exprUUID)[9:] + "_" + except: + pass + + try: + exprMail = '//%s/%s' % (adept('credentials'), adept('username')) + keyName = keyName + tree.find(exprMail).attrib["method"] + "_" + keyName = keyName + tree.findtext(exprMail) + "_" + except: + pass + + if keyName == "": + keyName = "Unknown" + else: + keyName = keyName[:-1] + + + + userkey = b64decode(userkey) + userkey = userkey[26:] + return [userkey], [keyName] + +else: + def adeptkeys(): + raise ADEPTError("This script only supports Windows and Mac OS X.") + return [], [] + +# interface for Python DeDRM +def getkey(outpath): + keys, names = adeptkeys() + if len(keys) > 0: + if not os.path.isdir(outpath): + outfile = outpath + with open(outfile, 'wb') as keyfileout: + keyfileout.write(keys[0]) + print("Saved a key to {0}".format(outfile)) + else: + keycount = 0 + name_index = 0 + for key in keys: + while True: + keycount += 1 + outfile = os.path.join(outpath,"adobekey{0:d}_uuid_{1}.der".format(keycount, names[name_index])) + if not os.path.exists(outfile): + break + with open(outfile, 'wb') as keyfileout: + keyfileout.write(key) + print("Saved a key to {0}".format(outfile)) + name_index += 1 + return True + return False + +def usage(progname): + print("Finds, decrypts and saves the default Adobe Adept encryption key(s).") + print("Keys are saved to the current directory, or a specified output directory.") + print("If a file name is passed instead of a directory, only the first key is saved, in that file.") + print("Usage:") + print(" {0:s} [-h] []".format(progname)) + +def cli_main(): + sys.stdout=SafeUnbuffered(sys.stdout) + sys.stderr=SafeUnbuffered(sys.stderr) + argv=unicode_argv() + progname = os.path.basename(argv[0]) + print("{0} v{1}\nCopyright © 2009-2020 i♥cabbages, Apprentice Harper et al.".format(progname,__version__)) + + try: + opts, args = getopt.getopt(argv[1:], "h") + except getopt.GetoptError as err: + print("Error in options or arguments: {0}".format(err.args[0])) + usage(progname) + sys.exit(2) + + for o, a in opts: + if o == "-h": + usage(progname) + sys.exit(0) + + if len(args) > 1: + usage(progname) + sys.exit(2) + + if len(args) == 1: + # save to the specified file or directory + outpath = args[0] + if not os.path.isabs(outpath): + outpath = os.path.abspath(outpath) + else: + # save to the same directory as the script + outpath = os.path.dirname(argv[0]) + + # make sure the outpath is the + outpath = os.path.realpath(os.path.normpath(outpath)) + + keys, names = adeptkeys() + if len(keys) > 0: + if not os.path.isdir(outpath): + outfile = outpath + with open(outfile, 'wb') as keyfileout: + keyfileout.write(keys[0]) + print("Saved a key to {0}".format(outfile)) + else: + keycount = 0 + name_index = 0 + for key in keys: + while True: + keycount += 1 + outfile = os.path.join(outpath,"adobekey{0:d}_uuid_{1}.der".format(keycount, names[name_index])) + if not os.path.exists(outfile): + break + with open(outfile, 'wb') as keyfileout: + keyfileout.write(key) + print("Saved a key to {0}".format(outfile)) + name_index += 1 + else: + print("Could not retrieve Adobe Adept key.") + return 0 + + +def gui_main(): + try: + import tkinter + import tkinter.constants + import tkinter.messagebox + import traceback + except: + return cli_main() + + class ExceptionDialog(tkinter.Frame): + def __init__(self, root, text): + tkinter.Frame.__init__(self, root, border=5) + label = tkinter.Label(self, text="Unexpected error:", + anchor=tkinter.constants.W, justify=tkinter.constants.LEFT) + label.pack(fill=tkinter.constants.X, expand=0) + self.text = tkinter.Text(self) + self.text.pack(fill=tkinter.constants.BOTH, expand=1) + + self.text.insert(tkinter.constants.END, text) + + + argv=unicode_argv() + root = tkinter.Tk() + root.withdraw() + progpath, progname = os.path.split(argv[0]) + success = False + try: + keys, names = adeptkeys() + print(keys) + print(names) + keycount = 0 + name_index = 0 + for key in keys: + while True: + keycount += 1 + outfile = os.path.join(progpath,"adobekey{0:d}_uuid_{1}.der".format(keycount, names[name_index])) + if not os.path.exists(outfile): + break + + with open(outfile, 'wb') as keyfileout: + keyfileout.write(key) + success = True + tkinter.messagebox.showinfo(progname, "Key successfully retrieved to {0}".format(outfile)) + name_index += 1 + except ADEPTError as e: + tkinter.messagebox.showerror(progname, "Error: {0}".format(str(e))) + except Exception: + root.wm_state('normal') + root.title(progname) + text = traceback.format_exc() + ExceptionDialog(root, text).pack(fill=tkinter.constants.BOTH, expand=1) + root.mainloop() + if not success: + return 1 + return 0 + +if __name__ == '__main__': + if len(sys.argv) > 1: + sys.exit(cli_main()) + sys.exit(gui_main()) diff --git a/arch-config/.config/calibre/plugins/DeDRM/libraryfiles/kindlekey.py b/arch-config/.config/calibre/plugins/DeDRM/libraryfiles/kindlekey.py new file mode 100644 index 00000000..0ce800d8 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeDRM/libraryfiles/kindlekey.py @@ -0,0 +1,1087 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +# kindlekey.py +# Copyright © 2008-2022 Apprentice Harper et al. + +__license__ = 'GPL v3' +__version__ = '3.1' + +# Revision history: +# 1.0 - Kindle info file decryption, extracted from k4mobidedrm, etc. +# 1.1 - Added Tkinter to match adobekey.py +# 1.2 - Fixed testing of successful retrieval on Mac +# 1.3 - Added getkey interface for Windows DeDRM application +# Simplified some of the Kindle for Mac code. +# 1.4 - Remove dependency on alfcrypto +# 1.5 - moved unicode_argv call inside main for Windows DeDRM compatibility +# 1.6 - Fixed a problem getting the disk serial numbers +# 1.7 - Work if TkInter is missing +# 1.8 - Fixes for Kindle for Mac, and non-ascii in Windows user names +# 1.9 - Fixes for Unicode in Windows user names +# 2.0 - Added comments and extra fix for non-ascii Windows user names +# 2.1 - Fixed Kindle for PC encryption changes March 2016 +# 2.2 - Fixes for Macs with bonded ethernet ports +# Also removed old .kinfo file support (pre-2011) +# 2.3 - Added more field names thanks to concavegit's KFX code. +# 2.4 - Fix for complex Mac disk setups, thanks to Tibs +# 2.5 - Final Fix for Windows user names with non-ascii characters, thanks to oneofusoneofus +# 2.6 - Start adding support for Kindle 1.25+ .kinf2018 file +# 2.7 - Finish .kinf2018 support, PC & Mac by Apprentice Sakuya +# 2.8 - Fix for Mac OS X Big Sur +# 3.0 - Python 3 for calibre 5.0 +# 3.1 - Only support PyCryptodome; clean up the code + + +""" +Retrieve Kindle for PC/Mac user key. +""" + +import sys, os, re +import codecs +from struct import pack, unpack, unpack_from +import json +import getopt +import traceback +import hashlib + +try: + from Cryptodome.Cipher import AES + from Cryptodome.Util import Counter + from Cryptodome.Protocol.KDF import PBKDF2 +except ImportError: + from Crypto.Cipher import AES + from Crypto.Util import Counter + from Crypto.Protocol.KDF import PBKDF2 + +try: + RegError +except NameError: + class RegError(Exception): + pass + +# Routines common to Mac and PC + +# Wrap a stream so that output gets flushed immediately +# and also make sure that any unicode strings get +# encoded using "replace" before writing them. +class SafeUnbuffered: + def __init__(self, stream): + self.stream = stream + self.encoding = stream.encoding + if self.encoding == None: + self.encoding = "utf-8" + def write(self, data): + if isinstance(data,str) or isinstance(data,unicode): + # str for Python3, unicode for Python2 + data = data.encode(self.encoding,"replace") + try: + buffer = getattr(self.stream, 'buffer', self.stream) + # self.stream.buffer for Python3, self.stream for Python2 + buffer.write(data) + buffer.flush() + except: + # We can do nothing if a write fails + raise + def __getattr__(self, attr): + return getattr(self.stream, attr) + +try: + from calibre.constants import iswindows, isosx +except: + iswindows = sys.platform.startswith('win') + isosx = sys.platform.startswith('darwin') + +def unicode_argv(): + if iswindows: + # Uses shell32.GetCommandLineArgvW to get sys.argv as a list of Unicode + # strings. + + # Versions 2.x of Python don't support Unicode in sys.argv on + # Windows, with the underlying Windows API instead replacing multi-byte + # characters with '?'. So use shell32.GetCommandLineArgvW to get sys.argv + # as a list of Unicode strings and encode them as utf-8 + + from ctypes import POINTER, byref, cdll, c_int, windll + from ctypes.wintypes import LPCWSTR, LPWSTR + + GetCommandLineW = cdll.kernel32.GetCommandLineW + GetCommandLineW.argtypes = [] + GetCommandLineW.restype = LPCWSTR + + CommandLineToArgvW = windll.shell32.CommandLineToArgvW + CommandLineToArgvW.argtypes = [LPCWSTR, POINTER(c_int)] + CommandLineToArgvW.restype = POINTER(LPWSTR) + + cmd = GetCommandLineW() + argc = c_int(0) + argv = CommandLineToArgvW(cmd, byref(argc)) + if argc.value > 0: + # Remove Python executable and commands if present + start = argc.value - len(sys.argv) + return [argv[i] for i in + range(start, argc.value)] + # if we don't have any arguments at all, just pass back script name + # this should never happen + return ["kindlekey.py"] + else: + argvencoding = sys.stdin.encoding or "utf-8" + return [arg if (isinstance(arg, str) or isinstance(arg,unicode)) else str(arg, argvencoding) for arg in sys.argv] + +class DrmException(Exception): + pass + +# crypto digestroutines + +def MD5(message): + return hashlib.md5(message).digest() + +def SHA1(message): + return hashlib.sha1(message).digest() + +def SHA256(message): + return hashlib.sha256(message).digest() + + +# For K4M/PC 1.6.X and later +def primes(n): + """ + Return a list of prime integers smaller than or equal to n + :param n: int + :return: list->int + """ + if n == 2: + return [2] + elif n < 2: + return [] + primeList = [2] + + for potentialPrime in range(3, n + 1, 2): + isItPrime = True + for prime in primeList: + if potentialPrime % prime == 0: + isItPrime = False + if isItPrime is True: + primeList.append(potentialPrime) + + return primeList + +# Encode the bytes in data with the characters in map +# data and map should be byte arrays +def encode(data, map): + result = b'' + for char in data: + value = char + Q = (value ^ 0x80) // len(map) + R = value % len(map) + result += bytes([map[Q]]) + result += bytes([map[R]]) + return result + +# Hash the bytes in data and then encode the digest with the characters in map +def encodeHash(data,map): + return encode(MD5(data),map) + +# Decode the string in data with the characters in map. Returns the decoded bytes +def decode(data,map): + result = b'' + for i in range (0,len(data)-1,2): + high = map.find(data[i]) + low = map.find(data[i+1]) + if (high == -1) or (low == -1) : + break + value = (((high * len(map)) ^ 0x80) & 0xFF) + low + result += pack('B',value) + return result + +def UnprotectHeaderData(encryptedData): + passwdData = b'header_key_data' + salt = b'HEADER.2011' + key_iv = PBKDF2(passwdData, salt, dkLen=256, count=128) + return AES.new(key_iv[0:32], AES.MODE_CBC, key_iv[32:48]).decrypt(encryptedData) + +# Routines unique to Mac and PC +if iswindows: + from ctypes import windll, c_char_p, c_wchar_p, c_uint, POINTER, byref, \ + create_unicode_buffer, create_string_buffer, CFUNCTYPE, addressof, \ + string_at, Structure, c_void_p, cast + + try: + import winreg + except ImportError: + import _winreg as winreg + + MAX_PATH = 255 + kernel32 = windll.kernel32 + advapi32 = windll.advapi32 + crypt32 = windll.crypt32 + + # Various character maps used to decrypt kindle info values. + # Probably supposed to act as obfuscation + charMap2 = b"AaZzB0bYyCc1XxDdW2wEeVv3FfUuG4g-TtHh5SsIiR6rJjQq7KkPpL8lOoMm9Nn_" + charMap5 = b"AzB0bYyCeVvaZ3FfUuG4g-TtHh5SsIiR6rJjQq7KkPpL8lOoMm9Nn_c1XxDdW2wE" + # New maps in K4PC 1.9.0 + testMap1 = b"n5Pr6St7Uv8Wx9YzAb0Cd1Ef2Gh3Jk4M" + testMap6 = b"9YzAb0Cd1Ef2n5Pr6St7Uvh3Jk4M8WxG" + testMap8 = b"YvaZ3FfUm9Nn_c1XuG4yCAzB0beVg-TtHh5SsIiR6rJjQdW2wEq7KkPpL8lOoMxD" + + # interface with Windows OS Routines + class DataBlob(Structure): + _fields_ = [('cbData', c_uint), + ('pbData', c_void_p)] + DataBlob_p = POINTER(DataBlob) + + + def GetSystemDirectory(): + GetSystemDirectoryW = kernel32.GetSystemDirectoryW + GetSystemDirectoryW.argtypes = [c_wchar_p, c_uint] + GetSystemDirectoryW.restype = c_uint + def GetSystemDirectory(): + buffer = create_unicode_buffer(MAX_PATH + 1) + GetSystemDirectoryW(buffer, len(buffer)) + return buffer.value + return GetSystemDirectory + GetSystemDirectory = GetSystemDirectory() + + def GetVolumeSerialNumber(): + GetVolumeInformationW = kernel32.GetVolumeInformationW + GetVolumeInformationW.argtypes = [c_wchar_p, c_wchar_p, c_uint, + POINTER(c_uint), POINTER(c_uint), + POINTER(c_uint), c_wchar_p, c_uint] + GetVolumeInformationW.restype = c_uint + def GetVolumeSerialNumber(path = GetSystemDirectory().split('\\')[0] + '\\'): + vsn = c_uint(0) + GetVolumeInformationW(path, None, 0, byref(vsn), None, None, None, 0) + return str(vsn.value) + return GetVolumeSerialNumber + GetVolumeSerialNumber = GetVolumeSerialNumber() + + def GetIDString(): + vsn = GetVolumeSerialNumber() + #print('Using Volume Serial Number for ID: '+vsn) + return vsn + + def getLastError(): + GetLastError = kernel32.GetLastError + GetLastError.argtypes = None + GetLastError.restype = c_uint + def getLastError(): + return GetLastError() + return getLastError + getLastError = getLastError() + + def GetUserName(): + GetUserNameW = advapi32.GetUserNameW + GetUserNameW.argtypes = [c_wchar_p, POINTER(c_uint)] + GetUserNameW.restype = c_uint + def GetUserName(): + buffer = create_unicode_buffer(2) + size = c_uint(len(buffer)) + while not GetUserNameW(buffer, byref(size)): + errcd = getLastError() + if errcd == 234: + # bad wine implementation up through wine 1.3.21 + return "AlternateUserName" + # double the buffer size + buffer = create_unicode_buffer(len(buffer) * 2) + size.value = len(buffer) + + # replace any non-ASCII values with 0xfffd + for i in range(0,len(buffer)): + if buffer[i]>"\u007f": + #print "swapping char "+str(i)+" ("+buffer[i]+")" + buffer[i] = "\ufffd" + # return utf-8 encoding of modified username + #print "modified username:"+buffer.value + return buffer.value.encode('utf-8') + return GetUserName + GetUserName = GetUserName() + + def CryptUnprotectData(): + _CryptUnprotectData = crypt32.CryptUnprotectData + _CryptUnprotectData.argtypes = [DataBlob_p, c_wchar_p, DataBlob_p, + c_void_p, c_void_p, c_uint, DataBlob_p] + _CryptUnprotectData.restype = c_uint + def CryptUnprotectData(indata, entropy, flags): + indatab = create_string_buffer(indata) + indata = DataBlob(len(indata), cast(indatab, c_void_p)) + entropyb = create_string_buffer(entropy) + entropy = DataBlob(len(entropy), cast(entropyb, c_void_p)) + outdata = DataBlob() + if not _CryptUnprotectData(byref(indata), None, byref(entropy), + None, None, flags, byref(outdata)): + # raise DrmException("Failed to Unprotect Data") + return b'failed' + return string_at(outdata.pbData, outdata.cbData) + return CryptUnprotectData + CryptUnprotectData = CryptUnprotectData() + + # Returns Environmental Variables that contain unicode + # name must be unicode string, not byte string. + def getEnvironmentVariable(name): + import ctypes + n = ctypes.windll.kernel32.GetEnvironmentVariableW(name, None, 0) + if n == 0: + return None + buf = ctypes.create_unicode_buffer("\0"*n) + ctypes.windll.kernel32.GetEnvironmentVariableW(name, buf, n) + return buf.value + + # Locate all of the kindle-info style files and return as list + def getKindleInfoFiles(): + kInfoFiles = [] + # some 64 bit machines do not have the proper registry key for some reason + # or the python interface to the 32 vs 64 bit registry is broken + path = "" + if 'LOCALAPPDATA' in os.environ.keys(): + # Python 2.x does not return unicode env. Use Python 3.x + path = winreg.ExpandEnvironmentStrings("%LOCALAPPDATA%") + # this is just another alternative. + # path = getEnvironmentVariable('LOCALAPPDATA') + if not os.path.isdir(path): + path = "" + else: + # User Shell Folders show take precedent over Shell Folders if present + try: + # this will still break + regkey = winreg.OpenKey(winreg.HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders\\") + path = winreg.QueryValueEx(regkey, 'Local AppData')[0] + if not os.path.isdir(path): + path = "" + try: + regkey = winreg.OpenKey(winreg.HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders\\") + path = winreg.QueryValueEx(regkey, 'Local AppData')[0] + if not os.path.isdir(path): + path = "" + except RegError: + pass + except RegError: + pass + + found = False + if path == "": + print ('Could not find the folder in which to look for kinfoFiles.') + else: + # Probably not the best. To Fix (shouldn't ignore in encoding) or use utf-8 + print("searching for kinfoFiles in " + path) + + # look for (K4PC 1.25.1 and later) .kinf2018 file + kinfopath = path +'\\Amazon\\Kindle\\storage\\.kinf2018' + if os.path.isfile(kinfopath): + found = True + print('Found K4PC 1.25+ kinf2018 file: ' + kinfopath) + kInfoFiles.append(kinfopath) + + # look for (K4PC 1.9.0 and later) .kinf2011 file + kinfopath = path +'\\Amazon\\Kindle\\storage\\.kinf2011' + if os.path.isfile(kinfopath): + found = True + print('Found K4PC 1.9+ kinf2011 file: ' + kinfopath) + kInfoFiles.append(kinfopath) + + # look for (K4PC 1.6.0 and later) rainier.2.1.1.kinf file + kinfopath = path +'\\Amazon\\Kindle\\storage\\rainier.2.1.1.kinf' + if os.path.isfile(kinfopath): + found = True + print('Found K4PC 1.6-1.8 kinf file: ' + kinfopath) + kInfoFiles.append(kinfopath) + + # look for (K4PC 1.5.0 and later) rainier.2.1.1.kinf file + kinfopath = path +'\\Amazon\\Kindle For PC\\storage\\rainier.2.1.1.kinf' + if os.path.isfile(kinfopath): + found = True + print('Found K4PC 1.5 kinf file: ' + kinfopath) + kInfoFiles.append(kinfopath) + + # look for original (earlier than K4PC 1.5.0) kindle-info files + kinfopath = path +'\\Amazon\\Kindle For PC\\{AMAwzsaPaaZAzmZzZQzgZCAkZ3AjA_AY}\\kindle.info' + if os.path.isfile(kinfopath): + found = True + print('Found K4PC kindle.info file: ' + kinfopath) + kInfoFiles.append(kinfopath) + + if not found: + print('No K4PC kindle.info/kinf/kinf2011 files have been found.') + return kInfoFiles + + + # determine type of kindle info provided and return a + # database of keynames and values + def getDBfromFile(kInfoFile): + names = [\ + b'kindle.account.tokens',\ + b'kindle.cookie.item',\ + b'eulaVersionAccepted',\ + b'login_date',\ + b'kindle.token.item',\ + b'login',\ + b'kindle.key.item',\ + b'kindle.name.info',\ + b'kindle.device.info',\ + b'MazamaRandomNumber',\ + b'max_date',\ + b'SIGVERIF',\ + b'build_version',\ + b'SerialNumber',\ + b'UsernameHash',\ + b'kindle.directedid.info',\ + b'DSN',\ + b'kindle.accounttype.info',\ + b'krx.flashcardsplugin.data.encryption_key',\ + b'krx.notebookexportplugin.data.encryption_key',\ + b'proxy.http.password',\ + b'proxy.http.username' + ] + namehashmap = {encodeHash(n,testMap8):n for n in names} + # print(namehashmap) + DB = {} + with open(kInfoFile, 'rb') as infoReader: + data = infoReader.read() + # assume .kinf2011 or .kinf2018 style .kinf file + # the .kinf file uses "/" to separate it into records + # so remove the trailing "/" to make it easy to use split + data = data[:-1] + items = data.split(b'/') + + # starts with an encoded and encrypted header blob + headerblob = items.pop(0) + encryptedValue = decode(headerblob, testMap1) + cleartext = UnprotectHeaderData(encryptedValue) + #print "header cleartext:",cleartext + # now extract the pieces that form the added entropy + pattern = re.compile(br'''\[Version:(\d+)\]\[Build:(\d+)\]\[Cksum:([^\]]+)\]\[Guid:([\{\}a-z0-9\-]+)\]''', re.IGNORECASE) + for m in re.finditer(pattern, cleartext): + version = int(m.group(1)) + build = m.group(2) + guid = m.group(4) + + if version == 5: # .kinf2011 + added_entropy = build + guid + elif version == 6: # .kinf2018 + salt = str(0x6d8 * int(build)).encode('utf-8') + guid + sp = GetUserName() + b'+@#$%+' + GetIDString().encode('utf-8') + passwd = encode(SHA256(sp), charMap5) + key = PBKDF2(passwd, salt, count=10000, dkLen=0x400)[:32] # this is very slow + + # loop through the item records until all are processed + while len(items) > 0: + + # get the first item record + item = items.pop(0) + + # the first 32 chars of the first record of a group + # is the MD5 hash of the key name encoded by charMap5 + keyhash = item[0:32] + + # the remainder of the first record when decoded with charMap5 + # has the ':' split char followed by the string representation + # of the number of records that follow + # and make up the contents + srcnt = decode(item[34:],charMap5) + rcnt = int(srcnt) + + # read and store in rcnt records of data + # that make up the contents value + edlst = [] + for i in range(rcnt): + item = items.pop(0) + edlst.append(item) + + # key names now use the new testMap8 encoding + if keyhash in namehashmap: + keyname=namehashmap[keyhash] + #print "keyname found from hash:",keyname + else: + keyname = keyhash + #print "keyname not found, hash is:",keyname + + # the testMap8 encoded contents data has had a length + # of chars (always odd) cut off of the front and moved + # to the end to prevent decoding using testMap8 from + # working properly, and thereby preventing the ensuing + # CryptUnprotectData call from succeeding. + + # The offset into the testMap8 encoded contents seems to be: + # len(contents)-largest prime number <= int(len(content)/3) + # (in other words split "about" 2/3rds of the way through) + + # move first offsets chars to end to align for decode by testMap8 + # by moving noffset chars from the start of the + # string to the end of the string + encdata = b"".join(edlst) + #print "encrypted data:",encdata + contlen = len(encdata) + noffset = contlen - primes(int(contlen/3))[-1] + pfx = encdata[0:noffset] + encdata = encdata[noffset:] + encdata = encdata + pfx + #print "rearranged data:",encdata + + if version == 5: + # decode using new testMap8 to get the original CryptProtect Data + encryptedValue = decode(encdata,testMap8) + #print "decoded data:",encryptedValue.encode('hex') + entropy = SHA1(keyhash) + added_entropy + cleartext = CryptUnprotectData(encryptedValue, entropy, 1) + elif version == 6: + # decode using new testMap8 to get IV + ciphertext + iv_ciphertext = decode(encdata, testMap8) + # pad IV so that we can substitute AES-CTR for GCM + iv = iv_ciphertext[:12] + b'\x00\x00\x00\x02' + ciphertext = iv_ciphertext[12:] + # convert IV to int for use with pycrypto + iv_ints = unpack('>QQ', iv) + iv = iv_ints[0] << 64 | iv_ints[1] + # set up AES-CTR + ctr = Counter.new(128, initial_value=iv) + cipher = AES.new(key, AES.MODE_CTR, counter=ctr) + # decrypt and decode + cleartext = decode(cipher.decrypt(ciphertext), charMap5) + + if len(cleartext)>0: + #print "cleartext data:",cleartext,":end data" + DB[keyname] = cleartext + #print keyname, cleartext + + if len(DB)>6: + # store values used in decryption + DB[b'IDString'] = GetIDString().encode('utf-8') + DB[b'UserName'] = GetUserName() + print("Decrypted key file using IDString '{0:s}' and UserName '{1:s}'".format(GetIDString(), GetUserName().decode('utf-8'))) + else: + print("Couldn't decrypt file.") + DB = {} + return DB +elif isosx: + import subprocess + + # Various character maps used to decrypt books. Probably supposed to act as obfuscation + charMap1 = b'n5Pr6St7Uv8Wx9YzAb0Cd1Ef2Gh3Jk4M' + charMap2 = b'ZB0bYyc1xDdW2wEV3Ff7KkPpL8UuGA4gz-Tme9Nn_tHh5SvXCsIiR6rJjQaqlOoM' + + # For kinf approach of K4Mac 1.6.X or later + # On K4PC charMap5 = 'AzB0bYyCeVvaZ3FfUuG4g-TtHh5SsIiR6rJjQq7KkPpL8lOoMm9Nn_c1XxDdW2wE' + # For Mac they seem to re-use charMap2 here + charMap5 = charMap2 + + # new in K4M 1.9.X + testMap8 = b'YvaZ3FfUm9Nn_c1XuG4yCAzB0beVg-TtHh5SsIiR6rJjQdW2wEq7KkPpL8lOoMxD' + + # uses a sub process to get the Hard Drive Serial Number using ioreg + # returns serial numbers of all internal hard drive drives + def GetVolumesSerialNumbers(): + sernums = [] + sernum = os.getenv('MYSERIALNUMBER') + if sernum != None: + sernums.append(sernum.strip()) + cmdline = '/usr/sbin/ioreg -w 0 -r -c AppleAHCIDiskDriver' + cmdline = cmdline.encode(sys.getfilesystemencoding()) + p = subprocess.Popen(cmdline, shell=True, stdin=None, stdout=subprocess.PIPE, stderr=subprocess.PIPE, close_fds=False) + out1, out2 = p.communicate() + #print out1 + reslst = out1.split(b'\n') + cnt = len(reslst) + for j in range(cnt): + resline = reslst[j] + pp = resline.find(b'\"Serial Number\" = \"') + if pp >= 0: + sernum = resline[pp+19:-1] + sernums.append(sernum.strip()) + return sernums + + def GetDiskPartitionNames(): + names = [] + cmdline = '/sbin/mount' + cmdline = cmdline.encode(sys.getfilesystemencoding()) + p = subprocess.Popen(cmdline, shell=True, stdin=None, stdout=subprocess.PIPE, stderr=subprocess.PIPE, close_fds=False) + out1, out2 = p.communicate() + reslst = out1.split(b'\n') + cnt = len(reslst) + for j in range(cnt): + resline = reslst[j] + if resline.startswith(b'/dev'): + (devpart, mpath) = resline.split(b' on ')[:2] + dpart = devpart[5:] + names.append(dpart) + return names + + # uses a sub process to get the UUID of all disk partitions + def GetDiskPartitionUUIDs(): + uuids = [] + uuidnum = os.getenv('MYUUIDNUMBER') + if uuidnum != None: + uuids.append(uuidnum.strip()) + cmdline = '/usr/sbin/ioreg -l -S -w 0 -r -c AppleAHCIDiskDriver' + cmdline = cmdline.encode(sys.getfilesystemencoding()) + p = subprocess.Popen(cmdline, shell=True, stdin=None, stdout=subprocess.PIPE, stderr=subprocess.PIPE, close_fds=False) + out1, out2 = p.communicate() + #print out1 + reslst = out1.split(b'\n') + cnt = len(reslst) + for j in range(cnt): + resline = reslst[j] + pp = resline.find(b'\"UUID\" = \"') + if pp >= 0: + uuidnum = resline[pp+10:-1] + uuidnum = uuidnum.strip() + uuids.append(uuidnum) + return uuids + + def GetMACAddressesMunged(): + macnums = [] + macnum = os.getenv('MYMACNUM') + if macnum != None: + macnums.append(macnum) + cmdline = 'networksetup -listallhardwareports' # en0' + cmdline = cmdline.encode(sys.getfilesystemencoding()) + p = subprocess.Popen(cmdline, shell=True, stdin=None, stdout=subprocess.PIPE, stderr=subprocess.PIPE, close_fds=False) + out1, out2 = p.communicate() + reslst = out1.split(b'\n') + cnt = len(reslst) + for j in range(cnt): + resline = reslst[j] + pp = resline.find(b'Ethernet Address: ') + if pp >= 0: + #print resline + macnum = resline[pp+18:] + macnum = macnum.strip() + maclst = macnum.split(b':') + n = len(maclst) + if n != 6: + continue + #print 'original mac', macnum + # now munge it up the way Kindle app does + # by xoring it with 0xa5 and swapping elements 3 and 4 + for i in range(6): + maclst[i] = int(b'0x' + maclst[i], 0) + mlst = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00] + mlst[5] = maclst[5] ^ 0xa5 + mlst[4] = maclst[3] ^ 0xa5 + mlst[3] = maclst[4] ^ 0xa5 + mlst[2] = maclst[2] ^ 0xa5 + mlst[1] = maclst[1] ^ 0xa5 + mlst[0] = maclst[0] ^ 0xa5 + macnum = b'%0.2x%0.2x%0.2x%0.2x%0.2x%0.2x' % (mlst[0], mlst[1], mlst[2], mlst[3], mlst[4], mlst[5]) + #print 'munged mac', macnum + macnums.append(macnum) + return macnums + + + # uses unix env to get username instead of using sysctlbyname + def GetUserName(): + username = os.getenv('USER') + #print "Username:",username + return username.encode('utf-8') + + def GetIDStrings(): + # Return all possible ID Strings + strings = [] + strings.extend(GetMACAddressesMunged()) + strings.extend(GetVolumesSerialNumbers()) + strings.extend(GetDiskPartitionNames()) + strings.extend(GetDiskPartitionUUIDs()) + strings.append(b'9999999999') + #print "ID Strings:\n",strings + return strings + + # implements an Pseudo Mac Version of Windows built-in Crypto routine + class CryptUnprotectData(object): + def __init__(self, entropy, IDString): + sp = GetUserName() + b'+@#$%+' + IDString + passwdData = encode(SHA256(sp),charMap2) + salt = entropy + key_iv = PBKDF2(passwdData, salt, count=0x800, dkLen=0x400) + self.key = key_iv[0:32] + self.iv = key_iv[32:48] + self.crp.set_decrypt_key(self.key, self.iv) + + def decrypt(self, encryptedData): + cleartext = self.crp.decrypt(encryptedData) + cleartext = decode(cleartext, charMap2) + return cleartext + + + # Locate the .kindle-info files + def getKindleInfoFiles(): + # file searches can take a long time on some systems, so just look in known specific places. + kInfoFiles=[] + found = False + home = os.getenv('HOME') + # check for .kinf2018 file in new location (App Store Kindle for Mac) + testpath = home + '/Library/Containers/com.amazon.Kindle/Data/Library/Application Support/Kindle/storage/.kinf2018' + if os.path.isfile(testpath): + kInfoFiles.append(testpath) + print('Found k4Mac kinf2018 file: ' + testpath) + found = True + # check for .kinf2018 files + testpath = home + '/Library/Application Support/Kindle/storage/.kinf2018' + if os.path.isfile(testpath): + kInfoFiles.append(testpath) + print('Found k4Mac kinf2018 file: ' + testpath) + found = True + # check for .kinf2011 file in new location (App Store Kindle for Mac) + testpath = home + '/Library/Containers/com.amazon.Kindle/Data/Library/Application Support/Kindle/storage/.kinf2011' + if os.path.isfile(testpath): + kInfoFiles.append(testpath) + print('Found k4Mac kinf2011 file: ' + testpath) + found = True + # check for .kinf2011 files from 1.10 + testpath = home + '/Library/Application Support/Kindle/storage/.kinf2011' + if os.path.isfile(testpath): + kInfoFiles.append(testpath) + print('Found k4Mac kinf2011 file: ' + testpath) + found = True + # check for .rainier-2.1.1-kinf files from 1.6 + testpath = home + '/Library/Application Support/Kindle/storage/.rainier-2.1.1-kinf' + if os.path.isfile(testpath): + kInfoFiles.append(testpath) + print('Found k4Mac rainier file: ' + testpath) + found = True + # check for .kindle-info files from 1.4 + testpath = home + '/Library/Application Support/Kindle/storage/.kindle-info' + if os.path.isfile(testpath): + kInfoFiles.append(testpath) + print('Found k4Mac kindle-info file: ' + testpath) + found = True + # check for .kindle-info file from 1.2.2 + testpath = home + '/Library/Application Support/Amazon/Kindle/storage/.kindle-info' + if os.path.isfile(testpath): + kInfoFiles.append(testpath) + print('Found k4Mac kindle-info file: ' + testpath) + found = True + # check for .kindle-info file from 1.0 beta 1 (27214) + testpath = home + '/Library/Application Support/Amazon/Kindle for Mac/storage/.kindle-info' + if os.path.isfile(testpath): + kInfoFiles.append(testpath) + print('Found k4Mac kindle-info file: ' + testpath) + found = True + if not found: + print('No k4Mac kindle-info/rainier/kinf2011 files have been found.') + return kInfoFiles + + # determine type of kindle info provided and return a + # database of keynames and values + def getDBfromFile(kInfoFile): + names = [\ + b'kindle.account.tokens',\ + b'kindle.cookie.item',\ + b'eulaVersionAccepted',\ + b'login_date',\ + b'kindle.token.item',\ + b'login',\ + b'kindle.key.item',\ + b'kindle.name.info',\ + b'kindle.device.info',\ + b'MazamaRandomNumber',\ + b'max_date',\ + b'SIGVERIF',\ + b'build_version',\ + b'SerialNumber',\ + b'UsernameHash',\ + b'kindle.directedid.info',\ + b'DSN',\ + b'kindle.accounttype.info',\ + b'krx.flashcardsplugin.data.encryption_key',\ + b'krx.notebookexportplugin.data.encryption_key',\ + b'proxy.http.password',\ + b'proxy.http.username' + ] + with open(kInfoFile, 'rb') as infoReader: + filedata = infoReader.read() + + data = filedata[:-1] + items = data.split(b'/') + IDStrings = GetIDStrings() + print ("trying username ", GetUserName(), " on file ", kInfoFile) + for IDString in IDStrings: + print ("trying IDString:",IDString) + try: + DB = {} + items = data.split(b'/') + + # the headerblob is the encrypted information needed to build the entropy string + headerblob = items.pop(0) + #print ("headerblob: ",headerblob) + encryptedValue = decode(headerblob, charMap1) + #print ("encryptedvalue: ",encryptedValue) + cleartext = UnprotectHeaderData(encryptedValue) + #print ("cleartext: ",cleartext) + + # now extract the pieces in the same way + pattern = re.compile(br'''\[Version:(\d+)\]\[Build:(\d+)\]\[Cksum:([^\]]+)\]\[Guid:([\{\}a-z0-9\-]+)\]''', re.IGNORECASE) + for m in re.finditer(pattern, cleartext): + version = int(m.group(1)) + build = m.group(2) + guid = m.group(4) + + #print ("version",version) + #print ("build",build) + #print ("guid",guid,"\n") + + if version == 5: # .kinf2011: identical to K4PC, except the build number gets multiplied + entropy = str(0x2df * int(build)).encode('utf-8') + guid + cud = CryptUnprotectData(entropy,IDString) + #print ("entropy",entropy) + #print ("cud",cud) + + elif version == 6: # .kinf2018: identical to K4PC + salt = str(0x6d8 * int(build)).encode('utf-8') + guid + sp = GetUserName() + b'+@#$%+' + IDString + passwd = encode(SHA256(sp), charMap5) + key = PBKDF2(passwd, salt, count=10000, dkLen=0x400)[:32] + + #print ("salt",salt) + #print ("sp",sp) + #print ("passwd",passwd) + #print ("key",key) + + # loop through the item records until all are processed + while len(items) > 0: + + # get the first item record + item = items.pop(0) + + # the first 32 chars of the first record of a group + # is the MD5 hash of the key name encoded by charMap5 + keyhash = item[0:32] + keyname = b'unknown' + + # unlike K4PC the keyhash is not used in generating entropy + # entropy = SHA1(keyhash) + added_entropy + # entropy = added_entropy + + # the remainder of the first record when decoded with charMap5 + # has the ':' split char followed by the string representation + # of the number of records that follow + # and make up the contents + srcnt = decode(item[34:],charMap5) + rcnt = int(srcnt) + + # read and store in rcnt records of data + # that make up the contents value + edlst = [] + for i in range(rcnt): + item = items.pop(0) + edlst.append(item) + + keyname = b'unknown' + for name in names: + if encodeHash(name,testMap8) == keyhash: + keyname = name + break + if keyname == b'unknown': + keyname = keyhash + + # the testMap8 encoded contents data has had a length + # of chars (always odd) cut off of the front and moved + # to the end to prevent decoding using testMap8 from + # working properly, and thereby preventing the ensuing + # CryptUnprotectData call from succeeding. + + # The offset into the testMap8 encoded contents seems to be: + # len(contents) - largest prime number less than or equal to int(len(content)/3) + # (in other words split 'about' 2/3rds of the way through) + + # move first offsets chars to end to align for decode by testMap8 + encdata = b''.join(edlst) + contlen = len(encdata) + + # now properly split and recombine + # by moving noffset chars from the start of the + # string to the end of the string + noffset = contlen - primes(int(contlen/3))[-1] + pfx = encdata[0:noffset] + encdata = encdata[noffset:] + encdata = encdata + pfx + + if version == 5: + # decode using testMap8 to get the CryptProtect Data + encryptedValue = decode(encdata,testMap8) + cleartext = cud.decrypt(encryptedValue) + + elif version == 6: + # decode using new testMap8 to get IV + ciphertext + iv_ciphertext = decode(encdata, testMap8) + # pad IV so that we can substitute AES-CTR for GCM + iv = iv_ciphertext[:12] + b'\x00\x00\x00\x02' + ciphertext = iv_ciphertext[12:] + # convert IV to int for use with pycrypto + iv_ints = unpack('>QQ', iv) + iv = iv_ints[0] << 64 | iv_ints[1] + # set up AES-CTR + ctr = Counter.new(128, initial_value=iv) + cipher = AES.new(key, AES.MODE_CTR, counter=ctr) + # decrypt and decode + cleartext = decode(cipher.decrypt(ciphertext), charMap5) + + # print keyname + # print cleartext + if len(cleartext) > 0: + DB[keyname] = cleartext + + if len(DB)>6: + break + + except Exception: + print (traceback.format_exc()) + pass + if len(DB)>6: + # store values used in decryption + print("Decrypted key file using IDString '{0:s}' and UserName '{1:s}'".format(IDString.decode('utf-8'), GetUserName().decode('utf-8'))) + DB[b'IDString'] = IDString + DB[b'UserName'] = GetUserName() + else: + print("Couldn't decrypt file.") + DB = {} + return DB +else: + def getDBfromFile(kInfoFile): + raise DrmException("This script only runs under Windows or Mac OS X.") + return {} + +def kindlekeys(files = []): + keys = [] + if files == []: + files = getKindleInfoFiles() + for file in files: + key = getDBfromFile(file) + if key: + # convert all values to hex, just in case. + n_key = {} + for k,v in key.items(): + n_key[k.decode()]=codecs.encode(v, 'hex_codec').decode() + # key = {k.decode():v.decode() for k,v in key.items()} + keys.append(n_key) + return keys + +# interface for Python DeDRM +# returns single key or multiple keys, depending on path or file passed in +def getkey(outpath, files=[]): + keys = kindlekeys(files) + if len(keys) > 0: + if not os.path.isdir(outpath): + outfile = outpath + with open(outfile, 'w') as keyfileout: + keyfileout.write(json.dumps(keys[0])) + print("Saved a key to {0}".format(outfile)) + else: + keycount = 0 + for key in keys: + while True: + keycount += 1 + outfile = os.path.join(outpath,"kindlekey{0:d}.k4i".format(keycount)) + if not os.path.exists(outfile): + break + with open(outfile, 'w') as keyfileout: + keyfileout.write(json.dumps(key)) + print("Saved a key to {0}".format(outfile)) + return True + return False + +def usage(progname): + print("Finds, decrypts and saves the default Kindle For Mac/PC encryption keys.") + print("Keys are saved to the current directory, or a specified output directory.") + print("If a file name is passed instead of a directory, only the first key is saved, in that file.") + print("Usage:") + print(" {0:s} [-h] [-k ] []".format(progname)) + + +def cli_main(): + sys.stdout=SafeUnbuffered(sys.stdout) + sys.stderr=SafeUnbuffered(sys.stderr) + argv=unicode_argv() + progname = os.path.basename(argv[0]) + print("{0} v{1}\nCopyright © 2010-2020 by some_updates, Apprentice Harper et al.".format(progname,__version__)) + + try: + opts, args = getopt.getopt(argv[1:], "hk:") + except getopt.GetoptError as err: + print("Error in options or arguments: {0}".format(err.args[0])) + usage(progname) + sys.exit(2) + + files = [] + for o, a in opts: + if o == "-h": + usage(progname) + sys.exit(0) + if o == "-k": + files = [a] + + if len(args) > 1: + usage(progname) + sys.exit(2) + + if len(args) == 1: + # save to the specified file or directory + outpath = args[0] + if not os.path.isabs(outpath): + outpath = os.path.abspath(outpath) + else: + # save to the same directory as the script + outpath = os.path.dirname(argv[0]) + + # make sure the outpath is canonical + outpath = os.path.realpath(os.path.normpath(outpath)) + + if not getkey(outpath, files): + print("Could not retrieve Kindle for Mac/PC key.") + return 0 + + +def gui_main(): + try: + import tkinter + import tkinter.constants + import tkinter.messagebox + import traceback + except: + return cli_main() + + class ExceptionDialog(tkinter.Frame): + def __init__(self, root, text): + tkinter.Frame.__init__(self, root, border=5) + label = tkinter.Label(self, text="Unexpected error:", + anchor=tkinter.constants.W, justify=tkinter.constants.LEFT) + label.pack(fill=tkinter.constants.X, expand=0) + self.text = tkinter.Text(self) + self.text.pack(fill=tkinter.constants.BOTH, expand=1) + + self.text.insert(tkinter.constants.END, text) + + + argv=unicode_argv() + root = tkinter.Tk() + root.withdraw() + progpath, progname = os.path.split(argv[0]) + success = False + try: + keys = kindlekeys() + keycount = 0 + for key in keys: + while True: + keycount += 1 + outfile = os.path.join(progpath,"kindlekey{0:d}.k4i".format(keycount)) + if not os.path.exists(outfile): + break + + with open(outfile, 'w') as keyfileout: + keyfileout.write(json.dumps(key)) + success = True + tkinter.messagebox.showinfo(progname, "Key successfully retrieved to {0}".format(outfile)) + except DrmException as e: + tkinter.messagebox.showerror(progname, "Error: {0}".format(str(e))) + except Exception: + root.wm_state('normal') + root.title(progname) + text = traceback.format_exc() + ExceptionDialog(root, text).pack(fill=tkinter.constants.BOTH, expand=1) + root.mainloop() + if not success: + return 1 + return 0 + +if __name__ == '__main__': + if len(sys.argv) > 1: + sys.exit(cli_main()) + sys.exit(gui_main()) diff --git a/arch-config/.config/calibre/plugins/DeDRM/libraryfiles/libalfcrypto32.so b/arch-config/.config/calibre/plugins/DeDRM/libraryfiles/libalfcrypto32.so new file mode 100644 index 00000000..9a5a4426 Binary files /dev/null and b/arch-config/.config/calibre/plugins/DeDRM/libraryfiles/libalfcrypto32.so differ diff --git a/arch-config/.config/calibre/plugins/DeDRM/libraryfiles/libalfcrypto64.so b/arch-config/.config/calibre/plugins/DeDRM/libraryfiles/libalfcrypto64.so new file mode 100644 index 00000000..a08ac289 Binary files /dev/null and b/arch-config/.config/calibre/plugins/DeDRM/libraryfiles/libalfcrypto64.so differ diff --git a/arch-config/.config/calibre/plugins/DeDRM/libraryfiles/subasyncio.py b/arch-config/.config/calibre/plugins/DeDRM/libraryfiles/subasyncio.py new file mode 100644 index 00000000..de084d30 --- /dev/null +++ b/arch-config/.config/calibre/plugins/DeDRM/libraryfiles/subasyncio.py @@ -0,0 +1,148 @@ +#!/usr/bin/env python +# vim:ts=4:sw=4:softtabstop=4:smarttab:expandtab + +import os, sys +import signal +import threading +import subprocess +from subprocess import Popen, PIPE, STDOUT + +# **heavily** chopped up and modfied version of asyncproc.py +# to make it actually work on Windows as well as Mac/Linux +# For the original see: +# "http://www.lysator.liu.se/~bellman/download/" +# author is "Thomas Bellman " +# available under GPL version 3 or Later + +# create an asynchronous subprocess whose output can be collected in +# a non-blocking manner + +# What a mess! Have to use threads just to get non-blocking io +# in a cross-platform manner + +# luckily all thread use is hidden within this class + +class Process(object): + def __init__(self, *params, **kwparams): + if len(params) <= 3: + kwparams.setdefault('stdin', subprocess.PIPE) + if len(params) <= 4: + kwparams.setdefault('stdout', subprocess.PIPE) + if len(params) <= 5: + kwparams.setdefault('stderr', subprocess.PIPE) + self.__pending_input = [] + self.__collected_outdata = [] + self.__collected_errdata = [] + self.__exitstatus = None + self.__lock = threading.Lock() + self.__inputsem = threading.Semaphore(0) + self.__quit = False + + self.__process = subprocess.Popen(*params, **kwparams) + + if self.__process.stdin: + self.__stdin_thread = threading.Thread( + name="stdin-thread", + target=self.__feeder, args=(self.__pending_input, + self.__process.stdin)) + self.__stdin_thread.setDaemon(True) + self.__stdin_thread.start() + + if self.__process.stdout: + self.__stdout_thread = threading.Thread( + name="stdout-thread", + target=self.__reader, args=(self.__collected_outdata, + self.__process.stdout)) + self.__stdout_thread.setDaemon(True) + self.__stdout_thread.start() + + if self.__process.stderr: + self.__stderr_thread = threading.Thread( + name="stderr-thread", + target=self.__reader, args=(self.__collected_errdata, + self.__process.stderr)) + self.__stderr_thread.setDaemon(True) + self.__stderr_thread.start() + + def pid(self): + return self.__process.pid + + def kill(self, signal): + self.__process.send_signal(signal) + + # check on subprocess (pass in 'nowait') to act like poll + def wait(self, flag): + if flag.lower() == 'nowait': + rc = self.__process.poll() + else: + rc = self.__process.wait() + if rc != None: + if self.__process.stdin: + self.closeinput() + if self.__process.stdout: + self.__stdout_thread.join() + if self.__process.stderr: + self.__stderr_thread.join() + return self.__process.returncode + + def terminate(self): + if self.__process.stdin: + self.closeinput() + self.__process.terminate() + + # thread gets data from subprocess stdout + def __reader(self, collector, source): + while True: + data = os.read(source.fileno(), 65536) + self.__lock.acquire() + collector.append(data) + self.__lock.release() + if data == "": + source.close() + break + return + + # thread feeds data to subprocess stdin + def __feeder(self, pending, drain): + while True: + self.__inputsem.acquire() + self.__lock.acquire() + if not pending and self.__quit: + drain.close() + self.__lock.release() + break + data = pending.pop(0) + self.__lock.release() + drain.write(data) + + # non-blocking read of data from subprocess stdout + def read(self): + self.__lock.acquire() + outdata = "".join(self.__collected_outdata) + del self.__collected_outdata[:] + self.__lock.release() + return outdata + + # non-blocking read of data from subprocess stderr + def readerr(self): + self.__lock.acquire() + errdata = "".join(self.__collected_errdata) + del self.__collected_errdata[:] + self.__lock.release() + return errdata + + # non-blocking write to stdin of subprocess + def write(self, data): + if self.__process.stdin is None: + raise ValueError("Writing to process with stdin not a pipe") + self.__lock.acquire() + self.__pending_input.append(data) + self.__inputsem.release() + self.__lock.release() + + # close stdinput of subprocess + def closeinput(self): + self.__lock.acquire() + self.__quit = True + self.__inputsem.release() + self.__lock.release() diff --git a/arch-config/.config/calibre/plugins/KFX Input.zip b/arch-config/.config/calibre/plugins/KFX Input.zip new file mode 100644 index 00000000..d37793d8 Binary files /dev/null and b/arch-config/.config/calibre/plugins/KFX Input.zip differ diff --git a/arch-config/.config/calibre/plugins/Obok DeDRM.zip b/arch-config/.config/calibre/plugins/Obok DeDRM.zip new file mode 100644 index 00000000..aada8f27 Binary files /dev/null and b/arch-config/.config/calibre/plugins/Obok DeDRM.zip differ diff --git a/arch-config/.config/calibre/plugins/deacsm.json b/arch-config/.config/calibre/plugins/deacsm.json new file mode 100644 index 00000000..e717f9c0 --- /dev/null +++ b/arch-config/.config/calibre/plugins/deacsm.json @@ -0,0 +1,7 @@ +{ + "configured": true, + "delete_acsm_after_fulfill": false, + "detailed_logging": false, + "list_of_rented_books": [], + "notify_fulfillment": true +} \ No newline at end of file diff --git a/arch-config/.config/calibre/plugins/dedrm.json b/arch-config/.config/calibre/plugins/dedrm.json new file mode 100644 index 00000000..540f4ab1 --- /dev/null +++ b/arch-config/.config/calibre/plugins/dedrm.json @@ -0,0 +1,43 @@ +{ + "adeptkeys": { + "DeACSM_uuid_2d6cfbec-33fd-43ca-bcf9-e8b281114a17": "3082025d02010002818100dff9b3de3efe0631b18146cb24ff775792dc349c8a2ef1b85609785ad62fab462dd5a6e847923d362a006339a116119cb75e48e4bfb24679dbf6713d194a1202eb03af193b0a4f6637209a4d816a19ce789a58fcf5cc018a7df7b8d6f8e1ad58fef156ed9add0c87151b337b80e3b79c852eca83d0a9d37eb2747617ef411e5502030100010281805fc34ef186736c4891019a383f606f31655c7bae36b2edad0834525e5c57d35e5538957d992460c1a8e1b38b2f61d533f17f01a1b488cff348662d72973e81462b24d185fd59d90b0b79f5f5861a4786e588e8dc44b5089488de280fe8a0bc85909cf624449b6d875e21bce925f70b5033acc51b5215fbc86465fea027873c81024100fab72bf51f4a31f3d58988a3ceb0194f1b6479ec768dae397d1b887ddc436d16b0bbf6723eb0a3f0e616054013c85b6245b6c9fadf37f75d2f5b245d33879d21024100e4b23ea6719cb344e5be0c60ba72c34432e2957b3eff0e559a9383385f059af30a5064f02a8a534f8e6add2b5dc1b26c69f13ad00c026de21ff5e86ad66846b50241008dd810009081539d9654478015b1bfbfe7c982c96b9160de998f783b6ce0a0d953882438228ba154eb77cde4a0cc9c170f460923ec2227cb0abdcfe702fe58c1024100956aa768139e6fb9b9e87b29cf671f90b53638b7b726e8f4a0f373ae26d700af7db39cdf14cc1f3641342ca022b7649d5472591c885c25f2b132f6d0a698a669024073589faf3542d94e602d40c8c15c9ffc3bf03990c130ea94a232c7da3269126511caba29278182ed4b274a4662aff9106318ae9d0aa8c9ffa9743fd4e49363d3" + }, + "adobe_pdf_passphrases": [], + "adobewineprefix": "", + "androidkeys": {}, + "bandnkeys": {}, + "configured": true, + "deobfuscate_fonts": true, + "ereaderkeys": {}, + "kindlekeys": { + "default_key_1648538642": { + "DSN": "35623531727a3631724d505537335062365336596e68536e7436744150685338723035325347356e", + "IDString": "31363033353339333533", + "MazamaRandomNumber": "535972376e647231537a50537234374135666e765339367253396e476e74746437685045724d373550683633746b6e3374663653727250373778506253375332", + "SIGVERIF": "3f3f3f3f3f3f7a416e5a694261523f3f3f3f3f3f", + "SerialNumber": "3776355572387243534a727235333543373474396e3835783559726e5355507a", + "UserName": "6d617263", + "UsernameHash": "6e66723572536e4a36723731726e7231744a3641506453627439353036363774", + "build_version": "312e32362e302e3535303736", + "eulaVersionAccepted": "312e31", + "kindle.account.tokens": "30326132663438636535333463313963656337623861623335353662653862393133333766366166", + "kindle.accounttype.info": "526567756c6172", + "kindle.cookie.item": "4b564836453257506a7366516f69644c413477504679627630653535734246315464667a724e452b5471666b50754178797a667136415a355971366e33746962614a4264687271483461656f632f34756e486f637548376b637132567249495a5762465a334272676364756f4b353151457865734966584f45757469347a324c75717756704b5a5978314f47364258706d696261416f4b2f4d5a51647a70614574425133536b77686344554c664d522b742b50366c46613834544c6e4643486b", + "kindle.device.info": "4d61726373204b696e646c65206626233235323b722050432035", + "kindle.directedid.info": "616d7a6e312e6163636f756e742e41464a49514152565a55565a344451574c5a4a41585a4942324a5751", + "kindle.key.item": "2d2d2d2d2d424547494e205253412050524956415445204b45592d2d2d2d2d0a4d4949456f77494241414b434151454174424348652f79437a6d564571664a3166574973515262706b72725a4f4633334b6f496831626d4c4a6455626a4b6e330a55784a70594c35596a5a426a4e556b6d794a30515479765571424e4d6e6b6537486b6e7457564b34506e2f617531384e73635452656c4e59302b4f44514a50550a46327471636948304d6a7a2b485a4b5a5a434c7536444c68577444373158366c4355762b30704e516c75784964757036534d4565455342766e566e4e4d5530520a4e436337646c444549423976415131734739543578654e2f6e7041506e6d2f41356661392f5042704d634b6c75465968324f2f4a6177617076666e42664c534d0a4261594a79702b4f6665507250414735627a6f6b345438706551484f314f4552304b6474494d736130334242754f69444356784b4a39712b4a44625478555a310a594847576a6d486a4350776665536576526b41686732376d784a776d4c664e5a77772f476851494441514142416f49424151434d5756336844443741745470420a354e51692b4d525a723477376242776e7a55583841685a7853662f6c6179666743684c573030454477526d7772647847436c434b6962484f6f2f464c57452b650a4233635838724e6e72677768327649596e63784578593470644a4747426f326c5a68516f6450637849726e39396f427a65484c4c4646643238554770306236590a392b2b585158374c6a7a742f683467722b444e3852646f7a717a36554f37784f396671436b5531304b436573616e2b34664f37654772726e75677a6f345573630a4d584856414e6d7979306244582f67724d2b5648306a677935704978727730583079646c53703655337a584272685343626e315443437971544d545a626443520a4e486262716d6254764361444e48385638686446416631743030324a4b31723541314942357a38696d6b754f633747544b5854514c774d6a374444327176586b0a6367547162644542416f4742414f314837775465746644465054635a37393462673235666e51696b45796d5074444b4138715253624f3462464546426d3132620a6b504f52347756776e6c7069374b33647057426b357a326a4534476e734d6f35424f385655424143316d544d726b61636c6e37666a6d556e6a6d72327a3462420a334d483970653474306a784d7a442f543070376d65616743466c51616464336a5252654a68556f556e7653302f6978724b34452f62347968416f4742414d4a460a45546c4933552b442b58454a62434b4a6b4651344a2f726d2f6c5134476c5a337165792b62487365596e55753047384f6143545934334e4271766658753348530a395365454a6a6e36366b3368316c3038352b78756f6e664e3779485750565335346f4f4c734245594377306a324e467830712b396953375839676364773555530a375a30456c4f694f456e533373367530726c4b486a75544532416f757130594363715341686d746c416f4741613934557362455249766833674c4967306d624e0a6c414b5258396b2f414e6a635155315067525962675137385955495441445831616c5436304946473636346e444539446e424f69372b6c507439526b30546d6b0a6e592b687976575051316d744c46714a4b2f6f7a514a622f376d357648304c494f63513268355637436f43624a6255452f636d6d71704c77566147467a6135410a765a6439365a534151707835492f5a4157387862794b45436759415268424b7966497866774146386e4b48675631447046777362787a6f464d2b3345414251560a49584938673566544176364f464e6c31415130343969484a4b4f3167724f6d6e763357473473572f636535584238664e664967766a795452677a5353634251700a556933307a4a7371657948776548664c6d715a457a2f6f42324541724c384b3231705071682b7a49453077693369366469465673385161646e476d61375675530a3033664c4e514b426743775157586f74443147495a5351426f59463364346c4f4c4c4e73656a6c32304c6734716a385261624137383969454344344f414678390a2b6b467a694839643939303478707546616a6d6b497539622b2b476a477135634a6b795678443673623045754f4743576a354b6c3246304b69716a6e615553740a65472b4553626d6c4355464f54636d4f46703973474f477751573263363039554a41314141526e70316d374f6c713338394246790a2d2d2d2d2d454e44205253412050524956415445204b45592d2d2d2d2d0a", + "kindle.name.info": "4d617263", + "kindle.token.item": "7b656e633a69334e564b756362326c714247665052376f346e357473596b496d547039594f686a6e45762b324a55436364662f7a306a35486c656a76445a4c2f586f51467945694d69664d4e644d5630533266485a422f46336d724a383365754373444a50304c2b48685a6e3839655a3137446776456f73487841464469656c466e4e57705878554e4f4e45412b6a2f75563168387064573351776b4e673452426b747338766c7749734e524b7073684637346e6373744b3548556f6c4d77524e553158774d3151566b33514743754b6671493542476d52416c347a64364345535078534474304a73566e4a396c6e6a32483073525636374a5972336d4f704a726546536a79705a4c375157654d67787663686a6445713537384f6e342b4678456646674f744e44523331695266735350713471414d51625077374f2f7773374364536263347749664431455445755444546e4261554f34777936446b412b7641566a37322b3049626a66314f72313238624e393152777a692b6c6132356f70715a4e447344554e784c447a766e6b57374b68757a3757367746534e7574466e704568544e4d622b65554731734578544153527555734d2b7647455731714a396532352b3079742f4337496371516f6264484648326f31794c6144693765745a54715276344268587238723846584c587652544f69644f36754b42687230555974545561743635304f70306d6b776e334d6d703957697231526d7a54684247324f714c4f3775426262336c6a634e50795539583056326f495a63597454704f576e64674347656775674b7a625877664b6e6c536c734a344d79725643614d656a456735666e78484f6e34577941734e4546374e7a61516b654b2b49496c43666361466b72796f794832726b2f6d6a33725237507443734a58737a39392b674c6a6579516767596f46384b39474943754365424852795547676d7a5434666e4f74453869354b46364935693746744a6d7464536e4244354b6a552b7a466d3865357352464f6466477a6333706a2b6f5533705972524a4e326d6c715847676f50537353626f37364f732f2b7a4f5a4b45562f69717a56335a6f716930393461564e556c3275626263454e587a564358724754764374696d68674c514930673566456c62596c6b2f4c5363636c443969535857624e45786765756c6169315639704f6b6b6d345379564e7757563263583752697a2b517674485a33746463664c7461544e682f6757454e4d2f6f596c6f42716a6b73505676455368686f3079316f4a69472f5553494c4568346c3968487277532b53486e2b42496e486f39354c5332386873324d2f44797a55354d3458712b61376832686b487944352b344c66645a7a53422f327a316a476d6c33647937763064332f4d33744f5457697337744e7034747a63377a6e6543674872596852434767525a643577654f6d307a2f2b57586c49552b673744316c4e644739694672464152383254364d302f6e373653615a472b6d41627d7b6b65793a684f394578637546454f522b667a6166464c4d6f714b4c73314e556174575a664d55616f6a6b5766657a546f74655646506b4d7359326c746d56764d504e457a372f336e746b59585535704b68356345426831653057535477704b7978684c5a3567534c306f6b416e534e78706452774d6f6e5457522b4c644a68595a62657641443879577a5274715235767569576135646f562b4c356b49674974387163314334727232716b385063394450494a7433346243685a513374736441385a71536c4147647a4e46635949594456544e576e53747077436e79463936674771345a46555279306f543541424f566d395551495135473342594b35676f63726c61794158494370564a62714e49436a562b537145364257306f304954437a4c36356c4b6a4f576f526d6f5a63354750625171527875393933734e616e356d736f46447a4f57476a50736f4442677476415a51664144392b773d3d7d7b69763a72502f6d56396938374f6163355671447149596175773d3d7d7b6e616d653a51555251564739725a573546626d4e796558423061573975533256357d7b73657269616c3a4d673d3d7d", + "krx.flashcardsplugin.data.encryption_key": "7b37353735643662642d613738652d346466362d383730392d3835353931393261613736627d", + "krx.notebookexportplugin.data.encryption_key": "7b31373636323330612d626563642d343966652d396663362d6135633462643362393062347d", + "login": "6d726366726d30314070726f746f6e6d61696c2e636f6d", + "login_date": "323032322d30322d3132", + "max_date": "323032322d30332d32395430393a32303a3231" + } + }, + "kindlewineprefix": "", + "lcp_passphrases": [], + "pids": [], + "remove_watermarks": false, + "serials": [] +} \ No newline at end of file diff --git a/arch-config/.config/calibre/resources/images/mimetypes/kfx.png b/arch-config/.config/calibre/resources/images/mimetypes/kfx.png new file mode 100644 index 00000000..57ac654d Binary files /dev/null and b/arch-config/.config/calibre/resources/images/mimetypes/kfx.png differ diff --git a/arch-config/.config/calibre/tweak_book_gui.json b/arch-config/.config/calibre/tweak_book_gui.json new file mode 100644 index 00000000..cf98a41b --- /dev/null +++ b/arch-config/.config/calibre/tweak_book_gui.json @@ -0,0 +1,153 @@ +{ + "check-book-splitter-state": { + "__class__": "bytearray", + "__value__": "AAAA/wAAAAEAAAACAAAARgAAAEYA/////wEAAAABAA==" + }, + "custom_colors_for_color_dialog": [ + [ + 255, + 255, + 255, + 255 + ], + [ + 255, + 255, + 255, + 255 + ], + [ + 255, + 255, + 255, + 255 + ], + [ + 255, + 255, + 255, + 255 + ], + [ + 255, + 255, + 255, + 255 + ], + [ + 255, + 255, + 255, + 255 + ], + [ + 255, + 255, + 255, + 255 + ], + [ + 255, + 255, + 255, + 255 + ], + [ + 255, + 255, + 255, + 255 + ], + [ + 255, + 255, + 255, + 255 + ], + [ + 255, + 255, + 255, + 255 + ], + [ + 255, + 255, + 255, + 255 + ], + [ + 255, + 255, + 255, + 255 + ], + [ + 255, + 255, + 255, + 255 + ], + [ + 255, + 255, + 255, + 255 + ], + [ + 255, + 255, + 255, + 255 + ] + ], + "find-widget-state": { + "case_sensitive": false, + "direction": "down", + "dot_all": false, + "mode": "normal", + "where": "current", + "wrap": true + }, + "html-editor-state": { + "__class__": "bytearray", + "__value__": "AAAA/wAAAAD9AAAAAAAAAgEAAANcAAAABAAAAAQAAAAIAAAACPwAAAABAAAAAgAAAAMAAAAUAGEAYwB0AGkAbwBuAF8AYgBhAHIBAAAAAP////8AAAAAAAAAAAAAABIAdABvAG8AbABzAF8AYgBhAHIBAAAA3f////8AAAAAAAAAAAAAAB4AaAB0AG0AbABfAGYAbwByAG0AYQB0AF8AYgBhAHIBAAABv/////8AAAAAAAAAAA==" + }, + "main_window_geometry": { + "__class__": "bytearray", + "__value__": "AdnQywADAAAAAAUCAAAACQAAB3YAAAQaAAAFBAAAAAsAAAd0AAAEGAAAAAAAAAAAB4AAAAUEAAAACwAAB3QAAAQY" + }, + "main_window_state": { + "__class__": "bytearray", + "__value__": "AAAA/wAAAAD9AAAABAAAAAAAAACsAAADsfwCAAAABfsAAAAkAGYAaQBsAGUAcwAtAGIAcgBvAHcAcwBlAHIALQBkAG8AYwBrAQAAAEIAAAOxAAAAXgD////7AAAAHgB0AG8AYwAtAHYAaQBlAHcAZQByAC0AZABvAGMAawAAAAAA/////wAAAF4A////+wAAACAAdABlAHgAdAAtAHMAZQBhAHIAYwBoAC0AZABvAGMAawAAAAAA/////wAAAJAA////+wAAACAAYwBoAGUAYwBrAHAAbwBpAG4AdABzAC0AZABvAGMAawAAAAAA/////wAAAJQA////+wAAACYAcwBhAHYAZQBkAC0AcwBlAGEAcgBjAGgAZQBzAC0AZABvAGMAawAAAAAA/////wAAAlIA////AAAAAQAAAEEAAAOx/AIAAAAC+wAAABgAcAByAGUAdgBpAGUAdwAtAGQAbwBjAGsBAAAAQgAAA7EAAABbAP////sAAAAaAGwAaQB2AGUALQBjAHMAcwAtAGQAbwBjAGsAAAAAAP////8AAABeAP///wAAAAIAAAAAAAAAAPwBAAAAAfsAAAAeAGMAaABlAGMAawAtAGIAbwBvAGsALQBkAG8AYwBrAAAAAAD/////AAAAkAD///8AAAADAAAAAAAAAAD8AQAAAAH7AAAAHABpAG4AcwBwAGUAYwB0AG8AcgAtAGQAbwBjAGsAAAAAAP////8AAAA/AP///wAAAXgAAAOxAAAABAAAAAQAAAAIAAAACPwAAAABAAAAAgAAAAMAAAAUAGcAbABvAGIAYQBsAC0AYgBhAHIBAAAAAP////8AAAAAAAAAAAAAABIAdABvAG8AbABzAC0AYgBhAHIBAAABJv////8AAAAAAAAAAAAAABYAcABsAHUAZwBpAG4AcwAtAGIAYQByAAAAAAD/////AAAAAAAAAAA=" + }, + "recent-books": [ + "/home/marc/Nextcloud/Books/Herbert, Frank/Frank Herbert's Dune Saga Collection_ Books 1 - 6/Frank Herbert's Dune Saga Collection_ Books 1 - 6 - Frank Herbert.epub", + "/home/marc/Downloads/books/Ignition!_ An Informal History of Liquid Rocket Propellants (Rutgers University Press Classics) - John Drury Clark.epub", + "/home/marc/Downloads/books/Kryptowährungen_ Bitcoin, Ethereum, Blockchain, ICO's & Co. einfach erklärt (German Edition) - Julian Hosp.epub", + "/home/marc/Downloads/books/12 Stationen der Odyssee - Hürden auf dem Weg zur Berufung (German Edition), Die - Johann Wolfgang Denzinger.epub", + "/home/marc/Nextcloud/Books/Unterhaltung/The Sword of Truth [1] - Wizard's First Rule by Terry Goodkind.epub", + "/home/marc/The Witcher_ Through the Worlds-ffnet_13520045.epub", + "/home/marc/Nextcloud/Books/other/Kill la Kill/Keep Your Shirt On by Geist (Ryuko x Senketsu).epub", + "/home/marc/Nextcloud/Books/other/Witcher/Yesterdays Child by HopeofDawn (Ciri x witchers) (incomplete).epub", + "/home/marc/Downloads/warmth by satsukichan (Ryuko x Satsuki).epub", + "/home/marc/Downloads/Keep Your Shirt On by Geist (Ryuko x Senketsu).epub" + ], + "reports-ui-state": {}, + "saved_seaches_state": { + "direction": "down", + "where": "current", + "wrap": true + }, + "search-panel-visible": false, + "text_search_widget_state": { + "case_sensitive": false, + "dot_all": true, + "mode": "normal", + "where": "current" + }, + "toc_editor_window_geom": { + "__class__": "bytearray", + "__value__": "AdnQywADAAAAAAHjAAAA0wAABZwAAANMAAAB5QAAANUAAAWaAAADSgAAAAAAAAAAB4AAAAHlAAAA1QAABZoAAANK" + } +} \ No newline at end of file diff --git a/arch-config/.config/calibre/viewer-webengine.json b/arch-config/.config/calibre/viewer-webengine.json new file mode 100644 index 00000000..a6c4924c --- /dev/null +++ b/arch-config/.config/calibre/viewer-webengine.json @@ -0,0 +1,188 @@ +{ + "main_window_geometry": { + "__class__": "bytearray", + "__value__": "AdnQywADAAAAAAAAAAAAFAAAB38AAAQjAAAAAgAAABQAAAd9AAAEIQAAAAAAAAAAB4AAAAACAAAAFAAAB30AAAQh" + }, + "main_window_state": { + "__class__": "bytearray", + "__value__": "AAAA/wAAAAH9AAAAAgAAAAAAAAAAAAAAAPwCAAAAAvsAAAAQAHQAbwBjAC0AZABvAGMAawAAAAAA/////wAAAIcA////+wAAABYAcwBlAGEAcgBjAGgALQBkAG8AYwBrAAAAAAD/////AAAAlQD///8AAAABAAAAAAAAAAD8AgAAAAT7AAAAFgBsAG8AbwBrAHUAcAAtAGQAbwBjAGsAAAAAAP////8AAAB9AP////sAAAAcAGIAbwBvAGsAbQBhAHIAawBzAC0AZABvAGMAawAAAAAA/////wAAAOcA////+wAAABwAaQBuAHMAcABlAGMAdABvAHIALQBkAG8AYwBrAAAAAAD/////AAAAEwD////7AAAAHgBoAGkAZwBoAGwAaQBnAGgAdABzAC0AZABvAGMAawAAAAAA/////wAAAMkA////AAAHfAAABA4AAAAEAAAABAAAAAgAAAAI/AAAAAEAAAAAAAAAAQAAAB4AYQBjAHQAaQBvAG4AcwBfAHQAbwBvAGwAYgBhAHICAAAAAP////8AAAAAAAAAAA==" + }, + "old_prefs_migrated": true, + "session_data": { + "base_font_size": 73, + "controls_help_shown_count": 2, + "controls_help_shown_count_rtl_page_progression": 2, + "standalone_font_settings": {}, + "standalone_misc_settings": { + "remember_last_read": true, + "remember_window_geometry": false, + "save_annotations_in_ebook": true, + "singleinstance": false + }, + "standalone_recently_opened": [ + { + "authors": [ + "Magica Quartet, Hanokage" + ], + "key": "/home/marc/Downloads/newBooks/tmp/Puella Magi Madoka Magica_ The Movie -Rebellion-, Vol. 1 - Magica Quartet, Hanokage.epub", + "pathtoebook": "/home/marc/Downloads/newBooks/tmp/Puella Magi Madoka Magica_ The Movie -Rebellion-, Vol. 1 - Magica Quartet, Hanokage.epub", + "timestamp": "2022-07-26T18:43:58.537Z", + "title": "Puella Magi Madoka Magica: The Movie -Rebellion-, Vol. 1" + }, + { + "authors": [ + "Magica Quartet, Hanokage" + ], + "key": "/home/marc/Calibre-Bibliothek/Magica Quartet, Hanokage/Puella Magi Madoka Magica_ The Movie -Rebellion-, Vol. 1 (808)/Puella Magi Madoka Magica_ The Movie -Rebe - Magica Quartet, Hanokage.epub", + "pathtoebook": "/home/marc/Calibre-Bibliothek/Magica Quartet, Hanokage/Puella Magi Madoka Magica_ The Movie -Rebellion-, Vol. 1 (808)/Puella Magi Madoka Magica_ The Movie -Rebe - Magica Quartet, Hanokage.epub", + "timestamp": "2022-07-26T18:36:05.269Z", + "title": "Puella Magi Madoka Magica: The Movie -Rebellion-, Vol. 1" + }, + { + "authors": [ + "Magica Quartet, Hanokage" + ], + "key": "/home/marc/Calibre-Bibliothek/Magica Quartet, Hanokage/Puella Magi Madoka Magica_ The Movie -Rebellion-, Vol. 1 (807)/Puella Magi Madoka Magica_ The Movie -Rebe - Magica Quartet, Hanokage.epub", + "pathtoebook": "/home/marc/Calibre-Bibliothek/Magica Quartet, Hanokage/Puella Magi Madoka Magica_ The Movie -Rebellion-, Vol. 1 (807)/Puella Magi Madoka Magica_ The Movie -Rebe - Magica Quartet, Hanokage.epub", + "timestamp": "2022-07-26T18:34:28.888Z", + "title": "Puella Magi Madoka Magica: The Movie -Rebellion-, Vol. 1" + }, + { + "authors": [ + "Magica Quartet, Hanokage" + ], + "key": "/home/marc/Calibre-Bibliothek/Magica Quartet, Hanokage/Puella Magi Madoka Magica_ The Movie -Rebellion-, Vol. 1 (805)/Puella Magi Madoka Magica_ The Movie -Rebe - Magica Quartet, Hanokage.original_epub", + "pathtoebook": "/home/marc/Calibre-Bibliothek/Magica Quartet, Hanokage/Puella Magi Madoka Magica_ The Movie -Rebellion-, Vol. 1 (805)/Puella Magi Madoka Magica_ The Movie -Rebe - Magica Quartet, Hanokage.original_epub", + "timestamp": "2022-07-26T18:28:23.341Z", + "title": "Puella Magi Madoka Magica The Movie -Rebe" + }, + { + "authors": [ + "Asato Asato" + ], + "key": "/home/marc/Calibre-Bibliothek/Asato Asato/86 EIGHTY-SIX, Vol. 1 (Light Novel) (345)/86 EIGHTY-SIX, Vol. 1 (Light Novel) - Asato Asato.epub", + "pathtoebook": "/home/marc/Calibre-Bibliothek/Asato Asato/86 EIGHTY-SIX, Vol. 1 (Light Novel) (345)/86 EIGHTY-SIX, Vol. 1 (Light Novel) - Asato Asato.epub", + "timestamp": "2022-01-28T09:53:33.176Z", + "title": "86 EIGHTY-SIX, Vol. 1 (Light Novel)" + }, + { + "authors": [ + "Asato Asato" + ], + "key": "/home/marc/Calibre-Bibliothek/Asato Asato/Run Through the Battlefront (Finish) (343)/Run Through the Battlefront (Finish) - Asato Asato.epub", + "pathtoebook": "/home/marc/Calibre-Bibliothek/Asato Asato/Run Through the Battlefront (Finish) (343)/Run Through the Battlefront (Finish) - Asato Asato.epub", + "timestamp": "2022-01-28T09:53:13.780Z", + "title": "86--EIGHTY-SIX, Vol. 3 (Light Novel): Run Through the Battlefront (Finish)" + }, + { + "authors": [ + "Rob Sanders" + ], + "key": "/home/marc/Calibre-Bibliothek/Rob Sanders/Archaon_ Lord of Chaos (252)/Archaon_ Lord of Chaos - Rob Sanders.epub", + "pathtoebook": "/home/marc/Calibre-Bibliothek/Rob Sanders/Archaon_ Lord of Chaos (252)/Archaon_ Lord of Chaos - Rob Sanders.epub", + "timestamp": "2022-01-28T08:49:55.153Z", + "title": "Archaon: Lord of Chaos" + }, + { + "authors": [ + "George Orwell" + ], + "key": "/home/marc/Calibre-Bibliothek/George Orwell/1984 (285)/1984 - George Orwell.epub", + "pathtoebook": "/home/marc/Calibre-Bibliothek/George Orwell/1984 (285)/1984 - George Orwell.epub", + "timestamp": "2022-01-28T08:02:38.823Z", + "title": "1984" + }, + { + "authors": [ + "Anthony Ryan" + ], + "key": "/home/marc/Calibre-Bibliothek/Anthony Ryan/Queen of Fire (Raven's Shadow) (105)/Queen of Fire (Raven's Shadow) - Anthony Ryan.epub", + "pathtoebook": "/home/marc/Calibre-Bibliothek/Anthony Ryan/Queen of Fire (Raven's Shadow) (105)/Queen of Fire (Raven's Shadow) - Anthony Ryan.epub", + "timestamp": "2022-01-11T14:38:45.635Z", + "title": "Queen of Fire (Raven's Shadow)" + }, + { + "authors": [ + "Anthony Ryan" + ], + "key": "/home/marc/Calibre-Bibliothek/Anthony Ryan/Blood Song (A Raven's Shadow Novel) (104)/Blood Song (A Raven's Shadow Novel) - Anthony Ryan.epub", + "pathtoebook": "/home/marc/Calibre-Bibliothek/Anthony Ryan/Blood Song (A Raven's Shadow Novel) (104)/Blood Song (A Raven's Shadow Novel) - Anthony Ryan.epub", + "timestamp": "2022-01-11T14:38:30.952Z", + "title": "Blood Song (A Raven's Shadow Novel)" + }, + { + "authors": [ + "ANGELA SMITH" + ], + "key": "/home/marc/Downloads/download/SMITH, ANGELA/86--EIGHTY-SIX, Vol.1 Manga/86--EIGHTY-SIX, Vol.1 Manga - ANGELA SMITH.epub", + "pathtoebook": "/home/marc/Downloads/download/SMITH, ANGELA/86--EIGHTY-SIX, Vol.1 Manga/86--EIGHTY-SIX, Vol.1 Manga - ANGELA SMITH.epub", + "timestamp": "2021-08-21T13:56:27.475Z", + "title": "86--EIGHTY-SIX, Vol.1 Manga" + }, + { + "authors": [ + "SMITH, ANGELA" + ], + "key": "/home/marc/Downloads/86.epub", + "pathtoebook": "/home/marc/Downloads/86.epub", + "timestamp": "2021-08-21T13:40:35.430Z", + "title": "86--EIGHTY-SIX, Vol.1 Manga" + }, + { + "authors": [ + "Finn Brunton", + "Helen Nissenbaum" + ], + "key": "/home/marc/Downloads/books/Obfuscation (The MIT Press) - Finn Brunton & Helen Nissenbaum.epub", + "pathtoebook": "/home/marc/Downloads/books/Obfuscation (The MIT Press) - Finn Brunton & Helen Nissenbaum.epub", + "timestamp": "2021-07-30T19:44:24.324Z", + "title": "Obfuscation (The MIT Press)" + }, + { + "authors": [ + "Unknown" + ], + "key": "/home/marc/Downloads/books/Brisingr (The Inheritance cycle) - Unknown.epub", + "pathtoebook": "/home/marc/Downloads/books/Brisingr (The Inheritance cycle) - Unknown.epub", + "timestamp": "2021-07-30T19:43:32.241Z", + "title": "Brisingr (The Inheritance cycle)" + }, + { + "authors": [ + "Adrian Tchaikovsky" + ], + "key": "/home/marc/Downloads/books/Children of Time_ Winner of the 2016 Arthur C. Clarke Award (The Children of Time Novels) - Adrian Tchaikovsky.epub", + "pathtoebook": "/home/marc/Downloads/books/Children of Time_ Winner of the 2016 Arthur C. Clarke Award (The Children of Time Novels) - Adrian Tchaikovsky.epub", + "timestamp": "2021-07-30T19:36:36.787Z", + "title": "Children of Time: Winner of the 2016 Arthur C. Clarke Award (The Children of Time Novels)" + }, + { + "authors": [ + "Unknown" + ], + "key": "/home/marc/Downloads/books/Brave New World - Unknown.epub", + "pathtoebook": "/home/marc/Downloads/books/Brave New World - Unknown.epub", + "timestamp": "2021-07-30T19:35:27.518Z", + "title": "Brave New World" + }, + { + "authors": [ + "Asato Asato" + ], + "key": "/home/marc/Downloads/books/86--EIGHTY-SIX, Vol. 1 (light novel) (86--EIGHTY-SIX (light novel)) - Asato Asato.epub", + "pathtoebook": "/home/marc/Downloads/books/86--EIGHTY-SIX, Vol. 1 (light novel) (86--EIGHTY-SIX (light novel)) - Asato Asato.epub", + "timestamp": "2021-07-30T19:35:01.534Z", + "title": "86--EIGHTY-SIX, Vol. 1 (light novel) (86--EIGHTY-SIX (light novel))" + }, + { + "authors": [ + "Johann Wolfgang Denzinger" + ], + "key": "/home/marc/Downloads/books/12 Stationen der Odyssee - Hürden auf dem Weg zur Berufung (German Edition), Die - Johann Wolfgang Denzinger.epub", + "pathtoebook": "/home/marc/Downloads/books/12 Stationen der Odyssee - Hürden auf dem Weg zur Berufung (German Edition), Die - Johann Wolfgang Denzinger.epub", + "timestamp": "2021-07-30T19:32:57.167Z", + "title": "Die 12 Stationen der Odyssee - Hürden auf dem Weg zur Berufung (German Edition)" + } + ] + } +} \ No newline at end of file diff --git a/arch-config/.config/calibre/viewer/annots/1a3f45127d236f66728de58065fa819d97d50379e7319ca38c18b2c2cec41fed.json b/arch-config/.config/calibre/viewer/annots/1a3f45127d236f66728de58065fa819d97d50379e7319ca38c18b2c2cec41fed.json new file mode 100644 index 00000000..a579a1ad --- /dev/null +++ b/arch-config/.config/calibre/viewer/annots/1a3f45127d236f66728de58065fa819d97d50379e7319ca38c18b2c2cec41fed.json @@ -0,0 +1 @@ +[{"pos": "epubcfi(/16/2/4/122/1:432)", "pos_type": "epubcfi", "timestamp": "2021-07-30T19:33:12.113195+00:00", "type": "last-read"}] \ No newline at end of file diff --git a/arch-config/.config/calibre/viewer/annots/323e3aebcccadd1251dc5c74cc3e41b167e467c851160902fda74266e0ac2c83.json b/arch-config/.config/calibre/viewer/annots/323e3aebcccadd1251dc5c74cc3e41b167e467c851160902fda74266e0ac2c83.json new file mode 100644 index 00000000..cfd440e7 --- /dev/null +++ b/arch-config/.config/calibre/viewer/annots/323e3aebcccadd1251dc5c74cc3e41b167e467c851160902fda74266e0ac2c83.json @@ -0,0 +1 @@ +[{"pos": "epubcfi(/10/2/4[page_2]/2[Ps46SZPnR7e7taO692yCdA1757]/1:1)", "pos_type": "epubcfi", "timestamp": "2022-01-28T08:02:45.228778+00:00", "type": "last-read"}] \ No newline at end of file diff --git a/arch-config/.config/calibre/viewer/annots/375dce2b6dd890702c707025d4c0ce53d1b3194be2f484b9fad183a70289507f.json b/arch-config/.config/calibre/viewer/annots/375dce2b6dd890702c707025d4c0ce53d1b3194be2f484b9fad183a70289507f.json new file mode 100644 index 00000000..a7fbfff2 --- /dev/null +++ b/arch-config/.config/calibre/viewer/annots/375dce2b6dd890702c707025d4c0ce53d1b3194be2f484b9fad183a70289507f.json @@ -0,0 +1 @@ +[{"pos": "epubcfi(/2/2/4/2@50:50)", "pos_type": "epubcfi", "timestamp": "2022-07-26T18:36:06.811173+00:00", "type": "last-read"}] \ No newline at end of file diff --git a/arch-config/.config/calibre/viewer/annots/39551ab0625d16e5483f5b200ef278cdcaf07ed128d36792df38dd9b25353753.json b/arch-config/.config/calibre/viewer/annots/39551ab0625d16e5483f5b200ef278cdcaf07ed128d36792df38dd9b25353753.json new file mode 100644 index 00000000..39db7462 --- /dev/null +++ b/arch-config/.config/calibre/viewer/annots/39551ab0625d16e5483f5b200ef278cdcaf07ed128d36792df38dd9b25353753.json @@ -0,0 +1 @@ +[{"pos": "epubcfi(/2/2/4/2@50:50)", "pos_type": "epubcfi", "timestamp": "2022-01-11T14:38:24.256785+00:00", "type": "last-read"}] \ No newline at end of file diff --git a/arch-config/.config/calibre/viewer/annots/515ca70abfe74873f88b4f33ab46201bff15e8b7fc989bfa88dee2d23dc2834a.json b/arch-config/.config/calibre/viewer/annots/515ca70abfe74873f88b4f33ab46201bff15e8b7fc989bfa88dee2d23dc2834a.json new file mode 100644 index 00000000..5ebd3b17 --- /dev/null +++ b/arch-config/.config/calibre/viewer/annots/515ca70abfe74873f88b4f33ab46201bff15e8b7fc989bfa88dee2d23dc2834a.json @@ -0,0 +1 @@ +[{"pos": "epubcfi(/2/2/4/2@50:50)", "pos_type": "epubcfi", "timestamp": "2022-07-26T18:34:33.547558+00:00", "type": "last-read"}] \ No newline at end of file diff --git a/arch-config/.config/calibre/viewer/annots/537a4a02fa3afa022b8258b27efc3d80be26c8c53c5c8b493349689193a5995c.json b/arch-config/.config/calibre/viewer/annots/537a4a02fa3afa022b8258b27efc3d80be26c8c53c5c8b493349689193a5995c.json new file mode 100644 index 00000000..0584481c --- /dev/null +++ b/arch-config/.config/calibre/viewer/annots/537a4a02fa3afa022b8258b27efc3d80be26c8c53c5c8b493349689193a5995c.json @@ -0,0 +1 @@ +[{"pos": "epubcfi(/8/2/4/2[a22Z]/6/1:116)", "pos_type": "epubcfi", "timestamp": "2021-07-30T19:35:35.162148+00:00", "type": "last-read"}] \ No newline at end of file diff --git a/arch-config/.config/calibre/viewer/annots/5e6e196c7de66b99978f5076791472a6fdab7351a8c2de2d6542e662520591e2.json b/arch-config/.config/calibre/viewer/annots/5e6e196c7de66b99978f5076791472a6fdab7351a8c2de2d6542e662520591e2.json new file mode 100644 index 00000000..cc0b95b6 --- /dev/null +++ b/arch-config/.config/calibre/viewer/annots/5e6e196c7de66b99978f5076791472a6fdab7351a8c2de2d6542e662520591e2.json @@ -0,0 +1 @@ +[{"pos": "epubcfi(/2/2/4/2@50:50)", "pos_type": "epubcfi", "timestamp": "2021-07-30T19:44:30.693524+00:00", "type": "last-read"}] \ No newline at end of file diff --git a/arch-config/.config/calibre/viewer/annots/62766be925c64650a5743737a9146ad2a5af1676c6483a5904d30c37a24db518.json b/arch-config/.config/calibre/viewer/annots/62766be925c64650a5743737a9146ad2a5af1676c6483a5904d30c37a24db518.json new file mode 100644 index 00000000..c6d4a064 --- /dev/null +++ b/arch-config/.config/calibre/viewer/annots/62766be925c64650a5743737a9146ad2a5af1676c6483a5904d30c37a24db518.json @@ -0,0 +1 @@ +[{"pos": "epubcfi(/18/2/4/2[archaon-lord-of-chaos]/2/12/1:251)", "pos_type": "epubcfi", "timestamp": "2022-01-28T08:50:04.267755+00:00", "type": "last-read"}] \ No newline at end of file diff --git a/arch-config/.config/calibre/viewer/annots/6277a9a5e76b3df3f1f6690d12a977fe86bc2cea9c7a61a83fa696311e90a98f.json b/arch-config/.config/calibre/viewer/annots/6277a9a5e76b3df3f1f6690d12a977fe86bc2cea9c7a61a83fa696311e90a98f.json new file mode 100644 index 00000000..228e7800 --- /dev/null +++ b/arch-config/.config/calibre/viewer/annots/6277a9a5e76b3df3f1f6690d12a977fe86bc2cea9c7a61a83fa696311e90a98f.json @@ -0,0 +1 @@ +[{"pos": "epubcfi(/2/2/4/2@50:50)", "pos_type": "epubcfi", "timestamp": "2021-07-30T19:36:41.701587+00:00", "type": "last-read"}] \ No newline at end of file diff --git a/arch-config/.config/calibre/viewer/annots/69344a19d0fa1e3356cd3b9c249919395c90c1c601070be213fde6bc9660c730.json b/arch-config/.config/calibre/viewer/annots/69344a19d0fa1e3356cd3b9c249919395c90c1c601070be213fde6bc9660c730.json new file mode 100644 index 00000000..c6e66a81 --- /dev/null +++ b/arch-config/.config/calibre/viewer/annots/69344a19d0fa1e3356cd3b9c249919395c90c1c601070be213fde6bc9660c730.json @@ -0,0 +1 @@ +[{"pos": "epubcfi(/2/2/4/2@50:50)", "pos_type": "epubcfi", "timestamp": "2021-07-30T19:43:49.635838+00:00", "type": "last-read"}] \ No newline at end of file diff --git a/arch-config/.config/calibre/viewer/annots/91ece147862b5dc7f4c8c7100b27cfe1700f4fd9f9c8d368ddc67a0099a7b79d.json b/arch-config/.config/calibre/viewer/annots/91ece147862b5dc7f4c8c7100b27cfe1700f4fd9f9c8d368ddc67a0099a7b79d.json new file mode 100644 index 00000000..0b567ad9 --- /dev/null +++ b/arch-config/.config/calibre/viewer/annots/91ece147862b5dc7f4c8c7100b27cfe1700f4fd9f9c8d368ddc67a0099a7b79d.json @@ -0,0 +1 @@ +[{"pos": "epubcfi(/2/2/4/2@50:50)", "pos_type": "epubcfi", "timestamp": "2022-07-26T18:44:00.078291+00:00", "type": "last-read"}] \ No newline at end of file diff --git a/arch-config/.config/calibre/viewer/annots/9eae537242b56d7f96f1c919938ab8f92f2c7b8b256c5ddd9061e44f2369a029.json b/arch-config/.config/calibre/viewer/annots/9eae537242b56d7f96f1c919938ab8f92f2c7b8b256c5ddd9061e44f2369a029.json new file mode 100644 index 00000000..7ac5f4c0 --- /dev/null +++ b/arch-config/.config/calibre/viewer/annots/9eae537242b56d7f96f1c919938ab8f92f2c7b8b256c5ddd9061e44f2369a029.json @@ -0,0 +1 @@ +[{"pos": "epubcfi(/2/2/4/2@50:50)", "pos_type": "epubcfi", "timestamp": "2022-07-26T18:28:48.581022+00:00", "type": "last-read"}] \ No newline at end of file diff --git a/arch-config/.config/calibre/viewer/annots/b1e555b5fdc24ec9fdae02f3d478a4ceef96cb27175e2faa27f16c55fe36ad96.json b/arch-config/.config/calibre/viewer/annots/b1e555b5fdc24ec9fdae02f3d478a4ceef96cb27175e2faa27f16c55fe36ad96.json new file mode 100644 index 00000000..85bf69fd --- /dev/null +++ b/arch-config/.config/calibre/viewer/annots/b1e555b5fdc24ec9fdae02f3d478a4ceef96cb27175e2faa27f16c55fe36ad96.json @@ -0,0 +1 @@ +[{"pos": "epubcfi(/18/2/4/12/1:33)", "pos_type": "epubcfi", "timestamp": "2021-07-30T19:35:14.454534+00:00", "type": "last-read"}] \ No newline at end of file diff --git a/arch-config/.config/calibre/viewer/annots/ba4deddd25f6c1ff1f3609fe687eeecfeb37a55a60ff044e8cf6d45aab09b103.json b/arch-config/.config/calibre/viewer/annots/ba4deddd25f6c1ff1f3609fe687eeecfeb37a55a60ff044e8cf6d45aab09b103.json new file mode 100644 index 00000000..851606e6 --- /dev/null +++ b/arch-config/.config/calibre/viewer/annots/ba4deddd25f6c1ff1f3609fe687eeecfeb37a55a60ff044e8cf6d45aab09b103.json @@ -0,0 +1 @@ +[{"pos": "epubcfi(/4/2/4/2[a2W4]/2/2[page_7]/2@50.2:50)", "pos_type": "epubcfi", "timestamp": "2022-01-28T09:53:45.255681+00:00", "type": "last-read"}] \ No newline at end of file diff --git a/arch-config/.config/calibre/viewer/annots/bb6ff6c545446b34489ec0b2563b6e58520078af55b4c85721bfec5aae562791.json b/arch-config/.config/calibre/viewer/annots/bb6ff6c545446b34489ec0b2563b6e58520078af55b4c85721bfec5aae562791.json new file mode 100644 index 00000000..cd30bbb5 --- /dev/null +++ b/arch-config/.config/calibre/viewer/annots/bb6ff6c545446b34489ec0b2563b6e58520078af55b4c85721bfec5aae562791.json @@ -0,0 +1 @@ +[{"pos": "epubcfi(/46/2/4[page_23]/2/2@73.86:61.87)", "pos_type": "epubcfi", "timestamp": "2021-08-21T13:57:13.592114+00:00", "type": "last-read"}] \ No newline at end of file diff --git a/arch-config/.config/calibre/viewer/annots/bd8eede3da68f1a90f0260abd50a38f889beab8d4bdf42e951ec01999da457fd.json b/arch-config/.config/calibre/viewer/annots/bd8eede3da68f1a90f0260abd50a38f889beab8d4bdf42e951ec01999da457fd.json new file mode 100644 index 00000000..2835eb96 --- /dev/null +++ b/arch-config/.config/calibre/viewer/annots/bd8eede3da68f1a90f0260abd50a38f889beab8d4bdf42e951ec01999da457fd.json @@ -0,0 +1 @@ +[{"pos": "epubcfi(/4/2/4/2[a2R7]/2/2/2@50.2:50)", "pos_type": "epubcfi", "timestamp": "2022-01-28T09:53:26.291253+00:00", "type": "last-read"}] \ No newline at end of file diff --git a/arch-config/.config/calibre/viewer/annots/bdb9a7c1c41b9e0650416865db52670ed47f556d89dfd9fbd10c07e8f8ccc87d.json b/arch-config/.config/calibre/viewer/annots/bdb9a7c1c41b9e0650416865db52670ed47f556d89dfd9fbd10c07e8f8ccc87d.json new file mode 100644 index 00000000..7fb286f8 --- /dev/null +++ b/arch-config/.config/calibre/viewer/annots/bdb9a7c1c41b9e0650416865db52670ed47f556d89dfd9fbd10c07e8f8ccc87d.json @@ -0,0 +1 @@ +[{"pos": "epubcfi(/20/2/4[page_10]/2/2@49.92:63.1)", "pos_type": "epubcfi", "timestamp": "2021-08-21T13:40:50.335500+00:00", "type": "last-read"}] \ No newline at end of file diff --git a/arch-config/.config/calibre/viewer/annots/f48170ca14b5b4468d26845abc2872441f097be212f018278d9d0e1cc465e4ba.json b/arch-config/.config/calibre/viewer/annots/f48170ca14b5b4468d26845abc2872441f097be212f018278d9d0e1cc465e4ba.json new file mode 100644 index 00000000..0637a088 --- /dev/null +++ b/arch-config/.config/calibre/viewer/annots/f48170ca14b5b4468d26845abc2872441f097be212f018278d9d0e1cc465e4ba.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/arch-config/.config/calibre/viewer/annots/fc73b570a3fdc5f1fe7ca9c889f73baab35450648ca0edb4afe65587ef25c6cf.json b/arch-config/.config/calibre/viewer/annots/fc73b570a3fdc5f1fe7ca9c889f73baab35450648ca0edb4afe65587ef25c6cf.json new file mode 100644 index 00000000..696c1e6b --- /dev/null +++ b/arch-config/.config/calibre/viewer/annots/fc73b570a3fdc5f1fe7ca9c889f73baab35450648ca0edb4afe65587ef25c6cf.json @@ -0,0 +1 @@ +[{"pos": "epubcfi(/6/2/4/10/1:5)", "pos_type": "epubcfi", "timestamp": "2022-01-11T14:38:52.844911+00:00", "type": "last-read"}] \ No newline at end of file