bug fix for userforms
[ooovba.git] / crashrep / source / unx / main.cxx
blob66253e9b6bc6eecb0b79cd61c0d89130b57df8b6
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: main.cxx,v $
10 * $Revision: 1.30 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
30 #include <cstdio>
31 #include <stdlib.h>
32 #include <sys/utsname.h>
33 #include <_version.h>
34 #include <errno.h>
35 #include <string>
36 #include <string.h>
37 #include <assert.h>
39 #include <sys/socket.h>
40 #include <netdb.h>
41 #include <unistd.h>
42 #include <pwd.h>
43 #include <pthread.h>
44 #include <limits.h>
46 #include <hash_map>
47 #include <vector>
48 #include <string>
50 #if defined (LINUX) || (FREEBSD)
51 #include <netinet/in.h>
52 #endif
54 typedef int SOCKET;
56 #define closesocket close
57 #define SOCKET_ERROR -1
59 #ifdef SOLARIS
60 const char *basename( const char *filename )
62 const char *pSlash = strrchr( filename, '/' );
64 return pSlash ? pSlash + 1 : pSlash;
66 #endif
68 using namespace std;
70 static bool g_bNoUI = false;
71 static bool g_bSendReport = false;
72 static bool g_bLoadReport = false;
74 static bool g_bDebugMode = false;
75 static int g_signal = 0;
77 static string g_strProductKey;
78 static string g_strReportServer;
79 static unsigned short g_uReportPort = 80;
80 static string g_buildid;
81 static string g_strDefaultLanguage;
82 static string g_strXMLFileName;
83 static string g_strPStackFileName;
84 static string g_strChecksumFileName;
85 static string g_strProgramDir;
87 static char g_szStackFile[L_tmpnam] = "";
88 static char g_szDescriptionFile[2048] = "";
89 static char g_szReportFile[2048] = "";
91 #define SO_CRASHREPORT_MAIL "so-report@sun.com"
92 #define PSTACK_CMD "pstack %d"
94 #ifdef LINUX
95 #define PMAP_CMD "cat /proc/%d/maps"
96 #else
97 #define PMAP_CMD "pmap %d"
98 #endif
100 #define REPORT_SERVER (g_strReportServer.c_str())
101 #define REPORT_PORT g_uReportPort
103 static string getprogramdir()
105 return g_strProgramDir;
108 static const char *getlocale()
110 const char * locale = getenv( "LC_ALL" );
112 if( NULL == locale )
113 locale = getenv( "LC_CTYPE" );
115 if( NULL == locale )
116 locale = getenv( "LANG" );
118 if( NULL == locale )
119 locale = "C";
121 return locale;
124 static const char *get_home_dir()
126 struct passwd *ppwd = getpwuid( getuid() );
128 return ppwd ? (ppwd->pw_dir ? ppwd->pw_dir : "/") : "/";
131 static string trim_string( const string& rString )
133 string temp = rString;
135 while ( temp.length() && temp[0] == ' ' || temp[0] == '\t' )
136 temp.erase( 0, 1 );
138 string::size_type len = temp.length();
140 while ( len && temp[len-1] == ' ' || temp[len-1] == '\t' )
142 temp.erase( len - 1, 1 );
143 len = temp.length();
146 return temp;
149 static string xml_encode( const string &rString )
151 string temp = rString;
152 string::size_type pos = 0;
154 // First replace all occurences of '&' because it may occur in further
155 // encoded chardters too
157 for( pos = 0; (pos = temp.find( '&', pos )) != string::npos; pos += 4 )
158 temp.replace( pos, 1, "&amp;" );
160 for( pos = 0; (pos = temp.find( '<', pos )) != string::npos; pos += 4 )
161 temp.replace( pos, 1, "&lt;" );
163 for( pos = 0; (pos = temp.find( '>', pos )) != string::npos; pos += 4 )
164 temp.replace( pos, 1, "&gt;" );
166 return temp;
169 static size_t fcopy( FILE *fpout, FILE *fpin )
171 char buffer[1024];
172 size_t nBytes;
173 size_t nBytesWritten = 0;
175 while ( 0 != (nBytes = fread( buffer, 1, sizeof(buffer), fpin )) )
177 nBytesWritten += fwrite( buffer, 1, nBytes, fpout );
180 return nBytesWritten;
184 writes the report to a temp-file
185 from which it can be reviewed and sent
188 bool write_report( const hash_map< string, string >& rSettings )
190 FILE *fp = fopen( tmpnam( g_szReportFile ), "w" );
191 const char *pszUserType = getenv( "STAROFFICE_USERTYPE" );
193 fprintf( fp,
194 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
195 "<!DOCTYPE errormail:errormail PUBLIC \"-//OpenOffice.org//DTD ErrorMail 1.0//EN\" \"errormail.dtd\">\n"
196 "<errormail:errormail xmlns:errormail=\"http://openoffice.org/2002/errormail\" usertype=\"%s\">\n"
197 "<reportmail:mail xmlns:reportmail=\"http://openoffice.org/2002/reportmail\" version=\"1.1\" feedback=\"%s\" email=\"%s\">\n"
198 "<reportmail:title>%s</reportmail:title>\n"
199 "<reportmail:attachment name=\"description.txt\" media-type=\"text/plain\" class=\"UserComment\"/>\n"
200 "<reportmail:attachment name=\"stack.txt\" media-type=\"text/plain\" class=\"pstack output\"/>\n"
201 "</reportmail:mail>\n"
202 "<officeinfo:officeinfo xmlns:officeinfo=\"http://openoffice.org/2002/officeinfo\" build=\"%s\" platform=\"%s\" language=\"%s\" exceptiontype=\"%d\" product=\"%s\" procpath=\"%s\"/>\n"
204 pszUserType ? xml_encode( pszUserType ).c_str() : "",
205 xml_encode(rSettings.find( "CONTACT" )->second).c_str(),
206 xml_encode(rSettings.find( "EMAIL" )->second).c_str(),
207 xml_encode(rSettings.find( "TITLE" )->second).c_str(),
208 g_buildid.length() ? xml_encode( g_buildid ).c_str() : "unknown",
209 _INPATH,
210 g_strDefaultLanguage.c_str(),
211 g_signal,
212 g_strProductKey.length() ? xml_encode(g_strProductKey).c_str() : "unknown",
213 xml_encode(getprogramdir()).c_str()
216 struct utsname info;
218 memset( &info, 0, sizeof(info) );
219 uname( &info );
221 fprintf( fp,
222 "<systeminfo:systeminfo xmlns:systeminfo=\"http://openoffice.org/2002/systeminfo\">\n"
223 "<systeminfo:System name=\"%s\" version=\"%s\" build=\"%s\" locale=\"%s\"/>\n"
225 xml_encode( info.sysname ).c_str(),
226 xml_encode( info.version ).c_str(),
227 xml_encode( info.release ).c_str(),
228 xml_encode( getlocale() ).c_str()
230 fprintf( fp, "<systeminfo:CPU type=\"%s\"/>\n", xml_encode( info.machine ).c_str() );
231 fprintf( fp, "</systeminfo:systeminfo>\n" );
233 FILE *fpxml = fopen( g_strXMLFileName.c_str(), "r" );
234 if ( fpxml )
236 fcopy( fp, fpxml );
237 fclose( fpxml );
240 FILE *fpchk = fopen( g_strChecksumFileName.c_str(), "r" );
241 if ( fpchk )
243 fcopy( fp, fpchk );
244 fclose( fpchk );
247 fprintf( fp, "</errormail:errormail>\n" );
249 fclose( fp );
251 return true;
255 bool write_description( const hash_map< string, string >& rSettings )
257 bool bSuccess = false;
258 FILE *fp = fopen( tmpnam( g_szDescriptionFile ), "w" );
260 if ( fp )
262 bSuccess = true;
263 fprintf( fp, "\xEF\xBB\xBF" );
264 fprintf( fp, "%s\n", rSettings.find( "DESCRIPTION" )->second.c_str() );
265 fclose( fp );
268 return bSuccess;
271 #if 0
272 // unused
273 static void printSettings( const hash_map<string,string>& rSettings )
275 printf( "Settings:\n" );
276 for( hash_map<string,string>::const_iterator it = rSettings.begin(); it != rSettings.end(); ++it )
278 printf( "%s=\"%s\"\n", it->first.c_str(), it->second.c_str() );
281 #endif
283 bool save_crash_report( const string& rFileName, const hash_map< string, string >& /*rSettings*/ )
285 bool bSuccess = false;
286 FILE *fpout = fopen( rFileName.c_str(), "w" );
288 if ( fpout )
290 FILE *fpin = fopen( g_szStackFile, "r" );
292 if ( fpin )
294 char buf[1024];
296 while (fgets(buf, sizeof(buf), fpin) != NULL)
298 fputs(buf, fpout);
301 bSuccess = true;
303 fclose ( fpin );
306 fclose( fpout );
309 return bSuccess;
312 bool SendHTTPRequest(
313 FILE *fp,
314 const char *pszServer,
315 unsigned short uPort = 80,
316 const char *pszProxyServer = NULL,
317 unsigned short uProxyPort = 8080 )
319 bool success = false;
321 struct hostent *hp;
323 if ( pszProxyServer )
324 hp = gethostbyname( pszProxyServer );
325 else
326 hp = gethostbyname( pszServer );
328 if ( hp )
330 SOCKET s = socket( AF_INET, SOCK_STREAM, 0 );
332 if ( s )
334 struct sockaddr_in address;
336 memcpy(&(address.sin_addr.s_addr), *(hp->h_addr_list),sizeof(struct in_addr));
337 address.sin_family = AF_INET;
339 if ( pszProxyServer )
340 address.sin_port = ntohs( uProxyPort );
341 else
342 address.sin_port = ntohs( uPort );
344 if ( 0 == connect( s, (struct sockaddr *)&address, sizeof(struct sockaddr_in)) )
346 fseek( fp, 0, SEEK_END );
347 size_t length = ftell( fp );
348 fseek( fp, 0, SEEK_SET );
350 char buffer[2048];
352 if ( pszProxyServer )
353 sprintf( buffer,
354 "POST http://%s:%d/soap/servlet/rpcrouter HTTP/1.0\r\n"
355 "Content-Type: text/xml; charset=\"utf-8\"\r\n"
356 "Content-Length: %d\r\n"
357 "SOAPAction: \"\"\r\n\r\n",
358 pszServer,
359 uPort,
360 (int)length
362 else
363 sprintf( buffer,
364 "POST /soap/servlet/rpcrouter HTTP/1.0\r\n"
365 "Content-Type: text/xml; charset=\"utf-8\"\r\n"
366 "Content-Length: %d\r\n"
367 "SOAPAction: \"\"\r\n\r\n",
368 (int)length
371 if ( g_bDebugMode )
373 printf( "*** Sending HTTP request ***\n\n" );
374 printf( buffer );
377 if ( SOCKET_ERROR != send( s, buffer, strlen(buffer), 0 ) )
379 size_t nBytes;
383 nBytes = fread( buffer, 1, sizeof(buffer), fp );
385 if ( nBytes )
387 if ( g_bDebugMode )
388 fwrite( buffer, 1, nBytes, stdout );
389 success = SOCKET_ERROR != send( s, buffer, nBytes, 0 );
391 } while( nBytes && success );
393 if ( success )
395 if ( g_bDebugMode )
396 printf( "*** Receiving HTTP response ***\n\n" );
398 memset( buffer, 0, sizeof(buffer) );
399 success = SOCKET_ERROR != recv( s, buffer, sizeof(buffer), 0 );
400 if ( success )
402 char szHTTPSignature[sizeof(buffer)] = "";
403 unsigned uHTTPReturnCode = 0;
405 sscanf( buffer, "%s %d ", szHTTPSignature, &uHTTPReturnCode );
406 success = uHTTPReturnCode == 200;
408 if ( g_bDebugMode )
411 printf( buffer );
412 memset( buffer, 0, sizeof(buffer) );
413 } while ( 0 < recv( s, buffer, sizeof(buffer), 0 ) );
419 closesocket( s );
423 return success;
426 static void WriteSOAPRequest( FILE *fp )
428 fprintf( fp,
429 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
430 "<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\"\n"
431 "xmlns:SOAP-ENC=\"http://schemas.xmlsoap.org/soap/encoding/\"\n"
432 "xmlns:xsi=\"http://www.w3.org/1999/XMLSchema-instance\"\n"
433 "xmlns:xsd=\"http://www.w3.org/1999/XMLSchema\"\n"
434 "xmlns:rds=\"urn:ReportDataService\"\n"
435 "xmlns:apache=\"http://xml.apache.org/xml-soap\"\n"
436 "SOAP-ENV:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">\n"
437 "<SOAP-ENV:Body>\n"
440 fprintf( fp, "<rds:submitReport>\n" );
441 fprintf( fp, "<body xsi:type=\"xsd:string\">This is an autogenerated crash report mail.</body>\n" );
442 fprintf( fp, "<hash xsi:type=\"apache:Map\">\n" );
444 FILE *fpin = fopen( g_szReportFile, "r" );
445 if ( fpin )
447 fprintf( fp,
448 "<item>\n"
449 "<key xsi:type=\"xsd:string\">reportmail.xml</key>\n"
450 "<value xsi:type=\"xsd:string\"><![CDATA[" );
451 fcopy( fp, fpin );
452 fprintf( fp, "]]></value></item>\n" );
453 fclose( fpin );
456 fpin = fopen( g_szDescriptionFile, "r" );
457 if ( fpin )
459 fprintf( fp,
460 "<item>\n"
461 "<key xsi:type=\"xsd:string\">description.txt</key>\n"
462 "<value xsi:type=\"xsd:string\"><![CDATA[" );
463 fcopy( fp, fpin );
464 fprintf( fp, "]]></value></item>\n" );
465 fclose( fpin );
468 fpin = fopen( g_szStackFile, "r" );
469 if ( fpin )
471 fprintf( fp,
472 "<item>\n"
473 "<key xsi:type=\"xsd:string\">stack.txt</key>\n"
474 "<value xsi:type=\"xsd:string\"><![CDATA[" );
475 fcopy( fp, fpin );
476 fprintf( fp, "]]></value></item>\n" );
477 fclose( fpin );
480 fprintf( fp,
481 "</hash>\n"
482 "</rds:submitReport>\n"
483 "</SOAP-ENV:Body>\n"
484 "</SOAP-ENV:Envelope>\n"
488 struct RequestParams
490 bool success;
491 FILE *fpin;
492 const char *pServer;
493 unsigned short uPort;
494 const char *pProxyServer;
495 unsigned short uProxyPort;
499 bool send_crash_report( const hash_map< string, string >& rSettings )
501 if ( 0 == strcasecmp( rSettings.find( "CONTACT" )->second.c_str(), "true" ) &&
502 !trim_string(rSettings.find( "EMAIL" )->second).length() )
504 return false;
507 char *endptr = NULL;
509 const char *pProxyServer = rSettings.find( "SERVER" )->second.c_str();
510 unsigned short uProxyPort = (unsigned short)strtoul( rSettings.find( "PORT" )->second.c_str(), &endptr, 10 );
512 bool bUseProxy = !strcasecmp( "true", rSettings.find( "USEPROXY" )->second.c_str() );
515 write_description( rSettings );
516 write_report( rSettings );
518 bool bSuccess = false;
520 FILE *fptemp = tmpfile();
521 if ( fptemp )
523 WriteSOAPRequest( fptemp );
524 fseek( fptemp, 0, SEEK_SET );
526 bSuccess = SendHTTPRequest(
527 fptemp,
528 REPORT_SERVER, REPORT_PORT,
529 bUseProxy ? pProxyServer : NULL,
530 uProxyPort ? uProxyPort : 8080
533 fclose( fptemp );
537 unlink( g_szDescriptionFile );
538 unlink( g_szReportFile );
540 return bSuccess;
544 static bool append_file( const char *filename, string& rString )
546 char buf[1024];
547 bool bSuccess = false;
549 FILE *fp = fopen( filename, "r" );
550 if ( fp )
552 bSuccess = true;
553 while (fgets(buf, sizeof(buf), fp) != NULL)
555 rString.append( buf );
557 fclose( fp );
560 return true;
563 string crash_get_details( const hash_map< string, string >& rSettings )
565 string aRet;
567 write_description( rSettings );
568 write_report( rSettings );
570 aRet.append( rSettings.find( "TITLE" )->second.c_str() );
571 aRet.append( "\n\n" );
572 append_file( g_szDescriptionFile, aRet );
573 aRet.append( "\n\n-------\n\n" );
574 append_file( g_szReportFile, aRet );
575 aRet.append( "\n\n-------\n\n" );
576 append_file( g_szStackFile, aRet );
578 unlink( g_szDescriptionFile );
579 unlink( g_szReportFile );
581 return aRet;
585 // ensure validity of program relative paths
586 static void setup_program_dir( const char* progname )
588 char szCanonicProgPath[PATH_MAX];
591 if ( realpath( progname, szCanonicProgPath ) )
593 string aDir = szCanonicProgPath;
595 size_t pos = aDir.rfind( '/' );
596 // FIXME: search PATH if necessary
597 assert( pos != string::npos );
599 g_strProgramDir = aDir.substr( 0, pos + 1 );
600 aDir.erase( pos );
601 chdir( aDir.c_str() );
605 //*************************************************************************
607 static long setup_commandline_arguments( int argc, char** argv, int *pSignal )
609 long pid = 0;
610 int signal = 0;
612 for ( int n = 1; n < argc; n++ )
614 if ( 0 == strcmp( argv[n], "-p" ) )
616 if ( ++n < argc )
617 pid = strtol( argv[n], NULL, 0 );
619 else if ( 0 == strcmp( argv[n], "-s" ) )
621 if ( ++n < argc )
622 signal = strtol( argv[n], NULL, 0 );
624 else if ( 0 == strcmp( argv[n], "-debug" ) )
626 g_bDebugMode = true;
628 else if ( 0 == strcmp( argv[n], "-xml" ) )
630 if ( ++n < argc )
631 g_strXMLFileName = argv[n];
633 else if ( 0 == strcmp( argv[n], "-stack" ) )
635 if ( ++n < argc )
636 g_strPStackFileName = argv[n];
638 else if ( 0 == strcmp( argv[n], "-chksum" ) )
640 if ( ++n < argc )
641 g_strChecksumFileName = argv[n];
643 else if ( 0 == strcmp( argv[n], "-noui" ) )
645 g_bNoUI = true;
647 else if ( 0 == strcmp( argv[n], "-send" ) )
649 g_bSendReport = true;
651 else if ( 0 == strcmp( argv[n], "-load" ) )
653 g_bLoadReport = true;
655 else if ( argv[n] && strlen(argv[n]) )
657 printf(
658 "\n%s crash_report %s\n\n" \
659 "/?, -h[elp] %s\n\n" \
660 "%-20s %s\n\n",
661 "%MSG_CMDLINE_USAGE%",
662 "%MSG_PARAM_PROCESSID%",
663 "%MSG_PARAM_HELP_DESCRIPTION%",
664 "%MSG_PARAM_PROCESSID%",
665 "%MSG_PARAM_PROCESSID_DESCRIPTION%"
667 break;
671 *pSignal = signal;
673 return pid;
676 //*************************************************************************
678 static bool read_line( FILE *fp, string& rLine )
680 char szBuffer[1024];
681 bool bSuccess = false;
682 bool bEOL = false;
683 string line;
686 while ( !bEOL && fgets( szBuffer, sizeof(szBuffer), fp ) )
688 int len = strlen(szBuffer);
690 bSuccess = true;
692 while ( len && szBuffer[len - 1] == '\n' )
694 szBuffer[--len] = 0;
695 bEOL = true;
698 line.append( szBuffer );
701 rLine = line;
702 return bSuccess;
705 static string get_script_string( const char *pFileName, const char *pKeyName )
707 FILE *fp = fopen( pFileName, "r" );
708 string retValue;
710 if ( fp )
712 string line;
713 string section;
715 while ( read_line( fp, line ) )
717 line = trim_string( line );
720 string::size_type iEqualSign = line.find( '=', 0 );
722 if ( iEqualSign != string::npos )
724 string keyname = line.substr( 0, iEqualSign );
725 keyname = trim_string( keyname );
727 string value = line.substr( iEqualSign + 1, string::npos );
728 value = trim_string( value );
730 if ( value.length() && '\"' == value[0] )
732 value.erase( 0, 1 );
734 string::size_type iQuotes = value.find( '"', 0 );
736 if ( iQuotes != string::npos )
737 value.erase( iQuotes );
740 if ( 0 == strcasecmp( keyname.c_str(), pKeyName ) )
742 retValue = value;
743 break;
748 fclose( fp );
751 return retValue;
754 static string get_profile_string( const char *pFileName, const char *pSectionName, const char *pKeyName, const char *pDefault = NULL )
756 FILE *fp = fopen( pFileName, "r" );
757 string retValue = pDefault ? pDefault : "";
759 if ( fp )
761 string line;
762 string section;
764 while ( read_line( fp, line ) )
766 line = trim_string( line );
768 if ( line.length() && line[0] == '[' )
770 line.erase( 0, 1 );
771 string::size_type end = line.find( ']', 0 );
773 if ( string::npos != end )
774 section = trim_string( line.substr( 0, end ) );
776 else
779 string::size_type iEqualSign = line.find( '=', 0 );
781 if ( iEqualSign != string::npos )
783 string keyname = line.substr( 0, iEqualSign );
784 keyname = trim_string( keyname );
786 string value = line.substr( iEqualSign + 1, string::npos );
787 value = trim_string( value );
789 if (
790 0 == strcasecmp( section.c_str(), pSectionName ) &&
791 0 == strcasecmp( keyname.c_str(), pKeyName )
794 retValue = value;
795 break;
801 fclose( fp );
804 return retValue;
807 static string get_environment_string( const char *pEnvName )
809 const char *pEnvValue = getenv( pEnvName );
811 if ( pEnvValue )
812 return pEnvValue;
813 else
814 return "";
817 static string read_from_file( const string& rFileName )
819 string content;
820 FILE *fp = fopen( rFileName.c_str(), "r" );
822 if ( fp )
824 char buffer[256 + 1];
825 size_t nBytesRead;
827 while( 0 != ( nBytesRead = fread( buffer, 1, sizeof(buffer) - 1, fp ) ) )
829 buffer[nBytesRead] = 0;
830 content += buffer;
833 fclose( fp );
836 return content;
839 #define RCFILE ".crash_reportrc"
840 #define XMLFILE ".crash_report_frames"
841 #define CHKFILE ".crash_report_checksum"
842 #define LCKFILE ".crash_report_unsent"
843 #define PRVFILE ".crash_report_preview"
845 static void load_crash_data()
847 g_strXMLFileName = get_home_dir();
848 g_strXMLFileName += "/";
849 g_strXMLFileName += string(XMLFILE);
851 g_strChecksumFileName = get_home_dir();
852 g_strChecksumFileName += "/";
853 g_strChecksumFileName += string(CHKFILE);
856 static bool write_crash_data()
858 bool success = true;
859 string sFile = get_home_dir();
861 sFile += "/";
862 sFile += string(XMLFILE);
864 FILE *fp = fopen( sFile.c_str(), "w" );
866 if ( fp )
868 FILE *fpin = fopen( g_strXMLFileName.c_str(), "r" );
870 if ( fpin )
872 fcopy( fp, fpin );
873 fclose( fpin );
876 fclose( fp );
879 sFile = get_home_dir();
881 sFile += "/";
882 sFile += string(CHKFILE);
884 fp = fopen( sFile.c_str(), "w" );
886 if ( fp )
888 FILE *fpin = fopen( g_strChecksumFileName.c_str(), "r" );
890 if ( fpin )
892 fcopy( fp, fpin );
893 fclose( fpin );
896 fclose( fp );
899 sFile = get_home_dir();
901 sFile += "/";
902 sFile += string(LCKFILE);
904 fp = fopen( sFile.c_str(), "w" );
906 if ( fp )
908 fprintf( fp, "Unsent\n" );
909 fclose( fp );
912 return success;
915 #if 0
916 // unused
917 static bool write_settings( const hash_map< string, string >& rSettings )
919 bool success = false;
920 string sRCFile = get_home_dir();
922 sRCFile += "/";
923 sRCFile += string(RCFILE);
925 FILE *fp = fopen( sRCFile.c_str(), "w" );
927 if ( fp )
929 fprintf( fp, "[Options]\n" );
930 fprintf( fp, "UseProxy=%s\n", rSettings.find( "USEPROXY" )->second.c_str() );
931 fprintf( fp, "ProxyServer=%s\n", rSettings.find( "SERVER" )->second.c_str() );
932 fprintf( fp, "ProxyPort=%s\n", rSettings.find( "PORT" )->second.c_str() );
933 fprintf( fp, "ReturnAddress=%s\n", rSettings.find( "EMAIL" )->second.c_str() );
934 fprintf( fp, "AllowContact=%s\n", rSettings.find( "CONTACT" )->second.c_str() );
935 fclose( fp );
938 return success;
940 #endif
942 static void read_settings( hash_map< string, string >& rSettings )
944 string sRCFile = get_home_dir();
946 sRCFile += "/";
947 sRCFile += string(RCFILE);
949 rSettings[ "EMAIL" ] = get_profile_string( sRCFile.c_str(), "Options", "ReturnAddress" );
950 rSettings[ "SERVER" ] = get_profile_string( sRCFile.c_str(), "Options", "ProxyServer" );
951 rSettings[ "PORT" ] = get_profile_string( sRCFile.c_str(), "Options", "ProxyPort" );
952 rSettings[ "USEPROXY" ] = get_profile_string( sRCFile.c_str(), "Options", "UseProxy" );
953 rSettings[ "CONTACT" ] = get_profile_string( sRCFile.c_str(), "Options", "AllowContact" );
954 rSettings[ "DESCRIPTION" ] = "";
955 rSettings[ "TITLE" ] = "";
958 static void read_settings_from_environment( hash_map< string, string >& rSettings )
960 string strEnv;
962 strEnv = get_environment_string( "ERRORREPORT_RETURNADDRESS" );
963 if ( strEnv.length() )
965 rSettings[ "EMAIL" ] = strEnv;
966 if ( !(rSettings.find( "CONTACT" )->second).length() )
967 rSettings[ "CONTACT" ] = "true";
969 else if ( !(rSettings.find( "CONTACT" )->second).length() )
970 rSettings[ "CONTACT" ] = "false";
973 strEnv = get_environment_string( "ERRORREPORT_HTTPPROXYSERVER" );
974 if ( strEnv.length() )
975 rSettings[ "SERVER" ] = strEnv;
977 strEnv = get_environment_string( "ERRORREPORT_HTTPPROXYPORT" );
978 if ( strEnv.length() )
979 rSettings[ "PORT" ] = strEnv;
981 strEnv = get_environment_string( "ERRORREPORT_HTTPCONNECTIONTYPE" );
982 if ( strEnv.length() )
983 rSettings[ "USEPROXY" ] = 0 == strcasecmp( strEnv.c_str(), "MANUALPROXY" ) ? "true" : "false";
985 strEnv = get_environment_string( "ERRORREPORT_BODYFILE" );
986 if ( strEnv.length() )
987 rSettings[ "DESCRIPTION" ] = read_from_file( strEnv );
989 strEnv = get_environment_string( "ERRORREPORT_SUBJECT" );
990 if ( strEnv.length() )
991 rSettings[ "TITLE" ] = strEnv;
994 static bool setup_version()
996 if ( !getenv( "PRODUCTNAME" ) )
998 string productkey = get_profile_string( "bootstraprc", "Bootstrap", "ProductKey" );
1000 g_strProductKey = productkey;
1002 if ( productkey.length() )
1004 static string productname;
1005 static string productversion;
1006 string::size_type iSpace = productkey.find( ' ', 0 );
1008 if ( string::npos != iSpace )
1010 productname = productkey.substr( 0, iSpace );
1011 productversion = productkey.substr( iSpace + 1, string::npos );
1013 else
1014 productname = productkey;
1016 productname.insert( 0, "PRODUCTNAME=" );
1017 putenv( (char *)productname.c_str() );
1019 productversion.insert( 0, "PRODUCTVERSION=" );
1020 putenv( (char *)productversion.c_str() );
1024 g_buildid = get_profile_string( "versionrc", "Version", "BuildId" );
1025 g_strDefaultLanguage = get_script_string( "instdb.ins", "DefaultLanguage" );
1027 g_strReportServer = get_profile_string( "bootstraprc", "ErrorReport", "ErrorReportServer" );
1029 string strReportPort = get_profile_string( "bootstraprc", "ErrorReport", "ErrorReportPort", "80" );
1030 char *endptr = NULL;
1031 unsigned short uReportPort = (unsigned short)strtoul( strReportPort.c_str(), &endptr, 10 );
1032 g_uReportPort = uReportPort ? uReportPort : 80;
1034 return 0 != g_strReportServer.length();
1037 #if 0
1038 // Use gconftool-2 to determine if gnome accessiblity is enabled
1039 // unused
1040 static bool get_accessibility_state()
1042 bool bAccessible = false;
1043 FILE *fin = popen( "gconftool-2 -g /desktop/gnome/interface/accessibility", "r");
1045 if ( fin )
1047 char buffer[sizeof("true")];
1049 bAccessible = fgets( buffer, sizeof(buffer), fin ) && 0 == strcmp( buffer, "true" );
1051 pclose( fin );
1054 return bAccessible;
1056 #endif
1058 int main( int argc, char** argv )
1060 freopen( "/dev/null", "w", stderr );
1062 setup_program_dir( argv[0] );
1064 // Don't start if accessiblity is enabled or report server is not given
1066 if ( setup_version() )
1068 /*long pid =*/ setup_commandline_arguments( argc, argv, &g_signal );
1070 if ( g_bLoadReport )
1072 load_crash_data();
1075 if ( g_bSendReport )
1077 hash_map< string, string > aDialogSettings;
1079 read_settings( aDialogSettings );
1080 read_settings_from_environment( aDialogSettings );
1082 send_crash_report( aDialogSettings );
1084 else
1086 hash_map< string, string > aDialogSettings;
1088 read_settings( aDialogSettings );
1089 read_settings_from_environment( aDialogSettings );
1091 write_crash_data();
1092 write_report( aDialogSettings );
1094 string sPreviewFile = get_home_dir();
1095 sPreviewFile += "/";
1096 sPreviewFile += string(PRVFILE);
1098 FILE *fpout = fopen( sPreviewFile.c_str(), "w+" );
1099 if ( fpout )
1101 FILE *fpin = fopen( g_szReportFile, "r" );
1102 if ( fpin )
1104 fcopy( fpout, fpin );
1105 fclose( fpin );
1107 fclose( fpout );
1110 unlink( g_szReportFile );
1113 if ( g_bLoadReport )
1115 unlink( g_strXMLFileName.c_str() );
1116 unlink( g_strChecksumFileName.c_str() );
1119 unlink( g_szStackFile );
1121 return 0;
1124 return -1;