summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Hughes <richard@hughsie.com>2016-08-03 14:43:14 +0100
committerRichard Hughes <richard@hughsie.com>2016-08-03 14:49:26 +0100
commit7635f2af0b456d193ca3f480aa9eaab7cf3499f8 (patch)
tree99ae696e8ea7d0fb77190188be10826d45839798
parentf3f0ee17d917be775b5258b431ef3f9d4c8607c9 (diff)
downloadappstream-glib-7635f2af0b456d193ca3f480aa9eaab7cf3499f8.tar.gz
Add support for Google .PAK file to extract the <lang> data for apps
-rw-r--r--libappstream-glib/as-app-builder.c127
1 files changed, 127 insertions, 0 deletions
diff --git a/libappstream-glib/as-app-builder.c b/libappstream-glib/as-app-builder.c
index 230b1cb..41ef64a 100644
--- a/libappstream-glib/as-app-builder.c
+++ b/libappstream-glib/as-app-builder.c
@@ -408,6 +408,129 @@ as_app_builder_search_translations_gettext (AsAppBuilderContext *ctx,
return TRUE;
}
+static gchar *
+as_app_builder_get_locale_from_pak_fn (const gchar *basename)
+{
+ gchar *locale;
+ gchar *str;
+
+ /* FIXME: convert using a lookup table where required */
+ locale = g_strdup (basename);
+ str = g_strrstr (locale, ".");
+ if (str != NULL)
+ *str = '\0';
+ g_strdelimit (locale, "-", '_');
+ return locale;
+}
+
+static gboolean
+as_app_builder_parse_file_pak (AsAppBuilderContext *ctx,
+ const gchar *locale,
+ const gchar *filename,
+ GError **error)
+{
+ AsAppBuilderEntry *entry;
+ gsize len = 0;
+ guint32 nr_resources;
+ guint32 version_number;
+ guint8 encoding;
+ g_autofree gchar *data = NULL;
+
+ if (!g_file_get_contents (filename, &data, &len, error))
+ return FALSE;
+ if (len < 9) {
+ g_set_error (error,
+ AS_APP_ERROR,
+ AS_APP_ERROR_FAILED,
+ "file invalid, %" G_GSIZE_FORMAT "b in size",
+ len);
+ return FALSE;
+ }
+
+ /* get 4 byte version number */
+ memcpy (&version_number, data + 0, 4);
+ if (version_number != 4) {
+ g_set_error (error,
+ AS_APP_ERROR,
+ AS_APP_ERROR_FAILED,
+ "version number invalid, "
+ "got %" G_GUINT32_FORMAT " expected 4",
+ version_number);
+ return FALSE;
+ }
+
+ /* get 4 byte number of resources */
+ memcpy (&nr_resources, data + 4, 4);
+ if (nr_resources == 0) {
+ g_set_error_literal (error,
+ AS_APP_ERROR,
+ AS_APP_ERROR_FAILED,
+ "no resources found");
+ return FALSE;
+ }
+
+ /* get single byte of encoding */
+ encoding = (guint8) data[8];
+ if (encoding != 0 && encoding != 1) {
+ g_set_error (error,
+ AS_APP_ERROR,
+ AS_APP_ERROR_FAILED,
+ "PAK encoding invalid, got %u expected 0 or 1",
+ encoding);
+ return FALSE;
+ }
+
+ /* create entry without reading resources */
+ entry = as_app_builder_entry_new ();
+ entry->locale = g_strdup (locale);
+ entry->nstrings = nr_resources;
+ if (entry->nstrings > ctx->max_nstrings)
+ ctx->max_nstrings = entry->nstrings;
+ ctx->data = g_list_prepend (ctx->data, entry);
+ return TRUE;
+}
+
+static gboolean
+as_app_builder_search_translations_pak (AsAppBuilderContext *ctx,
+ const gchar *prefix,
+ AsAppBuilderFlags flags,
+ GError **error)
+{
+ guint i;
+
+ /* search for each translation ID */
+ for (i = 0; i < ctx->translations->len; i++) {
+ const gchar *tmp;
+ g_autoptr(GDir) dir = NULL;
+ g_autofree gchar *path = NULL;
+ AsTranslation *t = g_ptr_array_index (ctx->translations, i);
+
+ /* required */
+ if (as_translation_get_id (t) == NULL)
+ continue;
+ path = g_build_filename (prefix,
+ "lib64",
+ as_translation_get_id (t),
+ "locales",
+ NULL);
+ if (!g_file_test (path, G_FILE_TEST_EXISTS))
+ return TRUE;
+ dir = g_dir_open (path, 0, error);
+ if (dir == NULL)
+ return FALSE;
+
+ /* parse file for sanity */
+ while ((tmp = g_dir_read_name (dir)) != 0) {
+ g_autofree gchar *locale = NULL;
+ g_autofree gchar *fn = g_build_filename (path, tmp, NULL);
+ locale = as_app_builder_get_locale_from_pak_fn (tmp);
+ if (!as_app_builder_parse_file_pak (ctx, locale, fn, error))
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
static gint
as_app_builder_entry_sort_cb (gconstpointer a, gconstpointer b)
{
@@ -467,6 +590,10 @@ as_app_builder_search_translations (AsApp *app,
if (!as_app_builder_search_translations_gettext (ctx, prefix, flags, error))
return FALSE;
+ /* search for Google .pak files */
+ if (!as_app_builder_search_translations_pak (ctx, prefix, flags, error))
+ return FALSE;
+
/* calculate percentages */
for (l = ctx->data; l != NULL; l = l->next) {
e = l->data;