Add more checksum types for files and archives (#75)

* Add more checksum types for files and archives

Many upstreams don't use sha256, some use even stronger checksums like
sha512, and its nice to be able to use these. Some system uses
weaker checksums, which you can work around by recomputing your own,
but sometimes that is a bit painful, for example when you're
auto-generating flatpak-builder manifests based on some other format
such as npm lock files.

This adds all the checksum types that GChecksum supports in the
glib version we currently use: md5, sha1, sha256, sha512
tingping/wmclass
Alexander Larsson 2017-12-07 15:40:04 +01:00 committed by GitHub
parent 336be88040
commit adc84ac4ca
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 392 additions and 51 deletions

View File

@ -531,10 +531,26 @@
<term><option>url</option> (string)</term>
<listitem><para>The URL of a remote archive that will be downloaded. This overrides path if both are specified.</para></listitem>
</varlistentry>
<varlistentry>
<term><option>md5</option> (string)</term>
<listitem><para>The md5 checksum of the file, verified after download</para>
<para>Note that md5 is no longer considered a safe checksum, we recommend you use at least sha256.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>sha1</option> (string)</term>
<listitem><para>The sha1 checksum of the file, verified after download</para>
<para>Note that sha1 is no longer considered a safe checksum, we recommend you use at least sha256.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>sha256</option> (string)</term>
<listitem><para>The sha256 checksum of the file, verified after download</para></listitem>
</varlistentry>
<varlistentry>
<term><option>sha512</option> (string)</term>
<listitem><para>The sha512 checksum of the file, verified after download</para></listitem>
</varlistentry>
<varlistentry>
<term><option>strip-components</option> (integer)</term>
<listitem><para>The number of initial pathname components to strip during extraction. Defaults to 1.</para></listitem>
@ -611,10 +627,26 @@
<term><option>url</option> (string)</term>
<listitem><para>The URL of a remote file that will be downloaded and copied into the source dir. This overrides path if both are specified.</para></listitem>
</varlistentry>
<varlistentry>
<term><option>md5</option> (string)</term>
<listitem><para>The md5 checksum of the file, verified after download. This is optional for local files.</para>
<para>Note that md5 is no longer considered a safe checksum, we recommend you use at least sha256.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>sha1</option> (string)</term>
<listitem><para>The sha1 checksum of the file, verified after download. This is optional for local files.</para>
<para>Note that sha1 is no longer considered a safe checksum, we recommend you use at least sha256.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>sha256</option> (string)</term>
<listitem><para>The sha256 checksum of the file, verified after download. This is optional for local files.</para></listitem>
</varlistentry>
<varlistentry>
<term><option>sha512</option> (string)</term>
<listitem><para>The sha512 checksum of the file, verified after download. This is optional for local files.</para></listitem>
</varlistentry>
<varlistentry>
<term><option>dest-filename</option> (string)</term>
<listitem><para>Filename to use inside the source dir, default to the basename of path.</para></listitem>

View File

@ -354,7 +354,8 @@ gboolean
builder_context_download_uri (BuilderContext *self,
const char *url,
GFile *dest,
char *sha256,
const char *checksums[BUILDER_CHECKSUMS_LEN],
GChecksumType checksums_type[BUILDER_CHECKSUMS_LEN],
GError **error)
{
int i;
@ -368,7 +369,7 @@ builder_context_download_uri (BuilderContext *self,
if (self->sources_urls != NULL)
{
g_autofree char *base_name = g_path_get_basename (soup_uri_get_path (original_uri));
g_autofree char *rel = g_build_filename ("downloads", sha256, base_name, NULL);
g_autofree char *rel = g_build_filename ("downloads", checksums[0], base_name, NULL);
for (i = 0; i < self->sources_urls->len; i++)
{
@ -380,7 +381,7 @@ builder_context_download_uri (BuilderContext *self,
if (builder_download_uri (mirror_uri,
dest,
sha256,
checksums, checksums_type,
builder_context_get_soup_session (self),
&my_error))
return TRUE;
@ -392,7 +393,7 @@ builder_context_download_uri (BuilderContext *self,
if (!builder_download_uri (original_uri,
dest,
sha256,
checksums, checksums_type,
builder_context_get_soup_session (self),
error))
return FALSE;

View File

@ -24,6 +24,7 @@
#include <gio/gio.h>
#include <libsoup/soup.h>
#include "builder-options.h"
#include "builder-utils.h"
G_BEGIN_DECLS
@ -62,7 +63,8 @@ void builder_context_set_sources_urls (BuilderContext *self,
gboolean builder_context_download_uri (BuilderContext *self,
const char *url,
GFile *dest,
char *sha256,
const char *checksums[BUILDER_CHECKSUMS_LEN],
GChecksumType checksums_type[BUILDER_CHECKSUMS_LEN],
GError **error);
SoupSession * builder_context_get_soup_session (BuilderContext *self);
const char * builder_context_get_arch (BuilderContext *self);

View File

@ -67,10 +67,13 @@ flatpak_write_update_checksum (GOutputStream *out,
gconstpointer data,
gsize len,
gsize *out_bytes_written,
GChecksum *checksum,
GChecksum **checksums,
gsize n_checksums,
GCancellable *cancellable,
GError **error)
{
gsize i;
if (out)
{
if (!g_output_stream_write_all (out, data, len, out_bytes_written,
@ -82,8 +85,8 @@ flatpak_write_update_checksum (GOutputStream *out,
*out_bytes_written = len;
}
if (checksum)
g_checksum_update (checksum, data, len);
for (i = 0; i < n_checksums; i++)
g_checksum_update (checksums[i], data, len);
return TRUE;
}
@ -91,7 +94,8 @@ flatpak_write_update_checksum (GOutputStream *out,
gboolean
flatpak_splice_update_checksum (GOutputStream *out,
GInputStream *in,
GChecksum *checksum,
GChecksum **checksums,
gsize n_checksums,
FlatpakLoadUriProgress progress,
gpointer progress_data,
GCancellable *cancellable,
@ -108,7 +112,8 @@ flatpak_splice_update_checksum (GOutputStream *out,
if (!g_input_stream_read_all (in, buf, sizeof buf, &bytes_read, cancellable, error))
return FALSE;
if (!flatpak_write_update_checksum (out, buf, bytes_read, &bytes_written, checksum,
if (!flatpak_write_update_checksum (out, buf, bytes_read, &bytes_written,
checksums, n_checksums,
cancellable, error))
return FALSE;

View File

@ -94,14 +94,16 @@ gboolean flatpak_write_update_checksum (GOutputStream *out,
gconstpointer data,
gsize len,
gsize *out_bytes_written,
GChecksum *checksum,
GChecksum **checksums,
gsize n_checksums,
GCancellable *cancellable,
GError **error);
gboolean flatpak_splice_update_checksum (GOutputStream *out,
GInputStream *in,
GChecksum *checksum,
GChecksum **checksums,
gsize n_checksums,
FlatpakLoadUriProgress progress,
gpointer progress_data,
GCancellable *cancellable,

View File

@ -38,7 +38,10 @@ struct BuilderSourceArchive
char *path;
char *url;
char *md5;
char *sha1;
char *sha256;
char *sha512;
guint strip_components;
};
@ -53,7 +56,10 @@ enum {
PROP_0,
PROP_PATH,
PROP_URL,
PROP_MD5,
PROP_SHA1,
PROP_SHA256,
PROP_SHA512,
PROP_STRIP_COMPONENTS,
LAST_PROP
};
@ -117,7 +123,10 @@ builder_source_archive_finalize (GObject *object)
g_free (self->url);
g_free (self->path);
g_free (self->md5);
g_free (self->sha1);
g_free (self->sha256);
g_free (self->sha512);
G_OBJECT_CLASS (builder_source_archive_parent_class)->finalize (object);
}
@ -140,10 +149,22 @@ builder_source_archive_get_property (GObject *object,
g_value_set_string (value, self->url);
break;
case PROP_MD5:
g_value_set_string (value, self->md5);
break;
case PROP_SHA1:
g_value_set_string (value, self->sha1);
break;
case PROP_SHA256:
g_value_set_string (value, self->sha256);
break;
case PROP_SHA512:
g_value_set_string (value, self->sha512);
break;
case PROP_STRIP_COMPONENTS:
g_value_set_uint (value, self->strip_components);
break;
@ -173,11 +194,26 @@ builder_source_archive_set_property (GObject *object,
self->url = g_value_dup_string (value);
break;
case PROP_MD5:
g_free (self->md5);
self->md5 = g_value_dup_string (value);
break;
case PROP_SHA1:
g_free (self->sha1);
self->sha1 = g_value_dup_string (value);
break;
case PROP_SHA256:
g_free (self->sha256);
self->sha256 = g_value_dup_string (value);
break;
case PROP_SHA512:
g_free (self->sha512);
self->sha512 = g_value_dup_string (value);
break;
case PROP_STRIP_COMPONENTS:
self->strip_components = g_value_get_uint (value);
break;
@ -218,6 +254,8 @@ get_download_location (BuilderSourceArchive *self,
const char *path;
g_autofree char *base_name = NULL;
g_autoptr(GFile) file = NULL;
const char *checksums[BUILDER_CHECKSUMS_LEN];
GChecksumType checksums_type[BUILDER_CHECKSUMS_LEN];
uri = get_uri (self, error);
if (uri == NULL)
@ -227,15 +265,21 @@ get_download_location (BuilderSourceArchive *self,
base_name = g_path_get_basename (path);
if (self->sha256 == NULL || *self->sha256 == 0)
builder_get_all_checksums (checksums, checksums_type,
self->md5,
self->sha1,
self->sha256,
self->sha512);
if (checksums[0] == NULL)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Sha256 not specified");
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "No checksum specified for archive source %s", base_name);
return FALSE;
}
file = builder_context_find_in_sources_dirs (context,
"downloads",
self->sha256,
checksums[0],
base_name,
NULL);
if (file)
@ -245,7 +289,7 @@ get_download_location (BuilderSourceArchive *self,
}
return flatpak_build_file (builder_context_get_download_dir (context),
self->sha256,
checksums[0],
base_name,
NULL);
}
@ -295,9 +339,10 @@ builder_source_archive_download (BuilderSource *source,
BuilderSourceArchive *self = BUILDER_SOURCE_ARCHIVE (source);
g_autoptr(GFile) file = NULL;
const char *sha256 = NULL;
g_autofree char *base_name = NULL;
gboolean is_local;
const char *checksums[BUILDER_CHECKSUMS_LEN];
GChecksumType checksums_type[BUILDER_CHECKSUMS_LEN];
file = get_source_file (self, context, &is_local, error);
if (file == NULL)
@ -305,9 +350,15 @@ builder_source_archive_download (BuilderSource *source,
base_name = g_file_get_basename (file);
builder_get_all_checksums (checksums, checksums_type,
self->md5,
self->sha1,
self->sha256,
self->sha512);
if (g_file_query_exists (file, NULL))
{
if (is_local && self->sha256 != NULL && *self->sha256 != 0)
if (is_local && checksums[0] != NULL)
{
g_autofree char *data = NULL;
gsize len;
@ -315,13 +366,11 @@ builder_source_archive_download (BuilderSource *source,
if (!g_file_load_contents (file, NULL, &data, &len, NULL, error))
return FALSE;
sha256 = g_compute_checksum_for_string (G_CHECKSUM_SHA256, data, len);
if (strcmp (sha256, self->sha256) != 0)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Wrong sha256 for %s, expected %s, was %s", base_name, self->sha256, sha256);
return FALSE;
}
if (!builder_verify_checksums (base_name,
data, len,
checksums, checksums_type,
error))
return FALSE;
}
return TRUE;
}
@ -335,7 +384,8 @@ builder_source_archive_download (BuilderSource *source,
if (!builder_context_download_uri (context,
self->url,
file,
self->sha256,
checksums,
checksums_type,
error))
return FALSE;
@ -603,16 +653,24 @@ builder_source_archive_bundle (BuilderSource *source,
g_autofree char *destination_file_path = NULL;
g_autofree char *app_dir_path = NULL;
gboolean is_local;
const char *checksums[BUILDER_CHECKSUMS_LEN];
GChecksumType checksums_type[BUILDER_CHECKSUMS_LEN];
file = get_source_file (self, context, &is_local, error);
if (file == NULL)
return FALSE;
builder_get_all_checksums (checksums, checksums_type,
self->md5,
self->sha1,
self->sha256,
self->sha512);
app_dir_path = g_file_get_path (builder_context_get_app_dir (context));
download_dir_path = g_build_filename (app_dir_path,
"sources",
"downloads",
self->sha256,
checksums[0],
NULL);
download_dir = g_file_new_for_path (download_dir_path);
if (!flatpak_mkdir_p (download_dir, NULL, error))
@ -643,6 +701,9 @@ builder_source_archive_checksum (BuilderSource *source,
builder_cache_checksum_str (cache, self->url);
builder_cache_checksum_str (cache, self->sha256);
builder_cache_checksum_compat_str (cache, self->md5);
builder_cache_checksum_compat_str (cache, self->sha1);
builder_cache_checksum_compat_str (cache, self->sha512);
builder_cache_checksum_uint32 (cache, self->strip_components);
}
@ -677,6 +738,20 @@ builder_source_archive_class_init (BuilderSourceArchiveClass *klass)
"",
NULL,
G_PARAM_READWRITE));
g_object_class_install_property (object_class,
PROP_MD5,
g_param_spec_string ("md5",
"",
"",
NULL,
G_PARAM_READWRITE));
g_object_class_install_property (object_class,
PROP_SHA1,
g_param_spec_string ("sha1",
"",
"",
NULL,
G_PARAM_READWRITE));
g_object_class_install_property (object_class,
PROP_SHA256,
g_param_spec_string ("sha256",
@ -684,6 +759,13 @@ builder_source_archive_class_init (BuilderSourceArchiveClass *klass)
"",
NULL,
G_PARAM_READWRITE));
g_object_class_install_property (object_class,
PROP_SHA512,
g_param_spec_string ("sha512",
"",
"",
NULL,
G_PARAM_READWRITE));
g_object_class_install_property (object_class,
PROP_STRIP_COMPONENTS,
g_param_spec_uint ("strip-components",

View File

@ -38,7 +38,10 @@ struct BuilderSourceFile
char *path;
char *url;
char *md5;
char *sha1;
char *sha256;
char *sha512;
char *dest_filename;
};
@ -53,7 +56,10 @@ enum {
PROP_0,
PROP_PATH,
PROP_URL,
PROP_MD5,
PROP_SHA1,
PROP_SHA256,
PROP_SHA512,
PROP_DEST_FILENAME,
LAST_PROP
};
@ -65,7 +71,10 @@ builder_source_file_finalize (GObject *object)
g_free (self->path);
g_free (self->url);
g_free (self->md5);
g_free (self->sha1);
g_free (self->sha256);
g_free (self->sha512);
g_free (self->dest_filename);
G_OBJECT_CLASS (builder_source_file_parent_class)->finalize (object);
@ -89,10 +98,22 @@ builder_source_file_get_property (GObject *object,
g_value_set_string (value, self->url);
break;
case PROP_MD5:
g_value_set_string (value, self->md5);
break;
case PROP_SHA1:
g_value_set_string (value, self->sha1);
break;
case PROP_SHA256:
g_value_set_string (value, self->sha256);
break;
case PROP_SHA512:
g_value_set_string (value, self->sha512);
break;
case PROP_DEST_FILENAME:
g_value_set_string (value, self->dest_filename);
break;
@ -122,11 +143,26 @@ builder_source_file_set_property (GObject *object,
self->url = g_value_dup_string (value);
break;
case PROP_MD5:
g_free (self->md5);
self->md5 = g_value_dup_string (value);
break;
case PROP_SHA1:
g_free (self->sha1);
self->sha1 = g_value_dup_string (value);
break;
case PROP_SHA256:
g_free (self->sha256);
self->sha256 = g_value_dup_string (value);
break;
case PROP_SHA512:
g_free (self->sha512);
self->sha512 = g_value_dup_string (value);
break;
case PROP_DEST_FILENAME:
g_free (self->dest_filename);
self->dest_filename = g_value_dup_string (value);
@ -168,6 +204,8 @@ get_download_location (BuilderSourceFile *self,
const char *path;
g_autofree char *base_name = NULL;
g_autoptr(GFile) file = NULL;
const char *checksums[BUILDER_CHECKSUMS_LEN];
GChecksumType checksums_type[BUILDER_CHECKSUMS_LEN];
uri = get_uri (self, error);
if (uri == NULL)
@ -184,22 +222,28 @@ get_download_location (BuilderSourceFile *self,
base_name = g_path_get_basename (path);
if (self->sha256 == NULL || *self->sha256 == 0)
builder_get_all_checksums (checksums, checksums_type,
self->md5,
self->sha1,
self->sha256,
self->sha512);
if (checksums[0] == NULL)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Sha256 not specified");
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "No checksum specified for file source %s", base_name);
return FALSE;
}
file = builder_context_find_in_sources_dirs (context,
"downloads",
self->sha256,
checksums[0],
base_name,
NULL);
if (file != NULL)
return g_steal_pointer (&file);
file = flatpak_build_file (builder_context_get_download_dir (context),
self->sha256,
checksums[0],
base_name,
NULL);
return g_steal_pointer (&file);
@ -285,8 +329,9 @@ builder_source_file_download (BuilderSource *source,
g_autoptr(GFile) file = NULL;
gboolean is_local, is_inline;
g_autofree char *sha256 = NULL;
g_autofree char *base_name = NULL;
const char *checksums[BUILDER_CHECKSUMS_LEN];
GChecksumType checksums_type[BUILDER_CHECKSUMS_LEN];
file = get_source_file (self, context, &is_local, &is_inline, error);
if (file == NULL)
@ -294,9 +339,15 @@ builder_source_file_download (BuilderSource *source,
base_name = g_file_get_basename (file);
builder_get_all_checksums (checksums, checksums_type,
self->md5,
self->sha1,
self->sha256,
self->sha512);
if (g_file_query_exists (file, NULL))
{
if (is_local && self->sha256 != NULL && *self->sha256 != 0)
if (is_local && checksums[0] != NULL)
{
g_autofree char *data = NULL;
gsize len;
@ -304,13 +355,11 @@ builder_source_file_download (BuilderSource *source,
if (!g_file_load_contents (file, NULL, &data, &len, NULL, error))
return FALSE;
sha256 = g_compute_checksum_for_string (G_CHECKSUM_SHA256, data, len);
if (strcmp (sha256, self->sha256) != 0)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Wrong sha256 for %s, expected %s, was %s", base_name, self->sha256, sha256);
return FALSE;
}
if (!builder_verify_checksums (base_name,
data, len,
checksums, checksums_type,
error))
return FALSE;
}
return TRUE;
}
@ -330,7 +379,8 @@ builder_source_file_download (BuilderSource *source,
if (!builder_context_download_uri (context,
self->url,
file,
self->sha256,
checksums,
checksums_type,
error))
return FALSE;
@ -422,6 +472,8 @@ builder_source_file_bundle (BuilderSource *source,
g_autoptr(GFile) destination_dir = NULL;
g_autofree char *file_name = NULL;
gboolean is_local, is_inline;
const char *checksums[BUILDER_CHECKSUMS_LEN];
GChecksumType checksums_type[BUILDER_CHECKSUMS_LEN];
file = get_source_file (self, context, &is_local, &is_inline, error);
if (file == NULL)
@ -431,6 +483,12 @@ builder_source_file_bundle (BuilderSource *source,
if (is_inline)
return TRUE;
builder_get_all_checksums (checksums, checksums_type,
self->md5,
self->sha1,
self->sha256,
self->sha512);
if (is_local)
{
GFile *manifest_base_dir = builder_context_get_base_dir (context);
@ -450,7 +508,7 @@ builder_source_file_bundle (BuilderSource *source,
file_name = g_file_get_basename (file);
destination_file = flatpak_build_file (builder_context_get_app_dir (context),
"sources/downloads",
self->sha256,
checksums[0],
file_name,
NULL);
}
@ -500,6 +558,9 @@ builder_source_file_checksum (BuilderSource *source,
builder_cache_checksum_str (cache, self->path);
builder_cache_checksum_str (cache, self->url);
builder_cache_checksum_str (cache, self->sha256);
builder_cache_checksum_compat_str (cache, self->md5);
builder_cache_checksum_compat_str (cache, self->sha1);
builder_cache_checksum_compat_str (cache, self->sha512);
builder_cache_checksum_str (cache, self->dest_filename);
}
@ -534,6 +595,20 @@ builder_source_file_class_init (BuilderSourceFileClass *klass)
"",
NULL,
G_PARAM_READWRITE));
g_object_class_install_property (object_class,
PROP_MD5,
g_param_spec_string ("md5",
"",
"",
NULL,
G_PARAM_READWRITE));
g_object_class_install_property (object_class,
PROP_SHA1,
g_param_spec_string ("sha1",
"",
"",
NULL,
G_PARAM_READWRITE));
g_object_class_install_property (object_class,
PROP_SHA256,
g_param_spec_string ("sha256",
@ -541,6 +616,13 @@ builder_source_file_class_init (BuilderSourceFileClass *klass)
"",
NULL,
G_PARAM_READWRITE));
g_object_class_install_property (object_class,
PROP_SHA512,
g_param_spec_string ("sha512",
"",
"",
NULL,
G_PARAM_READWRITE));
g_object_class_install_property (object_class,
PROP_DEST_FILENAME,
g_param_spec_string ("dest-filename",

View File

@ -1615,6 +1615,113 @@ builder_maybe_host_spawnv (GFile *dir,
return flatpak_spawnv (dir, output, 0, error, argv);
}
/**
* builder_get_all_checksums:
*
* Collect all the non-empty/null checksums into a single array with
* their type.
*
* The checksum are returned in order such that the first one is the
* one to use by default if using a single one. That is typically the
* longest checksum except it defaults to sha256 if set because
* that was historically the one flatpak-builder used
*/
gsize
builder_get_all_checksums (const char *checksums[BUILDER_CHECKSUMS_LEN],
GChecksumType checksums_type[BUILDER_CHECKSUMS_LEN],
const char *md5,
const char *sha1,
const char *sha256,
const char *sha512)
{
gsize i = 0;
if (sha256 != NULL && *sha256 != 0)
{
g_assert (i < BUILDER_CHECKSUMS_LEN);
checksums[i] = sha256;
checksums_type[i] = G_CHECKSUM_SHA256;
i++;
}
if (sha512 != NULL && *sha512 != 0)
{
g_assert (i < BUILDER_CHECKSUMS_LEN);
checksums[i] = sha512;
checksums_type[i] = G_CHECKSUM_SHA512;
i++;
}
if (sha1 != NULL && *sha1 != 0)
{
g_assert (i < BUILDER_CHECKSUMS_LEN);
checksums[i] = sha1;
checksums_type[i] = G_CHECKSUM_SHA1;
i++;
}
if (md5 != NULL && *md5 != 0)
{
g_assert (i < BUILDER_CHECKSUMS_LEN);
checksums[i] = md5;
checksums_type[i] = G_CHECKSUM_MD5;
i++;
}
g_assert (i < BUILDER_CHECKSUMS_LEN);
checksums[i++] = 0;
return i;
}
static gboolean
compare_checksum (const char *name,
const char *expected_checksum,
GChecksumType checksum_type,
const char *measured_checksum,
GError **error)
{
const char *type_names[] = { "md5", "sha1", "sha256", "sha512", "sha384" }; /* In GChecksumType order */
const char *type_name;
if (checksum_type < G_N_ELEMENTS (type_names))
type_name = type_names[checksum_type];
else
type_name = "unknown";
if (strcmp (expected_checksum, measured_checksum) != 0)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Wrong %s checksum for %s, expected %s, was %s", type_name, name,
expected_checksum, measured_checksum);
return FALSE;
}
return TRUE;
}
gboolean
builder_verify_checksums (const char *name,
const char *data,
gsize len,
const char *checksums[BUILDER_CHECKSUMS_LEN],
GChecksumType checksums_type[BUILDER_CHECKSUMS_LEN],
GError **error)
{
gsize i;
for (i = 0; checksums[i] != NULL; i++)
{
g_autofree char *checksum = NULL;
checksum = g_compute_checksum_for_string (checksums_type[i], data, len);
if (!compare_checksum (name, checksums[i], checksums_type[i], checksum, error))
return FALSE;
}
return TRUE;
}
typedef struct {
int stage;
gboolean printed_something;
@ -1644,7 +1751,8 @@ download_progress_cleanup (DownloadPromptData *progress_data)
gboolean
builder_download_uri (SoupURI *uri,
GFile *dest,
char *sha256,
const char *checksums[BUILDER_CHECKSUMS_LEN],
GChecksumType checksums_type[BUILDER_CHECKSUMS_LEN],
SoupSession *session,
GError **error)
{
@ -1653,10 +1761,15 @@ builder_download_uri (SoupURI *uri,
g_autoptr(GFileOutputStream) out = NULL;
g_autoptr(GFile) tmp = NULL;
g_autoptr(GFile) dir = NULL;
g_autoptr(GChecksum) checksum = g_checksum_new (G_CHECKSUM_SHA256);
g_autoptr(GPtrArray) checksum_array = g_ptr_array_new_with_free_func ((GDestroyNotify)g_checksum_free);
DownloadPromptData progress_data = {0};
g_autofree char *basename = g_file_get_basename (dest);
g_autofree char *template = g_strconcat (".", basename, "XXXXXX", NULL);
gsize i;
for (i = 0; checksums[i] != NULL; i++)
g_ptr_array_add (checksum_array,
g_checksum_new (checksums_type[i]));
dir = g_file_get_parent (dest);
g_mkdir_with_parents (flatpak_file_get_path_cached (dir), 0755);
@ -1688,7 +1801,9 @@ builder_download_uri (SoupURI *uri,
}
}
if (!flatpak_splice_update_checksum (G_OUTPUT_STREAM (out), input, checksum, download_progress, &progress_data, NULL, error))
if (!flatpak_splice_update_checksum (G_OUTPUT_STREAM (out), input,
(GChecksum **)checksum_array->pdata, checksum_array->len,
download_progress, &progress_data, NULL, error))
{
unlink (flatpak_file_get_path_cached (tmp));
return FALSE;
@ -1703,12 +1818,14 @@ builder_download_uri (SoupURI *uri,
download_progress_cleanup (&progress_data);
if (sha256 != NULL && strcmp (g_checksum_get_string (checksum), sha256) != 0)
for (i = 0; checksums[i] != NULL; i++)
{
unlink (flatpak_file_get_path_cached (tmp));
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Wrong sha256 for %s, expected %s, was %s", basename, sha256, g_checksum_get_string (checksum));
return FALSE;
const char *checksum = g_checksum_get_string (g_ptr_array_index (checksum_array, i));
if (!compare_checksum (basename, checksums[i], checksums_type[i], checksum, error))
{
unlink (flatpak_file_get_path_cached (tmp));
return FALSE;
}
}
if (rename (flatpak_file_get_path_cached (tmp), flatpak_file_get_path_cached (dest)) != 0)

View File

@ -29,6 +29,9 @@
G_BEGIN_DECLS
#define BUILDER_N_CHECKSUMS 4 /* We currently support 4 checksum types */
#define BUILDER_CHECKSUMS_LEN (BUILDER_N_CHECKSUMS + 1) /* One more for null termination */
typedef struct BuilderUtils BuilderUtils;
char *builder_uri_to_filename (const char *uri);
@ -69,10 +72,25 @@ gboolean builder_maybe_host_spawnv (GFile *dir,
gboolean builder_download_uri (SoupURI *uri,
GFile *dest,
char *sha256,
const char *checksums[BUILDER_CHECKSUMS_LEN],
GChecksumType checksums_type[BUILDER_CHECKSUMS_LEN],
SoupSession *soup_session,
GError **error);
gsize builder_get_all_checksums (const char *checksums[BUILDER_CHECKSUMS_LEN],
GChecksumType checksums_type[BUILDER_CHECKSUMS_LEN],
const char *md5,
const char *sha1,
const char *sha256,
const char *sha512);
gboolean builder_verify_checksums (const char *name,
const char *data,
gsize len,
const char *checksums[BUILDER_CHECKSUMS_LEN],
GChecksumType checksums_type[BUILDER_CHECKSUMS_LEN],
GError **error);
GParamSpec * builder_serializable_find_property_with_error (JsonSerializable *serializable,
const char *name);