From c3fe60ea974610939e39947b4a96db4f2f2d02a9 Mon Sep 17 00:00:00 2001 From: Fernando Herrera Date: Wed, 30 Jan 2008 18:14:46 +0000 Subject: [PATCH] Bump version to 2.21.90 remove UTF-8 control characters from the report to 2008-01-30 Fernando Herrera * configure.in: Bump version to 2.21.90 * src/bugzilla.c: (bugzilla_create_report): remove UTF-8 control characters from the report to make bugzilla.gnome.org happy. 2008-01-07 Dan Winship * configure.in: require libsoup-2.4 * src/bugzilla.c (bugzilla_create_report): Use new libsoup XML-RPC API. (bugzilla_parse_response): Likewise. Now returns SOUP_XMLRPC_FAULT GErrors in some cases. * src/bug-buddy.c: Update for libsoup 2.4 (bug_sent): deal with different bugzilla_parse_response() error semantics svn path=/trunk/; revision=2470 --- ChangeLog | 19 +++++ configure.in | 4 +- src/bug-buddy.c | 104 +++++++++++--------------- src/bugzilla.c | 223 +++++++++++++++++++++----------------------------------- src/bugzilla.h | 5 +- 5 files changed, 149 insertions(+), 206 deletions(-) diff --git a/ChangeLog b/ChangeLog index 18fc2cad..0512149c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,22 @@ +2008-01-30 Fernando Herrera + + * configure.in: Bump version to 2.21.90 + * src/bugzilla.c: (bugzilla_create_report): remove UTF-8 control + characters from the report to make bugzilla.gnome.org happy. + +2008-01-07 Dan Winship + + * configure.in: require libsoup-2.4 + + * src/bugzilla.c (bugzilla_create_report): Use new libsoup XML-RPC + API. + (bugzilla_parse_response): Likewise. Now returns SOUP_XMLRPC_FAULT + GErrors in some cases. + + * src/bug-buddy.c: Update for libsoup 2.4 + (bug_sent): deal with different bugzilla_parse_response() error + semantics + 2007-10-06 Fernando Herrera * Merge from http://www.gnome.org/~fherrera/bug-buddy.git diff --git a/configure.in b/configure.in index 95210110..11d9203a 100644 --- a/configure.in +++ b/configure.in @@ -1,6 +1,6 @@ dnl Configure script for bug-buddy -AC_INIT([bug-buddy],[2.20.1],[http://bugzilla.gnome.org/enter_bug.cgi?product=bug-buddy]) +AC_INIT([bug-buddy],[2.21.90],[http://bugzilla.gnome.org/enter_bug.cgi?product=bug-buddy]) AC_CANONICAL_TARGET @@ -45,7 +45,7 @@ LIBGNOMEMENU_REQUIRED="libgnome-menu >= 2.11.1" LIBGNOMEUI_REQUIRED="libgnomeui-2.0 >= 2.5.92" LIBXML_REQUIRED="libxml-2.0 >= 2.4.6" GTK_REQUIRED="gtk+-2.0 >= 2.12" -LIBSOUP_REQUIRED="libsoup-2.2 >= 2.2.96" +LIBSOUP_REQUIRED="libsoup-2.4" LIBGTOP_REQUIRED="libgtop-2.0 >= 2.13.3" LIBNM_GLIB_REQUIRED="libnm_glib >= 0.6.2" diff --git a/src/bug-buddy.c b/src/bug-buddy.c index ee414084..86befa65 100644 --- a/src/bug-buddy.c +++ b/src/bug-buddy.c @@ -60,7 +60,6 @@ #endif #include -#include #include #include @@ -414,7 +413,6 @@ network_error (SoupMessage *msg, GtkBuilder *ui) if (res == GTK_RESPONSE_YES) { gchar *dirname; gchar *filename; - xmlChar *message_string; dirname = g_strdup_printf ("%s/.gnome2/bug-buddy/pending_reports", g_get_home_dir ()); if (!g_file_test (dirname, G_FILE_TEST_IS_DIR)) { @@ -423,11 +421,8 @@ network_error (SoupMessage *msg, GtkBuilder *ui) filename = g_strdup_printf ("%s/%ld", dirname, (long)time (NULL)); - message_string = soup_xmlrpc_message_to_string (SOUP_XMLRPC_MESSAGE (msg)); + save_to_file (filename, msg->request_body->data); - save_to_file (filename, (const gchar*) message_string); - - xmlFree (message_string); g_free (dirname); g_free (filename); } @@ -473,7 +468,7 @@ all_sent (GtkBuilder *ui) } static void -previous_sent (SoupMessage *msg, GtkBuilder *ui) +previous_sent (SoupSession *session, SoupMessage *msg, GtkBuilder *ui) { if (--bug_count == 0) { all_sent (ui); @@ -482,14 +477,13 @@ previous_sent (SoupMessage *msg, GtkBuilder *ui) static void -bug_sent (SoupMessage *msg, GtkBuilder *ui) +bug_sent (SoupSession *session, SoupMessage *msg, GtkBuilder *ui) { GtkWidget *button; GtkWidget *image; char *text = NULL; char *errmsg = NULL; char *str = NULL; - char *ptr = NULL; long bugid; char *response; char *tmp; @@ -554,7 +548,34 @@ bug_sent (SoupMessage *msg, GtkBuilder *ui) errmsg = _("Bug Buddy has encountered an error while submitting your report " "to the Bugzilla server. Details of the error are included below.\n\n"); - if (err != NULL) { + if (err && err->domain == SOUP_XMLRPC_FAULT) { + /* see http://cvs.gnome.org/viewcvs/bugzilla-newer/Bugzilla/RPC.pm?view=markup */ + if (err->message == NULL) { + text = g_strdup_printf (_("Bugzilla reported an error when trying to process your " + "request, but was unable to parse the response.")); + } else if (g_str_equal (err->message, "invalid_username")) { + text = g_strdup_printf (_("The email address you provided is not valid.")); + } else if (g_str_equal (err->message, "account_disabled")) { + text = g_strdup_printf (_("The account associated with the email address " + "provided has been disabled.")); + } else if (g_str_equal (err->message, "product_doesnt_exist")) { + text = g_strdup_printf (_("The product specified doesn't exist or has been " + "renamed. Please upgrade to the latest version.")); + } else if (g_str_equal (err->message, "component_not_valid")) { + text = g_strdup_printf (_("The component specified doesn't exist or has been " + "renamed. Please upgrade to the latest version.")); + } else if (g_str_equal (err->message, "require_summary")) { + text = g_strdup_printf (_("The summary is required in your bug report. " + "This should not happen with the latest Bug Buddy.")); + } else if (g_str_equal (err->message, "description_required")) { + text = g_strdup_printf (_("The description is required in your bug report. " + "This should not happen with the latest Bug Buddy.")); + } else { + text = g_strdup_printf (_("The fault code returned by Bugzilla is not recognized. " + "Please report the following information to " + "bugzilla.gnome.org manually:\n\n%s"), err->message); + } + } else if (err) { switch (err->code) { case BUGZILLA_ERROR_RECV_BAD_STATUS: text = g_strdup_printf (_("Server returned bad state. This is most likely a server " @@ -565,45 +586,6 @@ bug_sent (SoupMessage *msg, GtkBuilder *ui) text = g_strdup_printf (_("Failed to parse the xml-rpc response. Response follows:\n\n%s"), err->message); break; - case BUGZILLA_ERROR_RECV_FAULT: - /* in this case, the error message returned is the faultCode and faultString from - * the XML-RPC response, separated by a colon. We construct our error message - * based on the faultString */ - ptr = strstr (err->message, ":"); - if (ptr == NULL) { - text = g_strdup_printf (_("Bugzilla reported an error when trying to process your " - "request, but was unable to parse the response.")); - break; - } - - /* skip the colon */ - ptr++; - - /* see http://cvs.gnome.org/viewcvs/bugzilla-newer/Bugzilla/RPC.pm?view=markup */ - if (g_str_equal (ptr, "invalid_username")) { - text = g_strdup_printf (_("The email address you provided is not valid.")); - } else if (g_str_equal (ptr, "account_disabled")) { - text = g_strdup_printf (_("The account associated with the email address " - "provided has been disabled.")); - } else if (g_str_equal (ptr, "product_doesnt_exist")) { - text = g_strdup_printf (_("The product specified doesn't exist or has been " - "renamed. Please upgrade to the latest version.")); - } else if (g_str_equal (ptr, "component_not_valid")) { - text = g_strdup_printf (_("The component specified doesn't exist or has been " - "renamed. Please upgrade to the latest version.")); - } else if (g_str_equal (ptr, "require_summary")) { - text = g_strdup_printf (_("The summary is required in your bug report. " - "This should not happen with the latest Bug Buddy.")); - } else if (g_str_equal (ptr, "description_required")) { - text = g_strdup_printf (_("The description is required in your bug report. " - "This should not happen with the latest Bug Buddy.")); - } else { - text = g_strdup_printf (_("The fault code returned by Bugzilla is not recognized. " - "Please report the following information to " - "bugzilla.gnome.org manually:\n\n%s"), err->message); - } - - break; default: text = g_strdup_printf (_("An unknown error occurred. This is most likely a problem with " "bug-buddy. Please report this problem manually at bugzilla." @@ -640,7 +622,7 @@ set_proxy (SoupSession *session) char *host; int port; char *proxy_uri; - SoupUri *uri; + SoupURI *uri; char *username = NULL; char *password = NULL; @@ -730,7 +712,7 @@ send_report (BugzillaApplication *app, GnomeVersionInfo *gnome_version, GtkBuild char *final_text; const char *email; SoupSession *session; - SoupXmlrpcMessage *message; + SoupMessage *message; GError *err = NULL; gtk_widget_hide (GTK_WIDGET (gtk_builder_get_object (ui, "pending-reports-check"))); @@ -792,17 +774,18 @@ send_report (BugzillaApplication *app, GnomeVersionInfo *gnome_version, GtkBuild while (name != NULL) { char *path; char *contents; + gsize length; path = g_strdup_printf ("%s/%s", dirname, name); - if (g_file_get_contents (path, &contents, NULL, NULL)) { - SoupXmlrpcMessage *msg; - msg = soup_xmlrpc_message_new ("http://bugzilla.gnome.org/bugbuddy.cgi"); - soup_xmlrpc_message_from_string (msg, contents); + if (g_file_get_contents (path, &contents, &length, NULL)) { + SoupMessage *msg; + msg = soup_message_new ("POST", "http://bugzilla.gnome.org/bugbuddy.cgi"); + soup_message_set_request (msg, "text/xml", + SOUP_MEMORY_TAKE, + contents, length); bug_count++; - soup_xmlrpc_message_persist (msg); soup_session_queue_message (session, SOUP_MESSAGE (msg), - (SoupMessageCallbackFn)previous_sent, ui); - g_free (contents); + (SoupSessionCallback)previous_sent, ui); } g_free (path); name = g_dir_read_name (dir); @@ -814,9 +797,8 @@ send_report (BugzillaApplication *app, GnomeVersionInfo *gnome_version, GtkBuild bug_count++; - soup_xmlrpc_message_persist (message); - soup_session_queue_message (session, SOUP_MESSAGE (message), - (SoupMessageCallbackFn)bug_sent, ui); + soup_session_queue_message (session, message, + (SoupSessionCallback)bug_sent, ui); g_free (gdb_text); g_free (details_text); g_free (title); diff --git a/src/bugzilla.c b/src/bugzilla.c index c706794d..aed213f8 100644 --- a/src/bugzilla.c +++ b/src/bugzilla.c @@ -47,7 +47,6 @@ #include #include -#include #define APPLET_REQUIREMENTS \ @@ -461,10 +460,8 @@ bugzilla_search_for_package (gpointer key, gpointer value, const char *package) char * bugzilla_parse_response (SoupMessage *msg, GError **err) { - SoupXmlrpcResponse *response; - SoupXmlrpcValue *value; - long bugid = 0; - int debug = 0; + GValue value; + int bugid = 0; char *url; g_return_val_if_fail ((err == NULL || *err == NULL), NULL); @@ -475,88 +472,39 @@ bugzilla_parse_response (SoupMessage *msg, GError **err) return NULL; } - response = soup_xmlrpc_message_parse_response (SOUP_XMLRPC_MESSAGE (msg)); - if (!response) { - g_set_error (err, BUGZILLA_ERROR, BUGZILLA_ERROR_RECV_PARSE_FAILED, - _("Unable to parse XML-RPC Response")); + if (!soup_xmlrpc_parse_method_response (msg->response_body->data, + msg->response_body->length, + &value, err)) return NULL; - } - - /* check to see if the XMLRPC response was a */ - if (soup_xmlrpc_response_is_fault (response)) { - SoupXmlrpcValue *faultCode = NULL; - SoupXmlrpcValue *faultString = NULL; - GHashTable *fault = NULL; - gchar *errormsg = NULL; - long errorcode = -1; - - value = soup_xmlrpc_response_get_value (response); - if (!value) { - debug = 1; - goto parse_error; - } - - /* get the struct representing the fault */ - if (!soup_xmlrpc_value_get_struct (value, &fault)) { - debug = 2; - goto parse_error; - } - /* get the integer representing the fault code */ - faultCode = g_hash_table_lookup (fault, "faultCode"); - if (faultCode == NULL || !soup_xmlrpc_value_get_int (faultCode, &errorcode)) { - debug = 3; - goto parse_error; - } - - /* get the string representing the fault string */ - faultString = g_hash_table_lookup (fault, "faultString"); - if (faultString == NULL || !soup_xmlrpc_value_get_string (faultString, &errormsg)) { - debug = 4; - goto parse_error; - } - - /* send back a BUGZILLA_ERROR_FAULT, using the errorcode and errorstring to - * construct the GError message */ - g_set_error (err, BUGZILLA_ERROR, BUGZILLA_ERROR_RECV_FAULT, - "%ld:%s", errorcode, errormsg); + if (G_VALUE_HOLDS_INT (&value)) + bugid = g_value_get_int (&value); + else if (G_VALUE_HOLDS_STRING (&value)) + url = g_value_dup_string (&value); + else { + g_value_unset (&value); + g_set_error (err, BUGZILLA_ERROR, BUGZILLA_ERROR_RECV_PARSE_FAILED, + _("Unable to parse XML-RPC Response\n\n%s"), + msg->response_body->data); return NULL; - } + g_value_unset (&value); - value = soup_xmlrpc_response_get_value (response); - if (!value) { - debug = 5; - goto parse_error; - } - - if (!soup_xmlrpc_value_get_int (value, &bugid)) { - if (!soup_xmlrpc_value_get_string (value, &url)) { - debug = 6; - goto parse_error; - } - } - - /* whew, everything checked out, send back the bug id */ - g_object_unref (response); - return bugid ? g_strdup_printf ("%ld", bugid) : url; - -parse_error: - g_set_error (err, BUGZILLA_ERROR, BUGZILLA_ERROR_RECV_PARSE_FAILED, - _("Unable to parse XML-RPC Response\n\n%d\n\n%s"), - debug, soup_xmlrpc_response_to_string (response)); - g_object_unref (response); - return NULL; + return bugid ? g_strdup_printf ("%d", bugid) : url; } -SoupXmlrpcMessage* +SoupMessage* bugzilla_create_report (BugzillaApplication *app, int type, GnomeVersionInfo *gnome_version, const char *username, const char *title, const char *text, GtkBuilder *ui, const char *minidump_file, GError **err) { - SoupXmlrpcMessage *message; + SoupMessage *message; + const char *uri; + GHashTable *report; char *user_agent; char *os_version; + gchar *crt; + GString *rv; g_return_val_if_fail (app != NULL, NULL); g_return_val_if_fail (gnome_version != NULL, NULL); @@ -578,70 +526,42 @@ bugzilla_create_report (BugzillaApplication *app, int type, GnomeVersionInfo *gn return NULL; } - if (minidump_file) - //message = soup_xmlrpc_message_new ("http://localhost/breakpad/xmlrpc.py"); - message = soup_xmlrpc_message_new ("http://socorro.gnome.org/collect.py"); - else - message = soup_xmlrpc_message_new ("http://bugzilla.gnome.org/bugbuddy.cgi"); - - if (message == NULL) { - g_set_error (err, BUGZILLA_ERROR, BUGZILLA_ERROR_SEND_ERROR, - _("Unable to create XML-RPC message.")); - return NULL; - } - - user_agent = g_strdup_printf ("Bug-Buddy: %s", VERSION); - soup_message_add_header (SOUP_MESSAGE(message)->request_headers, "User-Agent", user_agent); - g_free (user_agent); - - soup_xmlrpc_message_start_call (message, "BugBuddy.createBug"); - soup_xmlrpc_message_start_param (message); - soup_xmlrpc_message_start_struct (message); - - soup_xmlrpc_message_start_member (message, "version"); - soup_xmlrpc_message_write_string (message, app->version ? app->version : "unspecified"); - soup_xmlrpc_message_end_member (message); - - soup_xmlrpc_message_start_member (message, "product"); - soup_xmlrpc_message_write_string (message, app->product); - soup_xmlrpc_message_end_member (message); + report = soup_value_hash_new (); - soup_xmlrpc_message_start_member (message, "component"); - soup_xmlrpc_message_write_string (message, app->component); - soup_xmlrpc_message_end_member (message); - - soup_xmlrpc_message_start_member (message, "gnome_version"); - soup_xmlrpc_message_write_string (message, gnome_version->gnome_platform); - soup_xmlrpc_message_end_member (message); - - soup_xmlrpc_message_start_member (message, "reporter"); - soup_xmlrpc_message_write_string (message, username); - soup_xmlrpc_message_end_member (message); + soup_value_hash_insert (report, "version", G_TYPE_STRING, + app->version ? app->version : "unspecified"); + soup_value_hash_insert (report, "product", G_TYPE_STRING, app->product); + soup_value_hash_insert (report, "component", G_TYPE_STRING, app->component); + soup_value_hash_insert (report, "gnome_version", G_TYPE_STRING, + gnome_version->gnome_platform); + soup_value_hash_insert (report, "reporter", G_TYPE_STRING, username); os_version = get_distro_name (); - soup_xmlrpc_message_start_member (message, "os_version"); - soup_xmlrpc_message_write_string (message, os_version); - soup_xmlrpc_message_end_member (message); + soup_value_hash_insert (report, "os_version", G_TYPE_STRING, os_version); g_free (os_version); if (type == BUG_TYPE_CRASH) { - soup_xmlrpc_message_start_member (message, "priority"); - soup_xmlrpc_message_write_string (message, "High"); - soup_xmlrpc_message_end_member (message); - - soup_xmlrpc_message_start_member (message, "bug_severity"); - soup_xmlrpc_message_write_string (message, "critical"); - soup_xmlrpc_message_end_member (message); + soup_value_hash_insert (report, "priority", G_TYPE_STRING, "High"); + soup_value_hash_insert (report, "bug_severity", G_TYPE_STRING, "critical"); } - soup_xmlrpc_message_start_member (message, "short_desc"); - soup_xmlrpc_message_write_string (message, title); - soup_xmlrpc_message_end_member (message); + soup_value_hash_insert (report, "short_desc", G_TYPE_STRING, "title"); - soup_xmlrpc_message_start_member (message, "comment"); - soup_xmlrpc_message_write_string (message, text); - soup_xmlrpc_message_end_member (message); + /* Skip UTF-8 control chars that are not valid in XML.*/ + rv = g_string_new (NULL); + crt = text; + while (*crt) { + gchar *next = g_utf8_next_char (crt); + gunichar uni = g_utf8_get_char (crt); + if (!g_unichar_iscntrl (uni) || (uni == '\n') || (uni == '\t')) + g_string_append_len (rv, crt, next - crt); + + crt = next; + } + + soup_value_hash_insert (report, "comment", G_TYPE_STRING, rv->str); + g_string_free (rv, TRUE); if (minidump_file) { gchar *minidumpbuf; @@ -659,31 +579,54 @@ bugzilla_create_report (BugzillaApplication *app, int type, GnomeVersionInfo *gn if (base64) { gchar *basename; gchar *id; + GByteArray *ba; basename = g_path_get_basename (minidump_file); id = g_strndup (basename, strlen (basename) - strlen (".dmp")); - soup_xmlrpc_message_start_member (message, "minidump-id"); - soup_xmlrpc_message_write_string (message, id); - soup_xmlrpc_message_end_member (message); - - soup_xmlrpc_message_start_member (message, "minidump"); - soup_xmlrpc_message_write_base64 (message, base64, strlen(base64)); - soup_xmlrpc_message_end_member (message); + soup_value_hash_insert (report, "minidump-id", + G_TYPE_STRING, id); + + /* FIXME: This is broken; for some reason + * bug-buddy is base64-encoding the minidump + * *twice*. (Once itself, and once by asking + * libsoup to do it.) Fix this after verifying + * that the server side can deal with the + * fix... + */ + ba = g_byte_array_sized_new (strlen (base64)); + g_byte_array_append (ba, (guchar *)base64, strlen (base64)); + soup_value_hash_insert (report, "minidump", + SOUP_TYPE_BYTE_ARRAY, ba); + g_byte_array_free (ba, TRUE); g_free (base64); g_free (basename); g_free (id); } } + if (minidump_file) + //uri = "http://localhost/breakpad/xmlrpc.py"; + uri = "http://socorro.gnome.org/collect.py"; + else + uri = "http://bugzilla.gnome.org/bugbuddy.cgi"; + message = soup_xmlrpc_request_new (uri, "BugBuddy.createBug", + G_TYPE_HASH_TABLE, report, + G_TYPE_INVALID); + g_hash_table_destroy (report); + if (message == NULL) { + g_set_error (err, BUGZILLA_ERROR, BUGZILLA_ERROR_SEND_ERROR, + _("Unable to create XML-RPC message.")); + return NULL; + } - soup_xmlrpc_message_end_param (message); - soup_xmlrpc_message_end_struct (message); - - soup_xmlrpc_message_end_call (message); + /* FIXME: wrong User-Agent syntax. Should be "Bug-Buddy (VERSION)" */ + user_agent = g_strdup_printf ("Bug-Buddy: %s", VERSION); + soup_message_headers_append (message->request_headers, + "User-Agent", user_agent); + g_free (user_agent); return message; - } diff --git a/src/bugzilla.h b/src/bugzilla.h index 0bc98aa5..ecf6d0d9 100644 --- a/src/bugzilla.h +++ b/src/bugzilla.h @@ -28,7 +28,7 @@ #include #include -#include +#include extern GQuark bugzilla_error_quark (void); #define BUGZILLA_ERROR bugzilla_error_quark () @@ -36,7 +36,6 @@ extern GQuark bugzilla_error_quark (void); typedef enum { BUGZILLA_ERROR_RECV_BAD_STATUS, BUGZILLA_ERROR_RECV_PARSE_FAILED, - BUGZILLA_ERROR_RECV_FAULT, BUGZILLA_ERROR_SEND_NOTSUPPORTED_APP, BUGZILLA_ERROR_SEND_ERROR } BugzillaError; @@ -78,7 +77,7 @@ char* bugzilla_parse_response (SoupMessage *msg, GError **err); gboolean bugzilla_search_for_package (gpointer key, gpointer value, const char *package); -SoupXmlrpcMessage* bugzilla_create_report (BugzillaApplication *app, +SoupMessage* bugzilla_create_report (BugzillaApplication *app, int type, GnomeVersionInfo *gnome_version, const char *username, -- 2.11.4.GIT