diff options
author | Richard Hughes <richard@hughsie.com> | 2016-01-26 19:37:14 +0000 |
---|---|---|
committer | Richard Hughes <richard@hughsie.com> | 2016-01-26 19:37:14 +0000 |
commit | c795d33aa1906df4af80336e3f6df39344d7632f (patch) | |
tree | 202b3beae8539c41a2869a00fbb57ad18df92267 | |
parent | e740ab00457cd7bbbf5a940d79a356ed0b918d1b (diff) | |
download | appstream-glib-c795d33aa1906df4af80336e3f6df39344d7632f.tar.gz |
Parse the sections in the QM file format
Many thanks to Thiago Macieira for the extra help.
-rw-r--r-- | libappstream-glib/as-app-builder.c | 140 |
1 files changed, 72 insertions, 68 deletions
diff --git a/libappstream-glib/as-app-builder.c b/libappstream-glib/as-app-builder.c index 8e0cea3..799e862 100644 --- a/libappstream-glib/as-app-builder.c +++ b/libappstream-glib/as-app-builder.c @@ -217,18 +217,27 @@ as_app_builder_search_locale_gettext (AsAppBuilderContext *ctx, } typedef enum { - AS_APP_TRANSLATION_QM_TAG_END = 1, + AS_APP_TRANSLATION_QM_TAG_END = 0x1, /* SourceText16 */ - AS_APP_TRANSLATION_QM_TAG_TRANSLATION = 3, + AS_APP_TRANSLATION_QM_TAG_TRANSLATION = 0x3, /* Context16 */ - AS_APP_TRANSLATION_QM_TAG_OBSOLETE1 = 5, - AS_APP_TRANSLATION_QM_TAG_SOURCE_TEXT = 6, - AS_APP_TRANSLATION_QM_TAG_CONTEXT = 7, - AS_APP_TRANSLATION_QM_TAG_COMMENT = 8, + AS_APP_TRANSLATION_QM_TAG_OBSOLETE1 = 0x5, + AS_APP_TRANSLATION_QM_TAG_SOURCE_TEXT = 0x6, + AS_APP_TRANSLATION_QM_TAG_CONTEXT = 0x7, + AS_APP_TRANSLATION_QM_TAG_COMMENT = 0x8, /* Obsolete2 */ AS_APP_TRANSLATION_QM_TAG_LAST } AsAppBuilderQmTag; +typedef enum { + AS_APP_TRANSLATION_QM_SECTION_CONTEXTS = 0x2f, + AS_APP_TRANSLATION_QM_SECTION_HASHES = 0x42, + AS_APP_TRANSLATION_QM_SECTION_MESSAGES = 0x69, + AS_APP_TRANSLATION_QM_SECTION_NUMERUS = 0x88, + AS_APP_TRANSLATION_QM_SECTION_DEPS = 0x96, + AS_APP_TRANSLATION_QM_SECTION_LAST +} AsAppBuilderQmSection; + static guint8 _read_uint8 (const guint8 *data, guint32 *offset) { @@ -248,96 +257,44 @@ _read_uint32 (const guint8 *data, guint32 *offset) } /** - * as_app_builder_parse_file_qt: + * as_app_builder_parse_data_qt: **/ -static gboolean -as_app_builder_parse_file_qt (AsAppBuilderContext *ctx, +static void +as_app_builder_parse_data_qt (AsAppBuilderContext *ctx, const gchar *locale, - const gchar *filename, - GError **error) + const guint8 *data, + guint32 len) { AsAppBuilderEntry *entry; - guint32 addr = 0; - guint32 len; guint32 m = 0; guint nstrings = 0; - g_autofree guint8 *data = NULL; - const guint8 qm_magic[] = { - 0x3c, 0xb8, 0x64, 0x18, 0xca, 0xef, 0x9c, 0x95, - 0xcd, 0x21, 0x1c, 0xbf, 0x60, 0xa1, 0xbd, 0xdd - }; - - /* load file */ - if (!g_file_get_contents (filename, (gchar **) &data, (gsize *) &len, error)) - return FALSE; - - /* check header */ - if (len < sizeof(qm_magic) || - memcmp (data, qm_magic, sizeof(qm_magic)) != 0) { - g_set_error_literal (error, - AS_APP_ERROR, - AS_APP_ERROR_FAILED, - "file is invalid"); - return FALSE; - } - m += sizeof(qm_magic); - - /* unknown value 0x42? */ - _read_uint8 (data, &m); - - /* find offset to data table */ - addr = _read_uint32 (data, &m); - m += addr; - - /* unknown! */ - _read_uint8 (data, &m); - _read_uint32 (data, &m); - //g_debug ("seeking to QM @ %x\n", m); /* read data */ while (m < len) { - guint8 tag; guint32 tag_len; - //g_debug ("QM @%x", m); - tag = _read_uint8(data, &m); + AsAppBuilderQmTag tag = _read_uint8(data, &m); switch (tag) { case AS_APP_TRANSLATION_QM_TAG_END: - //g_debug ("QM{END}"); break; case AS_APP_TRANSLATION_QM_TAG_OBSOLETE1: m += 4; break; case AS_APP_TRANSLATION_QM_TAG_TRANSLATION: - tag_len = _read_uint32 (data, &m); - if (tag_len < 0xffffffff) - m += tag_len; - //g_debug ("QM{TRANSLATION} len %i", tag_len); - nstrings++; - break; case AS_APP_TRANSLATION_QM_TAG_SOURCE_TEXT: - tag_len = _read_uint32 (data, &m); - m += tag_len; - //g_debug ("QM{SOURCE_TEXT} len %i", tag_len); - break; case AS_APP_TRANSLATION_QM_TAG_CONTEXT: - tag_len = _read_uint32 (data, &m); - m += tag_len; - //g_debug ("QM{CONTEXT} len %i", tag_len); - break; case AS_APP_TRANSLATION_QM_TAG_COMMENT: tag_len = _read_uint32 (data, &m); - m += tag_len; - //g_debug ("QM{COMMENT} len %i", tag_len); + if (tag_len < 0xffffffff) + m += tag_len; + if (tag == AS_APP_TRANSLATION_QM_TAG_TRANSLATION) + nstrings++; break; default: - //g_debug ("QM{unknown} tag kind %i", tag); m = G_MAXUINT32; break; } } -// g_debug ("for QT locale %s, nstrings=%i", locale, nstrings); - /* add new entry */ entry = as_app_builder_entry_new (); entry->locale = g_strdup (locale); @@ -345,6 +302,53 @@ as_app_builder_parse_file_qt (AsAppBuilderContext *ctx, if (entry->nstrings > ctx->max_nstrings) ctx->max_nstrings = entry->nstrings; ctx->data = g_list_prepend (ctx->data, entry); +} + +/** + * as_app_builder_parse_file_qt: + **/ +static gboolean +as_app_builder_parse_file_qt (AsAppBuilderContext *ctx, + const gchar *locale, + const gchar *filename, + GError **error) +{ + guint32 len; + guint32 m = 0; + g_autofree guint8 *data = NULL; + const guint8 qm_magic[] = { + 0x3c, 0xb8, 0x64, 0x18, 0xca, 0xef, 0x9c, 0x95, + 0xcd, 0x21, 0x1c, 0xbf, 0x60, 0xa1, 0xbd, 0xdd + }; + + /* load file */ + if (!g_file_get_contents (filename, (gchar **) &data, (gsize *) &len, error)) + return FALSE; + + /* check header */ + if (len < sizeof(qm_magic) || + memcmp (data, qm_magic, sizeof(qm_magic)) != 0) { + g_set_error_literal (error, + AS_APP_ERROR, + AS_APP_ERROR_FAILED, + "file is invalid"); + return FALSE; + } + m += sizeof(qm_magic); + + /* parse each section */ + while (m < len) { + AsAppBuilderQmSection section = _read_uint8(data, &m); + guint32 section_len = _read_uint32 (data, &m); + if (section == AS_APP_TRANSLATION_QM_SECTION_MESSAGES) { + as_app_builder_parse_data_qt (ctx, + locale, + data + m, + section_len); + } + m += section_len; + } + return TRUE; } |