static GHashTable *bodhi_query_list(const char *query, const char *release) { char *bodhi_url_bugs = xasprintf("%s/?%s", bodhi_url, query); post_state_t *post_state = new_post_state(POST_WANT_BODY | POST_WANT_SSL_VERIFY | POST_WANT_ERROR_MSG); const char *headers[] = { "Accept: application/json", NULL }; get(post_state, bodhi_url_bugs, "application/x-www-form-urlencoded", headers); if (post_state->http_resp_code != 200 && post_state->http_resp_code != 400) { char *errmsg = post_state->curl_error_msg; if (errmsg && errmsg[0]) error_msg_and_die("%s '%s'", errmsg, bodhi_url_bugs); } free(bodhi_url_bugs); // log_warning("%s", post_state->body); json_object *json = json_tokener_parse(post_state->body); if (is_error(json)) error_msg_and_die("fatal: unable parse response from bodhi server"); /* we must check the http_resp_code because only error responses contain * 'status' item. 'bodhi_read_value' function prints an error message in * the case it did not found the item */ if (post_state->http_resp_code != 200) { char *status_item = NULL; bodhi_read_value(json, "status", &status_item, BODHI_READ_STR); if (status_item != NULL && strcmp(status_item, "error") == 0) { free(status_item); bodhi_print_errors_from_json(json); json_object_put(json); xfunc_die(); // error_msg are printed in bodhi_print_errors_from_json } } GHashTable *bodhi_table = bodhi_parse_json(json, release); json_object_put(json); free_post_state(post_state); return bodhi_table; }
static int interactive_upload_file(const char *url, const char *file_name, map_string_t *settings, char **remote_name) { post_state_t *state = new_post_state(POST_WANT_ERROR_MSG); state->username = get_map_string_item_or_NULL(settings, "UploadUsername"); char *password_inp = NULL; if (state->username != NULL && state->username[0] != '\0') { /* Load Password only if Username is configured, it doesn't make */ /* much sense to load Password without Username. */ state->password = get_map_string_item_or_NULL(settings, "UploadPassword"); if (state->password == NULL) { /* Be permissive and nice, ask only once and don't check */ /* the result. User can dismiss this prompt but the upload */ /* may work somehow??? */ char *msg = xasprintf(_("Please enter password for uploading:"), state->username); state->password = password_inp = ask_password(msg); free(msg); } } /* set SSH keys */ state->client_ssh_public_keyfile = get_map_string_item_or_NULL(settings, "SSHPublicKey"); state->client_ssh_private_keyfile = get_map_string_item_or_NULL(settings, "SSHPrivateKey"); if (state->client_ssh_public_keyfile != NULL) log_debug("Using SSH public key '%s'", state->client_ssh_public_keyfile); if (state->client_ssh_private_keyfile != NULL) log_debug("Using SSH private key '%s'", state->client_ssh_private_keyfile); char *tmp = upload_file_ext(state, url, file_name, UPLOAD_FILE_HANDLE_ACCESS_DENIALS); if (remote_name) *remote_name = tmp; else free(tmp); free(password_inp); free_post_state(state); /* return 0 on success */ return tmp == NULL; }
static bool perform_attach(struct ureport_server_config *config, const char *ureport_hash, int rhbz_bug) { char *dest_url = concat_path_file(config->ur_url, ATTACH_URL_SFX); const char *old_url = config->ur_url; config->ur_url = dest_url; post_state_t *post_state = ureport_attach_rhbz(ureport_hash, rhbz_bug, config); config->ur_url = old_url; free(dest_url); struct ureport_server_response *resp = get_server_response(post_state, config); free_post_state(post_state); /* don't use str_bo_bool() because we require "true" string */ const int result = !resp || resp->is_error || strcmp(resp->value,"true") != 0; if (resp && resp->is_error) { error_msg(_("The server at '%s' responded with an error: '%s'"), config->ur_url, resp->value); } free_ureport_server_response(resp); return result; }
static GHashTable *bodhi_query_list(const char *query, const char *release) { char *bodhi_url_bugs = xasprintf("%s/list", bodhi_url); post_state_t *post_state = new_post_state(POST_WANT_BODY | POST_WANT_SSL_VERIFY | POST_WANT_ERROR_MSG); const char *headers[] = { "Accept: application/json", NULL }; post_string(post_state, bodhi_url_bugs, "application/x-www-form-urlencoded", headers, query); if (post_state->http_resp_code != 200) { char *errmsg = post_state->curl_error_msg; if (errmsg && errmsg[0]) error_msg_and_die("%s '%s'", errmsg, bodhi_url_bugs); } free(bodhi_url_bugs); // log("%s", post_state->body); json_object *json = json_tokener_parse(post_state->body); if (is_error(json)) error_msg_and_die("fatal: unable parse response from bodhi server"); GHashTable *bodhi_table = bodhi_parse_json(json, release); json_object_put(json); free_post_state(post_state); return bodhi_table; }
static int create_and_upload_archive( const char *dump_dir_name, map_string_t *settings) { int result = 1; /* error */ pid_t child; TAR* tar = NULL; const char* errmsg = NULL; char* tempfile = NULL; struct dump_dir *dd = dd_opendir(dump_dir_name, /*flags:*/ 0); if (!dd) xfunc_die(); /* error msg is already logged by dd_opendir */ /* Gzipping e.g. 0.5gig coredump takes a while. Let client know what we are doing */ log(_("Compressing data")); //TODO: //Encrypt = yes //ArchiveType = .tar.bz2 //ExcludeFiles = foo,bar*,b*z const char* opt = getenv("Upload_URL"); if (!opt) opt = get_map_string_item_or_empty(settings, "URL"); char *url = opt[0] != '\0' ? xstrdup(opt) : ask_url(_("Please enter a URL (scp, ftp, etc.) where the problem data is to be exported:")); /* Create a child gzip which will compress the data */ /* SELinux guys are not happy with /tmp, using /var/run/abrt */ /* Reverted back to /tmp for ABRT2 */ /* Changed again to /var/tmp because of Fedora feature tmp-on-tmpfs */ tempfile = concat_path_basename(LARGE_DATA_TMP_DIR, dump_dir_name); tempfile = append_to_malloced_string(tempfile, ".tar.gz"); int pipe_from_parent_to_child[2]; xpipe(pipe_from_parent_to_child); child = vfork(); if (child == 0) { /* child */ close(pipe_from_parent_to_child[1]); xmove_fd(pipe_from_parent_to_child[0], 0); xmove_fd(xopen3(tempfile, O_WRONLY | O_CREAT | O_EXCL, 0600), 1); execlp("gzip", "gzip", NULL); perror_msg_and_die("Can't execute '%s'", "gzip"); } close(pipe_from_parent_to_child[0]); /* If child died (say, in xopen), then parent might get SIGPIPE. * We want to properly unlock dd, therefore we must not die on SIGPIPE: */ signal(SIGPIPE, SIG_IGN); /* Create tar writer object */ if (tar_fdopen(&tar, pipe_from_parent_to_child[1], tempfile, /*fileops:(standard)*/ NULL, O_WRONLY | O_CREAT, 0644, TAR_GNU) != 0) { errmsg = "Can't create temporary file in "LARGE_DATA_TMP_DIR; goto ret; } /* Write data to the tarball */ { string_vector_ptr_t exclude_from_report = get_global_always_excluded_elements(); dd_init_next_file(dd); char *short_name, *full_name; while (dd_get_next_file(dd, &short_name, &full_name)) { if (exclude_from_report && is_in_string_list(short_name, (const_string_vector_const_ptr_t)exclude_from_report)) goto next; // dd_get_next_file guarantees that it's a REG: //struct stat stbuf; //if (stat(full_name, &stbuf) != 0) // || !S_ISREG(stbuf.st_mode) //) { // goto next; //} if (tar_append_file(tar, full_name, short_name) != 0) { errmsg = "Can't create temporary file in "LARGE_DATA_TMP_DIR; free(short_name); free(full_name); goto ret; } next: free(short_name); free(full_name); } } dd_close(dd); dd = NULL; /* Close tar writer... */ if (tar_append_eof(tar) != 0 || tar_close(tar) != 0) { errmsg = "Can't create temporary file in "LARGE_DATA_TMP_DIR; goto ret; } tar = NULL; /* ...and check that gzip child finished successfully */ int status; safe_waitpid(child, &status, 0); child = -1; if (status != 0) { /* We assume the error was out-of-disk-space or out-of-quota */ errmsg = "Can't create temporary file in "LARGE_DATA_TMP_DIR; goto ret; } /* Upload the tarball */ /* Upload from /tmp to /tmp + deletion -> BAD, exclude this possibility */ if (url && url[0] && strcmp(url, "file://"LARGE_DATA_TMP_DIR"/") != 0) { post_state_t *state = new_post_state(POST_WANT_ERROR_MSG); state->username = getenv("Upload_Username"); char *password_inp = NULL; if (state->username != NULL && state->username[0] != '\0') { /* Load Password only if Username is configured, it doesn't make */ /* much sense to load Password without Username. */ state->password = getenv("Upload_Password"); if (state->password == NULL) { /* Be permissive and nice, ask only once and don't check */ /* the result. User can dismiss this prompt but the upload */ /* may work somehow??? */ char *msg = xasprintf(_("Please enter password for uploading:"), state->username); state->password = password_inp = ask_password(msg); free(msg); } } char *remote_name = upload_file_ext(state, url, tempfile, UPLOAD_FILE_HANDLE_ACCESS_DENIALS); result = (remote_name == NULL); /* error if NULL */ free(remote_name); free(password_inp); free_post_state(state); /* cleanup code will delete tempfile */ } else { result = 0; /* success */ log(_("Archive is created: '%s'"), tempfile); free(tempfile); tempfile = NULL; } ret: free(url); dd_close(dd); if (tar) tar_close(tar); /* close(pipe_from_parent_to_child[1]); - tar_close() does it itself */ if (child > 0) safe_waitpid(child, NULL, 0); if (tempfile) { unlink(tempfile); free(tempfile); } if (errmsg) error_msg_and_die("%s", errmsg); return result; }
int main(int argc, char **argv) { setlocale(LC_ALL, ""); #if ENABLE_NLS bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); #endif abrt_init(argv); struct ureport_server_config config = { .ur_url = SERVER_URL, .ur_ssl_verify = true, }; bool insecure = !config.ur_ssl_verify; bool attach_reported_to = false; const char *dump_dir_path = "."; const char *ureport_hash = NULL; int rhbz_bug = -1; struct dump_dir *dd = NULL; struct options program_options[] = { OPT__VERBOSE(&g_verbose), OPT__DUMP_DIR(&dump_dir_path), OPT_STRING('u', "url", &config.ur_url, "URL", _("Specify server URL")), OPT_BOOL('k', "insecure", &insecure, _("Allow insecure connection to ureport server")), OPT_STRING('a', "attach", &ureport_hash, "BTHASH", _("bthash of uReport to attach")), OPT_INTEGER('b', "bug-id", &rhbz_bug, _("Attach RHBZ bug (requires -a)")), OPT_BOOL('r', "attach-reported-to", &attach_reported_to, _("Attach contents of reported_to")), OPT_END(), }; const char *program_usage_string = _( "& [-v] [-u URL] [-k] [-a bthash -b bug-id] [-r] [-d DIR]\n" "\n" "Upload micro report or add an attachment to a micro report" ); parse_opts(argc, argv, program_options, program_usage_string); config.ur_ssl_verify = !insecure; load_ureport_server_config(&config); post_state_t *post_state = NULL; /* we either need both -b & -a or none of them */ if (ureport_hash && rhbz_bug > 0) return perform_attach(&config, ureport_hash, rhbz_bug); if (ureport_hash && rhbz_bug <= 0) error_msg_and_die(_("You need to specify bug ID to attach.")); if (!ureport_hash && rhbz_bug > 0) error_msg_and_die(_("You need to specify bthash of the uReport to attach.")); /* -r */ if (attach_reported_to) { dd = dd_opendir(dump_dir_path, DD_OPEN_READONLY); if (!dd) xfunc_die(); report_result_t *ureport_result = find_in_reported_to(dd, "uReport"); report_result_t *bz_result = find_in_reported_to(dd, "Bugzilla"); dd_close(dd); if (!ureport_result || !ureport_result->bthash) error_msg_and_die(_("This problem does not have an uReport assigned.")); if (!bz_result || !bz_result->url) error_msg_and_die(_("This problem has not been reported to Bugzilla.")); char *bthash = xstrdup(ureport_result->bthash); free_report_result(ureport_result); char *bugid_ptr = strstr(bz_result->url, "show_bug.cgi?id="); if (!bugid_ptr) error_msg_and_die(_("Unable to find bug ID in bugzilla URL '%s'"), bz_result->url); bugid_ptr += strlen("show_bug.cgi?id="); int bugid; /* we're just reading int, sscanf works fine */ if (sscanf(bugid_ptr, "%d", &bugid) != 1) error_msg_and_die(_("Unable to parse bug ID from bugzilla URL '%s'"), bz_result->url); free_report_result(bz_result); const int result = perform_attach(&config, bthash, bugid); free(bthash); return result; } /* -b, -a nor -r were specified - upload uReport from dump_dir */ int ret = 1; /* "failure" (for now) */ char *dest_url = concat_path_file(config.ur_url, REPORT_URL_SFX); config.ur_url = dest_url; char *json_ureport = ureport_from_dump_dir(dump_dir_path); if (!json_ureport) { error_msg(_("Not uploading an empty uReport")); goto format_err; } post_state = post_ureport(json_ureport, &config); free(json_ureport); if (!post_state) { error_msg(_("Failed on submitting the problem")); goto format_err; } struct ureport_server_response *response = get_server_response(post_state, &config); if (!response) goto format_err; if (!response->is_error) { VERB1 log("is known: %s", response->value); ret = 0; /* "success" */ dd = dd_opendir(dump_dir_path, /* flags */ 0); if (!dd) xfunc_die(); if (response->bthash) { char *msg = xasprintf("uReport: BTHASH=%s", response->bthash); add_reported_to(dd, msg); free(msg); } if (response->reported_to_list) { for (GList *e = response->reported_to_list; e; e = g_list_next(e)) add_reported_to(dd, e->data); } if (response->solution) dd_save_text(dd, FILENAME_NOT_REPORTABLE, response->solution); dd_close(dd); /* If a reported problem is not known then emit NEEDMORE */ if (strcmp("true", response->value) == 0) { log(_("This problem has already been reported.")); if (response->message) log(response->message); ret = EXIT_STOP_EVENT_RUN; } } else { error_msg(_("Server responded with an error: '%s'"), response->value); } free_ureport_server_response(response); format_err: free_post_state(post_state); free(dest_url); return ret; }