~ubuntu-branches/ubuntu/oneiric/bug-buddy/oneiric

« back to all changes in this revision

Viewing changes to src/bug-buddy.c

  • Committer: Bazaar Package Importer
  • Author(s): Didier Roche
  • Date: 2009-03-17 11:52:38 UTC
  • mfrom: (1.1.27 upstream)
  • Revision ID: james.westby@ubuntu.com-20090317115238-pelki75p8yvl9bw1
Tags: 2.26.0+dfsg-0ubuntu1
* New upstream release: (LP: #344132)
  - Don't hardcode a scrollkeeper check in the configure script.
  - Build correctly with --disable-eds.
  - Fix a segfault (Josseline Mouette).
  - Don't free uninitialized memory.
  - Drop libgnome and libgnomeui dependencies.
  - Make google-breakpad support optional (but enabled by default).
    Thanks to Sjoerd Simons.
  - Obtain the real path of the crashed process by looking in /proc.
    Thanks to Sam Morris and Matt Keenan.
  - Add an option to delete the included file after bug-buddy has
    processed it.
  - Implement a logger for pasting critical and fatal warnings in the
    stacktraces.
  - Include the loaded GTK+ modules in the stacktraces sent to bugzilla.
  - Update google-breakpad to SVN r290.
  - Compile with all the GLib/GTK+ deprecation flags.
* debian/control.in:
  - remove scroolkeeper, libgnome2-dev and libgnomeui-dev b-d
  - bump libgtk2.0-dev to 2.14
  - add libgconf2-dev
  - add Vcs-Bzr tag
  - re-generate debian/control
* debian/patches:
  - remove 01_double-free.patch as taken upstream
  - remove 02_disable_breakpad.patch as upstream handle --disable-*
    (and so, --disable-google-breakpad)
  - refresh 70_automake-autoconf.patch
* debian/rules: remove --disable-scrollkeeper as removed in configure
  file
* Adapt debian/watch to get unstable version

Show diffs side-by-side

added added

removed removed

Lines of Context:
42
42
#include <glib/gstdio.h>
43
43
#include <glib/gi18n.h>
44
44
#include <gio/gio.h>
45
 
#include <gnome.h>
46
45
#include <gtk/gtk.h>
47
46
#include <gdk-pixbuf/gdk-pixbuf.h>
48
 
#include <libgnome/libgnometypebuiltins.h>
49
47
#include <gdk/gdkx.h>
50
48
#include <gdk/gdk.h>
 
49
#include <gdk/gdkkeysyms.h>
 
50
#include <bonobo-activation/bonobo-activation.h>
51
51
 
52
52
#include <libxml/tree.h>
53
53
#include <libxml/parser.h>
65
65
#define ACCESSIBILITY_KEY "/desktop/gnome/interface/accessibility"
66
66
#define GTK_THEME_KEY   "/desktop/gnome/interface/gtk_theme"
67
67
#define ICON_THEME_KEY  "/desktop/gnome/interface/icon_theme"
 
68
#define GTK_MODULES_KEY "/apps/gnome_settings_daemon/gtk-modules"
68
69
#define DESKTOP_IS_HOME_DIR "/apps/nautilus/preferences/desktop_is_home_dir"
69
70
#define MIN_REPORT_DETAILS_CHARS 10
70
71
 
72
73
static int bug_count = 0;
73
74
static GHashTable *apps = NULL;
74
75
 
 
76
static gboolean
 
77
show_version_cb (const char *option_name,
 
78
                 const char *value,
 
79
                 gpointer data,
 
80
                 GError **error)
 
81
{
 
82
        g_print ("%s %s\n", _("GNOME bug-buddy"), VERSION);
 
83
 
 
84
        exit (EXIT_SUCCESS);
 
85
 
 
86
        return FALSE;
 
87
}
 
88
 
75
89
static const GOptionEntry options[] = {
76
90
        { "package",    '\0', 0, G_OPTION_ARG_STRING,   &gopt_data.package,       N_("Package containing the program"),          N_("PACKAGE") },
77
91
        { "appname",    '\0', 0, G_OPTION_ARG_FILENAME, &gopt_data.app_file,      N_("File name of crashed program"),            N_("FILE") },
78
92
        { "pid",        '\0', 0, G_OPTION_ARG_INT,      &gopt_data.pid,           N_("PID of crashed program"),                  N_("PID") },
79
93
        { "include",    '\0', 0, G_OPTION_ARG_FILENAME, &gopt_data.include_file,  N_("Text file to include in the report"),      N_("FILE") },
 
94
        { "unlink-tempfile", '\0', 0, G_OPTION_ARG_NONE, &gopt_data.own_file,     N_("Delete the included file after reporting"),NULL},
80
95
        { "minidump",   '\0', 0, G_OPTION_ARG_FILENAME, &gopt_data.minidump_file, N_("MiniDump file with info about the crash"), N_("FILE") },
 
96
        { "version", '\0', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, show_version_cb, NULL, NULL },
81
97
        { NULL }
82
98
};
83
99
 
85
101
static void fill_custom_info (BugzillaApplication *app, GtkBuilder *ui);
86
102
static void close_callback   (GtkWidget *widget, gpointer user_data);
87
103
static void bug_buddy_quit   (GtkBuilder *ui);
 
104
static void fill_include_file (char *filename, gboolean own_file, GtkBuilder *ui);
88
105
 
89
106
 
90
107
static void
276
293
 
277
294
        version = g_new0 (GnomeVersionInfo, 1);
278
295
 
279
 
        xml_file = gnome_program_locate_file (NULL, GNOME_FILE_DOMAIN_DATADIR,
280
 
                                              "gnome-about/gnome-version.xml",
281
 
                                              TRUE, NULL);
282
 
        if (!xml_file)
283
 
                return NULL;
 
296
        xml_file = g_build_filename (DATADIR, "gnome-about/gnome-version.xml", NULL);
 
297
        
284
298
        doc = xmlParseFile (xml_file);
285
299
        g_free (xml_file);
286
300
 
288
302
                return NULL;
289
303
 
290
304
        platform = minor = micro = distributor = date = NULL;
291
 
        
 
305
 
292
306
        for (node = xmlDocGetRootElement (doc)->children; node; node = node->next) {
293
307
                if (!strcmp ((char *)node->name, "platform"))
294
308
                        platform = xmlNodeGetContent (node);
395
409
link_callback (GtkLinkButton *button, gpointer user_data)
396
410
{
397
411
        const gchar *link = gtk_link_button_get_uri (button);
398
 
#if GTK_CHECK_VERSION (2,13,0)
399
412
        GdkAppLaunchContext *context;
400
413
 
401
414
        context = gdk_app_launch_context_new ();
407
420
        if (!g_app_info_launch_default_for_uri (link,
408
421
                                                G_APP_LAUNCH_CONTEXT (context),
409
422
                                                NULL))
410
 
#else
411
 
        if (!g_app_info_launch_default_for_uri (link, NULL, NULL))
412
 
#endif
413
 
    {
 
423
        {
414
424
                char *text;
415
425
 
416
426
                text = g_markup_printf_escaped (_("Bug Buddy was unable to view the link \"%s\"\n"), link);
418
428
                g_free (text);
419
429
        }
420
430
 
421
 
#if GTK_CHECK_VERSION (2,13,0)
422
431
        g_object_unref (context);
423
 
#endif
424
432
 
425
433
        return;
426
434
}
779
787
        gtk_text_buffer_get_end_iter (buffer, &end);
780
788
        details_text = gtk_text_buffer_get_text (buffer, &start, &end, FALSE);
781
789
 
782
 
        type = GPOINTER_TO_INT (g_object_get_data (G_OBJECT(ui), "type"));
 
790
        type = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (ui), "type"));
783
791
        final_text = g_strdup_printf ("%s%s\n\n\n%s", 
784
792
                                      type == BUG_TYPE_CRASH ? "What were you doing when the application crashed?\n" : "",
785
793
                                      details_text != NULL ? details_text : "",
1377
1385
{
1378
1386
        GtkWidget *button;
1379
1387
        char *label_text;
 
1388
        
 
1389
        /* add the include file information now that gdb has run */
 
1390
        if (gopt_data.include_file != NULL) {
 
1391
                fill_include_file (gopt_data.include_file, gopt_data.own_file, ui);
 
1392
        }
1380
1393
 
1381
1394
        fill_stderr_info (ui);
1382
1395
 
1471
1484
static void
1472
1485
help_callback (GtkWidget *widget, gpointer user_data)
1473
1486
{
1474
 
        GnomeProgram *program = (GnomeProgram *)user_data;
1475
1487
        GError *error = NULL;
1476
 
 
1477
 
        gnome_help_display_desktop (program, 
1478
 
                                    "user-guide",
1479
 
                                    "user-guide", 
1480
 
                                    "feedback-bugs",
1481
 
                                    &error);
1482
 
 
1483
 
        if (error) {
 
1488
        gboolean res;
 
1489
 
 
1490
        res = gtk_show_uri (gtk_widget_get_screen (widget),
 
1491
                            "ghelp:user-guide#feedback-bugs",
 
1492
                            gtk_get_current_event_time (), &error);
 
1493
 
 
1494
        if (!res) {
1484
1495
                GtkWidget *error_dialog = 
1485
1496
                    gtk_message_dialog_new (NULL, 
1486
1497
                                            GTK_DIALOG_MODAL,
1554
1565
        g_return_if_fail (app != NULL);
1555
1566
        g_return_if_fail (ui != NULL);
1556
1567
 
 
1568
        /* fill the include info now that gdb has run */
 
1569
        if (gopt_data.include_file != NULL) {
 
1570
                fill_include_file (gopt_data.include_file, gopt_data.own_file, ui);
 
1571
        }
 
1572
 
1557
1573
        if (app->extra_info_script == NULL) {
1558
1574
                return;
1559
1575
        }
1617
1633
}
1618
1634
 
1619
1635
static void
1620
 
fill_include_file (char *filename, GtkBuilder *ui)
 
1636
fill_include_file (char *filename, gboolean own_file, GtkBuilder *ui)
1621
1637
{
1622
1638
        GtkTextView *text_view;
1623
1639
        GtkTextIter end;
1624
1640
        GtkTextBuffer *buffer;
1625
1641
        char *text;
 
1642
        gboolean res;
1626
1643
        GError *error = NULL;
1627
1644
 
1628
 
        if (g_file_get_contents (filename, &text, NULL, &error) != TRUE) {
 
1645
        res = g_file_get_contents (filename, &text, NULL, &error);
 
1646
 
 
1647
        /* if own_file is set, delete the file regardless of the result:
 
1648
         * if _get_contents () fails chances are the file has already been
 
1649
         * deleted anyway.
 
1650
         */
 
1651
 
 
1652
        if (own_file) {
 
1653
                if (g_unlink (filename) == -1)
 
1654
                        g_warning ("Unable to delete %s", filename);
 
1655
        }
 
1656
 
 
1657
        if (!res) {
1629
1658
                buddy_error (NULL, error->message);
1630
1659
                g_error_free (error);
1631
1660
                return;
1632
1661
        }
1633
 
        
 
1662
 
1634
1663
        text_view = GTK_TEXT_VIEW (gtk_builder_get_object (ui, "gdb-text"));
1635
1664
        buffer = gtk_text_view_get_buffer (text_view);
1636
1665
        gtk_text_buffer_get_end_iter (buffer, &end);
1640
1669
 
1641
1670
}
1642
1671
 
 
1672
/* copied from gconf-editor/gconf-util.c */
 
1673
 
 
1674
static gchar *
 
1675
gconf_get_key_name_from_path (const gchar *path)
 
1676
{
 
1677
        const gchar *ptr;
 
1678
 
 
1679
        ptr = path + strlen (path);
 
1680
 
 
1681
        while (ptr[-1] != '/')
 
1682
                ptr--;
 
1683
 
 
1684
        return g_strdup (ptr);
 
1685
}
1643
1686
 
1644
1687
static void
1645
1688
fill_system_info (GtkBuilder *ui)
1648
1691
        GtkTextView *text_view;
1649
1692
        GtkTextIter end;
1650
1693
        GtkTextBuffer *buffer;
1651
 
        GString *system_info;
 
1694
        GString *system_info, *modules;
 
1695
        GSList *entries;
1652
1696
        struct utsname uts_buf;
1653
1697
        char *str;
1654
1698
        gboolean has_selinux, enforcing, a11y;
1656
1700
        g_return_if_fail (ui != NULL);
1657
1701
        
1658
1702
        system_info = g_string_new ("");
 
1703
        modules = NULL;
1659
1704
 
1660
1705
        if (uname (&uts_buf) == 0) {
1661
1706
                g_string_append_printf (system_info, "System: %s %s %s %s\n", uts_buf.sysname, uts_buf.release, uts_buf.version, uts_buf.machine);
1693
1738
        str = gconf_client_get_string (gconf_client, ICON_THEME_KEY, NULL);
1694
1739
        g_string_append_printf (system_info, "Icon Theme: %s\n", str);
1695
1740
        g_free (str);
 
1741
 
 
1742
        /* add the GTK+ loaded modules. to do that, we look both in GConf and
 
1743
         * inside the GTK_MODULES env var.
 
1744
         */
 
1745
 
 
1746
        entries = gconf_client_all_entries (gconf_client, GTK_MODULES_KEY, NULL);
 
1747
        if (entries) {
 
1748
                GSList *l;
 
1749
                GConfEntry *entry;
 
1750
                char *name;
 
1751
                GConfValue *val;
 
1752
 
 
1753
                modules = g_string_new ("GTK+ Modules: ");
 
1754
 
 
1755
                for (l = entries; l != NULL; l = l->next)  {
 
1756
                        entry = l->data;
 
1757
                        val = gconf_entry_get_value (entry);
 
1758
 
 
1759
                        /* if the value is a boolean, check if it's activated, otherwise if it's
 
1760
                         * a string, it will refer to a boolean; check that.
 
1761
                         * i know this is quite ugly.
 
1762
                         */
 
1763
                        if ((val->type == GCONF_VALUE_BOOL && gconf_value_get_bool (val)) ||
 
1764
                            (val->type == GCONF_VALUE_STRING && gconf_client_get_bool (gconf_client,
 
1765
                                                                                       gconf_value_get_string (val),
 
1766
                                                                                       NULL)))
 
1767
                        {
 
1768
 
 
1769
                                name = gconf_get_key_name_from_path (gconf_entry_get_key (entry));
 
1770
 
 
1771
                                if (!g_strstr_len (modules->str, modules->len, name)) {
 
1772
                                        g_string_append_printf (modules, "%s, ", name);
 
1773
                                }
 
1774
 
 
1775
                                g_free (name);
 
1776
                        }
 
1777
 
 
1778
                        gconf_entry_unref (entry);
 
1779
                }
 
1780
 
 
1781
                g_slist_free (entries);
 
1782
        }
 
1783
 
 
1784
        str = (char * ) g_getenv ("GTK_MODULES");
 
1785
        if (str) {
 
1786
                char **splitted;
 
1787
                int i;
 
1788
 
 
1789
                if (!modules) {
 
1790
                        modules = g_string_new ("GTK+ Modules: ");
 
1791
                }
 
1792
 
 
1793
                /* modules are divided by G_SEARCHPATH_SEPARATOR */
 
1794
                splitted = pango_split_file_list (str);
 
1795
 
 
1796
                for (i = 0; splitted[i]; i++) {
 
1797
                        if (!g_strstr_len (modules->str, modules->len, splitted[i])) {
 
1798
                                g_string_append_printf (modules, "%s, ", splitted[i]);
 
1799
                        }
 
1800
                }
 
1801
 
 
1802
                g_strfreev (splitted);
 
1803
        }
 
1804
 
 
1805
        if (modules) {
 
1806
                /* discard the last ", " */
 
1807
                g_string_append_len (system_info, modules->str, (modules->len - 2));
 
1808
                g_string_append (system_info, "\n");
 
1809
                g_string_free (modules, TRUE);
 
1810
        }
 
1811
 
1696
1812
        g_object_unref (gconf_client);
1697
1813
 
1698
1814
        g_string_append (system_info, "\n");
1783
1899
        guint progress;
1784
1900
        GtkWidget *main_window;
1785
1901
        GOptionContext *context;
1786
 
        GnomeProgram *program;
1787
1902
        guint source_id;
1788
1903
        GError *err = NULL;
1789
1904
        GtkBuilder *ui = NULL;
1790
1905
                
1791
1906
        memset (&gopt_data,  0, sizeof (gopt_data));
1792
1907
 
1793
 
        bindtextdomain (PACKAGE, GNOMELOCALEDIR);
1794
 
        bind_textdomain_codeset (PACKAGE, "UTF-8");
1795
 
        textdomain (PACKAGE);
 
1908
        bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR);
 
1909
        bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
 
1910
        textdomain (GETTEXT_PACKAGE);
1796
1911
 
1797
1912
        context = g_option_context_new (N_("\n\nBug Buddy is a utility that helps report debugging\n"
1798
1913
                                          "information to the GNOME Bugzilla when a program crashes."));
1799
1914
 
1800
1915
        g_option_context_set_translation_domain (context, GETTEXT_PACKAGE);
1801
 
 
1802
1916
        g_option_context_add_main_entries (context, options, GETTEXT_PACKAGE);
1803
 
 
1804
 
        program = gnome_program_init (PACKAGE, VERSION,
1805
 
                                      LIBGNOMEUI_MODULE,
1806
 
                                      argc, argv,
1807
 
                                      GNOME_PARAM_GOPTION_CONTEXT, context,
1808
 
                                      GNOME_PARAM_APP_DATADIR, BUDDY_DATADIR,
1809
 
                                      GNOME_CLIENT_PARAM_SM_CONNECT, FALSE,
1810
 
                                      NULL);
 
1917
        g_option_context_add_group (context, gtk_get_option_group (TRUE));
 
1918
 
 
1919
        if (!g_option_context_parse (context, &argc, &argv, &err)) {
 
1920
                g_critical ("Failed to parse arguments: %s\n", err->message);
 
1921
                g_error_free (err);
 
1922
                g_option_context_free (context);
 
1923
                exit (1);
 
1924
        }
 
1925
 
 
1926
        g_option_context_free (context);
 
1927
 
 
1928
        if (!bonobo_activation_is_initialized ())
 
1929
                bonobo_activation_init (argc, argv);
1811
1930
 
1812
1931
        g_set_application_name (_("Bug Buddy"));
1813
1932
        gtk_window_set_default_icon_name ("bug-buddy");
1814
1933
 
 
1934
        s = g_build_filename (BUDDY_DATADIR, "bug-buddy.gtkbuilder", NULL);
1815
1935
 
1816
 
        s = gnome_program_locate_file (NULL, GNOME_FILE_DOMAIN_APP_DATADIR,
1817
 
                                       "bug-buddy.gtkbuilder", TRUE, NULL);
1818
 
        if (s) {
1819
 
                ui = gtk_builder_new ();
1820
 
                gtk_builder_add_from_file (ui, s, &err);
1821
 
                gtk_builder_set_translation_domain (ui, GETTEXT_PACKAGE);
1822
 
        }
 
1936
        ui = gtk_builder_new ();
 
1937
        gtk_builder_add_from_file (ui, s, &err);
 
1938
        gtk_builder_set_translation_domain (ui, GETTEXT_PACKAGE);
1823
1939
 
1824
1940
        g_free (s);
1825
1941
 
1830
1946
                if (err) {
1831
1947
                        g_error_free (err);
1832
1948
                }
1833
 
                g_object_unref (program);
1834
1949
                return 0;
1835
1950
        }
1836
1951
 
1847
1962
 
1848
1963
        if (gopt_data.app_file == NULL && gopt_data.package == NULL) {
1849
1964
                buddy_error (NULL, _("Either --appname or --package arguments are required.\n"));       
1850
 
                g_object_unref (program);
1851
1965
                return 0;
1852
1966
        }       
1853
1967
 
1855
1969
            gopt_data.include_file == NULL && 
1856
1970
            gopt_data.minidump_file == NULL) {
1857
1971
                buddy_error (NULL, _("Either --pid , --include or --minidump arguments are required.\n"));      
1858
 
                g_object_unref (program);
1859
 
                return 0;
1860
 
        }       
 
1972
                return 0;
 
1973
        }
 
1974
 
 
1975
        if (gopt_data.own_file == TRUE && gopt_data.include_file == NULL) {
 
1976
                buddy_error (NULL, _("The --unlink-tempfile option needs a --include argument.\n"));
 
1977
                return 0;
 
1978
        }
1861
1979
        
1862
1980
        /* get some information about the gnome version */
1863
1981
        gnome_version = get_gnome_version_info ();
1865
1983
                buddy_error (NULL, _("Bug Buddy was unable to retrieve information regarding "
1866
1984
                                     "the version of GNOME you are running.  This is most likely "
1867
1985
                                     "due to a missing installation of gnome-desktop.\n"));
1868
 
                g_object_unref (program);
1869
1986
                return 0;
1870
1987
        }
1871
1988
        
1873
1990
 
1874
1991
        /* connect the signal handler for the help button */
1875
1992
        g_signal_connect (gtk_builder_get_object (ui, "help-button"), "clicked", 
1876
 
                          G_CALLBACK (help_callback), program);
 
1993
                          G_CALLBACK (help_callback), NULL);
1877
1994
 
1878
1995
        gtk_widget_show (main_window);
1879
1996
 
1922
2039
                                buddy_error (NULL, _("Bug Buddy encountered the following error when trying "
1923
2040
                                                     "to retrieve debugging information: %s\n"), err->message);
1924
2041
                                g_error_free (err);
1925
 
                                g_object_unref (program);
1926
2042
                                return 0;
1927
2043
                        }
1928
2044
 
1999
2115
                        gtk_entry_set_text (GTK_ENTRY (email_entry), default_email);
2000
2116
                        g_free (default_email);
2001
2117
                }
2002
 
                g_object_set_data (G_OBJECT (ui), "type", GINT_TO_POINTER(BUG_TYPE_REQUEST));
2003
 
        }
2004
 
        
2005
 
        if (gopt_data.include_file != NULL) {
2006
 
                fill_include_file (gopt_data.include_file, ui);
 
2118
                g_object_set_data (G_OBJECT (ui), "type", GINT_TO_POINTER (BUG_TYPE_REQUEST));
2007
2119
        }
2008
2120
 
2009
 
        
2010
2121
        g_signal_connect (gtk_builder_get_object (ui, "close-button"), "clicked", 
2011
2122
                          G_CALLBACK (close_callback), ui);
2012
 
        
 
2123
 
2013
2124
        gtk_main ();
2014
2125
 
2015
 
        g_object_unref (program);
2016
 
 
2017
2126
        return 0;
2018
2127
}