static gboolean gs_plugin_fedora_distro_upgrades_refresh (GsPlugin *plugin, guint cache_age, GCancellable *cancellable, GError **error) { GsPluginData *priv = gs_plugin_get_data (plugin); /* check cache age */ if (cache_age > 0) { guint tmp; g_autoptr(GFile) file = g_file_new_for_path (priv->cachefn); tmp = gs_utils_get_file_age (file); if (tmp < cache_age) { g_debug ("%s is only %u seconds old", priv->cachefn, tmp); return TRUE; } } /* download new file */ if (!gs_plugin_download_file (plugin, NULL, FEDORA_PKGDB_COLLECTIONS_API_URI, priv->cachefn, cancellable, error)) { gs_utils_error_add_unique_id (error, priv->cached_origin); return FALSE; } /* success */ return TRUE; }
static gchar * gs_utils_filename_array_return_newest (GPtrArray *array) { const gchar *filename_best = NULL; guint age_lowest = G_MAXUINT; guint i; for (i = 0; i < array->len; i++) { const gchar *fn = g_ptr_array_index (array, i); g_autoptr(GFile) file = g_file_new_for_path (fn); guint age_tmp = gs_utils_get_file_age (file); if (age_tmp < age_lowest) { age_lowest = age_tmp; filename_best = fn; } } return g_strdup (filename_best); }
static gboolean gs_plugin_odrs_refresh_ratings (GsPlugin *plugin, guint cache_age, GCancellable *cancellable, GError **error) { GsPluginData *priv = gs_plugin_get_data (plugin); g_autofree gchar *fn = NULL; g_autofree gchar *uri = NULL; g_autoptr(GsApp) app_dl = gs_app_new (gs_plugin_get_name (plugin)); /* check cache age */ fn = gs_utils_get_cache_filename ("ratings", "odrs.json", GS_UTILS_CACHE_FLAG_WRITEABLE, error); if (fn == NULL) return FALSE; if (cache_age > 0) { guint tmp; g_autoptr(GFile) file = NULL; file = g_file_new_for_path (fn); tmp = gs_utils_get_file_age (file); if (tmp < cache_age) { g_debug ("%s is only %u seconds old, so ignoring refresh", fn, tmp); return gs_plugin_odrs_load_ratings (plugin, fn, error); } } /* download the complete file */ uri = g_strdup_printf ("%s/ratings", priv->review_server); if (!gs_plugin_download_file (plugin, app_dl, uri, fn, cancellable, error)) { gs_utils_error_add_unique_id (error, priv->cached_origin); return FALSE; } return gs_plugin_odrs_load_ratings (plugin, fn, error); }
static GPtrArray * gs_plugin_odrs_fetch_for_app (GsPlugin *plugin, GsApp *app, GError **error) { GsPluginData *priv = gs_plugin_get_data (plugin); const gchar *version; guint status_code; g_autofree gchar *cachefn_basename = NULL; g_autofree gchar *cachefn = NULL; g_autofree gchar *data = NULL; g_autofree gchar *uri = NULL; g_autoptr(GFile) cachefn_file = NULL; g_autoptr(GPtrArray) reviews = NULL; g_autoptr(JsonBuilder) builder = NULL; g_autoptr(JsonGenerator) json_generator = NULL; g_autoptr(JsonNode) json_root = NULL; g_autoptr(SoupMessage) msg = NULL; /* look in the cache */ cachefn_basename = g_strdup_printf ("%s.json", gs_app_get_id (app)); cachefn = gs_utils_get_cache_filename ("reviews", cachefn_basename, GS_UTILS_CACHE_FLAG_WRITEABLE, error); if (cachefn == NULL) return NULL; cachefn_file = g_file_new_for_path (cachefn); if (gs_utils_get_file_age (cachefn_file) < ODRS_REVIEW_CACHE_AGE_MAX) { g_autofree gchar *json_data = NULL; if (!g_file_get_contents (cachefn, &json_data, NULL, error)) return NULL; g_debug ("got review data for %s from %s", gs_app_get_id (app), cachefn); return gs_plugin_odrs_parse_reviews (plugin, json_data, -1, error); } /* not always available */ version = gs_app_get_version (app); if (version == NULL) version = "unknown"; /* create object with review data */ builder = json_builder_new (); json_builder_begin_object (builder); json_builder_set_member_name (builder, "user_hash"); json_builder_add_string_value (builder, priv->user_hash); json_builder_set_member_name (builder, "app_id"); json_builder_add_string_value (builder, gs_app_get_id (app)); json_builder_set_member_name (builder, "locale"); json_builder_add_string_value (builder, gs_plugin_get_locale (plugin)); json_builder_set_member_name (builder, "distro"); json_builder_add_string_value (builder, priv->distro); json_builder_set_member_name (builder, "version"); json_builder_add_string_value (builder, version); json_builder_set_member_name (builder, "limit"); json_builder_add_int_value (builder, ODRS_REVIEW_NUMBER_RESULTS_MAX); json_builder_end_object (builder); /* export as a string */ json_root = json_builder_get_root (builder); json_generator = json_generator_new (); json_generator_set_pretty (json_generator, TRUE); json_generator_set_root (json_generator, json_root); data = json_generator_to_data (json_generator, NULL); if (data == NULL) return NULL; uri = g_strdup_printf ("%s/fetch", priv->review_server); msg = soup_message_new (SOUP_METHOD_POST, uri); soup_message_set_request (msg, "application/json; charset=utf-8", SOUP_MEMORY_COPY, data, strlen (data)); status_code = soup_session_send_message (gs_plugin_get_soup_session (plugin), msg); if (status_code != SOUP_STATUS_OK) { if (!gs_plugin_odrs_parse_success (msg->response_body->data, msg->response_body->length, error)) return NULL; /* not sure what to do here */ g_set_error_literal (error, GS_PLUGIN_ERROR, GS_PLUGIN_ERROR_DOWNLOAD_FAILED, "status code invalid"); gs_utils_error_add_unique_id (error, priv->cached_origin); return NULL; } reviews = gs_plugin_odrs_parse_reviews (plugin, msg->response_body->data, msg->response_body->length, error); if (reviews == NULL) return NULL; g_debug ("odrs returned: %s", msg->response_body->data); /* save to the cache */ if (!g_file_set_contents (cachefn, msg->response_body->data, msg->response_body->length, error)) return NULL; /* success */ return g_steal_pointer (&reviews); }
/** * gs_plugin_refresh_appstream: */ static gboolean gs_plugin_refresh_appstream (GsPlugin *plugin, guint cache_age, GCancellable *cancellable, GError **error) { GsPluginData *priv = gs_plugin_get_data (plugin); gboolean ret; guint i; g_autoptr(GPtrArray) xremotes = NULL; xremotes = xdg_app_installation_list_remotes (priv->installation, cancellable, error); if (xremotes == NULL) return FALSE; for (i = 0; i < xremotes->len; i++) { guint tmp; g_autoptr(GError) error_local = NULL; g_autoptr(GFile) file = NULL; g_autoptr(GFile) file_timestamp = NULL; g_autofree gchar *appstream_fn = NULL; XdgAppRemote *xremote = g_ptr_array_index (xremotes, i); /* skip known-broken repos */ if (g_strcmp0 (xdg_app_remote_get_name (xremote), "gnome-sdk") == 0) continue; if (g_strcmp0 (xdg_app_remote_get_name (xremote), "test-apps") == 0) continue; /* is the timestamp new enough */ file_timestamp = xdg_app_remote_get_appstream_timestamp (xremote, NULL); tmp = gs_utils_get_file_age (file_timestamp); if (tmp < cache_age) { g_autofree gchar *fn = g_file_get_path (file_timestamp); g_debug ("%s is only %i seconds old, so ignoring refresh", fn, tmp); continue; } /* download new data */ ret = xdg_app_installation_update_appstream_sync (priv->installation, xdg_app_remote_get_name (xremote), NULL, /* arch */ NULL, /* out_changed */ cancellable, &error_local); if (!ret) { if (g_error_matches (error_local, G_IO_ERROR, G_IO_ERROR_FAILED)) { g_debug ("Failed to get AppStream metadata: %s", error_local->message); continue; } g_set_error (error, GS_PLUGIN_ERROR, GS_PLUGIN_ERROR_NOT_SUPPORTED, "Failed to get AppStream metadata: %s", error_local->message); return FALSE; } /* add the new AppStream repo to the shared store */ file = xdg_app_remote_get_appstream_dir (xremote, NULL); appstream_fn = g_file_get_path (file); g_debug ("using AppStream metadata found at: %s", appstream_fn); } return TRUE; }
static gboolean gs_plugin_steam_refresh (GsPlugin *plugin, guint cache_age, GCancellable *cancellable, GError **error) { g_autoptr(AsStore) store = NULL; g_autoptr(GFile) file = NULL; g_autoptr(GPtrArray) apps = NULL; g_autofree gchar *fn = NULL; g_autofree gchar *fn_xml = NULL; /* check if exists */ fn = g_build_filename (g_get_user_data_dir (), "Steam", "appcache", "appinfo.vdf", NULL); if (!g_file_test (fn, G_FILE_TEST_EXISTS)) { g_debug ("no %s, so skipping", fn); return TRUE; } /* test cache age */ fn_xml = g_build_filename (g_get_user_data_dir (), "app-info", "xmls", "steam.xml.gz", NULL); file = g_file_new_for_path (fn_xml); if (cache_age > 0) { guint tmp; tmp = gs_utils_get_file_age (file); if (tmp < cache_age) { g_debug ("%s is only %u seconds old, so ignoring refresh", fn_xml, tmp); return TRUE; } } /* parse it */ apps = gs_plugin_steam_parse_appinfo_file (fn, error); if (apps == NULL) return FALSE; /* debug */ if (g_getenv ("GS_PLUGIN_STEAM_DEBUG") != NULL) gs_plugin_steam_dump_apps (apps); /* load existing AppStream XML */ store = as_store_new (); as_store_set_origin (store, "steam"); if (g_file_query_exists (file, cancellable)) { if (!as_store_from_file (store, file, NULL, cancellable, error)) return FALSE; } /* update any new applications */ if (!gs_plugin_steam_update_store (plugin, store, apps, error)) return FALSE; /* save new file */ if (!as_store_to_file (store, file, AS_NODE_TO_XML_FLAG_FORMAT_INDENT | AS_NODE_TO_XML_FLAG_FORMAT_MULTILINE, NULL, error)) { gs_utils_error_convert_appstream (error); return FALSE; } return TRUE; }
/** * xdg_app_review_get_ratings: */ static GArray * xdg_app_review_get_ratings (GsPlugin *plugin, GsApp *app, GError **error) { GArray *ratings; guint status_code; g_autofree gchar *cachedir = NULL; g_autofree gchar *cachefn = NULL; g_autofree gchar *data = NULL; g_autofree gchar *uri = NULL; g_autoptr(GFile) cachefn_file = NULL; g_autoptr(SoupMessage) msg = NULL; /* look in the cache */ cachedir = gs_utils_get_cachedir ("ratings", error); if (cachedir == NULL) return NULL; cachefn = g_strdup_printf ("%s/%s.json", cachedir, gs_app_get_id_no_prefix (app)); cachefn_file = g_file_new_for_path (cachefn); if (gs_utils_get_file_age (cachefn_file) < XDG_APP_REVIEW_CACHE_AGE_MAX) { g_autofree gchar *json_data = NULL; if (!g_file_get_contents (cachefn, &json_data, NULL, error)) return NULL; g_debug ("got ratings data for %s from %s", gs_app_get_id_no_prefix (app), cachefn); return xdg_app_review_parse_ratings (json_data, -1, error); } /* create the GET data *with* the machine hash so we can later * review the application ourselves */ uri = g_strdup_printf ("%s/ratings/%s", plugin->priv->review_server, gs_app_get_id_no_prefix (app)); msg = soup_message_new (SOUP_METHOD_GET, uri); status_code = soup_session_send_message (plugin->soup_session, msg); if (status_code != SOUP_STATUS_OK) { if (!xdg_app_review_parse_success (msg->response_body->data, msg->response_body->length, error)) return NULL; /* not sure what to do here */ g_set_error_literal (error, GS_PLUGIN_ERROR, GS_PLUGIN_ERROR_FAILED, "status code invalid"); return NULL; } g_debug ("xdg-app-review returned: %s", msg->response_body->data); ratings = xdg_app_review_parse_ratings (msg->response_body->data, msg->response_body->length, error); if (ratings == NULL) return NULL; /* save to the cache */ if (!g_file_set_contents (cachefn, msg->response_body->data, msg->response_body->length, error)) return NULL; return ratings; }
void gs_screenshot_image_load_async (GsScreenshotImage *ssimg, GCancellable *cancellable) { AsImage *im = NULL; const gchar *url; g_autofree gchar *basename = NULL; g_autofree gchar *cache_kind = NULL; g_autofree gchar *cachefn_thumb = NULL; g_autofree gchar *sizedir = NULL; g_autoptr(SoupURI) base_uri = NULL; g_return_if_fail (GS_IS_SCREENSHOT_IMAGE (ssimg)); g_return_if_fail (AS_IS_SCREENSHOT (ssimg->screenshot)); g_return_if_fail (ssimg->width != 0); g_return_if_fail (ssimg->height != 0); /* load an image according to the scale factor */ ssimg->scale = (guint) gtk_widget_get_scale_factor (GTK_WIDGET (ssimg)); im = as_screenshot_get_image (ssimg->screenshot, ssimg->width * ssimg->scale, ssimg->height * ssimg->scale); /* if we've failed to load a HiDPI image, fallback to LoDPI */ if (im == NULL && ssimg->scale > 1) { ssimg->scale = 1; im = as_screenshot_get_image (ssimg->screenshot, ssimg->width, ssimg->height); } if (im == NULL) { /* TRANSLATORS: this is when we request a screenshot size that * the generator did not create or the parser did not add */ gs_screenshot_image_set_error (ssimg, _("Screenshot size not found")); return; } /* check if the URL points to a local file */ url = as_image_get_url (im); if (g_str_has_prefix (url, "file://")) { g_free (ssimg->filename); ssimg->filename = g_strdup (url + 7); if (g_file_test (ssimg->filename, G_FILE_TEST_EXISTS)) { as_screenshot_show_image (ssimg); return; } } basename = gs_screenshot_get_cachefn_for_url (url); if (ssimg->width == G_MAXUINT || ssimg->height == G_MAXUINT) { sizedir = g_strdup ("unknown"); } else { sizedir = g_strdup_printf ("%ux%u", ssimg->width * ssimg->scale, ssimg->height * ssimg->scale); } cache_kind = g_build_filename ("screenshots", sizedir, NULL); g_free (ssimg->filename); ssimg->filename = gs_utils_get_cache_filename (cache_kind, basename, GS_UTILS_CACHE_FLAG_NONE, NULL); if (ssimg->filename == NULL) { /* TRANSLATORS: this is when we try create the cache directory * but we were out of space or permission was denied */ gs_screenshot_image_set_error (ssimg, _("Could not create cache")); return; } /* does local file already exist and has recently been downloaded */ if (g_file_test (ssimg->filename, G_FILE_TEST_EXISTS)) { guint64 age_max; g_autoptr(GFile) file = NULL; /* show the image we have in cache while we're checking for the * new screenshot (which probably won't have changed) */ as_screenshot_show_image (ssimg); /* verify the cache age against the maximum allowed */ age_max = g_settings_get_uint (ssimg->settings, "screenshot-cache-age-maximum"); file = g_file_new_for_path (ssimg->filename); /* image new enough, not re-requesting from server */ if (age_max > 0 && gs_utils_get_file_age (file) < age_max) return; } /* if we're not showing a full-size image, we try loading a blurred * smaller version of it straight away */ if (!ssimg->showing_image && ssimg->width > AS_IMAGE_THUMBNAIL_WIDTH && ssimg->height > AS_IMAGE_THUMBNAIL_HEIGHT) { const gchar *url_thumb; g_autofree gchar *basename_thumb = NULL; g_autofree gchar *cache_kind_thumb = NULL; im = as_screenshot_get_image (ssimg->screenshot, AS_IMAGE_THUMBNAIL_WIDTH * ssimg->scale, AS_IMAGE_THUMBNAIL_HEIGHT * ssimg->scale); url_thumb = as_image_get_url (im); basename_thumb = gs_screenshot_get_cachefn_for_url (url_thumb); cache_kind_thumb = g_build_filename ("screenshots", "112x63", NULL); cachefn_thumb = gs_utils_get_cache_filename (cache_kind_thumb, basename_thumb, GS_UTILS_CACHE_FLAG_NONE, NULL); if (cachefn_thumb == NULL) return; if (g_file_test (cachefn_thumb, G_FILE_TEST_EXISTS)) gs_screenshot_image_show_blurred (ssimg, cachefn_thumb); } /* re-request the cache filename, which might be different as it needs * to be writable this time */ g_free (ssimg->filename); ssimg->filename = gs_utils_get_cache_filename (cache_kind, basename, GS_UTILS_CACHE_FLAG_WRITEABLE, NULL); /* download file */ g_debug ("downloading %s to %s", url, ssimg->filename); base_uri = soup_uri_new (url); if (base_uri == NULL || !SOUP_URI_VALID_FOR_HTTP (base_uri)) { /* TRANSLATORS: this is when we try to download a screenshot * that was not a valid URL */ gs_screenshot_image_set_error (ssimg, _("Screenshot not valid")); return; } /* cancel any previous messages */ if (ssimg->message != NULL) { soup_session_cancel_message (ssimg->session, ssimg->message, SOUP_STATUS_CANCELLED); g_clear_object (&ssimg->message); } ssimg->message = soup_message_new_from_uri (SOUP_METHOD_GET, base_uri); if (ssimg->message == NULL) { /* TRANSLATORS: this is when networking is not available */ gs_screenshot_image_set_error (ssimg, _("Screenshot not available")); return; } /* not all servers support If-Modified-Since, but worst case we just * re-download the entire file again every 30 days */ if (g_file_test (ssimg->filename, G_FILE_TEST_EXISTS)) { g_autoptr(GFile) file = g_file_new_for_path (ssimg->filename); gs_screenshot_soup_msg_set_modified_request (ssimg->message, file); } /* send async */ soup_session_queue_message (ssimg->session, g_object_ref (ssimg->message) /* transfer full */, gs_screenshot_image_complete_cb, g_object_ref (ssimg)); }