From d5456a4fcdd02ef8fe4256b1b912689de0d4bc8b Mon Sep 17 00:00:00 2001 From: probonopd Date: Mon, 26 Jun 2023 23:14:50 +0200 Subject: [PATCH 1/7] Guess updateinformation for GitHub Actions https://github.com/AppImage/appimagetool/issues/7 Compiles, but still needs to be tested for correctness. --- src/appimagetool.c | 49 ++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 45 insertions(+), 4 deletions(-) diff --git a/src/appimagetool.c b/src/appimagetool.c index 9c8a865..c07b976 100644 --- a/src/appimagetool.c +++ b/src/appimagetool.c @@ -490,7 +490,7 @@ static GOptionEntry entries[] = { { "list", 'l', 0, G_OPTION_ARG_NONE, &list, "List files in SOURCE AppImage", NULL }, { "updateinformation", 'u', 0, G_OPTION_ARG_STRING, &updateinformation, "Embed update information STRING; if zsyncmake is installed, generate zsync file", NULL }, - { "guess", 'g', 0, G_OPTION_ARG_NONE, &guess_update_information, "Guess update information based on Travis CI or GitLab environment variables", NULL }, + { "guess", 'g', 0, G_OPTION_ARG_NONE, &guess_update_information, "Guess update information based on GitHub or GitLab environment variables", NULL }, { "version", 0, 0, G_OPTION_ARG_NONE, &showVersionOnly, "Show version number", NULL }, { "verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose, "Produce verbose output", NULL }, { "sign", 's', 0, G_OPTION_ARG_NONE, &sign, "Sign with gpg[2]", NULL }, @@ -522,10 +522,34 @@ main (int argc, char *argv[]) travis_tag = getenv("TRAVIS_TAG"); char* travis_pull_request; travis_pull_request = getenv("TRAVIS_PULL_REQUEST"); + + /* Parse GitHub Actions environment variables. + * https://docs.github.com/en/actions/learn-github-actions/variables + * GITHUB_REPOSITORY: The owner and repository name. For example, octocat/Hello-World. + * GITHUB_REPOSITORY_OWNER: The repository owner's name. For example, octocat. + */ + /* https://github.com/probonopd/uploadtool */ char* github_token; github_token = getenv("GITHUB_TOKEN"); + // Construct the repository name from github_repository and github_repository_owner + // by removing the github_repository_owner from the beginning of github_repository + // and the slash that follows it + char* github_repository = getenv("GITHUB_REPOSITORY"); + char* github_repository_owner = getenv("GITHUB_REPOSITORY_OWNER"); + char* github_repository_name = ""; + if (github_repository_owner != NULL && github_repository != NULL) { + char* owner_start = strstr(github_repository, github_repository_owner); + if (owner_start != NULL) { + owner_start += strlen(github_repository_owner); + if (*owner_start == '/') { + owner_start++; // Skip the '/' + github_repository_name = owner_start; + } + } + } + /* Parse GitLab CI environment variables. * https://docs.gitlab.com/ee/ci/variables/#predefined-variables-environment-variables * echo "${CI_PROJECT_URL}/-/jobs/artifacts/${CI_COMMIT_REF_NAME}/raw/QtQuickApp-x86_64.AppImage?job=${CI_JOB_NAME}" @@ -890,10 +914,27 @@ main (int argc, char *argv[]) exit(1); } - /* If the user has not provided update information but we know this is a Travis CI build, - * then fill in update information based on TRAVIS_REPO_SLUG */ + /* If the user has not provided update information but we know this is a CI build, + * then fill in update information based on well-known CI environment variables */ if(guess_update_information){ - if(travis_repo_slug){ + + if(github_repository_name){ + if(!github_token) { + printf("Will not guess update information since $GITHUB_TOKEN is missing\n"); + } else { + gchar *zsyncmake_path = g_find_program_in_path ("zsyncmake"); + if(zsyncmake_path){ + char buf[1024]; + // gh-releases-zsync|probono|AppImages|latest|Subsurface-*x86_64.AppImage.zsync + sprintf(buf, "gh-releases-zsync|%s|%s|latest|%s*-%s.AppImage.zsync", github_repository_owner, github_repository_name, app_name_for_filename, arch); + updateinformation = buf; + printf("Guessing update information based on $GITHUB_REPOSITORY=%s\n", github_repository); + printf("%s\n", updateinformation); + } else { + printf("Will not guess update information since zsyncmake is missing\n"); + } + } + } else if(travis_repo_slug){ if(!github_token) { printf("Will not guess update information since $GITHUB_TOKEN is missing,\n"); if(0 != strcmp(travis_pull_request, "false")){ From 6755313d63bfcd8c4e3b0f4e0941bd0186104b89 Mon Sep 17 00:00:00 2001 From: probonopd Date: Tue, 27 Jun 2023 19:44:17 +0200 Subject: [PATCH 2/7] Only guess update information for GitHub if environment variables exist --- src/appimagetool.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/appimagetool.c b/src/appimagetool.c index c07b976..d79c702 100644 --- a/src/appimagetool.c +++ b/src/appimagetool.c @@ -538,7 +538,7 @@ main (int argc, char *argv[]) // and the slash that follows it char* github_repository = getenv("GITHUB_REPOSITORY"); char* github_repository_owner = getenv("GITHUB_REPOSITORY_OWNER"); - char* github_repository_name = ""; + char* github_repository_name = NULL; if (github_repository_owner != NULL && github_repository != NULL) { char* owner_start = strstr(github_repository, github_repository_owner); if (owner_start != NULL) { From 59d507b8b6dee9a5758708a85879a4801df30281 Mon Sep 17 00:00:00 2001 From: probonopd Date: Sun, 2 Jul 2023 09:20:10 -0400 Subject: [PATCH 3/7] Implement change suggested by reviewer * github_repository_name regardless of owner_start * Move comment above if statement --- src/appimagetool.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/appimagetool.c b/src/appimagetool.c index d79c702..147e105 100644 --- a/src/appimagetool.c +++ b/src/appimagetool.c @@ -543,10 +543,10 @@ main (int argc, char *argv[]) char* owner_start = strstr(github_repository, github_repository_owner); if (owner_start != NULL) { owner_start += strlen(github_repository_owner); - if (*owner_start == '/') { - owner_start++; // Skip the '/' - github_repository_name = owner_start; - } + // Skip the '/' + if (*owner_start == '/') + owner_start++; + github_repository_name = owner_start; } } From 57b2c1d1c48708670c2102088e4bc0542ea644c2 Mon Sep 17 00:00:00 2001 From: probonopd Date: Wed, 5 Jul 2023 19:34:16 +0000 Subject: [PATCH 4/7] Use snprintf https://github.com/AppImage/appimagetool/pull/13#pullrequestreview-1515168220 --- src/appimagetool.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/appimagetool.c b/src/appimagetool.c index 147e105..ce5945e 100644 --- a/src/appimagetool.c +++ b/src/appimagetool.c @@ -956,7 +956,12 @@ main (int argc, char *argv[]) channel = "latest"; } } - sprintf(buf, "gh-releases-zsync|%s|%s|%s|%s*-%s.AppImage.zsync", parts[0], parts[1], channel, app_name_for_filename, arch); + int ret = snprintf(buf, sizeof(buf), "gh-releases-zsync|%s|%s|%s|%s*-%s.AppImage.zsync", parts[0], parts[1], channel, app_name_for_filename, arch); + if (ret < 0) { + die("snprintf error"); + } else if (ret >= sizeof(buf)) { + die("snprintf buffer overflow"); + } updateinformation = buf; printf("Guessing update information based on $TRAVIS_TAG=%s and $TRAVIS_REPO_SLUG=%s\n", travis_tag, travis_repo_slug); printf("%s\n", updateinformation); From caa7f0d6327ef65e2fda8f33d9bcfe7060a01409 Mon Sep 17 00:00:00 2001 From: probonopd Date: Wed, 5 Jul 2023 20:23:15 +0000 Subject: [PATCH 5/7] Use snprintf everywhere https://github.com/AppImage/appimagetool/pull/13#discussion_r1253591732 --- src/appimagetool.c | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/src/appimagetool.c b/src/appimagetool.c index ce5945e..e2d644a 100644 --- a/src/appimagetool.c +++ b/src/appimagetool.c @@ -578,7 +578,7 @@ main (int argc, char *argv[]) GOptionContext *context; // initialize help text of argument - sprintf(_exclude_file_desc, "Uses given file as exclude file for mksquashfs, in addition to %s.", APPIMAGEIGNORE); + snprintf(_exclude_file_desc, "Uses given file as exclude file for mksquashfs, in addition to %s.", APPIMAGEIGNORE); context = g_option_context_new ("SOURCE [DESTINATION] - Generate AppImages from existing AppDirs"); g_option_context_add_main_entries (context, entries, NULL); @@ -750,7 +750,7 @@ main (int argc, char *argv[]) fprintf(stderr, "Using architecture %s\n", arch); char app_name_for_filename[PATH_MAX]; - sprintf(app_name_for_filename, "%s", get_desktop_entry(kf, "Name")); + snprintf(app_name_for_filename, PATH_MAX, "%s", get_desktop_entry(kf, "Name")); replacestr(app_name_for_filename, " ", "_"); if(verbose) @@ -765,9 +765,9 @@ main (int argc, char *argv[]) // if $VERSION is specified, we embed it into the filename if (version_env != NULL) { - sprintf(dest_path, "%s-%s-%s.AppImage", app_name_for_filename, version_env, arch); + snprintf(dest_path, "%s-%s-%s.AppImage", app_name_for_filename, version_env, arch); } else { - sprintf(dest_path, "%s-%s.AppImage", app_name_for_filename, arch); + snprintf(dest_path, "%s-%s.AppImage", app_name_for_filename, arch); } destination = strdup(dest_path); @@ -826,7 +826,7 @@ main (int argc, char *argv[]) /* Check if AppStream upstream metadata is present in source AppDir */ if(! no_appstream){ char application_id[PATH_MAX]; - sprintf (application_id, "%s", basename(desktop_file)); + snprintf (application_id, "%s", basename(desktop_file)); replacestr(application_id, ".desktop", ".appdata.xml"); gchar *appdata_path = g_build_filename(source, "/usr/share/metainfo/", application_id, NULL); if (! g_file_test(appdata_path, G_FILE_TEST_IS_REGULAR)){ @@ -926,7 +926,12 @@ main (int argc, char *argv[]) if(zsyncmake_path){ char buf[1024]; // gh-releases-zsync|probono|AppImages|latest|Subsurface-*x86_64.AppImage.zsync - sprintf(buf, "gh-releases-zsync|%s|%s|latest|%s*-%s.AppImage.zsync", github_repository_owner, github_repository_name, app_name_for_filename, arch); + int ret = snprintf(buf, "gh-releases-zsync|%s|%s|latest|%s*-%s.AppImage.zsync", github_repository_owner, github_repository_name, app_name_for_filename, arch); + if (ret < 0) { + die("snprintf error"); + } else if (ret >= sizeof(buf)) { + die("snprintf buffer overflow"); + } updateinformation = buf; printf("Guessing update information based on $GITHUB_REPOSITORY=%s\n", github_repository); printf("%s\n", updateinformation); @@ -974,7 +979,12 @@ main (int argc, char *argv[]) gchar *zsyncmake_path = g_find_program_in_path ("zsyncmake"); if(zsyncmake_path){ char buf[1024]; - sprintf(buf, "zsync|%s/-/jobs/artifacts/%s/raw/%s-%s.AppImage.zsync?job=%s", CI_PROJECT_URL, CI_COMMIT_REF_NAME, app_name_for_filename, arch, CI_JOB_NAME); + int ret = snprintf(buf, sizeof(buf), "zsync|%s/-/jobs/artifacts/%s/raw/%s-%s.AppImage.zsync?job=%s", CI_PROJECT_URL, CI_COMMIT_REF_NAME, app_name_for_filename, arch, CI_JOB_NAME); + if (ret < 0) { + die("snprintf error"); + } else if (ret >= sizeof(buf)) { + die("snprintf buffer overflow"); + } updateinformation = buf; printf("Guessing update information based on $CI_COMMIT_REF_NAME=%s and $CI_JOB_NAME=%s\n", CI_COMMIT_REF_NAME, CI_JOB_NAME); printf("%s\n", updateinformation); From d6a5081f0a846ffb91226bcaf8a9f6de652e08b3 Mon Sep 17 00:00:00 2001 From: probonopd Date: Wed, 5 Jul 2023 21:01:28 +0000 Subject: [PATCH 6/7] Use snprintf only where we use buf --- src/appimagetool.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/appimagetool.c b/src/appimagetool.c index e2d644a..25a3246 100644 --- a/src/appimagetool.c +++ b/src/appimagetool.c @@ -543,7 +543,7 @@ main (int argc, char *argv[]) char* owner_start = strstr(github_repository, github_repository_owner); if (owner_start != NULL) { owner_start += strlen(github_repository_owner); - // Skip the '/' + // Skip the '/' if (*owner_start == '/') owner_start++; github_repository_name = owner_start; @@ -578,7 +578,7 @@ main (int argc, char *argv[]) GOptionContext *context; // initialize help text of argument - snprintf(_exclude_file_desc, "Uses given file as exclude file for mksquashfs, in addition to %s.", APPIMAGEIGNORE); + sprintf(_exclude_file_desc, "Uses given file as exclude file for mksquashfs, in addition to %s.", APPIMAGEIGNORE); context = g_option_context_new ("SOURCE [DESTINATION] - Generate AppImages from existing AppDirs"); g_option_context_add_main_entries (context, entries, NULL); @@ -750,7 +750,7 @@ main (int argc, char *argv[]) fprintf(stderr, "Using architecture %s\n", arch); char app_name_for_filename[PATH_MAX]; - snprintf(app_name_for_filename, PATH_MAX, "%s", get_desktop_entry(kf, "Name")); + sprintf(app_name_for_filename, PATH_MAX, "%s", get_desktop_entry(kf, "Name")); replacestr(app_name_for_filename, " ", "_"); if(verbose) @@ -765,9 +765,9 @@ main (int argc, char *argv[]) // if $VERSION is specified, we embed it into the filename if (version_env != NULL) { - snprintf(dest_path, "%s-%s-%s.AppImage", app_name_for_filename, version_env, arch); + sprintf(dest_path, "%s-%s-%s.AppImage", app_name_for_filename, version_env, arch); } else { - snprintf(dest_path, "%s-%s.AppImage", app_name_for_filename, arch); + sprintf(dest_path, "%s-%s.AppImage", app_name_for_filename, arch); } destination = strdup(dest_path); @@ -826,7 +826,7 @@ main (int argc, char *argv[]) /* Check if AppStream upstream metadata is present in source AppDir */ if(! no_appstream){ char application_id[PATH_MAX]; - snprintf (application_id, "%s", basename(desktop_file)); + sprintf (application_id, "%s", basename(desktop_file)); replacestr(application_id, ".desktop", ".appdata.xml"); gchar *appdata_path = g_build_filename(source, "/usr/share/metainfo/", application_id, NULL); if (! g_file_test(appdata_path, G_FILE_TEST_IS_REGULAR)){ From e1200c364af8d4ea64170fb205e7e5bc1af8ebcd Mon Sep 17 00:00:00 2001 From: probonopd Date: Wed, 5 Jul 2023 21:15:31 +0000 Subject: [PATCH 7/7] Fix compilation --- src/appimagetool.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/appimagetool.c b/src/appimagetool.c index 25a3246..5ccb49a 100644 --- a/src/appimagetool.c +++ b/src/appimagetool.c @@ -750,7 +750,7 @@ main (int argc, char *argv[]) fprintf(stderr, "Using architecture %s\n", arch); char app_name_for_filename[PATH_MAX]; - sprintf(app_name_for_filename, PATH_MAX, "%s", get_desktop_entry(kf, "Name")); + sprintf(app_name_for_filename, "%s", get_desktop_entry(kf, "Name")); replacestr(app_name_for_filename, " ", "_"); if(verbose)