static gboolean pk_backend_spawn_parse_stdout (PkBackendSpawn *backend_spawn, PkBackendJob *job, const gchar *line, GError **error) { guint size; gchar *command; gchar *text; guint64 speed; guint64 download_size_remaining; PkInfoEnum info; PkRestartEnum restart; PkGroupEnum group; gulong package_size; gint percentage; PkErrorEnum error_enum; PkStatusEnum status_enum; PkRestartEnum restart_enum; PkSigTypeEnum sig_type; PkUpdateStateEnum update_state_enum; PkMediaTypeEnum media_type_enum; PkDistroUpgradeEnum distro_upgrade_enum; PkBackendSpawnPrivate *priv = backend_spawn->priv; g_auto(GStrv) sections = NULL; g_return_val_if_fail (PK_IS_BACKEND_SPAWN (backend_spawn), FALSE); /* check if output line */ if (line == NULL) return FALSE; /* split by tab */ sections = g_strsplit (line, "\t", 0); command = sections[0]; /* get size */ size = g_strv_length (sections); if (g_strcmp0 (command, "package") == 0) { if (size != 4) { g_set_error (error, 1, 0, "invalid command'%s', size %i", command, size); return FALSE; } if (pk_package_id_check (sections[2]) == FALSE) { g_set_error_literal (error, 1, 0, "invalid package_id"); return FALSE; } info = pk_info_enum_from_string (sections[1]); if (info == PK_INFO_ENUM_UNKNOWN) { g_set_error (error, 1, 0, "Info enum not recognised, and hence ignored: '%s'", sections[1]); return FALSE; } g_strdelimit (sections[3], PK_UNSAFE_DELIMITERS, ' '); if (!g_utf8_validate (sections[3], -1, NULL)) { g_set_error (error, 1, 0, "text '%s' was not valid UTF8!", sections[3]); return FALSE; } pk_backend_job_package (job, info, sections[2], sections[3]); } else if (g_strcmp0 (command, "details") == 0) { if (size != 8) { g_set_error (error, 1, 0, "invalid command'%s', size %i", command, size); return FALSE; } group = pk_group_enum_from_string (sections[4]); /* ITS4: ignore, checked for overflow */ package_size = atol (sections[7]); if (package_size > 1073741824) { g_set_error_literal (error, 1, 0, "package size cannot be that large"); return FALSE; } g_strdelimit (sections[5], PK_UNSAFE_DELIMITERS, ' '); if (!g_utf8_validate (sections[4], -1, NULL)) { g_set_error (error, 1, 0, "text '%s' was not valid UTF8!", sections[5]); return FALSE; } text = g_strdup (sections[5]); /* convert ; to \n as we can't emit them on stdout */ g_strdelimit (text, ";", '\n'); pk_backend_job_details (job, sections[1], sections[2], sections[3], group, text, sections[6], package_size); g_free (text); } else if (g_strcmp0 (command, "finished") == 0) { if (size != 1) { g_set_error (error, 1, 0, "invalid command'%s', size %i", command, size); return FALSE; } pk_backend_job_finished (job); priv->is_busy = FALSE; /* from this point on, we can start the kill timer */ pk_backend_spawn_start_kill_timer (backend_spawn); } else if (g_strcmp0 (command, "files") == 0) { g_auto(GStrv) tmp = NULL; if (size != 3) { g_set_error (error, 1, 0, "invalid command'%s', size %i", command, size); return FALSE; } tmp = g_strsplit (sections[2], ";", -1); pk_backend_job_files (job, sections[1], tmp); } else if (g_strcmp0 (command, "repo-detail") == 0) { if (size != 4) { g_set_error (error, 1, 0, "invalid command'%s', size %i", command, size); return FALSE; } g_strdelimit (sections[2], PK_UNSAFE_DELIMITERS, ' '); if (!g_utf8_validate (sections[2], -1, NULL)) { g_set_error (error, 1, 0, "text '%s' was not valid UTF8!", sections[2]); return FALSE; } if (g_strcmp0 (sections[3], "true") == 0) { pk_backend_job_repo_detail (job, sections[1], sections[2], TRUE); } else if (g_strcmp0 (sections[3], "false") == 0) { pk_backend_job_repo_detail (job, sections[1], sections[2], FALSE); } else { g_set_error (error, 1, 0, "invalid qualifier '%s'", sections[3]); return FALSE; } } else if (g_strcmp0 (command, "updatedetail") == 0) { g_auto(GStrv) updates = NULL; g_auto(GStrv) obsoletes = NULL; g_auto(GStrv) vendor_urls = NULL; g_auto(GStrv) bugzilla_urls = NULL; g_auto(GStrv) cve_urls = NULL; if (size != 13) { g_set_error (error, 1, 0, "invalid command '%s', size %i", command, size); return FALSE; } restart = pk_restart_enum_from_string (sections[7]); if (restart == PK_RESTART_ENUM_UNKNOWN) { g_set_error (error, 1, 0, "Restart enum not recognised, and hence ignored: '%s'", sections[7]); return FALSE; } g_strdelimit (sections[12], PK_UNSAFE_DELIMITERS, ' '); if (!g_utf8_validate (sections[12], -1, NULL)) { g_set_error (error, 1, 0, "text '%s' was not valid UTF8!", sections[12]); return FALSE; } update_state_enum = pk_update_state_enum_from_string (sections[10]); /* convert ; to \n as we can't emit them on stdout */ g_strdelimit (sections[8], ";", '\n'); g_strdelimit (sections[9], ";", '\n'); updates = g_strsplit (sections[2], "&", -1); obsoletes = g_strsplit (sections[3], "&", -1); vendor_urls = g_strsplit (sections[4], ";", -1); bugzilla_urls = g_strsplit (sections[5], ";", -1); cve_urls = g_strsplit (sections[6], ";", -1); pk_backend_job_update_detail (job, sections[1], updates, obsoletes, vendor_urls, bugzilla_urls, cve_urls, restart, sections[8], sections[9], update_state_enum, sections[11], sections[12]); } else if (g_strcmp0 (command, "percentage") == 0) { if (size != 2) { g_set_error (error, 1, 0, "invalid command'%s', size %i", command, size); return FALSE; } if (!pk_strtoint (sections[1], &percentage)) { g_set_error (error, 1, 0, "invalid percentage value %s", sections[1]); return FALSE; } else if (percentage < 0 || percentage > 100) { g_set_error (error, 1, 0, "invalid percentage value %i", percentage); return FALSE; } else { pk_backend_job_set_percentage (job, percentage); } } else if (g_strcmp0 (command, "item-progress") == 0) { if (size != 4) { g_set_error (error, 1, 0, "invalid command'%s', size %i", command, size); return FALSE; } if (!pk_package_id_check (sections[1])) { g_set_error (error, 1, 0, "invalid package_id"); return FALSE; } status_enum = pk_status_enum_from_string (sections[2]); if (status_enum == PK_STATUS_ENUM_UNKNOWN) { g_set_error (error, 1, 0, "Status enum not recognised, and hence ignored: '%s'", sections[2]); return FALSE; } if (!pk_strtoint (sections[3], &percentage)) { g_set_error (error, 1, 0, "invalid item-progress value %s", sections[3]); return FALSE; } if (percentage < 0 || percentage > 100) { g_set_error (error, 1, 0, "invalid item-progress value %i", percentage); return FALSE; } pk_backend_job_set_item_progress (job, sections[1], status_enum, percentage); } else if (g_strcmp0 (command, "error") == 0) { if (size != 3) { g_set_error (error, 1, 0, "invalid command'%s', size %i", command, size); return FALSE; } error_enum = pk_error_enum_from_string (sections[1]); if (error_enum == PK_ERROR_ENUM_UNKNOWN) { g_set_error (error, 1, 0, "Error enum not recognised, and hence ignored: '%s'", sections[1]); return FALSE; } /* convert back all the ;'s to newlines */ text = g_strdup (sections[2]); /* convert ; to \n as we can't emit them on stdout */ g_strdelimit (text, ";", '\n'); /* convert % else we try to format them */ g_strdelimit (text, "%", '$'); pk_backend_job_error_code (job, error_enum, "%s", text); g_free (text); } else if (g_strcmp0 (command, "requirerestart") == 0) { if (size != 3) { g_set_error (error, 1, 0, "invalid command'%s', size %i", command, size); return FALSE; } restart_enum = pk_restart_enum_from_string (sections[1]); if (restart_enum == PK_RESTART_ENUM_UNKNOWN) { g_set_error (error, 1, 0, "Restart enum not recognised, and hence ignored: '%s'", sections[1]); return FALSE; } if (!pk_package_id_check (sections[2])) { g_set_error (error, 1, 0, "invalid package_id"); return FALSE; } pk_backend_job_require_restart (job, restart_enum, sections[2]); } else if (g_strcmp0 (command, "status") == 0) { if (size != 2) { g_set_error (error, 1, 0, "invalid command'%s', size %i", command, size); return FALSE; } status_enum = pk_status_enum_from_string (sections[1]); if (status_enum == PK_STATUS_ENUM_UNKNOWN) { g_set_error (error, 1, 0, "Status enum not recognised, and hence ignored: '%s'", sections[1]); return FALSE; } pk_backend_job_set_status (job, status_enum); } else if (g_strcmp0 (command, "speed") == 0) { if (size != 2) { g_set_error (error, 1, 0, "invalid command'%s', size %i", command, size); return FALSE; } if (!pk_strtouint64 (sections[1], &speed)) { g_set_error (error, 1, 0, "failed to parse speed: '%s'", sections[1]); return FALSE; } pk_backend_job_set_speed (job, speed); } else if (g_strcmp0 (command, "download-size-remaining") == 0) { if (size != 2) { g_set_error (error, 1, 0, "invalid command'%s', size %i", command, size); return FALSE; } if (!pk_strtouint64 (sections[1], &download_size_remaining)) { g_set_error (error, 1, 0, "failed to parse download_size_remaining: '%s'", sections[1]); return FALSE; } pk_backend_job_set_download_size_remaining (job, download_size_remaining); } else if (g_strcmp0 (command, "allow-cancel") == 0) { if (size != 2) { g_set_error (error, 1, 0, "invalid command'%s', size %i", command, size); return FALSE; } if (g_strcmp0 (sections[1], "true") == 0) { pk_backend_job_set_allow_cancel (job, TRUE); } else if (g_strcmp0 (sections[1], "false") == 0) { pk_backend_job_set_allow_cancel (job, FALSE); } else { g_set_error (error, 1, 0, "invalid section '%s'", sections[1]); return FALSE; } } else if (g_strcmp0 (command, "no-percentage-updates") == 0) { if (size != 1) { g_set_error (error, 1, 0, "invalid command'%s', size %i", command, size); return FALSE; } pk_backend_job_set_percentage (job, PK_BACKEND_PERCENTAGE_INVALID); } else if (g_strcmp0 (command, "repo-signature-required") == 0) { if (size != 9) { g_set_error (error, 1, 0, "invalid command'%s', size %i", command, size); return FALSE; } sig_type = pk_sig_type_enum_from_string (sections[8]); if (sig_type == PK_SIGTYPE_ENUM_UNKNOWN) { g_set_error (error, 1, 0, "Sig enum not recognised, and hence ignored: '%s'", sections[8]); return FALSE; } if (pk_strzero (sections[1])) { g_set_error (error, 1, 0, "package_id blank, and hence ignored: '%s'", sections[1]); return FALSE; } if (pk_strzero (sections[2])) { g_set_error (error, 1, 0, "repository name blank, and hence ignored: '%s'", sections[2]); return FALSE; } /* pass _all_ of the data */ pk_backend_job_repo_signature_required (job, sections[1], sections[2], sections[3], sections[4], sections[5], sections[6], sections[7], sig_type); } else if (g_strcmp0 (command, "eula-required") == 0) { if (size != 5) { g_set_error (error, 1, 0, "invalid command'%s', size %i", command, size); return FALSE; } if (pk_strzero (sections[1])) { g_set_error (error, 1, 0, "eula_id blank, and hence ignored: '%s'", sections[1]); return FALSE; } if (pk_strzero (sections[2])) { g_set_error (error, 1, 0, "package_id blank, and hence ignored: '%s'", sections[2]); return FALSE; } if (pk_strzero (sections[4])) { g_set_error (error, 1, 0, "agreement name blank, and hence ignored: '%s'", sections[4]); return FALSE; } pk_backend_job_eula_required (job, sections[1], sections[2], sections[3], sections[4]); } else if (g_strcmp0 (command, "media-change-required") == 0) { if (size != 4) { g_set_error (error, 1, 0, "invalid command'%s', size %i", command, size); return FALSE; } media_type_enum = pk_media_type_enum_from_string (sections[1]); if (media_type_enum == PK_MEDIA_TYPE_ENUM_UNKNOWN) { g_set_error (error, 1, 0, "media type enum not recognised, and hence ignored: '%s'", sections[1]); return FALSE; } pk_backend_job_media_change_required (job, media_type_enum, sections[2], sections[3]); } else if (g_strcmp0 (command, "distro-upgrade") == 0) { if (size != 4) { g_set_error (error, 1, 0, "invalid command'%s', size %i", command, size); return FALSE; } distro_upgrade_enum = pk_distro_upgrade_enum_from_string (sections[1]); if (distro_upgrade_enum == PK_DISTRO_UPGRADE_ENUM_UNKNOWN) { g_set_error (error, 1, 0, "distro upgrade enum not recognised, and hence ignored: '%s'", sections[1]); return FALSE; } g_strdelimit (sections[3], PK_UNSAFE_DELIMITERS, ' '); if (!g_utf8_validate (sections[3], -1, NULL)) { g_set_error (error, 1, 0, "text '%s' was not valid UTF8!", sections[3]); return FALSE; } pk_backend_job_distro_upgrade (job, distro_upgrade_enum, sections[2], sections[3]); } else if (g_strcmp0 (command, "category") == 0) { if (size != 6) { g_set_error (error, 1, 0, "invalid command'%s', size %i", command, size); return FALSE; } if (g_strcmp0 (sections[1], sections[2]) == 0) { g_set_error_literal (error, 1, 0, "cat_id cannot be the same as parent_id"); return FALSE; } if (pk_strzero (sections[2])) { g_set_error_literal (error, 1, 0, "cat_id cannot not blank"); return FALSE; } if (pk_strzero (sections[3])) { g_set_error_literal (error, 1, 0, "name cannot not blank"); return FALSE; } g_strdelimit (sections[4], PK_UNSAFE_DELIMITERS, ' '); if (!g_utf8_validate (sections[4], -1, NULL)) { g_set_error (error, 1, 0, "text '%s' was not valid UTF8!", sections[4]); return FALSE; } if (pk_strzero (sections[5])) { g_set_error_literal (error, 1, 0, "icon cannot not blank"); return FALSE; } if (g_str_has_prefix (sections[5], "/")) { g_set_error (error, 1, 0, "icon '%s' should be a named icon, not a path", sections[5]); return FALSE; } pk_backend_job_category (job, sections[1], sections[2], sections[3], sections[4], sections[5]); } else { g_set_error (error, 1, 0, "invalid command '%s'", command); return FALSE; } return TRUE; }
/** * pk_backend_spawn_parse_stdout: **/ static gboolean pk_backend_spawn_parse_stdout (PkBackendSpawn *backend_spawn, PkBackendJob *job, const gchar *line, GError **error) { gchar **sections; guint size; gchar *command; gchar *text; gboolean ret = TRUE; guint64 speed; guint64 download_size_remaining; PkInfoEnum info; PkRestartEnum restart; PkGroupEnum group; gulong package_size; gint percentage; PkErrorEnum error_enum; PkStatusEnum status_enum; PkMessageEnum message_enum; PkRestartEnum restart_enum; PkSigTypeEnum sig_type; PkUpdateStateEnum update_state_enum; PkMediaTypeEnum media_type_enum; PkDistroUpgradeEnum distro_upgrade_enum; PkBackendSpawnPrivate *priv = backend_spawn->priv; g_return_val_if_fail (PK_IS_BACKEND_SPAWN (backend_spawn), FALSE); /* check if output line */ if (line == NULL) return FALSE; /* split by tab */ sections = g_strsplit (line, "\t", 0); command = sections[0]; /* get size */ size = g_strv_length (sections); if (g_strcmp0 (command, "package") == 0) { if (size != 4) { g_set_error (error, 1, 0, "invalid command'%s', size %i", command, size); ret = FALSE; goto out; } if (pk_package_id_check (sections[2]) == FALSE) { g_set_error_literal (error, 1, 0, "invalid package_id"); ret = FALSE; goto out; } info = pk_info_enum_from_string (sections[1]); if (info == PK_INFO_ENUM_UNKNOWN) { g_set_error (error, 1, 0, "Info enum not recognised, and hence ignored: '%s'", sections[1]); ret = FALSE; goto out; } g_strdelimit (sections[3], PK_UNSAFE_DELIMITERS, ' '); ret = g_utf8_validate (sections[3], -1, NULL); if (!ret) { g_set_error (error, 1, 0, "text '%s' was not valid UTF8!", sections[3]); ret = FALSE; goto out; } pk_backend_job_package (job, info, sections[2], sections[3]); } else if (g_strcmp0 (command, "details") == 0) { if (size != 7) { g_set_error (error, 1, 0, "invalid command'%s', size %i", command, size); ret = FALSE; goto out; } group = pk_group_enum_from_string (sections[3]); /* ITS4: ignore, checked for overflow */ package_size = atol (sections[6]); if (package_size > 1073741824) { g_set_error_literal (error, 1, 0, "package size cannot be larger than one Gb"); ret = FALSE; goto out; } g_strdelimit (sections[4], PK_UNSAFE_DELIMITERS, ' '); ret = g_utf8_validate (sections[4], -1, NULL); if (!ret) { g_set_error (error, 1, 0, "text '%s' was not valid UTF8!", sections[4]); ret = FALSE; goto out; } text = g_strdup (sections[4]); /* convert ; to \n as we can't emit them on stdout */ g_strdelimit (text, ";", '\n'); pk_backend_job_details (job, sections[1], sections[2], group, text, sections[5], package_size); g_free (text); } else if (g_strcmp0 (command, "finished") == 0) { if (size != 1) { g_set_error (error, 1, 0, "invalid command'%s', size %i", command, size); ret = FALSE; goto out; } pk_backend_job_finished (job); priv->is_busy = FALSE; /* from this point on, we can start the kill timer */ pk_backend_spawn_start_kill_timer (backend_spawn); } else if (g_strcmp0 (command, "files") == 0) { gchar **tmp; if (size != 3) { g_set_error (error, 1, 0, "invalid command'%s', size %i", command, size); ret = FALSE; goto out; } tmp = g_strsplit (sections[2], ";", -1); pk_backend_job_files (job, sections[1], tmp); g_strfreev (tmp); } else if (g_strcmp0 (command, "repo-detail") == 0) { if (size != 4) { g_set_error (error, 1, 0, "invalid command'%s', size %i", command, size); ret = FALSE; goto out; } g_strdelimit (sections[2], PK_UNSAFE_DELIMITERS, ' '); ret = g_utf8_validate (sections[2], -1, NULL); if (!ret) { g_set_error (error, 1, 0, "text '%s' was not valid UTF8!", sections[2]); ret = FALSE; goto out; } if (g_strcmp0 (sections[3], "true") == 0) { pk_backend_job_repo_detail (job, sections[1], sections[2], TRUE); } else if (g_strcmp0 (sections[3], "false") == 0) { pk_backend_job_repo_detail (job, sections[1], sections[2], FALSE); } else { g_set_error (error, 1, 0, "invalid qualifier '%s'", sections[3]); ret = FALSE; goto out; } } else if (g_strcmp0 (command, "updatedetail") == 0) { gchar **updates; gchar **obsoletes; gchar **vendor_urls; gchar **bugzilla_urls; gchar **cve_urls; if (size != 13) { g_set_error (error, 1, 0, "invalid command '%s', size %i", command, size); ret = FALSE; goto out; } restart = pk_restart_enum_from_string (sections[7]); if (restart == PK_RESTART_ENUM_UNKNOWN) { g_set_error (error, 1, 0, "Restart enum not recognised, and hence ignored: '%s'", sections[7]); ret = FALSE; goto out; } g_strdelimit (sections[12], PK_UNSAFE_DELIMITERS, ' '); ret = g_utf8_validate (sections[12], -1, NULL); if (!ret) { g_set_error (error, 1, 0, "text '%s' was not valid UTF8!", sections[12]); ret = FALSE; goto out; } update_state_enum = pk_update_state_enum_from_string (sections[10]); /* convert ; to \n as we can't emit them on stdout */ g_strdelimit (sections[8], ";", '\n'); g_strdelimit (sections[9], ";", '\n'); updates = g_strsplit (sections[2], "&", -1); obsoletes = g_strsplit (sections[3], "&", -1); vendor_urls = g_strsplit (sections[4], ";", -1); bugzilla_urls = g_strsplit (sections[5], ";", -1); cve_urls = g_strsplit (sections[6], ";", -1); pk_backend_job_update_detail (job, sections[1], updates, obsoletes, vendor_urls, bugzilla_urls, cve_urls, restart, sections[8], sections[9], update_state_enum, sections[11], sections[12]); g_strfreev (updates); g_strfreev (obsoletes); g_strfreev (vendor_urls); g_strfreev (bugzilla_urls); g_strfreev (cve_urls); } else if (g_strcmp0 (command, "percentage") == 0) { if (size != 2) { g_set_error (error, 1, 0, "invalid command'%s', size %i", command, size); ret = FALSE; goto out; } ret = pk_strtoint (sections[1], &percentage); if (!ret) { g_set_error (error, 1, 0, "invalid percentage value %s", sections[1]); ret = FALSE; } else if (percentage < 0 || percentage > 100) { g_set_error (error, 1, 0, "invalid percentage value %i", percentage); ret = FALSE; } else { pk_backend_job_set_percentage (job, percentage); } } else if (g_strcmp0 (command, "item-progress") == 0) { if (size != 4) { g_set_error (error, 1, 0, "invalid command'%s', size %i", command, size); ret = FALSE; goto out; } if (!pk_package_id_check (sections[1])) { g_set_error (error, 1, 0, "invalid package_id"); ret = FALSE; goto out; } status_enum = pk_status_enum_from_string (sections[2]); if (status_enum == PK_STATUS_ENUM_UNKNOWN) { g_set_error (error, 1, 0, "Status enum not recognised, and hence ignored: '%s'", sections[2]); ret = FALSE; goto out; } ret = pk_strtoint (sections[3], &percentage); if (!ret) { g_set_error (error, 1, 0, "invalid item-progress value %s", sections[3]); ret = FALSE; goto out; } if (percentage < 0 || percentage > 100) { g_set_error (error, 1, 0, "invalid item-progress value %i", percentage); ret = FALSE; goto out; } pk_backend_job_set_item_progress (job, sections[1], status_enum, percentage); } else if (g_strcmp0 (command, "error") == 0) { if (size != 3) { g_set_error (error, 1, 0, "invalid command'%s', size %i", command, size); ret = FALSE; goto out; } error_enum = pk_error_enum_from_string (sections[1]); if (error_enum == PK_ERROR_ENUM_UNKNOWN) { g_set_error (error, 1, 0, "Error enum not recognised, and hence ignored: '%s'", sections[1]); ret = FALSE; goto out; } /* convert back all the ;'s to newlines */ text = g_strdup (sections[2]); /* convert ; to \n as we can't emit them on stdout */ g_strdelimit (text, ";", '\n'); /* convert % else we try to format them */ g_strdelimit (text, "%", '$'); pk_backend_job_error_code (job, error_enum, "%s", text); g_free (text); } else if (g_strcmp0 (command, "requirerestart") == 0) { if (size != 3) { g_set_error (error, 1, 0, "invalid command'%s', size %i", command, size); ret = FALSE; goto out; } restart_enum = pk_restart_enum_from_string (sections[1]); if (restart_enum == PK_RESTART_ENUM_UNKNOWN) { g_set_error (error, 1, 0, "Restart enum not recognised, and hence ignored: '%s'", sections[1]); ret = FALSE; goto out; } if (!pk_package_id_check (sections[2])) { g_set_error (error, 1, 0, "invalid package_id"); ret = FALSE; goto out; } pk_backend_job_require_restart (job, restart_enum, sections[2]); } else if (g_strcmp0 (command, "message") == 0) { if (size != 3) { g_set_error (error, 1, 0, "invalid command'%s', size %i", command, size); ret = FALSE; goto out; } G_GNUC_BEGIN_IGNORE_DEPRECATIONS message_enum = pk_message_enum_from_string (sections[1]); G_GNUC_END_IGNORE_DEPRECATIONS if (message_enum == PK_MESSAGE_ENUM_UNKNOWN) { g_set_error (error, 1, 0, "Message enum not recognised, and hence ignored: '%s'", sections[1]); ret = FALSE; goto out; } text = g_strdup (sections[2]); /* convert ; to \n as we can't emit them on stdout */ g_strdelimit (text, ";", '\n'); G_GNUC_BEGIN_IGNORE_DEPRECATIONS pk_backend_job_message (job, message_enum, "%s", text); G_GNUC_END_IGNORE_DEPRECATIONS g_free (text); } else if (g_strcmp0 (command, "status") == 0) {
/** * pk_backend_spawn_parse_stdout: **/ static gboolean pk_backend_spawn_parse_stdout (PkBackendSpawn *backend_spawn, const gchar *line, GError **error) { gchar **sections; guint size; gchar *command; gchar *text; gboolean ret = TRUE; guint64 speed; PkInfoEnum info; PkRestartEnum restart; PkGroupEnum group; gulong package_size; gint percentage; PkErrorEnum error_enum; PkStatusEnum status_enum; PkMessageEnum message_enum; PkRestartEnum restart_enum; PkSigTypeEnum sig_type; PkUpdateStateEnum update_state_enum; PkMediaTypeEnum media_type_enum; PkDistroUpgradeEnum distro_upgrade_enum; PkBackendSpawnPrivate *priv = backend_spawn->priv; g_return_val_if_fail (PK_IS_BACKEND_SPAWN (backend_spawn), FALSE); /* check if output line */ if (line == NULL) return FALSE; /* split by tab */ sections = g_strsplit (line, "\t", 0); command = sections[0]; /* get size */ size = g_strv_length (sections); if (g_strcmp0 (command, "package") == 0) { if (size != 4) { g_set_error (error, 1, 0, "invalid command'%s', size %i", command, size); ret = FALSE; goto out; } if (pk_package_id_check (sections[2]) == FALSE) { g_set_error_literal (error, 1, 0, "invalid package_id"); ret = FALSE; goto out; } info = pk_info_enum_from_string (sections[1]); if (info == PK_INFO_ENUM_UNKNOWN) { g_set_error (error, 1, 0, "Info enum not recognised, and hence ignored: '%s'", sections[1]); ret = FALSE; goto out; } pk_backend_package (priv->backend, info, sections[2], sections[3]); } else if (g_strcmp0 (command, "details") == 0) { if (size != 7) { g_set_error (error, 1, 0, "invalid command'%s', size %i", command, size); ret = FALSE; goto out; } group = pk_group_enum_from_string (sections[3]); /* ITS4: ignore, checked for overflow */ package_size = atol (sections[6]); if (package_size > 1073741824) { g_set_error_literal (error, 1, 0, "package size cannot be larger than one Gb"); ret = FALSE; goto out; } text = g_strdup (sections[4]); /* convert ; to \n as we can't emit them on stdout */ g_strdelimit (text, ";", '\n'); pk_backend_details (priv->backend, sections[1], sections[2], group, text, sections[5], package_size); g_free (text); } else if (g_strcmp0 (command, "finished") == 0) { if (size != 1) { g_set_error (error, 1, 0, "invalid command'%s', size %i", command, size); ret = FALSE; goto out; } pk_backend_finished (priv->backend); /* from this point on, we can start the kill timer */ pk_backend_spawn_start_kill_timer (backend_spawn); } else if (g_strcmp0 (command, "files") == 0) { if (size != 3) { g_set_error (error, 1, 0, "invalid command'%s', size %i", command, size); ret = FALSE; goto out; } pk_backend_files (priv->backend, sections[1], sections[2]); } else if (g_strcmp0 (command, "repo-detail") == 0) { if (size != 4) { g_set_error (error, 1, 0, "invalid command'%s', size %i", command, size); ret = FALSE; goto out; } if (g_strcmp0 (sections[3], "true") == 0) { pk_backend_repo_detail (priv->backend, sections[1], sections[2], TRUE); } else if (g_strcmp0 (sections[3], "false") == 0) { pk_backend_repo_detail (priv->backend, sections[1], sections[2], FALSE); } else { g_set_error (error, 1, 0, "invalid qualifier '%s'", sections[3]); ret = FALSE; goto out; } } else if (g_strcmp0 (command, "updatedetail") == 0) { if (size != 13) { g_set_error (error, 1, 0, "invalid command '%s', size %i", command, size); ret = FALSE; goto out; } restart = pk_restart_enum_from_string (sections[7]); if (restart == PK_RESTART_ENUM_UNKNOWN) { g_set_error (error, 1, 0, "Restart enum not recognised, and hence ignored: '%s'", sections[7]); ret = FALSE; goto out; } update_state_enum = pk_update_state_enum_from_string (sections[10]); /* convert ; to \n as we can't emit them on stdout */ g_strdelimit (sections[8], ";", '\n'); g_strdelimit (sections[9], ";", '\n'); pk_backend_update_detail (priv->backend, sections[1], sections[2], sections[3], sections[4], sections[5], sections[6], restart, sections[8], sections[9], update_state_enum, sections[11], sections[12]); } else if (g_strcmp0 (command, "percentage") == 0) { if (size != 2) { g_set_error (error, 1, 0, "invalid command'%s', size %i", command, size); ret = FALSE; goto out; } ret = pk_strtoint (sections[1], &percentage); if (!ret) { g_set_error (error, 1, 0, "invalid percentage value %s", sections[1]); ret = FALSE; } else if (percentage < 0 || percentage > 100) { g_set_error (error, 1, 0, "invalid percentage value %i", percentage); ret = FALSE; } else { pk_backend_set_percentage (priv->backend, percentage); } } else if (g_strcmp0 (command, "subpercentage") == 0) { if (size != 2) { g_set_error (error, 1, 0, "invalid command'%s', size %i", command, size); ret = FALSE; goto out; } ret = pk_strtoint (sections[1], &percentage); if (!ret) { g_set_error (error, 1, 0, "invalid subpercentage value %s", sections[1]); ret = FALSE; } else if (percentage < 0 || percentage > 100) { g_set_error (error, 1, 0, "invalid subpercentage value %i", percentage); ret = FALSE; } else { pk_backend_set_sub_percentage (priv->backend, percentage); } } else if (g_strcmp0 (command, "item-percentage") == 0) { if (size != 3) { g_set_error (error, 1, 0, "invalid command'%s', size %i", command, size); ret = FALSE; goto out; } if (!pk_package_id_check (sections[1])) { g_set_error (error, 1, 0, "invalid package_id"); ret = FALSE; goto out; } ret = pk_strtoint (sections[2], &percentage); if (!ret) { g_set_error (error, 1, 0, "invalid item-percentage value %s", sections[1]); ret = FALSE; } else if (percentage < 0 || percentage > 100) { g_set_error (error, 1, 0, "invalid item-percentage value %i", percentage); ret = FALSE; } else { pk_backend_set_item_progress (priv->backend, sections[1], percentage); } } else if (g_strcmp0 (command, "error") == 0) { if (size != 3) { g_set_error (error, 1, 0, "invalid command'%s', size %i", command, size); ret = FALSE; goto out; } error_enum = pk_error_enum_from_string (sections[1]); if (error_enum == PK_ERROR_ENUM_UNKNOWN) { g_set_error (error, 1, 0, "Error enum not recognised, and hence ignored: '%s'", sections[1]); ret = FALSE; goto out; } /* convert back all the ;'s to newlines */ text = g_strdup (sections[2]); /* convert ; to \n as we can't emit them on stdout */ g_strdelimit (text, ";", '\n'); /* convert % else we try to format them */ g_strdelimit (text, "%", '$'); pk_backend_error_code (priv->backend, error_enum, text); g_free (text); } else if (g_strcmp0 (command, "requirerestart") == 0) { if (size != 3) { g_set_error (error, 1, 0, "invalid command'%s', size %i", command, size); ret = FALSE; goto out; } restart_enum = pk_restart_enum_from_string (sections[1]); if (restart_enum == PK_RESTART_ENUM_UNKNOWN) { g_set_error (error, 1, 0, "Restart enum not recognised, and hence ignored: '%s'", sections[1]); ret = FALSE; goto out; } if (!pk_package_id_check (sections[2])) { g_set_error (error, 1, 0, "invalid package_id"); ret = FALSE; goto out; } pk_backend_require_restart (priv->backend, restart_enum, sections[2]); } else if (g_strcmp0 (command, "message") == 0) { if (size != 3) { g_set_error (error, 1, 0, "invalid command'%s', size %i", command, size); ret = FALSE; goto out; } message_enum = pk_message_enum_from_string (sections[1]); if (message_enum == PK_MESSAGE_ENUM_UNKNOWN) { g_set_error (error, 1, 0, "Message enum not recognised, and hence ignored: '%s'", sections[1]); ret = FALSE; goto out; } text = g_strdup (sections[2]); /* convert ; to \n as we can't emit them on stdout */ g_strdelimit (text, ";", '\n'); pk_backend_message (priv->backend, message_enum, text); g_free (text); } else if (g_strcmp0 (command, "change-transaction-data") == 0) { if (size != 2) { g_set_error (error, 1, 0, "invalid command'%s', size %i", command, size); ret = FALSE; goto out; } pk_backend_set_transaction_data (priv->backend, sections[1]); } else if (g_strcmp0 (command, "status") == 0) { if (size != 2) { g_set_error (error, 1, 0, "invalid command'%s', size %i", command, size); ret = FALSE; goto out; } status_enum = pk_status_enum_from_string (sections[1]); if (status_enum == PK_STATUS_ENUM_UNKNOWN) { g_set_error (error, 1, 0, "Status enum not recognised, and hence ignored: '%s'", sections[1]); ret = FALSE; goto out; } pk_backend_set_status (priv->backend, status_enum); } else if (g_strcmp0 (command, "speed") == 0) { if (size != 2) { g_set_error (error, 1, 0, "invalid command'%s', size %i", command, size); ret = FALSE; goto out; } ret = pk_strtouint64 (sections[1], &speed); if (!ret) { g_set_error (error, 1, 0, "failed to parse speed: '%s'", sections[1]); ret = FALSE; goto out; } pk_backend_set_speed (priv->backend, speed); } else if (g_strcmp0 (command, "allow-cancel") == 0) { if (size != 2) { g_set_error (error, 1, 0, "invalid command'%s', size %i", command, size); ret = FALSE; goto out; } if (g_strcmp0 (sections[1], "true") == 0) { pk_backend_set_allow_cancel (priv->backend, TRUE); } else if (g_strcmp0 (sections[1], "false") == 0) { pk_backend_set_allow_cancel (priv->backend, FALSE); } else { g_set_error (error, 1, 0, "invalid section '%s'", sections[1]); ret = FALSE; goto out; } } else if (g_strcmp0 (command, "no-percentage-updates") == 0) { if (size != 1) { g_set_error (error, 1, 0, "invalid command'%s', size %i", command, size); ret = FALSE; goto out; } pk_backend_set_percentage (priv->backend, PK_BACKEND_PERCENTAGE_INVALID); } else if (g_strcmp0 (command, "repo-signature-required") == 0) { if (size != 9) { g_set_error (error, 1, 0, "invalid command'%s', size %i", command, size); ret = FALSE; goto out; } sig_type = pk_sig_type_enum_from_string (sections[8]); if (sig_type == PK_SIGTYPE_ENUM_UNKNOWN) { g_set_error (error, 1, 0, "Sig enum not recognised, and hence ignored: '%s'", sections[8]); ret = FALSE; goto out; } if (pk_strzero (sections[1])) { g_set_error (error, 1, 0, "package_id blank, and hence ignored: '%s'", sections[1]); ret = FALSE; goto out; } if (pk_strzero (sections[2])) { g_set_error (error, 1, 0, "repository name blank, and hence ignored: '%s'", sections[2]); ret = FALSE; goto out; } /* pass _all_ of the data */ ret = pk_backend_repo_signature_required (priv->backend, sections[1], sections[2], sections[3], sections[4], sections[5], sections[6], sections[7], sig_type); goto out; } else if (g_strcmp0 (command, "eula-required") == 0) { if (size != 5) { g_set_error (error, 1, 0, "invalid command'%s', size %i", command, size); ret = FALSE; goto out; } if (pk_strzero (sections[1])) { g_set_error (error, 1, 0, "eula_id blank, and hence ignored: '%s'", sections[1]); ret = FALSE; goto out; } if (pk_strzero (sections[2])) { g_set_error (error, 1, 0, "package_id blank, and hence ignored: '%s'", sections[2]); ret = FALSE; goto out; } if (pk_strzero (sections[4])) { g_set_error (error, 1, 0, "agreement name blank, and hence ignored: '%s'", sections[4]); ret = FALSE; goto out; } ret = pk_backend_eula_required (priv->backend, sections[1], sections[2], sections[3], sections[4]); goto out; } else if (g_strcmp0 (command, "media-change-required") == 0) { if (size != 4) { g_set_error (error, 1, 0, "invalid command'%s', size %i", command, size); ret = FALSE; goto out; } media_type_enum = pk_media_type_enum_from_string (sections[1]); if (media_type_enum == PK_MEDIA_TYPE_ENUM_UNKNOWN) { g_set_error (error, 1, 0, "media type enum not recognised, and hence ignored: '%s'", sections[1]); ret = FALSE; goto out; } ret = pk_backend_media_change_required (priv->backend, media_type_enum, sections[2], sections[3]); goto out; } else if (g_strcmp0 (command, "distro-upgrade") == 0) { if (size != 4) { g_set_error (error, 1, 0, "invalid command'%s', size %i", command, size); ret = FALSE; goto out; } distro_upgrade_enum = pk_distro_upgrade_enum_from_string (sections[1]); if (distro_upgrade_enum == PK_DISTRO_UPGRADE_ENUM_UNKNOWN) { g_set_error (error, 1, 0, "distro upgrade enum not recognised, and hence ignored: '%s'", sections[1]); ret = FALSE; goto out; } ret = pk_backend_distro_upgrade (priv->backend, distro_upgrade_enum, sections[2], sections[3]); goto out; } else if (g_strcmp0 (command, "category") == 0) { if (size != 6) { g_set_error (error, 1, 0, "invalid command'%s', size %i", command, size); ret = FALSE; goto out; } if (g_strcmp0 (sections[1], sections[2]) == 0) { g_set_error_literal (error, 1, 0, "cat_id cannot be the same as parent_id"); ret = FALSE; goto out; } if (pk_strzero (sections[2])) { g_set_error_literal (error, 1, 0, "cat_id cannot not blank"); ret = FALSE; goto out; } if (pk_strzero (sections[3])) { g_set_error_literal (error, 1, 0, "name cannot not blank"); ret = FALSE; goto out; } if (pk_strzero (sections[5])) { g_set_error_literal (error, 1, 0, "icon cannot not blank"); ret = FALSE; goto out; } if (g_str_has_prefix (sections[5], "/")) { g_set_error (error, 1, 0, "icon '%s' should be a named icon, not a path", sections[5]); ret = FALSE; goto out; } ret = pk_backend_category (priv->backend, sections[1], sections[2], sections[3], sections[4], sections[5]); goto out; } else { ret = FALSE; g_set_error (error, 1, 0, "invalid command '%s'", command); } out: g_strfreev (sections); return ret; }
/** * pk_offline_get_results: * @error: A #GError or %NULL * * Gets the last result of the offline transaction. * * Return value: (transfer full): A #PkResults, or %NULL * * Since: 0.9.6 **/ PkResults * pk_offline_get_results (GError **error) { gboolean ret; gboolean success; guint i; g_autoptr(GError) error_local = NULL; g_autofree gchar *data = NULL; g_autoptr(GKeyFile) file = NULL; g_autoptr(PkError) pk_error = NULL; g_autoptr(PkResults) results = NULL; g_auto(GStrv) package_ids = NULL; g_return_val_if_fail (error == NULL || *error == NULL, NULL); /* does not exist */ if (!g_file_test (PK_OFFLINE_RESULTS_FILENAME, G_FILE_TEST_EXISTS)) { g_set_error_literal (error, PK_OFFLINE_ERROR, PK_OFFLINE_ERROR_NO_DATA, "no update results available"); return NULL; } /* load data */ file = g_key_file_new (); ret = g_key_file_load_from_file (file, PK_OFFLINE_RESULTS_FILENAME, G_KEY_FILE_NONE, &error_local); if (!ret) { g_set_error (error, PK_OFFLINE_ERROR, PK_OFFLINE_ERROR_FAILED, "results file invalid: %s", error_local->message); return NULL; } /* add error */ results = pk_results_new (); success = g_key_file_get_boolean (file, PK_OFFLINE_RESULTS_GROUP, "Success", NULL); if (!success) { g_autofree gchar *details = NULL; g_autofree gchar *enum_str = NULL; pk_error = pk_error_new (); enum_str = g_key_file_get_string (file, PK_OFFLINE_RESULTS_GROUP, "ErrorCode", NULL); details = g_key_file_get_string (file, PK_OFFLINE_RESULTS_GROUP, "ErrorDetails", NULL); g_object_set (pk_error, "code", pk_error_enum_from_string (enum_str), "details", details, NULL); pk_results_set_error_code (results, pk_error); pk_results_set_exit_code (results, PK_EXIT_ENUM_FAILED); } else { pk_results_set_exit_code (results, PK_EXIT_ENUM_SUCCESS); } /* add packages */ data = g_key_file_get_string (file, PK_OFFLINE_RESULTS_GROUP, "Packages", NULL); if (data != NULL) { package_ids = g_strsplit (data, ",", -1); for (i = 0; package_ids[i] != NULL; i++) { g_autoptr(PkPackage) pkg = NULL; pkg = pk_package_new (); pk_package_set_info (pkg, PK_INFO_ENUM_UPDATING); if (!pk_package_set_id (pkg, package_ids[i], error)) return NULL; pk_results_add_package (results, pkg); } } return g_object_ref (results); }
gboolean gs_plugin_add_updates_historical (GsPlugin *plugin, GsAppList *list, GCancellable *cancellable, GError **error) { gboolean ret; guint64 mtime; guint i; g_auto(GStrv) package_ids = NULL; g_autofree gchar *packages = NULL; g_autoptr(GFile) file = NULL; g_autoptr(GFileInfo) info = NULL; g_autoptr(GKeyFile) key_file = NULL; /* was any offline update attempted */ if (!g_file_test (PK_OFFLINE_UPDATE_RESULTS_FILENAME, G_FILE_TEST_EXISTS)) return TRUE; /* get the mtime of the results */ file = g_file_new_for_path (PK_OFFLINE_UPDATE_RESULTS_FILENAME); info = g_file_query_info (file, G_FILE_ATTRIBUTE_TIME_MODIFIED, G_FILE_QUERY_INFO_NONE, cancellable, error); if (info == NULL) return FALSE; mtime = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_TIME_MODIFIED); /* open the file */ key_file = g_key_file_new (); ret = g_key_file_load_from_file (key_file, PK_OFFLINE_UPDATE_RESULTS_FILENAME, G_KEY_FILE_NONE, error); if (!ret) return FALSE; /* only return results if successful */ ret = g_key_file_get_boolean (key_file, PK_OFFLINE_UPDATE_RESULTS_GROUP, "Success", NULL); if (!ret) { g_autofree gchar *code = NULL; g_autofree gchar *details = NULL; code = g_key_file_get_string (key_file, PK_OFFLINE_UPDATE_RESULTS_GROUP, "ErrorCode", error); if (code == NULL) return FALSE; details = g_key_file_get_string (key_file, PK_OFFLINE_UPDATE_RESULTS_GROUP, "ErrorDetails", error); if (details == NULL) return FALSE; return gs_plugin_packagekit_convert_error (error, pk_error_enum_from_string (code), details); } /* get list of package-ids */ packages = g_key_file_get_string (key_file, PK_OFFLINE_UPDATE_RESULTS_GROUP, "Packages", NULL); if (packages == NULL) { g_set_error (error, GS_PLUGIN_ERROR, GS_PLUGIN_ERROR_NOT_SUPPORTED, "No 'Packages' in %s", PK_OFFLINE_UPDATE_RESULTS_FILENAME); return FALSE; } package_ids = g_strsplit (packages, ",", -1); for (i = 0; package_ids[i] != NULL; i++) { g_autoptr(GsApp) app = NULL; g_auto(GStrv) split = NULL; app = gs_app_new (NULL); split = g_strsplit (package_ids[i], ";", 4); gs_app_add_source (app, split[0]); gs_app_set_update_version (app, split[1]); gs_app_set_management_plugin (app, "packagekit"); gs_app_add_source_id (app, package_ids[i]); gs_app_set_state (app, AS_APP_STATE_UPDATABLE); gs_app_set_kind (app, AS_APP_KIND_GENERIC); gs_app_set_install_date (app, mtime); gs_app_set_metadata (app, "GnomeSoftware::Creator", gs_plugin_get_name (plugin)); gs_app_list_add (list, app); } return TRUE; }