2009-07-03 18:23:51 +04:00
/*
* $ Id $
*
* ede - bug - report , a tool to report bugs on EDE bugzilla instance
* Part of Equinox Desktop Environment ( EDE ) .
* Copyright ( c ) 2009 EDE Authors .
*
* This program is licensed under terms of the
* GNU General Public License version 2 or newer .
* See COPYING for details .
*/
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
# include <unistd.h>
/* used from local xmlrpc-c source */
# include <pthreadx.h>
# include <FL/Fl_Double_Window.H>
# include <FL/Fl_Button.H>
# include <FL/Fl.H>
# include <edelib/Nls.h>
# include <edelib/MessageBox.h>
# include <edelib/String.h>
# include "PulseProgress.h"
# include "Bugzilla.h"
2012-11-07 16:49:43 +04:00
# include "BugzillaSender.h"
2009-07-03 18:23:51 +04:00
2012-11-07 16:49:43 +04:00
# define EDE_BUGZILLA_XMLRPC_URL "http: //bugs.equinox-project.org/xmlrpc.cgi"
2009-07-03 18:23:51 +04:00
/* must match to existing user */
# define EDE_BUGZILLA_USER "ede-bugs@lists.sourceforge.net"
# define EDE_BUGZILLA_PASS "edebugs2709"
# define PROGRESS_STEP_REFRESH 0.06
/* message length without '\n' */
# define REPORT_STR_LEN 1024
EDELIB_NS_USING ( alert )
EDELIB_NS_USING ( message )
EDELIB_NS_USING ( String )
/* for easier passing it to the thread */
struct BugContent {
const char * bug_title ;
const char * bug_content ;
2012-11-07 16:49:43 +04:00
const char * bug_sender ;
2009-07-03 18:23:51 +04:00
} ;
static Fl_Double_Window * win ;
static PulseProgress * progress ;
static BugzillaData * bdata ;
static bool data_submitted ;
/* we use only one additional thread */
static int report_pipe [ 2 ] ;
static pthread_mutex_t runner_mutex ;
/* to prevent sending data; shared between threads */
static bool cancel_sending ;
static void write_string ( int fd , const char * str ) {
int len = strlen ( str ) ;
if ( len > REPORT_STR_LEN )
len = REPORT_STR_LEN ;
: : write ( fd , str , len ) ;
: : write ( fd , " \n " , 1 ) ;
}
/* these are messages prepended with 'FAILED' so we knows how error was emited */
static void write_string_fail ( int fd , const char * str ) {
int len = strlen ( str ) ;
if ( len > REPORT_STR_LEN ) {
/* our max message size sans 'FAILED' header */
len = REPORT_STR_LEN - 6 ;
}
: : write ( fd , " FAILED " , 6 ) ;
: : write ( fd , str , len ) ;
: : write ( fd , " \n " , 1 ) ;
}
static int read_string ( int fd , String & ret ) {
char c ;
char buf [ REPORT_STR_LEN ] ;
int i , nc ;
memset ( buf , 0 , sizeof ( buf ) ) ;
i = 0 ;
nc = : : read ( fd , & c , 1 ) ;
while ( nc > 0 & & c ! = ' \n ' & & i < REPORT_STR_LEN ) {
buf [ i ] = c ;
i = i + nc ;
nc = : : read ( fd , & c , 1 ) ;
}
buf [ i ] = ' \0 ' ;
ret = buf ;
return i ;
}
static void cancel_cb ( Fl_Widget * , void * ) {
/*
* XXX : we must not use win - > hide ( ) here , mostly due sucky xmlrpc - c design . When window
* is going to be closed , but we still have pending RPC connections , we will get assertion from
* xmlrpc - c . To prevent that , we will change cancel_state and hope thread will catch it before
* bugzilla_submit_bug ( ) is called . If it was called , we can ' t do anything about it , because data
* is already send to Bugzilla so we can only log out from it .
*
* Alternative ( and crude ) solution would be to comment assertion check xmlrpc_curl_transport . c ( 977 )
* and leave cleaning stuff to the kernel .
*/
pthread_mutex_lock ( & runner_mutex ) ;
cancel_sending = true ;
pthread_mutex_unlock ( & runner_mutex ) ;
}
static void progress_timeout ( void * ) {
progress - > step ( ) ;
Fl : : repeat_timeout ( PROGRESS_STEP_REFRESH , progress_timeout ) ;
}
static void clear_timeouts ( void ) {
Fl : : remove_timeout ( progress_timeout ) ;
}
static void report_pipe_cb ( int fd , void * ) {
String s ;
if ( read_string ( report_pipe [ 0 ] , s ) < = 0 )
return ;
/* check if the message started with 'FAILED' and see it as error */
if ( strncmp ( s . c_str ( ) , " FAILED " , 6 ) = = 0 ) {
win - > hide ( ) ;
const char * str = s . c_str ( ) ;
str + = 6 ; /* do not show our header */
alert ( str ) ;
}
progress - > copy_label ( s . c_str ( ) ) ;
/* marked as completed successfully */
if ( s = = " DONE " ) {
win - > hide ( ) ;
message ( _ ( " The report was sent successfully. Thank you for your contribution " ) ) ;
/* the only case when data was submitted correctly */
data_submitted = true ;
return ;
}
/* marked as canceled */
if ( s = = " CANCELED " )
win - > hide ( ) ;
}
static void * thread_worker ( void * d ) {
int ret ;
BugContent * data = ( BugContent * ) d ;
bool should_cancel ;
ret = bugzilla_login ( bdata , EDE_BUGZILLA_USER , EDE_BUGZILLA_PASS ) ;
if ( ret = = - 1 ) {
write_string_fail ( report_pipe [ 1 ] , _ ( " Unable to properly login. Probably the host is temporarily down or your are not connected to the internet " ) ) ;
goto done ;
}
pthread_mutex_lock ( & runner_mutex ) ;
should_cancel = cancel_sending ;
pthread_mutex_unlock ( & runner_mutex ) ;
2012-11-07 16:49:43 +04:00
/* allow user to cancel it */
sleep ( 1 ) ;
2009-07-03 18:23:51 +04:00
if ( should_cancel ) {
write_string ( report_pipe [ 1 ] , " CANCELED " ) ;
goto done ;
}
write_string ( report_pipe [ 1 ] , _ ( " Submitting the report... " ) ) ;
ret = bugzilla_submit_bug ( bdata ,
2012-11-07 16:49:43 +04:00
" ede " ,
" general " ,
data - > bug_title ,
" unspecified " ,
data - > bug_content ,
" All " ,
" All " ,
" P5 " ,
" normal " ,
data - > bug_sender ) ;
2009-07-03 18:23:51 +04:00
if ( ret = = - 1 ) {
2012-11-07 16:49:43 +04:00
write_string_fail ( report_pipe [ 1 ] , _ ( " Unable to send the data. Either your email address is not registered on EDE Tracker or the host is temporarily down " ) ) ;
2009-07-03 18:23:51 +04:00
goto done ;
}
write_string ( report_pipe [ 1 ] , _ ( " Logging out... " ) ) ;
bugzilla_logout ( bdata ) ;
write_string ( report_pipe [ 1 ] , " DONE " ) ;
done :
delete data ;
pthread_exit ( NULL ) ;
2012-11-07 16:49:43 +04:00
/* shutup the compiler */
2009-07-03 18:23:51 +04:00
return NULL ;
}
2012-11-07 16:49:43 +04:00
static void perform_send ( const char * title , const char * content , const char * sender ) {
2009-07-03 18:23:51 +04:00
pthread_t thread ;
/*
* Must be allocated since this function could quit before thread was created
* of before thread could acceess the arguments . Freeing is done in that thread .
*/
BugContent * c = new BugContent ;
c - > bug_title = title ;
c - > bug_content = content ;
2012-11-07 16:49:43 +04:00
c - > bug_sender = sender ;
2009-07-03 18:23:51 +04:00
/* Create joinable thread. Some implementations prefer this explicitly was set. */
pthread_attr_t attr ;
pthread_attr_init ( & attr ) ;
pthread_attr_setdetachstate ( & attr , PTHREAD_CREATE_JOINABLE ) ;
int rc = pthread_create ( & thread , & attr , thread_worker , ( void * ) c ) ;
if ( rc ) {
alert ( _ ( " Unable to create additional thread " ) ) ;
/* close everything */
win - > hide ( ) ;
}
pthread_attr_destroy ( & attr ) ;
}
2012-11-07 16:49:43 +04:00
bool bugzilla_send_with_progress ( const char * title , const char * content , const char * cc ) {
2009-07-03 18:23:51 +04:00
data_submitted = false ;
cancel_sending = false ;
2012-11-07 16:49:43 +04:00
/* setup communication as soon as possible */
2009-07-03 18:23:51 +04:00
if ( pipe ( report_pipe ) ! = 0 ) {
alert ( _ ( " Unable to initialize communication pipe " ) ) ;
return false ;
}
2012-11-07 16:49:43 +04:00
Fl_Button * cancel ;
2009-07-03 18:23:51 +04:00
/* register our callback on pipe */
Fl : : add_fd ( report_pipe [ 0 ] , FL_READ , report_pipe_cb ) ;
2012-11-07 16:49:43 +04:00
bdata = bugzilla_new ( EDE_BUGZILLA_XMLRPC_URL ) ;
if ( ! bdata ) {
alert ( _ ( " Unable to initialize bugzilla interface! " ) ) ;
goto send_done ;
}
/* prepare mutex */
pthread_mutex_init ( & runner_mutex , NULL ) ;
2009-07-03 18:23:51 +04:00
win = new Fl_Double_Window ( 275 , 90 , _ ( " Sending report data " ) ) ;
win - > begin ( ) ;
progress = new PulseProgress ( 10 , 20 , 255 , 25 , _ ( " Sending report... " ) ) ;
progress - > selection_color ( ( Fl_Color ) 137 ) ;
2012-11-07 16:49:43 +04:00
cancel = new Fl_Button ( 175 , 55 , 90 , 25 , _ ( " &Cancel " ) ) ;
2009-07-03 18:23:51 +04:00
cancel - > callback ( cancel_cb ) ;
win - > end ( ) ;
win - > set_modal ( ) ;
win - > show ( ) ;
progress - > label ( _ ( " Preparing data... " ) ) ;
Fl : : add_timeout ( PROGRESS_STEP_REFRESH , progress_timeout ) ;
2012-11-07 16:49:43 +04:00
perform_send ( title , content , cc ) ;
2009-07-03 18:23:51 +04:00
while ( win - > shown ( ) )
Fl : : wait ( ) ;
2012-11-07 16:49:43 +04:00
pthread_mutex_destroy ( & runner_mutex ) ;
send_done :
2009-07-03 18:23:51 +04:00
/* clear pipe callback */
Fl : : remove_fd ( report_pipe [ 0 ] ) ;
clear_timeouts ( ) ;
close ( report_pipe [ 0 ] ) ;
close ( report_pipe [ 1 ] ) ;
bugzilla_free ( bdata ) ;
/* true if we completed all stages */
return data_submitted ;
}