summaryrefslogtreecommitdiff
path: root/crashrep/source/unx
diff options
context:
space:
mode:
Diffstat (limited to 'crashrep/source/unx')
-rwxr-xr-xcrashrep/source/unx/interface.cxx718
-rwxr-xr-xcrashrep/source/unx/interface.hxx192
-rwxr-xr-xcrashrep/source/unx/main.cxx1125
-rwxr-xr-xcrashrep/source/unx/makefile.mk81
-rwxr-xr-xcrashrep/source/unx/res.cxx140
-rwxr-xr-xcrashrep/source/unx/res/makefile.mk63
-rwxr-xr-xcrashrep/source/unx/res/unxcrashres.cxx104
7 files changed, 2423 insertions, 0 deletions
diff --git a/crashrep/source/unx/interface.cxx b/crashrep/source/unx/interface.cxx
new file mode 100755
index 000000000000..f9768ed4a5de
--- /dev/null
+++ b/crashrep/source/unx/interface.cxx
@@ -0,0 +1,718 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: interface.cxx,v $
+ * $Revision: 1.6 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#include <interface.hxx>
+#include <iostream.h>
+
+using namespace std;
+
+/*
+ * WizardPage
+ */
+WizardPage::~WizardPage()
+{
+}
+
+/*
+ * WizardDialog
+ */
+
+WizardDialog::WizardDialog()
+{
+ m_pStatusDialog = NULL;
+ m_pTopLevel = gtk_window_new( GTK_WINDOW_TOPLEVEL );
+ gtk_window_set_title( GTK_WINDOW(m_pTopLevel), StringResource::get( "%WELCOME_CAPTION%" ) );
+
+ m_pVBox = gtk_vbox_new( FALSE, 5 );
+ gtk_widget_show( m_pVBox );
+ gtk_container_add( GTK_CONTAINER(m_pTopLevel), m_pVBox );
+
+ m_pViewPort = gtk_viewport_new( NULL, NULL );
+ gtk_widget_show( m_pViewPort );
+
+ // set wizard title style
+ gtk_widget_ensure_style( m_pViewPort );
+ GtkStyle* pStyle = gtk_style_copy( gtk_widget_get_style( m_pViewPort ) );
+ for( int i = 0; i < 5; i++ )
+ {
+ pStyle->bg[i] = pStyle->white;
+ pStyle->text[i] = pStyle->black;
+ pStyle->bg_gc[i] = pStyle->white_gc;
+ pStyle->text_gc[i] = pStyle->black_gc;
+ }
+ gint nFontSize = pango_font_description_get_size( pStyle->font_desc );
+ nFontSize = nFontSize * 3 / 2;
+ pango_font_description_set_size( pStyle->font_desc, nFontSize );
+ gtk_widget_set_style( m_pViewPort, pStyle );
+ gtk_viewport_set_shadow_type( GTK_VIEWPORT(m_pViewPort), GTK_SHADOW_NONE );
+ gtk_box_pack_start( GTK_BOX(m_pVBox), m_pViewPort, FALSE, FALSE, 0 );
+
+ m_pWizardTitle = gtk_label_new( "Wizard" ); // to be replaced by resp. page titles
+ gtk_widget_show( m_pWizardTitle );
+ gtk_label_set_justify( GTK_LABEL(m_pWizardTitle), GTK_JUSTIFY_LEFT );
+ gtk_misc_set_alignment( GTK_MISC(m_pWizardTitle), 0, 1 );
+ gtk_misc_set_padding( GTK_MISC(m_pWizardTitle), 10, 10 );
+ gtk_widget_set_style( m_pWizardTitle, pStyle );
+ gtk_container_add( GTK_CONTAINER(m_pViewPort), m_pWizardTitle );
+
+ // prepare the area for the single pages
+ m_pPageArea = gtk_vbox_new( FALSE, 1);
+ gtk_widget_show( m_pPageArea );
+ gtk_box_pack_start( GTK_BOX(m_pVBox), m_pPageArea, TRUE, TRUE, 0 );
+
+ m_pSeparator = gtk_hseparator_new();
+ gtk_widget_show( m_pSeparator );
+ gtk_box_pack_start( GTK_BOX(m_pVBox), m_pSeparator, FALSE, FALSE, 0 );
+
+ m_pButtonBox = gtk_hbutton_box_new();
+ gtk_widget_show( m_pButtonBox );
+ gtk_box_pack_start( GTK_BOX(m_pVBox), m_pButtonBox, FALSE, FALSE, 0 );
+ gtk_button_box_set_layout( GTK_BUTTON_BOX(m_pButtonBox), GTK_BUTTONBOX_END );
+ gtk_button_box_set_spacing( GTK_BUTTON_BOX(m_pButtonBox), 0 );
+
+ m_pBackButton = gtk_button_new_with_mnemonic( StringResource::get( "%BACK_BUTTON%" ) );
+ gtk_widget_show( m_pBackButton );
+ gtk_container_add( GTK_CONTAINER(m_pButtonBox), m_pBackButton );
+ gtk_container_set_border_width( GTK_CONTAINER(m_pBackButton), 5 );
+ GTK_WIDGET_SET_FLAGS( m_pBackButton, GTK_CAN_DEFAULT );
+
+ m_pNextButton = gtk_button_new_with_mnemonic( StringResource::get( "%NEXT_BUTTON%" ) );
+ gtk_widget_show( m_pNextButton );
+ gtk_container_add( GTK_CONTAINER(m_pButtonBox), m_pNextButton );
+ gtk_container_set_border_width( GTK_CONTAINER(m_pNextButton), 5 );
+ GTK_WIDGET_SET_FLAGS( m_pNextButton, GTK_CAN_DEFAULT );
+
+ m_pSendButton = gtk_button_new_with_mnemonic( StringResource::get( "%SEND_BUTTON%" ) );
+ gtk_widget_show( m_pSendButton );
+ gtk_container_add( GTK_CONTAINER(m_pButtonBox), m_pSendButton );
+ gtk_container_set_border_width( GTK_CONTAINER(m_pSendButton), 5 );
+ GTK_WIDGET_SET_FLAGS( m_pSendButton, GTK_CAN_DEFAULT );
+
+ m_pCancelButton = gtk_button_new_with_mnemonic( StringResource::get( "%DONOT_SEND_BUTTON%" ) );
+ gtk_widget_show( m_pCancelButton );
+ gtk_container_add( GTK_CONTAINER(m_pButtonBox), m_pCancelButton );
+ gtk_container_set_border_width( GTK_CONTAINER(m_pCancelButton), 5 );
+ GTK_WIDGET_SET_FLAGS( m_pCancelButton, GTK_CAN_DEFAULT );
+
+ gtk_signal_connect( GTK_OBJECT(m_pTopLevel), "delete-event", G_CALLBACK(gtk_main_quit), NULL );
+ gtk_signal_connect( GTK_OBJECT(m_pCancelButton), "clicked", G_CALLBACK(gtk_main_quit), NULL );
+ gtk_signal_connect( GTK_OBJECT(m_pNextButton), "clicked", G_CALLBACK(button_clicked), this );
+ gtk_signal_connect( GTK_OBJECT(m_pBackButton), "clicked", G_CALLBACK(button_clicked), this );
+ gtk_signal_connect( GTK_OBJECT(m_pSendButton), "clicked", G_CALLBACK(button_clicked), this );
+ gtk_widget_set_sensitive( m_pSendButton, FALSE );
+
+ m_nCurrentPage = -1;
+}
+
+WizardDialog::~WizardDialog()
+{
+ int nPages = m_aPages.size();
+ while( nPages-- )
+ delete m_aPages[nPages];
+}
+
+void WizardDialog::show_messagebox( const std::string& rMessage )
+{
+ GtkWidget* messagebox = NULL;
+ GtkMessageType eType = GTK_MESSAGE_ERROR;
+
+ messagebox = gtk_message_dialog_new( NULL,
+ (GtkDialogFlags)0,
+ eType,
+ GTK_BUTTONS_OK,
+ rMessage.c_str(),
+ NULL
+ );
+
+ gtk_dialog_run( GTK_DIALOG(messagebox) );
+ gtk_widget_destroy( GTK_WIDGET(messagebox) );
+}
+
+
+
+// bInProgress: true=sending, false=finished
+gint WizardDialog::show_sendingstatus( bool bInProgress )
+{
+ m_pStatusDialog = gtk_dialog_new_with_buttons( StringResource::get( "%SENDING_REPORT_HEADER%" ),
+ getTopLevel(),
+ GTK_DIALOG_MODAL,
+ bInProgress ? GTK_STOCK_CANCEL : GTK_STOCK_OK,
+ bInProgress ? GTK_RESPONSE_REJECT : GTK_RESPONSE_OK,
+ NULL );
+
+ gtk_window_set_default_size( GTK_WINDOW(m_pStatusDialog), 350, 130 );
+
+ GtkWidget *pLabel = gtk_label_new( bInProgress ? StringResource::get( "%SENDING_REPORT_STATUS%" ) :
+ StringResource::get( "%SENDING_REPORT_STATUS_FINISHED%" ) );
+ gtk_widget_show( pLabel );
+ gtk_label_set_justify( GTK_LABEL(pLabel), GTK_JUSTIFY_CENTER);
+ gtk_misc_set_alignment( GTK_MISC(pLabel), 0, 0 );
+
+ gtk_container_add( GTK_CONTAINER(GTK_DIALOG(m_pStatusDialog)->vbox), pLabel );
+
+ gint ret = gtk_dialog_run( GTK_DIALOG(m_pStatusDialog) );
+ gtk_widget_destroy( m_pStatusDialog );
+ m_pStatusDialog = NULL;
+
+ return ret;
+}
+
+void WizardDialog::hide_sendingstatus()
+{
+ if( m_pStatusDialog )
+ {
+ gtk_dialog_response( GTK_DIALOG(m_pStatusDialog), GTK_RESPONSE_OK );
+
+ XEvent event;
+
+ memset( &event, 0, sizeof(event) );
+
+ event.xexpose.type = Expose;
+ event.xexpose.display = GDK_DISPLAY();
+ event.xexpose.window = GDK_WINDOW_XWINDOW( m_pStatusDialog->window );
+ event.xexpose.width = event.xexpose.height = 10;
+
+ XSendEvent(
+ GDK_DISPLAY(),
+ GDK_WINDOW_XWINDOW( m_pStatusDialog->window ),
+ True,
+ ExposureMask,
+ &event );
+
+ XFlush( GDK_DISPLAY() );
+ }
+}
+
+
+gint WizardDialog::button_clicked( GtkWidget* pButton, WizardDialog* pThis )
+{
+ if( pButton == pThis->m_pNextButton )
+ pThis->nextPage();
+ else if( pButton == pThis->m_pBackButton )
+ pThis->lastPage();
+ else if( pButton == pThis->m_pSendButton )
+ {
+ if( pThis->m_nCurrentPage != -1 )
+ pThis->m_aPages[pThis->m_nCurrentPage]->update();
+
+ if( send_crash_report( pThis, pThis->getSettings() ) )
+ gtk_main_quit();
+ }
+
+ return 0;
+}
+
+void WizardDialog::insertPage( WizardPage* pPage )
+{
+ m_aPages.push_back( pPage );
+ if( m_nCurrentPage == -1 )
+ {
+ m_nCurrentPage = 0;
+ gtk_label_set_text( GTK_LABEL(m_pWizardTitle), pPage->getTitle() );
+ gtk_box_pack_start( GTK_BOX(m_pPageArea), pPage->getContents(), TRUE, TRUE, 0 );
+ gtk_widget_set_sensitive( m_pNextButton, FALSE );
+ gtk_widget_set_sensitive( m_pBackButton, FALSE );
+ }
+ else
+ {
+ gtk_widget_set_sensitive( m_pNextButton, TRUE );
+ }
+}
+
+void WizardDialog::nextPage()
+{
+ if( m_aPages.empty() || m_nCurrentPage >= (int)m_aPages.size()-1 )
+ return;
+
+ m_aPages[m_nCurrentPage]->update();
+
+ gtk_container_remove( GTK_CONTAINER(m_pPageArea), m_aPages[m_nCurrentPage]->getContents() );
+ m_nCurrentPage++;
+ gtk_label_set_text( GTK_LABEL(m_pWizardTitle), m_aPages[m_nCurrentPage]->getTitle() );
+ gtk_box_pack_start( GTK_BOX(m_pPageArea), m_aPages[m_nCurrentPage]->getContents(), TRUE, TRUE, 0 );
+
+ if( m_nCurrentPage == (int)m_aPages.size()-1 )
+ {
+ gtk_widget_set_sensitive( m_pNextButton, FALSE );
+ gtk_widget_set_sensitive( m_pSendButton, TRUE );
+ }
+ if( m_aPages.size() > 1 )
+ gtk_widget_set_sensitive( m_pBackButton, TRUE );
+}
+
+void WizardDialog::lastPage()
+{
+ if( m_aPages.empty() || m_nCurrentPage <= 0 )
+ return;
+
+ m_aPages[m_nCurrentPage]->update();
+
+ gtk_container_remove( GTK_CONTAINER(m_pPageArea), m_aPages[m_nCurrentPage]->getContents() );
+ m_nCurrentPage--;
+ gtk_label_set_text( GTK_LABEL(m_pWizardTitle), m_aPages[m_nCurrentPage]->getTitle() );
+ gtk_box_pack_start( GTK_BOX(m_pPageArea), m_aPages[m_nCurrentPage]->getContents(), TRUE, TRUE, 0 );
+
+ if( m_nCurrentPage == 0 )
+ gtk_widget_set_sensitive( m_pBackButton, FALSE );
+ if( m_aPages.size() > 1 )
+ gtk_widget_set_sensitive( m_pNextButton, TRUE );
+}
+
+void WizardDialog::show( bool bShow )
+{
+ if( bShow )
+ gtk_widget_show( m_pTopLevel );
+ else
+ gtk_widget_hide( m_pTopLevel );
+}
+
+/*
+ * MainPage
+ */
+
+MainPage::MainPage( WizardDialog* pParent ) : WizardPage( pParent )
+{
+ hash_map< string, string >& rSettings = m_pDialog->getSettings();
+ m_aWizardTitle = StringResource::get( "%REPORT_HEADER%" );
+
+ m_pPageContents = gtk_vbox_new( FALSE, 0 );
+ gtk_widget_show( m_pPageContents );
+
+ m_pInfo = gtk_label_new( StringResource::get( "%REPORT_BODY%" ) );
+ gtk_widget_show( m_pInfo );
+ gtk_label_set_line_wrap( GTK_LABEL(m_pInfo), TRUE );
+ gtk_label_set_justify( GTK_LABEL(m_pInfo), GTK_JUSTIFY_LEFT);
+ gtk_misc_set_alignment( GTK_MISC(m_pInfo), 0, 1 );
+ gtk_misc_set_padding( GTK_MISC(m_pInfo ), 5, 5);
+ gtk_box_pack_start( GTK_BOX(m_pPageContents), m_pInfo, FALSE, FALSE, 0 );
+
+ m_pHBox = gtk_hbox_new( FALSE, 0 );
+ gtk_widget_show( m_pHBox );
+ gtk_box_pack_start( GTK_BOX(m_pPageContents), m_pHBox, TRUE, TRUE, 0 );
+
+ m_pLeftColumn = gtk_vbox_new( FALSE, 5 );
+ gtk_widget_show( m_pLeftColumn );
+ gtk_container_set_border_width( GTK_CONTAINER(m_pLeftColumn), 5 );
+ gtk_box_pack_start( GTK_BOX(m_pHBox), m_pLeftColumn, TRUE, TRUE, 0 );
+
+ m_pRightColumn = gtk_vbutton_box_new();
+ gtk_widget_show( m_pRightColumn );
+ gtk_button_box_set_layout( GTK_BUTTON_BOX(m_pRightColumn), GTK_BUTTONBOX_END );
+ gtk_box_pack_start( GTK_BOX(m_pHBox), m_pRightColumn, FALSE, FALSE, 0 );
+
+ m_pEditLabel = gtk_label_new_with_mnemonic( StringResource::get( "%ENTER_TITLE%" ) );
+ gtk_widget_show( m_pEditLabel );
+ gtk_label_set_justify( GTK_LABEL(m_pEditLabel), GTK_JUSTIFY_LEFT);
+ gtk_misc_set_alignment( GTK_MISC(m_pEditLabel), 0, 1 );
+ gtk_box_pack_start( GTK_BOX(m_pLeftColumn), m_pEditLabel, FALSE, FALSE, 0 );
+
+ m_pEdit = gtk_entry_new();
+ gtk_widget_show( m_pEdit );
+ gtk_box_pack_start( GTK_BOX(m_pLeftColumn), m_pEdit, FALSE, FALSE, 0 );
+
+ gtk_label_set_mnemonic_widget( GTK_LABEL(m_pEditLabel), m_pEdit );
+
+ hash_map<string, string>::iterator aIter;
+ aIter = rSettings.find( "TITLE" );
+ if( aIter != rSettings.end() )
+ gtk_entry_set_text( GTK_ENTRY(m_pEdit), aIter->second.c_str() );
+
+ m_pEntryVBox = gtk_vbox_new( FALSE, 5 );
+ gtk_widget_show( m_pEntryVBox );
+ gtk_box_pack_start( GTK_BOX(m_pLeftColumn), m_pEntryVBox, TRUE, TRUE, 0 );
+
+ m_pEntryLabel = gtk_label_new_with_mnemonic( StringResource::get( "%ENTER_DESCRIPTION%" ) );
+ gtk_widget_show( m_pEntryLabel );
+ gtk_label_set_justify( GTK_LABEL(m_pEntryLabel), GTK_JUSTIFY_LEFT);
+ gtk_misc_set_alignment( GTK_MISC(m_pEntryLabel), 0, 1 );
+ gtk_box_pack_start( GTK_BOX(m_pEntryVBox), m_pEntryLabel, FALSE, FALSE, 0 );
+
+ m_pScrolledEntry = gtk_scrolled_window_new( NULL, NULL );
+ gtk_widget_show( m_pScrolledEntry );
+ gtk_scrolled_window_set_shadow_type( GTK_SCROLLED_WINDOW(m_pScrolledEntry), GTK_SHADOW_IN );
+ gtk_box_pack_start( GTK_BOX(m_pEntryVBox), m_pScrolledEntry, TRUE, TRUE, 0 );
+
+ m_pEntry = gtk_text_view_new();
+ gtk_widget_show( m_pEntry );
+ gtk_text_view_set_wrap_mode( GTK_TEXT_VIEW(m_pEntry), GTK_WRAP_WORD );
+ gtk_container_add( GTK_CONTAINER(m_pScrolledEntry), m_pEntry );
+
+ aIter = rSettings.find( "DESCRIPTION" );
+ if( aIter != rSettings.end() )
+ {
+ GtkTextBuffer* pBuffer = gtk_text_view_get_buffer( GTK_TEXT_VIEW(m_pEntry) );
+ gtk_text_buffer_set_text( pBuffer, aIter->second.c_str(), -1 );
+ }
+
+
+ gtk_label_set_mnemonic_widget( GTK_LABEL(m_pEntryLabel), m_pEntry );
+
+ m_pDetails = gtk_button_new_with_mnemonic( StringResource::get( "%SHOW_REPORT_BUTTON%" ) );
+ gtk_widget_show(m_pDetails);
+ gtk_container_set_border_width( GTK_CONTAINER(m_pDetails), 5 );
+ gtk_container_add( GTK_CONTAINER(m_pRightColumn), m_pDetails );
+
+ m_pOptions = gtk_button_new_with_mnemonic( StringResource::get( "%OPTIONS_BUTTON%" ) );
+ gtk_widget_show(m_pOptions);
+ gtk_container_set_border_width( GTK_CONTAINER(m_pOptions), 5 );
+ gtk_container_add( GTK_CONTAINER(m_pRightColumn), m_pOptions );
+
+ // check env var for save button
+ const char *szUserType = getenv( "STAROFFICE_USERTYPE" );
+ if( szUserType && *szUserType )
+ {
+ m_pSave = gtk_button_new_with_mnemonic( StringResource::get( "%SAVE_REPORT_BUTTON%" ) );
+ gtk_widget_show(m_pSave);
+ gtk_container_set_border_width( GTK_CONTAINER(m_pSave), 5 );
+ gtk_container_add( GTK_CONTAINER(m_pRightColumn), m_pSave );
+ }
+ else
+ m_pSave = NULL;
+
+
+ m_pCheck = gtk_check_button_new_with_mnemonic( StringResource::get( "%ALLOW_CONTACT%" ) );
+ gtk_widget_show( m_pCheck );
+ gtk_container_set_border_width( GTK_CONTAINER(m_pCheck), 5 );
+ //gtk_box_pack_start( GTK_BOX(m_pPageContents), m_pCheck, FALSE, FALSE, 5 );
+ gtk_box_pack_start( GTK_BOX(m_pLeftColumn), m_pCheck, FALSE, FALSE, 5 );
+
+ aIter = rSettings.find( "CONTACT" );
+ if( aIter != rSettings.end() )
+ {
+ const char *str = aIter->second.c_str();
+ if( str && !strcasecmp(str, "true") )
+ gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(m_pCheck), TRUE );
+ }
+
+ m_pAddressLabel = gtk_label_new_with_mnemonic( StringResource::get( "%ENTER_EMAIL%" ) );
+ gtk_widget_show( m_pAddressLabel );
+ gtk_label_set_justify( GTK_LABEL(m_pAddressLabel), GTK_JUSTIFY_LEFT);
+ gtk_misc_set_alignment( GTK_MISC(m_pAddressLabel), 0, 1 );
+ gtk_box_pack_start( GTK_BOX(m_pLeftColumn), m_pAddressLabel, FALSE, FALSE, 5 );
+
+ m_pAddress = gtk_entry_new();
+ gtk_widget_show( m_pAddress );
+ gtk_box_pack_start( GTK_BOX(m_pLeftColumn), m_pAddress, FALSE, FALSE, 5 );
+
+ aIter = rSettings.find( "EMAIL" );
+ if( aIter != rSettings.end() )
+ gtk_entry_set_text( GTK_ENTRY(m_pAddress), aIter->second.c_str() );
+
+ gtk_signal_connect( GTK_OBJECT(m_pDetails), "clicked", G_CALLBACK(button_clicked), this );
+ gtk_signal_connect( GTK_OBJECT(m_pOptions), "clicked", G_CALLBACK(button_clicked), this );
+ if(m_pSave) // optional
+ gtk_signal_connect( GTK_OBJECT(m_pSave), "clicked", G_CALLBACK(button_clicked), this );
+
+ gtk_signal_connect( GTK_OBJECT(m_pCheck), "toggled", G_CALLBACK(button_toggled), this );
+ button_toggled( m_pCheck, this );
+
+ g_object_ref( G_OBJECT(m_pPageContents) );
+}
+
+MainPage::~MainPage()
+{
+ g_object_unref( G_OBJECT(m_pPageContents) );
+}
+
+void MainPage::update()
+{
+ hash_map< string, string >& rSettings = m_pDialog->getSettings();
+
+ GtkTextIter start, end;
+ GtkTextBuffer* pTextBuffer = gtk_text_view_get_buffer( GTK_TEXT_VIEW(m_pEntry) );
+ gtk_text_buffer_get_bounds( pTextBuffer, &start, &end );
+ rSettings[ "DESCRIPTION" ] = gtk_text_buffer_get_text( pTextBuffer, &start, &end, 1 );
+ rSettings[ "TITLE" ] = gtk_entry_get_text( GTK_ENTRY(m_pEdit) );
+ rSettings[ "CONTACT" ] = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(m_pCheck) ) ? "true" : "false";
+ rSettings[ "EMAIL" ] = gtk_entry_get_text( GTK_ENTRY(m_pAddress) );
+}
+
+gint MainPage::button_toggled( GtkWidget* pButton, MainPage* pThis )
+{
+ if ( GTK_TOGGLE_BUTTON (pThis->m_pCheck)->active )
+ {
+ gtk_widget_set_sensitive( pThis->m_pAddressLabel, TRUE);
+ gtk_widget_set_sensitive( pThis->m_pAddress, TRUE);
+ }
+ else
+ {
+ gtk_widget_set_sensitive( pThis->m_pAddressLabel, FALSE);
+ gtk_widget_set_sensitive( pThis->m_pAddress, FALSE);
+ }
+ return 0;
+}
+
+gint MainPage::button_clicked( GtkWidget* pButton, MainPage* pThis )
+{
+ if( pButton == pThis->m_pSave )
+ {
+ GtkWidget* pFile = gtk_file_selection_new( StringResource::get( "%SAVE_REPORT_TITLE%" ) );
+ gint nRet = gtk_dialog_run( GTK_DIALOG(pFile) );
+ if( nRet == GTK_RESPONSE_OK )
+ {
+ string aFile = gtk_file_selection_get_filename( GTK_FILE_SELECTION(pFile) );
+ pThis->update();
+ if( save_crash_report( aFile, pThis->m_pDialog->getSettings() ) )
+ {
+ // gtk_main_quit();
+ }
+ }
+ gtk_widget_destroy( pFile );
+ }
+ else if( pButton == pThis->m_pDetails )
+ {
+ pThis->update();
+
+ GtkWidget* pDialog = gtk_dialog_new_with_buttons( StringResource::get( "%REPORT_CAPTION%" ),
+ pThis->m_pDialog->getTopLevel(),
+ GTK_DIALOG_MODAL,
+ GTK_STOCK_OK,
+ GTK_RESPONSE_OK,
+ NULL );
+
+ gtk_window_set_default_size( GTK_WINDOW(pDialog), 500, 300 );
+ GtkWidget* pScroll = gtk_scrolled_window_new( NULL, NULL );
+ gtk_widget_show( pScroll );
+ gtk_scrolled_window_set_shadow_type( GTK_SCROLLED_WINDOW(pScroll), GTK_SHADOW_IN );
+ gtk_container_add( GTK_CONTAINER(GTK_DIALOG(pDialog)->vbox), pScroll );
+
+ string aText = crash_get_details( pThis->m_pDialog->getSettings() );
+ GtkWidget* pView = gtk_text_view_new();
+ gtk_widget_show( pView );
+ gtk_text_view_set_wrap_mode( GTK_TEXT_VIEW(pView), GTK_WRAP_WORD );
+ gtk_text_view_set_editable( GTK_TEXT_VIEW(pView), FALSE );
+ GtkTextBuffer* pBuffer = gtk_text_view_get_buffer( GTK_TEXT_VIEW(pView) );
+ gtk_text_buffer_set_text( pBuffer, aText.data(), aText.size() );
+ gtk_container_add( GTK_CONTAINER(pScroll), pView );
+
+ gtk_dialog_run( GTK_DIALOG(pDialog) );
+ gtk_widget_destroy( pDialog );
+ }
+ else if( pButton == pThis->m_pOptions )
+ {
+ OptionsDialog aOptions( pThis->m_pDialog->getTopLevel(), pThis->m_pDialog->getSettings() );
+ //pThis->m_pDialog->show_sendingstatus( true );
+ //pThis->m_pDialog->show_sendingstatus( false );
+ //sleep(5);
+ //pThis->m_pDialog->hide_sendingstatus();
+ }
+
+ return 0;
+}
+
+/*
+ * OptionsDialog (Proxy-Settings)
+ */
+
+OptionsDialog::OptionsDialog( GtkWindow *pParent ,hash_map< string, string >& rSettings )
+{
+ m_pDialog = gtk_dialog_new_with_buttons( StringResource::get( "%OPTIONS_TITLE%" ),
+ pParent,
+ GTK_DIALOG_MODAL,
+ GTK_STOCK_OK, GTK_RESPONSE_OK,
+ GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
+ NULL );
+
+ gtk_window_set_default_size( GTK_WINDOW(m_pDialog), 500, 300 );
+
+ m_pPage = gtk_vbox_new( FALSE, 0 );
+ m_pLeftColumn = gtk_vbox_new( FALSE, 5 );
+
+ gtk_widget_show( m_pPage );
+ gtk_widget_show( m_pLeftColumn );
+
+ gtk_container_add( GTK_CONTAINER(GTK_DIALOG(m_pDialog)->vbox), m_pPage );
+
+ gtk_container_set_border_width( GTK_CONTAINER(m_pLeftColumn), 5 );
+ gtk_box_pack_start( GTK_BOX(m_pPage), m_pLeftColumn, FALSE, FALSE, 5 );
+
+ // frame for proxy settings
+ m_pFrame = gtk_frame_new(StringResource::get( "%PROXY_SETTINGS_HEADER%" ));
+ gtk_frame_set_shadow_type( GTK_FRAME(m_pFrame), GTK_SHADOW_ETCHED_IN );
+ gtk_widget_show(m_pFrame);
+ gtk_box_pack_start(GTK_BOX (m_pLeftColumn), m_pFrame, TRUE, TRUE, 0);
+
+ m_pVBox = gtk_vbox_new( FALSE, 0 );
+ gtk_widget_show( m_pVBox );
+ gtk_container_add( GTK_CONTAINER( m_pFrame ), m_pVBox );
+
+ // the radio buttons
+ m_pDirect = gtk_radio_button_new_with_mnemonic( NULL,
+ StringResource::get( "%PROXY_SETTINGS_DIRECT%" ) );
+ gtk_widget_show(m_pDirect);
+ gtk_box_pack_start(GTK_BOX (m_pVBox), m_pDirect, FALSE, FALSE, 0);
+
+ m_pManual = gtk_radio_button_new_with_mnemonic( gtk_radio_button_group( GTK_RADIO_BUTTON(m_pDirect) ),
+ StringResource::get( "%PROXY_SETTINGS_MANUAL%" ) );
+ gtk_widget_show(m_pManual);
+ gtk_box_pack_start(GTK_BOX (m_pVBox), m_pManual, FALSE, FALSE, 0);
+
+ hash_map<string, string>::iterator aIter;
+ const char *str = NULL;
+ aIter = rSettings.find( "USEPROXY" );
+ if( aIter != rSettings.end() )
+ str = aIter->second.c_str();
+ if( str && !strcasecmp(str, "true") )
+ gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(m_pManual), TRUE );
+ else
+ gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(m_pDirect), TRUE );
+
+ // the server and port edit controls
+ m_pHBox = gtk_hbox_new( FALSE, 0 );
+ gtk_widget_show( m_pHBox );
+ gtk_box_pack_start(GTK_BOX (m_pVBox), m_pHBox, FALSE, FALSE, 10);
+
+ m_pVBoxServer = gtk_vbox_new( FALSE, 5 );
+ gtk_widget_show( m_pVBoxServer );
+ gtk_box_pack_start(GTK_BOX (m_pHBox), m_pVBoxServer, TRUE, TRUE, 10);
+
+ m_pVBoxPort = gtk_vbox_new( FALSE, 5 );
+ gtk_widget_show( m_pVBoxPort );
+ gtk_box_pack_start(GTK_BOX (m_pHBox), m_pVBoxPort, FALSE, FALSE, 10);
+
+ m_pServerLabel = gtk_label_new_with_mnemonic( StringResource::get( "%PROXY_SETTINGS_ADDRESS%" ) );
+ gtk_widget_show( m_pServerLabel );
+ gtk_label_set_justify( GTK_LABEL(m_pServerLabel), GTK_JUSTIFY_LEFT);
+ gtk_misc_set_alignment( GTK_MISC(m_pServerLabel), 0, 1 );
+ gtk_box_pack_start( GTK_BOX(m_pVBoxServer), m_pServerLabel, FALSE, FALSE, 0 );
+
+ m_pServer = gtk_entry_new();
+ gtk_widget_show( m_pServer );
+ gtk_box_pack_start( GTK_BOX(m_pVBoxServer), m_pServer, FALSE, FALSE, 0 );
+ gtk_label_set_mnemonic_widget( GTK_LABEL(m_pServerLabel), m_pServer );
+ aIter = rSettings.find( "SERVER" );
+ if( aIter != rSettings.end() )
+ gtk_entry_set_text( GTK_ENTRY(m_pServer), aIter->second.c_str() );
+
+ m_pPortLabel = gtk_label_new_with_mnemonic( StringResource::get( "%PROXY_SETTINGS_PORT%" ) );
+ gtk_widget_show( m_pPortLabel );
+ gtk_label_set_justify( GTK_LABEL(m_pPortLabel), GTK_JUSTIFY_LEFT);
+ gtk_misc_set_alignment( GTK_MISC(m_pPortLabel), 0, 1 );
+ gtk_box_pack_start( GTK_BOX(m_pVBoxPort), m_pPortLabel, FALSE, FALSE, 0 );
+
+ m_pPort = gtk_entry_new();
+ gtk_widget_show( m_pPort );
+ gtk_box_pack_start( GTK_BOX(m_pVBoxPort), m_pPort, FALSE, FALSE, 0 );
+ gtk_label_set_mnemonic_widget( GTK_LABEL(m_pPortLabel), m_pPort );
+ aIter = rSettings.find( "PORT" );
+ if( aIter != rSettings.end() )
+ gtk_entry_set_text( GTK_ENTRY(m_pPort), aIter->second.c_str() );
+
+ // help text
+ m_pNote = gtk_label_new( StringResource::get( "%PROXY_SETTINGS_DESCRIPTION%" ) );
+ gtk_widget_show( m_pNote );
+ gtk_label_set_justify( GTK_LABEL(m_pNote), GTK_JUSTIFY_LEFT);
+ gtk_misc_set_alignment( GTK_MISC(m_pNote), 0, 1 );
+ gtk_box_pack_start(GTK_BOX (m_pLeftColumn), m_pNote, FALSE, FALSE, 5);
+ gtk_label_set_line_wrap (GTK_LABEL (m_pNote), TRUE);
+
+
+ gtk_signal_connect( GTK_OBJECT(m_pDirect), "toggled", G_CALLBACK(button_toggled), this );
+ gtk_signal_connect( GTK_OBJECT(m_pManual), "toggled", G_CALLBACK(button_toggled), this );
+
+ button_toggled( m_pDirect, this );
+
+ if( gtk_dialog_run( GTK_DIALOG(m_pDialog) ) == GTK_RESPONSE_OK )
+ {
+ rSettings[ "SERVER" ] = getServer();
+ rSettings[ "PORT" ] = getPort();
+ rSettings[ "USEPROXY" ] = getUseProxy();
+ }
+ g_object_ref( G_OBJECT(m_pDialog) );
+}
+
+OptionsDialog::~OptionsDialog()
+{
+ gtk_widget_destroy( m_pDialog );
+ g_object_unref( G_OBJECT(m_pDialog) );
+}
+
+gint OptionsDialog::button_toggled( GtkWidget* pButton, OptionsDialog* pThis )
+{
+ if ( GTK_TOGGLE_BUTTON (pThis->m_pManual)->active )
+ {
+ gtk_widget_set_sensitive( pThis->m_pServerLabel, TRUE);
+ gtk_widget_set_sensitive( pThis->m_pServer, TRUE);
+ gtk_widget_set_sensitive( pThis->m_pPortLabel, TRUE);
+ gtk_widget_set_sensitive( pThis->m_pPort, TRUE);
+ }
+ else
+ {
+ gtk_widget_set_sensitive( pThis->m_pServerLabel, FALSE);
+ gtk_widget_set_sensitive( pThis->m_pServer, FALSE);
+ gtk_widget_set_sensitive( pThis->m_pPortLabel, FALSE);
+ gtk_widget_set_sensitive( pThis->m_pPort, FALSE);
+ }
+
+ return 0;
+}
+
+string OptionsDialog::getUseProxy()
+{
+ return gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(m_pDirect) ) ? "false" : "true";
+}
+string OptionsDialog::getServer()
+{
+ return gtk_entry_get_text( GTK_ENTRY(m_pServer) );
+}
+string OptionsDialog::getPort()
+{
+ return gtk_entry_get_text( GTK_ENTRY(m_pPort) );
+}
+
+/*
+ * WelcomePage
+ */
+WelcomePage::WelcomePage( WizardDialog* pParent ) : WizardPage( pParent )
+{
+ m_aWizardTitle = StringResource::get( "%WELCOME_HEADER%" );
+
+ string aBody = StringResource::get( "%WELCOME_BODY1%" );
+ aBody += StringResource::get( "%WELCOME_BODY2%" );
+ aBody += StringResource::get( "%WELCOME_BODY3%" );
+ aBody += "\n\n";
+ aBody += StringResource::get( "%PRIVACY_URL%" );
+ m_pPageContents = gtk_label_new( aBody.c_str() );
+ gtk_widget_show( m_pPageContents );
+ gtk_label_set_line_wrap( GTK_LABEL(m_pPageContents), TRUE );
+ gtk_label_set_justify( GTK_LABEL(m_pPageContents), GTK_JUSTIFY_LEFT);
+ gtk_misc_set_alignment( GTK_MISC(m_pPageContents), 0, 1 );
+ gtk_misc_set_padding( GTK_MISC(m_pPageContents ), 5, 5);
+
+ g_object_ref( G_OBJECT(m_pPageContents) );
+}
+
+WelcomePage::~WelcomePage()
+{
+ g_object_unref( G_OBJECT(m_pPageContents) );
+}
+
+void WelcomePage::update()
+{
+}
diff --git a/crashrep/source/unx/interface.hxx b/crashrep/source/unx/interface.hxx
new file mode 100755
index 000000000000..ad80c218fa65
--- /dev/null
+++ b/crashrep/source/unx/interface.hxx
@@ -0,0 +1,192 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: interface.hxx,v $
+ * $Revision: 1.6 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdio.h>
+
+#include <gdk/gdkkeysyms.h>
+#include <gtk/gtk.h>
+#include <gdk/gdk.h>
+#include <gdk/gdkx.h>
+
+#include <X11/Xlib.h>
+
+#include <hash_map>
+#include <vector>
+#include <string>
+
+class WizardDialog;
+
+// returns success, on true application will quit
+bool save_crash_report( const std::string& rFileName, const std::hash_map< std::string, std::string >& rSettings );
+// returns success, on true application will quit
+bool send_crash_report( WizardDialog *pDialog, const std::hash_map< std::string, std::string >& rSettings );
+// must return a valid UTF8 string containing the message that will be sent
+std::string crash_get_details( const std::hash_map< std::string, std::string >& rSettings );
+
+class StringResource
+{
+public:
+ static void init( int argc, char** argv );
+ static const char* get( const char* pKey );
+};
+
+class WizardPage
+{
+protected:
+ std::string m_aWizardTitle;
+ GtkWidget* m_pPageContents;
+ WizardDialog* m_pDialog;
+public:
+ WizardPage( WizardDialog* pDialog ) : m_pDialog( pDialog ) {}
+ virtual ~WizardPage();
+
+ const char* getTitle() const { return m_aWizardTitle.c_str(); }
+ GtkWidget* getContents() const { return m_pPageContents; }
+
+ virtual void update() = 0;
+};
+
+class WizardDialog
+{
+ std::vector< WizardPage* > m_aPages;
+ int m_nCurrentPage;
+
+ GtkWidget* m_pTopLevel;
+ GtkWidget* m_pVBox;
+ GtkWidget* m_pViewPort;
+ GtkWidget* m_pWizardTitle;
+ GtkWidget* m_pPageArea;
+ GtkWidget* m_pSeparator;
+ GtkWidget* m_pButtonBox;
+ GtkWidget* m_pBackButton;
+ GtkWidget* m_pNextButton;
+ GtkWidget* m_pSendButton;
+ GtkWidget* m_pCancelButton;
+
+ GtkWidget* m_pStatusDialog;
+
+ std::hash_map< std::string, std::string > m_aSettings;
+
+ static gint button_clicked( GtkWidget* pButton, WizardDialog* pThis );
+
+ void nextPage();
+ void lastPage();
+public:
+ WizardDialog();
+ ~WizardDialog();
+
+ // takes ownership of page
+ void insertPage( WizardPage* pPage );
+
+ void show( bool bShow = true );
+ void show_messagebox( const std::string& rMessage );
+ gint show_sendingstatus( bool bInProgress );
+ void hide_sendingstatus();
+
+ std::hash_map< std::string, std::string >& getSettings() { return m_aSettings; }
+ GtkWindow* getTopLevel() const { return GTK_WINDOW(m_pTopLevel); }
+};
+
+class MainPage : public WizardPage
+{
+ GtkWidget* m_pInfo;
+ GtkWidget* m_pEditLabel;
+ GtkWidget* m_pEdit;
+ GtkWidget* m_pEntryLabel;
+ GtkWidget* m_pEntryVBox;
+ GtkWidget* m_pScrolledEntry;
+ GtkWidget* m_pEntry;
+ GtkWidget* m_pHBox;
+ GtkWidget* m_pRightColumn;
+ GtkWidget* m_pLeftColumn;
+ GtkWidget* m_pDetails;
+ GtkWidget* m_pSave;
+ GtkWidget* m_pCheck;
+ GtkWidget* m_pOptions;
+ GtkWidget* m_pAddressLabel;
+ GtkWidget* m_pAddress;
+
+ static gint button_clicked( GtkWidget* pButton, MainPage* pThis );
+ static gint button_toggled( GtkWidget* pButton, MainPage* pThis );
+
+public:
+ MainPage( WizardDialog* );
+ virtual ~MainPage();
+
+ virtual void update();
+};
+
+class WelcomePage : public WizardPage
+{
+public:
+ WelcomePage( WizardDialog* );
+ virtual ~WelcomePage();
+
+ virtual void update();
+};
+
+class OptionsDialog
+{
+ GtkWidget* m_pDialog;
+ GtkWidget* m_pPage;
+ GtkWidget* m_pLeftColumn;
+ GtkWidget* m_pFrame;
+ GtkWidget* m_pDirect;
+ GtkWidget* m_pManual;
+ GtkWidget* m_pServerLabel;
+ GtkWidget* m_pServer;
+ GtkWidget* m_pColon;
+ GtkWidget* m_pPortLabel;
+ GtkWidget* m_pPort;
+ GtkWidget* m_pNote;
+ GtkWidget* m_pOkButton;
+ GtkWidget* m_pCancelButton;
+ GtkWidget* m_pButtonBox;
+ GtkWidget* m_pVBox;
+ GtkWidget* m_pHBox;
+ GtkWidget* m_pVBoxServer;
+ GtkWidget* m_pVBoxPort;
+
+ static gint button_toggled( GtkWidget* pButton, OptionsDialog* pThis );
+
+public:
+ OptionsDialog( GtkWindow* pParent,
+ std::hash_map< std::string, std::string >& rSettings );
+ virtual ~OptionsDialog();
+
+ std::string getUseProxy();
+ std::string getServer();
+ std::string getPort();
+
+};
diff --git a/crashrep/source/unx/main.cxx b/crashrep/source/unx/main.cxx
new file mode 100755
index 000000000000..ca24d508ae07
--- /dev/null
+++ b/crashrep/source/unx/main.cxx
@@ -0,0 +1,1125 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: main.cxx,v $
+ * $Revision: 1.30 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#include <cstdio>
+#include <stdlib.h>
+#include <sys/utsname.h>
+#include <_version.h>
+#include <errno.h>
+#include <string>
+#include <string.h>
+#include <assert.h>
+
+#include <sys/socket.h>
+#include <netdb.h>
+#include <unistd.h>
+#include <pwd.h>
+#include <pthread.h>
+#include <limits.h>
+
+#include <hash_map>
+#include <vector>
+#include <string>
+
+#if defined (LINUX) || (FREEBSD)
+#include <netinet/in.h>
+#endif
+
+typedef int SOCKET;
+
+#define closesocket close
+#define SOCKET_ERROR -1
+
+#ifdef SOLARIS
+const char *basename( const char *filename )
+{
+ const char *pSlash = strrchr( filename, '/' );
+
+ return pSlash ? pSlash + 1 : pSlash;
+}
+#endif
+
+using namespace std;
+
+static bool g_bNoUI = false;
+static bool g_bSendReport = false;
+static bool g_bLoadReport = false;
+
+static bool g_bDebugMode = false;
+static int g_signal = 0;
+
+static string g_strProductKey;
+static string g_strReportServer;
+static unsigned short g_uReportPort = 80;
+static string g_buildid;
+static string g_strDefaultLanguage;
+static string g_strXMLFileName;
+static string g_strPStackFileName;
+static string g_strChecksumFileName;
+static string g_strProgramDir;
+
+static char g_szStackFile[L_tmpnam] = "";
+static char g_szDescriptionFile[2048] = "";
+static char g_szReportFile[2048] = "";
+
+#define SO_CRASHREPORT_MAIL "so-report@sun.com"
+#define PSTACK_CMD "pstack %d"
+
+#ifdef LINUX
+#define PMAP_CMD "cat /proc/%d/maps"
+#else
+#define PMAP_CMD "pmap %d"
+#endif
+
+#define REPORT_SERVER (g_strReportServer.c_str())
+#define REPORT_PORT g_uReportPort
+
+static string getprogramdir()
+{
+ return g_strProgramDir;
+}
+
+static const char *getlocale()
+{
+ const char * locale = getenv( "LC_ALL" );
+
+ if( NULL == locale )
+ locale = getenv( "LC_CTYPE" );
+
+ if( NULL == locale )
+ locale = getenv( "LANG" );
+
+ if( NULL == locale )
+ locale = "C";
+
+ return locale;
+}
+
+static const char *get_home_dir()
+{
+ struct passwd *ppwd = getpwuid( getuid() );
+
+ return ppwd ? (ppwd->pw_dir ? ppwd->pw_dir : "/") : "/";
+}
+
+static string trim_string( const string& rString )
+{
+ string temp = rString;
+
+ while ( temp.length() && temp[0] == ' ' || temp[0] == '\t' )
+ temp.erase( 0, 1 );
+
+ string::size_type len = temp.length();
+
+ while ( len && temp[len-1] == ' ' || temp[len-1] == '\t' )
+ {
+ temp.erase( len - 1, 1 );
+ len = temp.length();
+ }
+
+ return temp;
+}
+
+static string xml_encode( const string &rString )
+{
+ string temp = rString;
+ string::size_type pos = 0;
+
+ // First replace all occurences of '&' because it may occur in further
+ // encoded chardters too
+
+ for( pos = 0; (pos = temp.find( '&', pos )) != string::npos; pos += 4 )
+ temp.replace( pos, 1, "&amp;" );
+
+ for( pos = 0; (pos = temp.find( '<', pos )) != string::npos; pos += 4 )
+ temp.replace( pos, 1, "&lt;" );
+
+ for( pos = 0; (pos = temp.find( '>', pos )) != string::npos; pos += 4 )
+ temp.replace( pos, 1, "&gt;" );
+
+ return temp;
+}
+
+static size_t fcopy( FILE *fpout, FILE *fpin )
+{
+ char buffer[1024];
+ size_t nBytes;
+ size_t nBytesWritten = 0;
+
+ while ( 0 != (nBytes = fread( buffer, 1, sizeof(buffer), fpin )) )
+ {
+ nBytesWritten += fwrite( buffer, 1, nBytes, fpout );
+ }
+
+ return nBytesWritten;
+}
+
+/*
+ writes the report to a temp-file
+ from which it can be reviewed and sent
+*/
+
+bool write_report( const hash_map< string, string >& rSettings )
+{
+ FILE *fp = fopen( tmpnam( g_szReportFile ), "w" );
+ const char *pszUserType = getenv( "STAROFFICE_USERTYPE" );
+
+ fprintf( fp,
+ "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+ "<!DOCTYPE errormail:errormail PUBLIC \"-//OpenOffice.org//DTD ErrorMail 1.0//EN\" \"errormail.dtd\">\n"
+ "<errormail:errormail xmlns:errormail=\"http://openoffice.org/2002/errormail\" usertype=\"%s\">\n"
+ "<reportmail:mail xmlns:reportmail=\"http://openoffice.org/2002/reportmail\" version=\"1.1\" feedback=\"%s\" email=\"%s\">\n"
+ "<reportmail:title>%s</reportmail:title>\n"
+ "<reportmail:attachment name=\"description.txt\" media-type=\"text/plain\" class=\"UserComment\"/>\n"
+ "<reportmail:attachment name=\"stack.txt\" media-type=\"text/plain\" class=\"pstack output\"/>\n"
+ "</reportmail:mail>\n"
+ "<officeinfo:officeinfo xmlns:officeinfo=\"http://openoffice.org/2002/officeinfo\" build=\"%s\" platform=\"%s\" language=\"%s\" exceptiontype=\"%d\" product=\"%s\" procpath=\"%s\"/>\n"
+ ,
+ pszUserType ? xml_encode( pszUserType ).c_str() : "",
+ xml_encode(rSettings.find( "CONTACT" )->second).c_str(),
+ xml_encode(rSettings.find( "EMAIL" )->second).c_str(),
+ xml_encode(rSettings.find( "TITLE" )->second).c_str(),
+ g_buildid.length() ? xml_encode( g_buildid ).c_str() : "unknown",
+ _INPATH,
+ g_strDefaultLanguage.c_str(),
+ g_signal,
+ g_strProductKey.length() ? xml_encode(g_strProductKey).c_str() : "unknown",
+ xml_encode(getprogramdir()).c_str()
+ );
+
+ struct utsname info;
+
+ memset( &info, 0, sizeof(info) );
+ uname( &info );
+
+ fprintf( fp,
+ "<systeminfo:systeminfo xmlns:systeminfo=\"http://openoffice.org/2002/systeminfo\">\n"
+ "<systeminfo:System name=\"%s\" version=\"%s\" build=\"%s\" locale=\"%s\"/>\n"
+ ,
+ xml_encode( info.sysname ).c_str(),
+ xml_encode( info.version ).c_str(),
+ xml_encode( info.release ).c_str(),
+ xml_encode( getlocale() ).c_str()
+ );
+ fprintf( fp, "<systeminfo:CPU type=\"%s\"/>\n", xml_encode( info.machine ).c_str() );
+ fprintf( fp, "</systeminfo:systeminfo>\n" );
+
+ FILE *fpxml = fopen( g_strXMLFileName.c_str(), "r" );
+ if ( fpxml )
+ {
+ fcopy( fp, fpxml );
+ fclose( fpxml );
+ }
+
+ FILE *fpchk = fopen( g_strChecksumFileName.c_str(), "r" );
+ if ( fpchk )
+ {
+ fcopy( fp, fpchk );
+ fclose( fpchk );
+ }
+
+ fprintf( fp, "</errormail:errormail>\n" );
+
+ fclose( fp );
+
+ return true;
+}
+
+
+bool write_description( const hash_map< string, string >& rSettings )
+{
+ bool bSuccess = false;
+ FILE *fp = fopen( tmpnam( g_szDescriptionFile ), "w" );
+
+ if ( fp )
+ {
+ bSuccess = true;
+ fprintf( fp, "\xEF\xBB\xBF" );
+ fprintf( fp, "%s\n", rSettings.find( "DESCRIPTION" )->second.c_str() );
+ fclose( fp );
+ }
+
+ return bSuccess;
+}
+
+#if 0
+// unused
+static void printSettings( const hash_map<string,string>& rSettings )
+{
+ printf( "Settings:\n" );
+ for( hash_map<string,string>::const_iterator it = rSettings.begin(); it != rSettings.end(); ++it )
+ {
+ printf( "%s=\"%s\"\n", it->first.c_str(), it->second.c_str() );
+ }
+}
+#endif
+
+bool save_crash_report( const string& rFileName, const hash_map< string, string >& /*rSettings*/ )
+{
+ bool bSuccess = false;
+ FILE *fpout = fopen( rFileName.c_str(), "w" );
+
+ if ( fpout )
+ {
+ FILE *fpin = fopen( g_szStackFile, "r" );
+
+ if ( fpin )
+ {
+ char buf[1024];
+
+ while (fgets(buf, sizeof(buf), fpin) != NULL)
+ {
+ fputs(buf, fpout);
+ }
+
+ bSuccess = true;
+
+ fclose ( fpin );
+ }
+
+ fclose( fpout );
+ }
+
+ return bSuccess;
+}
+
+bool SendHTTPRequest(
+ FILE *fp,
+ const char *pszServer,
+ unsigned short uPort = 80,
+ const char *pszProxyServer = NULL,
+ unsigned short uProxyPort = 8080 )
+{
+ bool success = false;
+
+ struct hostent *hp;
+
+ if ( pszProxyServer )
+ hp = gethostbyname( pszProxyServer );
+ else
+ hp = gethostbyname( pszServer );
+
+ if ( hp )
+ {
+ SOCKET s = socket( AF_INET, SOCK_STREAM, 0 );
+
+ if ( s )
+ {
+ struct sockaddr_in address;
+
+ memcpy(&(address.sin_addr.s_addr), *(hp->h_addr_list),sizeof(struct in_addr));
+ address.sin_family = AF_INET;
+
+ if ( pszProxyServer )
+ address.sin_port = ntohs( uProxyPort );
+ else
+ address.sin_port = ntohs( uPort );
+
+ if ( 0 == connect( s, (struct sockaddr *)&address, sizeof(struct sockaddr_in)) )
+ {
+ fseek( fp, 0, SEEK_END );
+ size_t length = ftell( fp );
+ fseek( fp, 0, SEEK_SET );
+
+ char buffer[2048];
+
+ if ( pszProxyServer )
+ sprintf( buffer,
+ "POST http://%s:%d/soap/servlet/rpcrouter HTTP/1.0\r\n"
+ "Content-Type: text/xml; charset=\"utf-8\"\r\n"
+ "Content-Length: %d\r\n"
+ "SOAPAction: \"\"\r\n\r\n",
+ pszServer,
+ uPort,
+ static_cast<int>(length)
+ );
+ else
+ sprintf( buffer,
+ "POST /soap/servlet/rpcrouter HTTP/1.0\r\n"
+ "Content-Type: text/xml; charset=\"utf-8\"\r\n"
+ "Content-Length: %d\r\n"
+ "SOAPAction: \"\"\r\n\r\n",
+ static_cast<int>(length)
+ );
+
+ if ( g_bDebugMode )
+ {
+ printf( "*** Sending HTTP request ***\n\n" );
+ printf( buffer );
+ }
+
+ if ( SOCKET_ERROR != send( s, buffer, strlen(buffer), 0 ) )
+ {
+ size_t nBytes;
+
+ do
+ {
+ nBytes = fread( buffer, 1, sizeof(buffer), fp );
+
+ if ( nBytes )
+ {
+ if ( g_bDebugMode )
+ fwrite( buffer, 1, nBytes, stdout );
+ success = SOCKET_ERROR != send( s, buffer, nBytes, 0 );
+ }
+ } while( nBytes && success );
+
+ if ( success )
+ {
+ if ( g_bDebugMode )
+ printf( "*** Receiving HTTP response ***\n\n" );
+
+ memset( buffer, 0, sizeof(buffer) );
+ success = SOCKET_ERROR != recv( s, buffer, sizeof(buffer), 0 );
+ if ( success )
+ {
+ char szHTTPSignature[sizeof(buffer)] = "";
+ unsigned uHTTPReturnCode = 0;
+
+ sscanf( buffer, "%s %d ", szHTTPSignature, &uHTTPReturnCode );
+ success = uHTTPReturnCode == 200;
+ }
+ if ( g_bDebugMode )
+ do
+ {
+ printf( buffer );
+ memset( buffer, 0, sizeof(buffer) );
+ } while ( 0 < recv( s, buffer, sizeof(buffer), 0 ) );
+ }
+ }
+
+ }
+
+ closesocket( s );
+ }
+ }
+
+ return success;
+}
+
+static void WriteSOAPRequest( FILE *fp )
+{
+ fprintf( fp,
+ "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+ "<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\"\n"
+ "xmlns:SOAP-ENC=\"http://schemas.xmlsoap.org/soap/encoding/\"\n"
+ "xmlns:xsi=\"http://www.w3.org/1999/XMLSchema-instance\"\n"
+ "xmlns:xsd=\"http://www.w3.org/1999/XMLSchema\"\n"
+ "xmlns:rds=\"urn:ReportDataService\"\n"
+ "xmlns:apache=\"http://xml.apache.org/xml-soap\"\n"
+ "SOAP-ENV:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">\n"
+ "<SOAP-ENV:Body>\n"
+ );
+
+ fprintf( fp, "<rds:submitReport>\n" );
+ fprintf( fp, "<body xsi:type=\"xsd:string\">This is an autogenerated crash report mail.</body>\n" );
+ fprintf( fp, "<hash xsi:type=\"apache:Map\">\n" );
+
+ FILE *fpin = fopen( g_szReportFile, "r" );
+ if ( fpin )
+ {
+ fprintf( fp,
+ "<item>\n"
+ "<key xsi:type=\"xsd:string\">reportmail.xml</key>\n"
+ "<value xsi:type=\"xsd:string\"><![CDATA[" );
+ fcopy( fp, fpin );
+ fprintf( fp, "]]></value></item>\n" );
+ fclose( fpin );
+ }
+
+ fpin = fopen( g_szDescriptionFile, "r" );
+ if ( fpin )
+ {
+ fprintf( fp,
+ "<item>\n"
+ "<key xsi:type=\"xsd:string\">description.txt</key>\n"
+ "<value xsi:type=\"xsd:string\"><![CDATA[" );
+ fcopy( fp, fpin );
+ fprintf( fp, "]]></value></item>\n" );
+ fclose( fpin );
+ };
+
+ fpin = fopen( g_szStackFile, "r" );
+ if ( fpin )
+ {
+ fprintf( fp,
+ "<item>\n"
+ "<key xsi:type=\"xsd:string\">stack.txt</key>\n"
+ "<value xsi:type=\"xsd:string\"><![CDATA[" );
+ fcopy( fp, fpin );
+ fprintf( fp, "]]></value></item>\n" );
+ fclose( fpin );
+ };
+
+ fprintf( fp,
+ "</hash>\n"
+ "</rds:submitReport>\n"
+ "</SOAP-ENV:Body>\n"
+ "</SOAP-ENV:Envelope>\n"
+ );
+}
+
+struct RequestParams
+{
+ bool success;
+ FILE *fpin;
+ const char *pServer;
+ unsigned short uPort;
+ const char *pProxyServer;
+ unsigned short uProxyPort;
+};
+
+
+bool send_crash_report( const hash_map< string, string >& rSettings )
+{
+ if ( 0 == strcasecmp( rSettings.find( "CONTACT" )->second.c_str(), "true" ) &&
+ !trim_string(rSettings.find( "EMAIL" )->second).length() )
+ {
+ return false;
+ }
+
+ char *endptr = NULL;
+
+ const char *pProxyServer = rSettings.find( "SERVER" )->second.c_str();
+ unsigned short uProxyPort = (unsigned short)strtoul( rSettings.find( "PORT" )->second.c_str(), &endptr, 10 );
+
+ bool bUseProxy = !strcasecmp( "true", rSettings.find( "USEPROXY" )->second.c_str() );
+
+
+ write_description( rSettings );
+ write_report( rSettings );
+
+ bool bSuccess = false;
+
+ FILE *fptemp = tmpfile();
+ if ( fptemp )
+ {
+ WriteSOAPRequest( fptemp );
+ fseek( fptemp, 0, SEEK_SET );
+
+ bSuccess = SendHTTPRequest(
+ fptemp,
+ REPORT_SERVER, REPORT_PORT,
+ bUseProxy ? pProxyServer : NULL,
+ uProxyPort ? uProxyPort : 8080
+ );
+
+ fclose( fptemp );
+
+ }
+
+ unlink( g_szDescriptionFile );
+ unlink( g_szReportFile );
+
+ return bSuccess;
+}
+
+
+static bool append_file( const char *filename, string& rString )
+{
+ char buf[1024];
+ bool bSuccess = false;
+
+ FILE *fp = fopen( filename, "r" );
+ if ( fp )
+ {
+ bSuccess = true;
+ while (fgets(buf, sizeof(buf), fp) != NULL)
+ {
+ rString.append( buf );
+ }
+ fclose( fp );
+ }
+
+ return true;
+}
+
+string crash_get_details( const hash_map< string, string >& rSettings )
+{
+ string aRet;
+
+ write_description( rSettings );
+ write_report( rSettings );
+
+ aRet.append( rSettings.find( "TITLE" )->second.c_str() );
+ aRet.append( "\n\n" );
+ append_file( g_szDescriptionFile, aRet );
+ aRet.append( "\n\n-------\n\n" );
+ append_file( g_szReportFile, aRet );
+ aRet.append( "\n\n-------\n\n" );
+ append_file( g_szStackFile, aRet );
+
+ unlink( g_szDescriptionFile );
+ unlink( g_szReportFile );
+
+ return aRet;
+}
+
+
+// ensure validity of program relative paths
+static void setup_program_dir( const char* progname )
+{
+ char szCanonicProgPath[PATH_MAX];
+
+
+ if ( realpath( progname, szCanonicProgPath ) )
+ {
+ string aDir = szCanonicProgPath;
+
+ size_t pos = aDir.rfind( '/' );
+ // FIXME: search PATH if necessary
+ assert( pos != string::npos );
+
+ g_strProgramDir = aDir.substr( 0, pos + 1 );
+ aDir.erase( pos );
+ chdir( aDir.c_str() );
+ }
+}
+
+//*************************************************************************
+
+static long setup_commandline_arguments( int argc, char** argv, int *pSignal )
+{
+ long pid = 0;
+ int signal = 0;
+
+ for ( int n = 1; n < argc; n++ )
+ {
+ if ( 0 == strcmp( argv[n], "-p" ) )
+ {
+ if ( ++n < argc )
+ pid = strtol( argv[n], NULL, 0 );
+ }
+ else if ( 0 == strcmp( argv[n], "-s" ) )
+ {
+ if ( ++n < argc )
+ signal = strtol( argv[n], NULL, 0 );
+ }
+ else if ( 0 == strcmp( argv[n], "-debug" ) )
+ {
+ g_bDebugMode = true;
+ }
+ else if ( 0 == strcmp( argv[n], "-xml" ) )
+ {
+ if ( ++n < argc )
+ g_strXMLFileName = argv[n];
+ }
+ else if ( 0 == strcmp( argv[n], "-stack" ) )
+ {
+ if ( ++n < argc )
+ g_strPStackFileName = argv[n];
+ }
+ else if ( 0 == strcmp( argv[n], "-chksum" ) )
+ {
+ if ( ++n < argc )
+ g_strChecksumFileName = argv[n];
+ }
+ else if ( 0 == strcmp( argv[n], "-noui" ) )
+ {
+ g_bNoUI = true;
+ }
+ else if ( 0 == strcmp( argv[n], "-send" ) )
+ {
+ g_bSendReport = true;
+ }
+ else if ( 0 == strcmp( argv[n], "-load" ) )
+ {
+ g_bLoadReport = true;
+ }
+ else if ( argv[n] && strlen(argv[n]) )
+ {
+ printf(
+ "\n%s crash_report %s\n\n" \
+ "/?, -h[elp] %s\n\n" \
+ "%-20s %s\n\n",
+ "%MSG_CMDLINE_USAGE%",
+ "%MSG_PARAM_PROCESSID%",
+ "%MSG_PARAM_HELP_DESCRIPTION%",
+ "%MSG_PARAM_PROCESSID%",
+ "%MSG_PARAM_PROCESSID_DESCRIPTION%"
+ );
+ break;
+ }
+ }
+
+ *pSignal = signal;
+
+ return pid;
+}
+
+//*************************************************************************
+
+static bool read_line( FILE *fp, string& rLine )
+{
+ char szBuffer[1024];
+ bool bSuccess = false;
+ bool bEOL = false;
+ string line;
+
+
+ while ( !bEOL && fgets( szBuffer, sizeof(szBuffer), fp ) )
+ {
+ int len = strlen(szBuffer);
+
+ bSuccess = true;
+
+ while ( len && szBuffer[len - 1] == '\n' )
+ {
+ szBuffer[--len] = 0;
+ bEOL = true;
+ }
+
+ line.append( szBuffer );
+ }
+
+ rLine = line;
+ return bSuccess;
+}
+
+static string get_script_string( const char *pFileName, const char *pKeyName )
+{
+ FILE *fp = fopen( pFileName, "r" );
+ string retValue;
+
+ if ( fp )
+ {
+ string line;
+ string section;
+
+ while ( read_line( fp, line ) )
+ {
+ line = trim_string( line );
+
+
+ string::size_type iEqualSign = line.find( '=', 0 );
+
+ if ( iEqualSign != string::npos )
+ {
+ string keyname = line.substr( 0, iEqualSign );
+ keyname = trim_string( keyname );
+
+ string value = line.substr( iEqualSign + 1, string::npos );
+ value = trim_string( value );
+
+ if ( value.length() && '\"' == value[0] )
+ {
+ value.erase( 0, 1 );
+
+ string::size_type iQuotes = value.find( '"', 0 );
+
+ if ( iQuotes != string::npos )
+ value.erase( iQuotes );
+ }
+
+ if ( 0 == strcasecmp( keyname.c_str(), pKeyName ) )
+ {
+ retValue = value;
+ break;
+ }
+ }
+ }
+
+ fclose( fp );
+ }
+
+ return retValue;
+}
+
+static string get_profile_string( const char *pFileName, const char *pSectionName, const char *pKeyName, const char *pDefault = NULL )
+{
+ FILE *fp = fopen( pFileName, "r" );
+ string retValue = pDefault ? pDefault : "";
+
+ if ( fp )
+ {
+ string line;
+ string section;
+
+ while ( read_line( fp, line ) )
+ {
+ line = trim_string( line );
+
+ if ( line.length() && line[0] == '[' )
+ {
+ line.erase( 0, 1 );
+ string::size_type end = line.find( ']', 0 );
+
+ if ( string::npos != end )
+ section = trim_string( line.substr( 0, end ) );
+ }
+ else
+ {
+
+ string::size_type iEqualSign = line.find( '=', 0 );
+
+ if ( iEqualSign != string::npos )
+ {
+ string keyname = line.substr( 0, iEqualSign );
+ keyname = trim_string( keyname );
+
+ string value = line.substr( iEqualSign + 1, string::npos );
+ value = trim_string( value );
+
+ if (
+ 0 == strcasecmp( section.c_str(), pSectionName ) &&
+ 0 == strcasecmp( keyname.c_str(), pKeyName )
+ )
+ {
+ retValue = value;
+ break;
+ }
+ }
+ }
+ }
+
+ fclose( fp );
+ }
+
+ return retValue;
+}
+
+static string get_environment_string( const char *pEnvName )
+{
+ const char *pEnvValue = getenv( pEnvName );
+
+ if ( pEnvValue )
+ return pEnvValue;
+ else
+ return "";
+}
+
+static string read_from_file( const string& rFileName )
+{
+ string content;
+ FILE *fp = fopen( rFileName.c_str(), "r" );
+
+ if ( fp )
+ {
+ char buffer[256 + 1];
+ size_t nBytesRead;
+
+ while( 0 != ( nBytesRead = fread( buffer, 1, sizeof(buffer) - 1, fp ) ) )
+ {
+ buffer[nBytesRead] = 0;
+ content += buffer;
+ }
+
+ fclose( fp );
+ }
+
+ return content;
+}
+
+#define RCFILE ".crash_reportrc"
+#define XMLFILE ".crash_report_frames"
+#define CHKFILE ".crash_report_checksum"
+#define LCKFILE ".crash_report_unsent"
+#define PRVFILE ".crash_report_preview"
+
+static void load_crash_data()
+{
+ g_strXMLFileName = get_home_dir();
+ g_strXMLFileName += "/";
+ g_strXMLFileName += string(XMLFILE);
+
+ g_strChecksumFileName = get_home_dir();
+ g_strChecksumFileName += "/";
+ g_strChecksumFileName += string(CHKFILE);
+}
+
+static bool write_crash_data()
+{
+ bool success = true;
+ string sFile = get_home_dir();
+
+ sFile += "/";
+ sFile += string(XMLFILE);
+
+ FILE *fp = fopen( sFile.c_str(), "w" );
+
+ if ( fp )
+ {
+ FILE *fpin = fopen( g_strXMLFileName.c_str(), "r" );
+
+ if ( fpin )
+ {
+ fcopy( fp, fpin );
+ fclose( fpin );
+ }
+
+ fclose( fp );
+ }
+
+ sFile = get_home_dir();
+
+ sFile += "/";
+ sFile += string(CHKFILE);
+
+ fp = fopen( sFile.c_str(), "w" );
+
+ if ( fp )
+ {
+ FILE *fpin = fopen( g_strChecksumFileName.c_str(), "r" );
+
+ if ( fpin )
+ {
+ fcopy( fp, fpin );
+ fclose( fpin );
+ }
+
+ fclose( fp );
+ }
+
+ sFile = get_home_dir();
+
+ sFile += "/";
+ sFile += string(LCKFILE);
+
+ fp = fopen( sFile.c_str(), "w" );
+
+ if ( fp )
+ {
+ fprintf( fp, "Unsent\n" );
+ fclose( fp );
+ }
+
+ return success;
+}
+
+#if 0
+// unused
+static bool write_settings( const hash_map< string, string >& rSettings )
+{
+ bool success = false;
+ string sRCFile = get_home_dir();
+
+ sRCFile += "/";
+ sRCFile += string(RCFILE);
+
+ FILE *fp = fopen( sRCFile.c_str(), "w" );
+
+ if ( fp )
+ {
+ fprintf( fp, "[Options]\n" );
+ fprintf( fp, "UseProxy=%s\n", rSettings.find( "USEPROXY" )->second.c_str() );
+ fprintf( fp, "ProxyServer=%s\n", rSettings.find( "SERVER" )->second.c_str() );
+ fprintf( fp, "ProxyPort=%s\n", rSettings.find( "PORT" )->second.c_str() );
+ fprintf( fp, "ReturnAddress=%s\n", rSettings.find( "EMAIL" )->second.c_str() );
+ fprintf( fp, "AllowContact=%s\n", rSettings.find( "CONTACT" )->second.c_str() );
+ fclose( fp );
+ }
+
+ return success;
+}
+#endif
+
+static void read_settings( hash_map< string, string >& rSettings )
+{
+ string sRCFile = get_home_dir();
+
+ sRCFile += "/";
+ sRCFile += string(RCFILE);
+
+ rSettings[ "EMAIL" ] = get_profile_string( sRCFile.c_str(), "Options", "ReturnAddress" );
+ rSettings[ "SERVER" ] = get_profile_string( sRCFile.c_str(), "Options", "ProxyServer" );
+ rSettings[ "PORT" ] = get_profile_string( sRCFile.c_str(), "Options", "ProxyPort" );
+ rSettings[ "USEPROXY" ] = get_profile_string( sRCFile.c_str(), "Options", "UseProxy" );
+ rSettings[ "CONTACT" ] = get_profile_string( sRCFile.c_str(), "Options", "AllowContact" );
+ rSettings[ "DESCRIPTION" ] = "";
+ rSettings[ "TITLE" ] = "";
+}
+
+static void read_settings_from_environment( hash_map< string, string >& rSettings )
+{
+ string strEnv;
+
+ strEnv = get_environment_string( "ERRORREPORT_RETURNADDRESS" );
+ if ( strEnv.length() )
+ {
+ rSettings[ "EMAIL" ] = strEnv;
+ if ( !(rSettings.find( "CONTACT" )->second).length() )
+ rSettings[ "CONTACT" ] = "true";
+ }
+ else if ( !(rSettings.find( "CONTACT" )->second).length() )
+ rSettings[ "CONTACT" ] = "false";
+
+
+ strEnv = get_environment_string( "ERRORREPORT_HTTPPROXYSERVER" );
+ if ( strEnv.length() )
+ rSettings[ "SERVER" ] = strEnv;
+
+ strEnv = get_environment_string( "ERRORREPORT_HTTPPROXYPORT" );
+ if ( strEnv.length() )
+ rSettings[ "PORT" ] = strEnv;
+
+ strEnv = get_environment_string( "ERRORREPORT_HTTPCONNECTIONTYPE" );
+ if ( strEnv.length() )
+ rSettings[ "USEPROXY" ] = 0 == strcasecmp( strEnv.c_str(), "MANUALPROXY" ) ? "true" : "false";
+
+ strEnv = get_environment_string( "ERRORREPORT_BODYFILE" );
+ if ( strEnv.length() )
+ rSettings[ "DESCRIPTION" ] = read_from_file( strEnv );
+
+ strEnv = get_environment_string( "ERRORREPORT_SUBJECT" );
+ if ( strEnv.length() )
+ rSettings[ "TITLE" ] = strEnv;
+}
+
+static bool setup_version()
+{
+ if ( !getenv( "PRODUCTNAME" ) )
+ {
+ string productkey = get_profile_string( "bootstraprc", "Bootstrap", "ProductKey" );
+
+ g_strProductKey = productkey;
+
+ if ( productkey.length() )
+ {
+ static string productname;
+ static string productversion;
+ string::size_type iSpace = productkey.find( ' ', 0 );
+
+ if ( string::npos != iSpace )
+ {
+ productname = productkey.substr( 0, iSpace );
+ productversion = productkey.substr( iSpace + 1, string::npos );
+ }
+ else
+ productname = productkey;
+
+ productname.insert( 0, "PRODUCTNAME=" );
+ putenv( (char *)productname.c_str() );
+
+ productversion.insert( 0, "PRODUCTVERSION=" );
+ putenv( (char *)productversion.c_str() );
+ }
+ }
+
+ g_buildid = get_profile_string( "versionrc", "Version", "BuildId" );
+ g_strDefaultLanguage = get_script_string( "instdb.ins", "DefaultLanguage" );
+
+ g_strReportServer = get_profile_string( "bootstraprc", "ErrorReport", "ErrorReportServer" );
+
+ string strReportPort = get_profile_string( "bootstraprc", "ErrorReport", "ErrorReportPort", "80" );
+ char *endptr = NULL;
+ unsigned short uReportPort = (unsigned short)strtoul( strReportPort.c_str(), &endptr, 10 );
+ g_uReportPort = uReportPort ? uReportPort : 80;
+
+ return 0 != g_strReportServer.length();
+}
+
+#if 0
+// Use gconftool-2 to determine if gnome accessiblity is enabled
+// unused
+static bool get_accessibility_state()
+{
+ bool bAccessible = false;
+ FILE *fin = popen( "gconftool-2 -g /desktop/gnome/interface/accessibility", "r");
+
+ if ( fin )
+ {
+ char buffer[sizeof("true")];
+
+ bAccessible = fgets( buffer, sizeof(buffer), fin ) && 0 == strcmp( buffer, "true" );
+
+ pclose( fin );
+ }
+
+ return bAccessible;
+}
+#endif
+
+int main( int argc, char** argv )
+{
+ freopen( "/dev/null", "w", stderr );
+
+ setup_program_dir( argv[0] );
+
+ // Don't start if accessiblity is enabled or report server is not given
+
+ if ( setup_version() )
+ {
+ /*long pid =*/ setup_commandline_arguments( argc, argv, &g_signal );
+
+ if ( g_bLoadReport )
+ {
+ load_crash_data();
+ }
+
+ if ( g_bSendReport )
+ {
+ hash_map< string, string > aDialogSettings;
+
+ read_settings( aDialogSettings );
+ read_settings_from_environment( aDialogSettings );
+
+ send_crash_report( aDialogSettings );
+ }
+ else
+ {
+ hash_map< string, string > aDialogSettings;
+
+ read_settings( aDialogSettings );
+ read_settings_from_environment( aDialogSettings );
+
+ write_crash_data();
+ write_report( aDialogSettings );
+
+ string sPreviewFile = get_home_dir();
+ sPreviewFile += "/";
+ sPreviewFile += string(PRVFILE);
+
+ FILE *fpout = fopen( sPreviewFile.c_str(), "w+" );
+ if ( fpout )
+ {
+ FILE *fpin = fopen( g_szReportFile, "r" );
+ if ( fpin )
+ {
+ fcopy( fpout, fpin );
+ fclose( fpin );
+ }
+ fclose( fpout );
+ }
+
+ unlink( g_szReportFile );
+ }
+
+ if ( g_bLoadReport )
+ {
+ unlink( g_strXMLFileName.c_str() );
+ unlink( g_strChecksumFileName.c_str() );
+ }
+
+ unlink( g_szStackFile );
+
+ return 0;
+ }
+
+ return -1;
+}
diff --git a/crashrep/source/unx/makefile.mk b/crashrep/source/unx/makefile.mk
new file mode 100755
index 000000000000..2f8be8f96a76
--- /dev/null
+++ b/crashrep/source/unx/makefile.mk
@@ -0,0 +1,81 @@
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2008 by Sun Microsystems, Inc.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# $RCSfile: makefile.mk,v $
+#
+# $Revision: 1.19 $
+#
+# This file is part of OpenOffice.org.
+#
+# OpenOffice.org is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# only, as published by the Free Software Foundation.
+#
+# OpenOffice.org is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License version 3 for more details
+# (a copy is included in the LICENSE file that accompanied this code).
+#
+# You should have received a copy of the GNU Lesser General Public License
+# version 3 along with OpenOffice.org. If not, see
+# <http://www.openoffice.org/license.html>
+# for a copy of the LGPLv3 License.
+#
+#*************************************************************************
+
+PRJ=..$/..
+
+PRJNAME=crashrep
+TARGET=crash_report.bin
+TARGETTYPE=CUI
+
+ENABLE_EXCEPTIONS=TRUE
+LIBTARGET=NO
+LIBSALCPPRT=$(0)
+
+# --- Settings -----------------------------------------------------
+
+.INCLUDE : settings.mk
+
+# ------------------------------------------------------------------
+
+# Only build crash reporter if either a product build with debug info
+# or a non-pro build is done.
+
+.IF "$(ENABLE_CRASHDUMP)" != "" || "$(PRODUCT)" == ""
+
+SOLARLIB!:=$(SOLARLIB:s/jre/jnore/)
+
+OBJFILES=\
+ $(OBJ)$/main.obj
+
+APP1NOSAL=TRUE
+APP1TARGET=$(TARGET)
+APP1OBJS=$(OBJFILES)
+APP1RPATH=BRAND
+
+.IF "$(OS)" != "MACOSX"
+APP1STDLIBS=$(DYNAMIC) -lXext -lX11
+.ENDIF
+.IF "$(OS)" != "FREEBSD" && "$(OS)" != "MACOSX" && "$(OS)"!="NETBSD"
+APP1STDLIBS+=-ldl -lnsl
+.ENDIF
+.IF "$(OS)" == "SOLARIS"
+APP1STDLIBS+=-lsocket
+.ENDIF
+
+.ENDIF # "$(ENABLE_CRASHDUMP)" != "" || "$(PRODUCT)" == ""
+
+# --- Targets ------------------------------------------------------
+
+.INCLUDE : target.mk
+
+$(OBJ)$/main.obj: $(INCCOM)$/_version.h
+
+# Building crash_report
diff --git a/crashrep/source/unx/res.cxx b/crashrep/source/unx/res.cxx
new file mode 100755
index 000000000000..63910d606a09
--- /dev/null
+++ b/crashrep/source/unx/res.cxx
@@ -0,0 +1,140 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: res.cxx,v $
+ * $Revision: 1.5 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#if OSL_DEBUG_LEVEL == 0
+# ifndef NDEBUG
+# define NDEBUG
+# endif
+#endif
+#include <assert.h>
+
+#include <interface.hxx>
+#include <cstdio>
+#include <hash_map>
+#include <string>
+
+using namespace std;
+
+static hash_map< string, string >* pStringResources = NULL;
+
+static string getResFileName( const char* progname )
+{
+ string aRet = progname;
+ size_t pos = aRet.rfind( '/' );
+ // FIXME: search PATH if necessary
+ assert( pos != string::npos );
+ aRet.erase( pos );
+ aRet.append( "/resource/crash_dump.res" );
+
+ return aRet;
+}
+
+static void filterString( string& rString )
+{
+ static const char* pProductName = getenv( "PRODUCTNAME" );
+ static int nProductLen = pProductName ? strlen( pProductName ) : 0;
+ static const char* pProductVersion = getenv( "PRODUCTVERSION" );
+ static int nVersionLen = pProductVersion ? strlen( pProductVersion ) : 0;
+
+ // fill in eventually escaped characters
+ string::size_type pos = 0;
+ while( (pos = rString.find( '\\' ) ) != string::npos )
+ {
+ char cRep = 0;
+ switch( rString[pos+1] )
+ {
+ case 't': cRep = '\t';break;
+ case 'n': cRep = '\n';break;
+ case 'r': cRep = '\r';break;
+ case 'f': cRep = '\f';break;
+ default: cRep = rString[pos+1];
+ }
+ if( cRep )
+ rString.replace( pos, 2, &cRep, 1 );
+ }
+ while( (pos = rString.find( '~' ) ) != string::npos )
+ {
+ // replace mnemonic marker
+ rString.replace( pos, 1, "_", 1 );
+ }
+ while( (pos = rString.find( "%PRODUCTNAME%" ) ) != string::npos )
+ {
+ rString.replace( pos, 13, pProductName ? pProductName : "OpenOffice" );
+ }
+ while( (pos = rString.find( "%PRODUCTVERSION%" ) ) != string::npos )
+ {
+ rString.replace( pos, 16, pProductVersion ? pProductVersion : "" );
+ }
+ // remove whitespace at end
+ pos = rString.find_last_not_of( "\r\n\t\f " );
+ if( pos != string::npos )
+ rString.erase( pos+1 );
+}
+
+void StringResource::init( int argc, char** argv )
+{
+ pStringResources = new hash_map< string, string >();
+
+ string aResFile = getResFileName( argv[0] );
+
+ FILE* fp = fopen( aResFile.c_str(), "r" );
+ if( fp )
+ {
+ char buf[4096];
+ string aKey;
+ string aValue;
+ while( ! feof( fp ) )
+ {
+ if( ! fgets( buf, sizeof(buf), fp ) )
+ break;
+
+ char* pEq = strchr( buf, '=' );
+ if( ! pEq || *(pEq+1) == 0 ) // invalid line
+ continue;
+ aKey = string(buf, pEq-buf);
+ aValue = pEq+1;
+ while( (aValue.empty() || aValue[ aValue.size()-1 ] != '\n') && ! feof( fp ) )
+ {
+ if( fgets( buf, sizeof( buf ), fp ) )
+ aValue.append( buf );
+ }
+ filterString( aValue );
+ (*pStringResources)[aKey] = aValue;
+ }
+ fclose( fp );
+ }
+}
+
+const char* StringResource::get( const char* pKey )
+{
+ hash_map< string, string >::const_iterator it = pStringResources->find( pKey );
+ return (it == pStringResources->end()) ? "" : it->second.c_str();
+}
+
diff --git a/crashrep/source/unx/res/makefile.mk b/crashrep/source/unx/res/makefile.mk
new file mode 100755
index 000000000000..4e6d733e2d37
--- /dev/null
+++ b/crashrep/source/unx/res/makefile.mk
@@ -0,0 +1,63 @@
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2008 by Sun Microsystems, Inc.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# $RCSfile: makefile.mk,v $
+#
+# $Revision: 1.6 $
+#
+# This file is part of OpenOffice.org.
+#
+# OpenOffice.org is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# only, as published by the Free Software Foundation.
+#
+# OpenOffice.org is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License version 3 for more details
+# (a copy is included in the LICENSE file that accompanied this code).
+#
+# You should have received a copy of the GNU Lesser General Public License
+# version 3 along with OpenOffice.org. If not, see
+# <http://www.openoffice.org/license.html>
+# for a copy of the LGPLv3 License.
+#
+#*************************************************************************
+
+PRJ=..$/..$/..
+
+PRJNAME=crashrep
+TARGET=unxcrashres
+LIBTARGET=NO
+TARGETTYPE=CUI
+
+# --- Settings -----------------------------------------------------
+
+.INCLUDE : settings.mk
+
+.IF "$(OS)"=="MACOSX"
+
+dummy:
+ @echo "Nothing to build for OS $(OS)"
+
+.ELSE # "$(OS)"=="MACOSX"
+
+# --- Files --------------------------------------------------------
+
+SOLARLIB!:=$(SOLARLIB:s/jre/jnore/)
+
+APP1TARGET=$(TARGET)
+APP1OBJS=$(OBJ)$/unxcrashres.obj
+APP1STDLIBS=$(TOOLSLIB) $(SALLIB)
+
+.ENDIF "$(OS)"=="MACOSX"
+
+# --- Targets ------------------------------------------------------
+
+.INCLUDE : target.mk
+
diff --git a/crashrep/source/unx/res/unxcrashres.cxx b/crashrep/source/unx/res/unxcrashres.cxx
new file mode 100755
index 000000000000..4bfd34f58ba0
--- /dev/null
+++ b/crashrep/source/unx/res/unxcrashres.cxx
@@ -0,0 +1,104 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: unxcrashres.cxx,v $
+ * $Revision: 1.5 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/#include <tools/config.hxx>
+#include <rtl/string.hxx>
+#include <osl/thread.h>
+
+#include <hash_map>
+#include <string>
+#include <cstdio>
+#include <cerrno>
+
+using namespace std;
+using namespace rtl;
+
+void filterValue( ByteString& rValue, const OString& rGroup, const ByteString& rKey )
+{
+ USHORT nStartPos = rValue.Search( '"' );
+ USHORT nStopPos = rValue.SearchBackward( '"' );
+ if( nStartPos == STRING_NOTFOUND || nStopPos == STRING_NOTFOUND )
+ {
+ fprintf( stderr, "Error: invalid key in [%s] in key \"%s\"\n",
+ rGroup.getStr(),
+ rKey.GetBuffer() );
+ exit( 1 );
+ }
+ rValue.Erase( nStopPos );
+ rValue.Erase( 0, nStartPos+1 );
+}
+
+int main( int argc, char** argv )
+{
+ if( argc != 3 )
+ {
+ fprintf( stderr, "USAGE: unxcrashres <in_lng_file> <out_file_prefix>\n" );
+ exit( 1 );
+ }
+
+ ByteString tmp_argv1( argv[1] );
+ Config aConfig( String( tmp_argv1, osl_getThreadTextEncoding() ) );
+ hash_map< ByteString, hash_map< OString, OString, OStringHash >, OStringHash > aFiles;
+
+ for( USHORT i = 0; i < aConfig.GetGroupCount(); i++ )
+ {
+ aConfig.SetGroup( aConfig.GetGroupName( i ) );
+ OString aGroup = aConfig.GetGroupName( i );
+ USHORT nKeys = aConfig.GetKeyCount();
+ for( USHORT n = 0; n < nKeys; n++ )
+ {
+ ByteString aKey = aConfig.GetKeyName( n );
+ ByteString aValue = aConfig.ReadKey( aKey );
+ // tailor key
+ filterValue( aValue, aGroup, aKey );
+
+ aFiles[aKey][aGroup] = ByteString( aValue );
+ }
+ }
+
+ for( hash_map< ByteString, hash_map< OString, OString, OStringHash >, OStringHash >::const_iterator lang_it = aFiles.begin(); lang_it != aFiles.end(); ++lang_it )
+ {
+ ByteString aFile( argv[2] );
+ aFile.Append( '.' );
+ aFile.Append( lang_it->first );
+ FILE* fp = fopen( aFile.GetBuffer(), "w" );
+ if( ! fp )
+ {
+ fprintf( stderr, "Error: could not open \"%s\" for writing: %s\n",
+ aFile.GetBuffer(), strerror( errno ) );
+ exit(1);
+ }
+ for( hash_map< OString, OString, OStringHash >::const_iterator line_it = lang_it->second.begin(); line_it != lang_it->second.end(); ++line_it )
+ {
+ fprintf( fp, "%s=%s\n", line_it->first.getStr(), line_it->second.getStr() );
+ }
+ fclose( fp );
+ }
+
+ return 0;
+}