xref: /aoo41x/main/crashrep/source/unx/main.cxx (revision 79aad27f)
1*c42202c3SAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3*c42202c3SAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4*c42202c3SAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5*c42202c3SAndrew Rist  * distributed with this work for additional information
6*c42202c3SAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7*c42202c3SAndrew Rist  * to you under the Apache License, Version 2.0 (the
8*c42202c3SAndrew Rist  * "License"); you may not use this file except in compliance
9*c42202c3SAndrew Rist  * with the License.  You may obtain a copy of the License at
10*c42202c3SAndrew Rist  *
11*c42202c3SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12*c42202c3SAndrew Rist  *
13*c42202c3SAndrew Rist  * Unless required by applicable law or agreed to in writing,
14*c42202c3SAndrew Rist  * software distributed under the License is distributed on an
15*c42202c3SAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*c42202c3SAndrew Rist  * KIND, either express or implied.  See the License for the
17*c42202c3SAndrew Rist  * specific language governing permissions and limitations
18*c42202c3SAndrew Rist  * under the License.
19*c42202c3SAndrew Rist  *
20*c42202c3SAndrew Rist  *************************************************************/
21*c42202c3SAndrew Rist 
22*c42202c3SAndrew Rist 
23cdf0e10cSrcweir #include <cstdio>
24cdf0e10cSrcweir #include <stdlib.h>
25cdf0e10cSrcweir #include <sys/utsname.h>
26cdf0e10cSrcweir #include <_version.h>
27cdf0e10cSrcweir #include <errno.h>
28cdf0e10cSrcweir #include <string>
29cdf0e10cSrcweir #include <string.h>
30cdf0e10cSrcweir #include <assert.h>
31cdf0e10cSrcweir 
32cdf0e10cSrcweir #include <sys/socket.h>
33cdf0e10cSrcweir #include <netdb.h>
34cdf0e10cSrcweir #include <unistd.h>
35cdf0e10cSrcweir #include <pwd.h>
36cdf0e10cSrcweir #include <pthread.h>
37cdf0e10cSrcweir #include <limits.h>
38cdf0e10cSrcweir 
39cdf0e10cSrcweir #include <hash_map>
40cdf0e10cSrcweir #include <vector>
41cdf0e10cSrcweir #include <string>
42cdf0e10cSrcweir 
43cdf0e10cSrcweir #if defined (LINUX) || (FREEBSD)
44cdf0e10cSrcweir #include <netinet/in.h>
45cdf0e10cSrcweir #endif
46cdf0e10cSrcweir 
47cdf0e10cSrcweir typedef int SOCKET;
48cdf0e10cSrcweir 
49cdf0e10cSrcweir #define closesocket		close
50cdf0e10cSrcweir #define SOCKET_ERROR	-1
51cdf0e10cSrcweir 
52cdf0e10cSrcweir #ifdef SOLARIS
basename(const char * filename)53cdf0e10cSrcweir const char *basename( const char *filename )
54cdf0e10cSrcweir {
55cdf0e10cSrcweir 	const char *pSlash = strrchr( filename, '/' );
56cdf0e10cSrcweir 
57cdf0e10cSrcweir 	return pSlash ? pSlash + 1 : pSlash;
58cdf0e10cSrcweir }
59cdf0e10cSrcweir #endif
60cdf0e10cSrcweir 
61cdf0e10cSrcweir using namespace std;
62cdf0e10cSrcweir 
63cdf0e10cSrcweir static bool	g_bNoUI = false;
64cdf0e10cSrcweir static bool g_bSendReport = false;
65cdf0e10cSrcweir static bool g_bLoadReport = false;
66cdf0e10cSrcweir 
67cdf0e10cSrcweir static bool g_bDebugMode = false;
68cdf0e10cSrcweir static int	g_signal = 0;
69cdf0e10cSrcweir 
70cdf0e10cSrcweir static string g_strProductKey;
71cdf0e10cSrcweir static string g_strReportServer;
72cdf0e10cSrcweir static unsigned short g_uReportPort = 80;
73cdf0e10cSrcweir static string g_buildid;
74cdf0e10cSrcweir static string g_strDefaultLanguage;
75cdf0e10cSrcweir static string g_strXMLFileName;
76cdf0e10cSrcweir static string g_strPStackFileName;
77cdf0e10cSrcweir static string g_strChecksumFileName;
78cdf0e10cSrcweir static string g_strProgramDir;
79cdf0e10cSrcweir 
80cdf0e10cSrcweir static char g_szStackFile[L_tmpnam] = "";
81cdf0e10cSrcweir static char g_szDescriptionFile[2048] = "";
82cdf0e10cSrcweir static char g_szReportFile[2048] = "";
83cdf0e10cSrcweir 
84cdf0e10cSrcweir #define SO_CRASHREPORT_MAIL	"so-report@sun.com"
85cdf0e10cSrcweir #define PSTACK_CMD			"pstack %d"
86cdf0e10cSrcweir 
87cdf0e10cSrcweir #ifdef LINUX
88cdf0e10cSrcweir #define PMAP_CMD			"cat /proc/%d/maps"
89cdf0e10cSrcweir #else
90cdf0e10cSrcweir #define PMAP_CMD			"pmap %d"
91cdf0e10cSrcweir #endif
92cdf0e10cSrcweir 
93cdf0e10cSrcweir #define REPORT_SERVER	(g_strReportServer.c_str())
94cdf0e10cSrcweir #define REPORT_PORT		g_uReportPort
95cdf0e10cSrcweir 
getprogramdir()96cdf0e10cSrcweir static string getprogramdir()
97cdf0e10cSrcweir {
98cdf0e10cSrcweir 	return g_strProgramDir;
99cdf0e10cSrcweir }
100cdf0e10cSrcweir 
getlocale()101cdf0e10cSrcweir static const char *getlocale()
102cdf0e10cSrcweir {
103cdf0e10cSrcweir     const char * locale = getenv( "LC_ALL" );
104cdf0e10cSrcweir 
105cdf0e10cSrcweir     if( NULL == locale )
106cdf0e10cSrcweir         locale = getenv( "LC_CTYPE" );
107cdf0e10cSrcweir 
108cdf0e10cSrcweir     if( NULL == locale )
109cdf0e10cSrcweir         locale = getenv( "LANG" );
110cdf0e10cSrcweir 
111cdf0e10cSrcweir     if( NULL == locale )
112cdf0e10cSrcweir         locale = "C";
113cdf0e10cSrcweir 
114cdf0e10cSrcweir 	return locale;
115cdf0e10cSrcweir }
116cdf0e10cSrcweir 
get_home_dir()117cdf0e10cSrcweir static const char *get_home_dir()
118cdf0e10cSrcweir {
119cdf0e10cSrcweir 	struct passwd *ppwd = getpwuid( getuid() );
120cdf0e10cSrcweir 
121cdf0e10cSrcweir 	return ppwd ? (ppwd->pw_dir ? ppwd->pw_dir : "/") : "/";
122cdf0e10cSrcweir }
123cdf0e10cSrcweir 
trim_string(const string & rString)124cdf0e10cSrcweir static string trim_string( const string& rString )
125cdf0e10cSrcweir {
126cdf0e10cSrcweir 	string temp = rString;
127cdf0e10cSrcweir 
128cdf0e10cSrcweir 	while ( temp.length() && (temp[0] == ' ' || temp[0] == '\t') )
129cdf0e10cSrcweir 		temp.erase( 0, 1 );
130cdf0e10cSrcweir 
131cdf0e10cSrcweir 	string::size_type	len = temp.length();
132cdf0e10cSrcweir 
133cdf0e10cSrcweir 	while ( len && (temp[len-1] == ' ' || temp[len-1] == '\t') )
134cdf0e10cSrcweir 	{
135cdf0e10cSrcweir 		temp.erase( len - 1, 1 );
136cdf0e10cSrcweir 		len = temp.length();
137cdf0e10cSrcweir 	}
138cdf0e10cSrcweir 
139cdf0e10cSrcweir 	return temp;
140cdf0e10cSrcweir }
141cdf0e10cSrcweir 
xml_encode(const string & rString)142cdf0e10cSrcweir static string xml_encode( const string &rString )
143cdf0e10cSrcweir {
144cdf0e10cSrcweir 	string temp = rString;
145cdf0e10cSrcweir     string::size_type pos = 0;
146cdf0e10cSrcweir 
147cdf0e10cSrcweir 	// First replace all occurences of '&' because it may occur in further
148cdf0e10cSrcweir 	// encoded chardters too
149cdf0e10cSrcweir 
150cdf0e10cSrcweir     for( pos = 0; (pos = temp.find( '&', pos )) != string::npos; pos += 4 )
151cdf0e10cSrcweir         temp.replace( pos, 1, "&amp;" );
152cdf0e10cSrcweir 
153cdf0e10cSrcweir 	for( pos = 0; (pos = temp.find( '<', pos )) != string::npos; pos += 4 )
154cdf0e10cSrcweir         temp.replace( pos, 1, "&lt;" );
155cdf0e10cSrcweir 
156cdf0e10cSrcweir     for( pos = 0; (pos = temp.find( '>', pos )) != string::npos; pos += 4 )
157cdf0e10cSrcweir         temp.replace( pos, 1, "&gt;" );
158cdf0e10cSrcweir 
159cdf0e10cSrcweir 	return temp;
160cdf0e10cSrcweir }
161cdf0e10cSrcweir 
fcopy(FILE * fpout,FILE * fpin)162cdf0e10cSrcweir static size_t fcopy( FILE *fpout, FILE *fpin )
163cdf0e10cSrcweir {
164cdf0e10cSrcweir 	char buffer[1024];
165cdf0e10cSrcweir 	size_t nBytes;
166cdf0e10cSrcweir 	size_t nBytesWritten = 0;
167cdf0e10cSrcweir 
168cdf0e10cSrcweir 	while ( 0 != (nBytes = fread( buffer, 1, sizeof(buffer), fpin )) )
169cdf0e10cSrcweir 	{
170cdf0e10cSrcweir 		nBytesWritten += fwrite( buffer, 1, nBytes, fpout );
171cdf0e10cSrcweir 	}
172cdf0e10cSrcweir 
173cdf0e10cSrcweir 	return nBytesWritten;
174cdf0e10cSrcweir }
175cdf0e10cSrcweir 
176cdf0e10cSrcweir /*
177cdf0e10cSrcweir    writes the report to a temp-file
178cdf0e10cSrcweir    from which it can be reviewed and sent
179cdf0e10cSrcweir */
180cdf0e10cSrcweir 
write_report(const hash_map<string,string> & rSettings)181cdf0e10cSrcweir bool write_report( const hash_map< string, string >& rSettings )
182cdf0e10cSrcweir {
183cdf0e10cSrcweir 	FILE	*fp = fopen( tmpnam( g_szReportFile ), "w" );
184cdf0e10cSrcweir 	const char *pszUserType = getenv( "STAROFFICE_USERTYPE" );
185cdf0e10cSrcweir 
186cdf0e10cSrcweir 	fprintf( fp,
187cdf0e10cSrcweir 	   "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
188cdf0e10cSrcweir 	   "<!DOCTYPE errormail:errormail PUBLIC \"-//OpenOffice.org//DTD ErrorMail 1.0//EN\" \"errormail.dtd\">\n"
189cdf0e10cSrcweir 	   "<errormail:errormail xmlns:errormail=\"http://openoffice.org/2002/errormail\" usertype=\"%s\">\n"
190cdf0e10cSrcweir 	   "<reportmail:mail xmlns:reportmail=\"http://openoffice.org/2002/reportmail\" version=\"1.1\" feedback=\"%s\" email=\"%s\">\n"
191cdf0e10cSrcweir 	   "<reportmail:title>%s</reportmail:title>\n"
192cdf0e10cSrcweir 	   "<reportmail:attachment name=\"description.txt\" media-type=\"text/plain\" class=\"UserComment\"/>\n"
193cdf0e10cSrcweir 	   "<reportmail:attachment name=\"stack.txt\" media-type=\"text/plain\" class=\"pstack output\"/>\n"
194cdf0e10cSrcweir 	   "</reportmail:mail>\n"
195cdf0e10cSrcweir 	   "<officeinfo:officeinfo xmlns:officeinfo=\"http://openoffice.org/2002/officeinfo\" build=\"%s\" platform=\"%s\" language=\"%s\" exceptiontype=\"%d\" product=\"%s\" procpath=\"%s\"/>\n"
196cdf0e10cSrcweir 	   ,
197cdf0e10cSrcweir 	   pszUserType ? xml_encode( pszUserType ).c_str() : "",
198cdf0e10cSrcweir 	   xml_encode(rSettings.find( "CONTACT" )->second).c_str(),
199cdf0e10cSrcweir 	   xml_encode(rSettings.find( "EMAIL" )->second).c_str(),
200cdf0e10cSrcweir 	   xml_encode(rSettings.find( "TITLE" )->second).c_str(),
201cdf0e10cSrcweir 	   g_buildid.length() ? xml_encode( g_buildid ).c_str() : "unknown",
202cdf0e10cSrcweir 	   _INPATH,
203cdf0e10cSrcweir 	   g_strDefaultLanguage.c_str(),
204cdf0e10cSrcweir 	   g_signal,
205cdf0e10cSrcweir 	   g_strProductKey.length() ? xml_encode(g_strProductKey).c_str() : "unknown",
206cdf0e10cSrcweir 	   xml_encode(getprogramdir()).c_str()
207cdf0e10cSrcweir 	   );
208cdf0e10cSrcweir 
209cdf0e10cSrcweir 	struct utsname	info;
210cdf0e10cSrcweir 
211cdf0e10cSrcweir 	memset( &info, 0, sizeof(info) );
212cdf0e10cSrcweir 	uname( &info );
213cdf0e10cSrcweir 
214cdf0e10cSrcweir 	fprintf( fp,
215cdf0e10cSrcweir 	   "<systeminfo:systeminfo xmlns:systeminfo=\"http://openoffice.org/2002/systeminfo\">\n"
216cdf0e10cSrcweir 	   "<systeminfo:System name=\"%s\" version=\"%s\" build=\"%s\" locale=\"%s\"/>\n"
217cdf0e10cSrcweir 	   ,
218cdf0e10cSrcweir 	   xml_encode( info.sysname ).c_str(),
219cdf0e10cSrcweir 	   xml_encode( info.version ).c_str(),
220cdf0e10cSrcweir 	   xml_encode( info.release ).c_str(),
221cdf0e10cSrcweir 	   xml_encode( getlocale() ).c_str()
222cdf0e10cSrcweir 	   );
223cdf0e10cSrcweir 	fprintf( fp, "<systeminfo:CPU type=\"%s\"/>\n", xml_encode( info.machine ).c_str() );
224cdf0e10cSrcweir 	fprintf( fp, "</systeminfo:systeminfo>\n" );
225cdf0e10cSrcweir 
226cdf0e10cSrcweir 	FILE *fpxml = fopen( g_strXMLFileName.c_str(), "r" );
227cdf0e10cSrcweir 	if ( fpxml )
228cdf0e10cSrcweir 	{
229cdf0e10cSrcweir 		fcopy( fp, fpxml );
230cdf0e10cSrcweir 		fclose( fpxml );
231cdf0e10cSrcweir 	}
232cdf0e10cSrcweir 
233cdf0e10cSrcweir 	FILE *fpchk = fopen( g_strChecksumFileName.c_str(), "r" );
234cdf0e10cSrcweir 	if ( fpchk )
235cdf0e10cSrcweir 	{
236cdf0e10cSrcweir 		fcopy( fp, fpchk );
237cdf0e10cSrcweir 		fclose( fpchk );
238cdf0e10cSrcweir 	}
239cdf0e10cSrcweir 
240cdf0e10cSrcweir 	fprintf( fp, "</errormail:errormail>\n" );
241cdf0e10cSrcweir 
242cdf0e10cSrcweir 	fclose( fp );
243cdf0e10cSrcweir 
244cdf0e10cSrcweir 	return true;
245cdf0e10cSrcweir }
246cdf0e10cSrcweir 
247cdf0e10cSrcweir 
write_description(const hash_map<string,string> & rSettings)248cdf0e10cSrcweir bool write_description( const hash_map< string, string >& rSettings )
249cdf0e10cSrcweir {
250cdf0e10cSrcweir 	bool	bSuccess = false;
251cdf0e10cSrcweir 	FILE	*fp = fopen( tmpnam( g_szDescriptionFile ), "w" );
252cdf0e10cSrcweir 
253cdf0e10cSrcweir 	if ( fp )
254cdf0e10cSrcweir 	{
255cdf0e10cSrcweir 		bSuccess = true;
256cdf0e10cSrcweir 		fprintf( fp, "\xEF\xBB\xBF" );
257cdf0e10cSrcweir 		fprintf( fp, "%s\n", rSettings.find( "DESCRIPTION" )->second.c_str() );
258cdf0e10cSrcweir 		fclose( fp );
259cdf0e10cSrcweir 	}
260cdf0e10cSrcweir 
261cdf0e10cSrcweir 	return bSuccess;
262cdf0e10cSrcweir }
263cdf0e10cSrcweir 
264cdf0e10cSrcweir #if 0
265cdf0e10cSrcweir // unused
266cdf0e10cSrcweir static void printSettings( const hash_map<string,string>& rSettings )
267cdf0e10cSrcweir {
268cdf0e10cSrcweir     printf( "Settings:\n" );
269cdf0e10cSrcweir     for( hash_map<string,string>::const_iterator it = rSettings.begin(); it != rSettings.end(); ++it )
270cdf0e10cSrcweir     {
271cdf0e10cSrcweir         printf( "%s=\"%s\"\n", it->first.c_str(), it->second.c_str() );
272cdf0e10cSrcweir     }
273cdf0e10cSrcweir }
274cdf0e10cSrcweir #endif
275cdf0e10cSrcweir 
save_crash_report(const string & rFileName,const hash_map<string,string> &)276cdf0e10cSrcweir bool save_crash_report( const string& rFileName, const hash_map< string, string >& /*rSettings*/ )
277cdf0e10cSrcweir {
278cdf0e10cSrcweir 	bool bSuccess = false;
279cdf0e10cSrcweir 	FILE	*fpout = fopen( rFileName.c_str(), "w" );
280cdf0e10cSrcweir 
281cdf0e10cSrcweir 	if ( fpout )
282cdf0e10cSrcweir 	{
283cdf0e10cSrcweir 		FILE *fpin = fopen( g_szStackFile, "r" );
284cdf0e10cSrcweir 
285cdf0e10cSrcweir 		if ( fpin )
286cdf0e10cSrcweir 		{
287cdf0e10cSrcweir 			char	buf[1024];
288cdf0e10cSrcweir 
289cdf0e10cSrcweir 			while (fgets(buf, sizeof(buf), fpin) != NULL)
290cdf0e10cSrcweir 			{
291cdf0e10cSrcweir 				fputs(buf, fpout);
292cdf0e10cSrcweir 			}
293cdf0e10cSrcweir 
294cdf0e10cSrcweir 			bSuccess = true;
295cdf0e10cSrcweir 
296cdf0e10cSrcweir 			fclose ( fpin );
297cdf0e10cSrcweir 		}
298cdf0e10cSrcweir 
299cdf0e10cSrcweir 		fclose( fpout );
300cdf0e10cSrcweir 	}
301cdf0e10cSrcweir 
302cdf0e10cSrcweir     return bSuccess;
303cdf0e10cSrcweir }
304cdf0e10cSrcweir 
SendHTTPRequest(FILE * fp,const char * pszServer,unsigned short uPort=80,const char * pszProxyServer=NULL,unsigned short uProxyPort=8080)305cdf0e10cSrcweir bool SendHTTPRequest(
306cdf0e10cSrcweir 				FILE *fp,
307cdf0e10cSrcweir 				const char *pszServer,
308cdf0e10cSrcweir 				unsigned short uPort = 80,
309cdf0e10cSrcweir 				const char *pszProxyServer = NULL,
310cdf0e10cSrcweir 				unsigned short uProxyPort = 8080 )
311cdf0e10cSrcweir {
312cdf0e10cSrcweir 	bool success = false;
313cdf0e10cSrcweir 
314cdf0e10cSrcweir 	struct hostent *hp;
315cdf0e10cSrcweir 
316cdf0e10cSrcweir 	if ( pszProxyServer )
317cdf0e10cSrcweir 		hp = gethostbyname( pszProxyServer );
318cdf0e10cSrcweir 	else
319cdf0e10cSrcweir 		hp = gethostbyname( pszServer );
320cdf0e10cSrcweir 
321cdf0e10cSrcweir 	if ( hp )
322cdf0e10cSrcweir 	{
323cdf0e10cSrcweir 		SOCKET	s = socket( AF_INET, SOCK_STREAM, 0 );
324cdf0e10cSrcweir 
325cdf0e10cSrcweir 		if ( s )
326cdf0e10cSrcweir 		{
327cdf0e10cSrcweir 			struct sockaddr_in address;
328cdf0e10cSrcweir 
329cdf0e10cSrcweir 			memcpy(&(address.sin_addr.s_addr), *(hp->h_addr_list),sizeof(struct in_addr));
330cdf0e10cSrcweir 			address.sin_family = AF_INET;
331cdf0e10cSrcweir 
332cdf0e10cSrcweir 			if ( pszProxyServer )
333cdf0e10cSrcweir 				address.sin_port = ntohs( uProxyPort );
334cdf0e10cSrcweir 			else
335cdf0e10cSrcweir 				address.sin_port = ntohs( uPort );
336cdf0e10cSrcweir 
337cdf0e10cSrcweir 			if ( 0 == connect( s, (struct sockaddr *)&address, sizeof(struct sockaddr_in)) )
338cdf0e10cSrcweir 			{
339cdf0e10cSrcweir 				fseek( fp, 0, SEEK_END );
340cdf0e10cSrcweir 				size_t length = ftell( fp );
341cdf0e10cSrcweir 				fseek( fp, 0, SEEK_SET );
342cdf0e10cSrcweir 
343cdf0e10cSrcweir 				char buffer[2048];
344cdf0e10cSrcweir 
345cdf0e10cSrcweir 				if ( pszProxyServer )
346cdf0e10cSrcweir 					sprintf( buffer,
347cdf0e10cSrcweir 					"POST http://%s:%d/soap/servlet/rpcrouter HTTP/1.0\r\n"
348cdf0e10cSrcweir 						"Content-Type: text/xml; charset=\"utf-8\"\r\n"
349cdf0e10cSrcweir 						"Content-Length: %d\r\n"
350cdf0e10cSrcweir 						"SOAPAction: \"\"\r\n\r\n",
351cdf0e10cSrcweir 						pszServer,
352cdf0e10cSrcweir 						uPort,
353cdf0e10cSrcweir 						static_cast<int>(length)
354cdf0e10cSrcweir 						);
355cdf0e10cSrcweir 				else
356cdf0e10cSrcweir 					sprintf( buffer,
357cdf0e10cSrcweir 						"POST /soap/servlet/rpcrouter HTTP/1.0\r\n"
358cdf0e10cSrcweir 						"Content-Type: text/xml; charset=\"utf-8\"\r\n"
359cdf0e10cSrcweir 						"Content-Length: %d\r\n"
360cdf0e10cSrcweir 						"SOAPAction: \"\"\r\n\r\n",
361cdf0e10cSrcweir 						static_cast<int>(length)
362cdf0e10cSrcweir 						);
363cdf0e10cSrcweir 
364cdf0e10cSrcweir 				if ( g_bDebugMode )
365cdf0e10cSrcweir 				{
366cdf0e10cSrcweir 					printf( "*** Sending HTTP request ***\n\n" );
367cdf0e10cSrcweir 					printf( buffer );
368cdf0e10cSrcweir 				}
369cdf0e10cSrcweir 
370cdf0e10cSrcweir 				if ( SOCKET_ERROR != send( s, buffer, strlen(buffer), 0 ) )
371cdf0e10cSrcweir 				{
372cdf0e10cSrcweir 					size_t nBytes;
373cdf0e10cSrcweir 
374cdf0e10cSrcweir 					do
375cdf0e10cSrcweir 					{
376cdf0e10cSrcweir 						nBytes = fread( buffer, 1, sizeof(buffer), fp );
377cdf0e10cSrcweir 
378cdf0e10cSrcweir 						if ( nBytes )
379cdf0e10cSrcweir 						{
380cdf0e10cSrcweir 							if ( g_bDebugMode )
381cdf0e10cSrcweir 								fwrite( buffer, 1, nBytes, stdout );
382cdf0e10cSrcweir 							success = SOCKET_ERROR != send( s, buffer, nBytes, 0 );
383cdf0e10cSrcweir 						}
384cdf0e10cSrcweir 					} while( nBytes && success );
385cdf0e10cSrcweir 
386cdf0e10cSrcweir 					if ( success )
387cdf0e10cSrcweir 					{
388cdf0e10cSrcweir 						if ( g_bDebugMode )
389cdf0e10cSrcweir 							printf( "*** Receiving HTTP response ***\n\n" );
390cdf0e10cSrcweir 
391cdf0e10cSrcweir 						memset( buffer, 0, sizeof(buffer) );
392cdf0e10cSrcweir 						success = SOCKET_ERROR != recv( s, buffer, sizeof(buffer), 0 );
393cdf0e10cSrcweir 						if ( success )
394cdf0e10cSrcweir 						{
395cdf0e10cSrcweir 							char szHTTPSignature[sizeof(buffer)] = "";
396cdf0e10cSrcweir 							unsigned uHTTPReturnCode = 0;
397cdf0e10cSrcweir 
398cdf0e10cSrcweir 							sscanf( buffer, "%s %d ", szHTTPSignature, &uHTTPReturnCode );
399cdf0e10cSrcweir 							success = uHTTPReturnCode == 200;
400cdf0e10cSrcweir 						}
401cdf0e10cSrcweir 						if ( g_bDebugMode )
402cdf0e10cSrcweir 							do
403cdf0e10cSrcweir 							{
404cdf0e10cSrcweir 								printf( buffer );
405cdf0e10cSrcweir 								memset( buffer, 0, sizeof(buffer) );
406cdf0e10cSrcweir 							} while ( 0 < recv( s, buffer, sizeof(buffer), 0 ) );
407cdf0e10cSrcweir 					}
408cdf0e10cSrcweir 				}
409cdf0e10cSrcweir 
410cdf0e10cSrcweir 			}
411cdf0e10cSrcweir 
412cdf0e10cSrcweir 			closesocket( s );
413cdf0e10cSrcweir 		}
414cdf0e10cSrcweir 	}
415cdf0e10cSrcweir 
416cdf0e10cSrcweir 	return success;
417cdf0e10cSrcweir }
418cdf0e10cSrcweir 
WriteSOAPRequest(FILE * fp)419cdf0e10cSrcweir static void WriteSOAPRequest( FILE *fp )
420cdf0e10cSrcweir {
421cdf0e10cSrcweir 	fprintf( fp,
422cdf0e10cSrcweir 		"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
423cdf0e10cSrcweir 		"<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\"\n"
424cdf0e10cSrcweir 		"xmlns:SOAP-ENC=\"http://schemas.xmlsoap.org/soap/encoding/\"\n"
425cdf0e10cSrcweir 		"xmlns:xsi=\"http://www.w3.org/1999/XMLSchema-instance\"\n"
426cdf0e10cSrcweir 		"xmlns:xsd=\"http://www.w3.org/1999/XMLSchema\"\n"
427cdf0e10cSrcweir 		"xmlns:rds=\"urn:ReportDataService\"\n"
428cdf0e10cSrcweir 		"xmlns:apache=\"http://xml.apache.org/xml-soap\"\n"
429cdf0e10cSrcweir 		"SOAP-ENV:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">\n"
430cdf0e10cSrcweir 		"<SOAP-ENV:Body>\n"
431cdf0e10cSrcweir 		);
432cdf0e10cSrcweir 
433cdf0e10cSrcweir 	fprintf( fp, "<rds:submitReport>\n"  );
434cdf0e10cSrcweir 	fprintf( fp, "<body xsi:type=\"xsd:string\">This is an autogenerated crash report mail.</body>\n" );
435cdf0e10cSrcweir 	fprintf( fp, "<hash xsi:type=\"apache:Map\">\n" );
436cdf0e10cSrcweir 
437cdf0e10cSrcweir 	FILE	*fpin = fopen( g_szReportFile, "r" );
438cdf0e10cSrcweir 	if ( fpin )
439cdf0e10cSrcweir 	{
440cdf0e10cSrcweir 		fprintf( fp,
441cdf0e10cSrcweir 			"<item>\n"
442cdf0e10cSrcweir 			"<key xsi:type=\"xsd:string\">reportmail.xml</key>\n"
443cdf0e10cSrcweir 			"<value xsi:type=\"xsd:string\"><![CDATA[" );
444cdf0e10cSrcweir 		fcopy( fp, fpin );
445cdf0e10cSrcweir 		fprintf( fp, "]]></value></item>\n" );
446cdf0e10cSrcweir 		fclose( fpin );
447cdf0e10cSrcweir 	}
448cdf0e10cSrcweir 
449cdf0e10cSrcweir 	fpin = fopen( g_szDescriptionFile, "r" );
450cdf0e10cSrcweir 	if ( fpin )
451cdf0e10cSrcweir 	{
452cdf0e10cSrcweir 		fprintf( fp,
453cdf0e10cSrcweir 			"<item>\n"
454cdf0e10cSrcweir 			"<key xsi:type=\"xsd:string\">description.txt</key>\n"
455cdf0e10cSrcweir 			"<value xsi:type=\"xsd:string\"><![CDATA[" );
456cdf0e10cSrcweir 		fcopy( fp, fpin );
457cdf0e10cSrcweir 		fprintf( fp, "]]></value></item>\n" );
458cdf0e10cSrcweir 		fclose( fpin );
459cdf0e10cSrcweir 	};
460cdf0e10cSrcweir 
461cdf0e10cSrcweir 	fpin = fopen( g_szStackFile, "r" );
462cdf0e10cSrcweir 	if ( fpin )
463cdf0e10cSrcweir 	{
464cdf0e10cSrcweir 		fprintf( fp,
465cdf0e10cSrcweir 			"<item>\n"
466cdf0e10cSrcweir 			"<key xsi:type=\"xsd:string\">stack.txt</key>\n"
467cdf0e10cSrcweir 			"<value xsi:type=\"xsd:string\"><![CDATA[" );
468cdf0e10cSrcweir 		fcopy( fp, fpin );
469cdf0e10cSrcweir 		fprintf( fp, "]]></value></item>\n" );
470cdf0e10cSrcweir 		fclose( fpin );
471cdf0e10cSrcweir 	};
472cdf0e10cSrcweir 
473cdf0e10cSrcweir 	fprintf( fp,
474cdf0e10cSrcweir 		"</hash>\n"
475cdf0e10cSrcweir 		"</rds:submitReport>\n"
476cdf0e10cSrcweir 		"</SOAP-ENV:Body>\n"
477cdf0e10cSrcweir 		"</SOAP-ENV:Envelope>\n"
478cdf0e10cSrcweir 		);
479cdf0e10cSrcweir }
480cdf0e10cSrcweir 
481cdf0e10cSrcweir struct RequestParams
482cdf0e10cSrcweir {
483cdf0e10cSrcweir 	bool    success;
484cdf0e10cSrcweir 	FILE	*fpin;
485cdf0e10cSrcweir 	const char *pServer;
486cdf0e10cSrcweir 	unsigned short uPort;
487cdf0e10cSrcweir 	const char *pProxyServer;
488cdf0e10cSrcweir 	unsigned short uProxyPort;
489cdf0e10cSrcweir };
490cdf0e10cSrcweir 
491cdf0e10cSrcweir 
send_crash_report(const hash_map<string,string> & rSettings)492cdf0e10cSrcweir bool send_crash_report( const hash_map< string, string >& rSettings )
493cdf0e10cSrcweir {
494cdf0e10cSrcweir 	if ( 0 == strcasecmp( rSettings.find( "CONTACT" )->second.c_str(), "true" ) &&
495cdf0e10cSrcweir 		 !trim_string(rSettings.find( "EMAIL" )->second).length() )
496cdf0e10cSrcweir 	{
497cdf0e10cSrcweir 		return false;
498cdf0e10cSrcweir 	}
499cdf0e10cSrcweir 
500cdf0e10cSrcweir 	char *endptr = NULL;
501cdf0e10cSrcweir 
502cdf0e10cSrcweir 	const char *pProxyServer = rSettings.find( "SERVER" )->second.c_str();
503cdf0e10cSrcweir 	unsigned short uProxyPort = (unsigned short)strtoul( rSettings.find( "PORT" )->second.c_str(), &endptr, 10 );
504cdf0e10cSrcweir 
505cdf0e10cSrcweir 	bool bUseProxy = !strcasecmp( "true", rSettings.find( "USEPROXY" )->second.c_str() );
506cdf0e10cSrcweir 
507cdf0e10cSrcweir 
508cdf0e10cSrcweir 	write_description( rSettings );
509cdf0e10cSrcweir 	write_report( rSettings );
510cdf0e10cSrcweir 
511cdf0e10cSrcweir 	bool bSuccess = false;
512cdf0e10cSrcweir 
513cdf0e10cSrcweir 	FILE	*fptemp = tmpfile();
514cdf0e10cSrcweir 	if ( fptemp )
515cdf0e10cSrcweir 	{
516cdf0e10cSrcweir 		WriteSOAPRequest( fptemp );
517cdf0e10cSrcweir 		fseek( fptemp, 0, SEEK_SET );
518cdf0e10cSrcweir 
519cdf0e10cSrcweir 		bSuccess = SendHTTPRequest(
520cdf0e10cSrcweir 			fptemp,
521cdf0e10cSrcweir 			REPORT_SERVER, REPORT_PORT,
522cdf0e10cSrcweir 			bUseProxy ? pProxyServer : NULL,
523cdf0e10cSrcweir 			uProxyPort ? uProxyPort : 8080
524cdf0e10cSrcweir 			);
525cdf0e10cSrcweir 
526cdf0e10cSrcweir 		fclose( fptemp );
527cdf0e10cSrcweir 
528cdf0e10cSrcweir 	}
529cdf0e10cSrcweir 
530cdf0e10cSrcweir 	unlink( g_szDescriptionFile );
531cdf0e10cSrcweir 	unlink( g_szReportFile );
532cdf0e10cSrcweir 
533cdf0e10cSrcweir     return bSuccess;
534cdf0e10cSrcweir }
535cdf0e10cSrcweir 
536cdf0e10cSrcweir 
append_file(const char * filename,string & rString)537cdf0e10cSrcweir static bool append_file( const char *filename, string& rString )
538cdf0e10cSrcweir {
539cdf0e10cSrcweir 	char	buf[1024];
540cdf0e10cSrcweir 	bool	bSuccess = false;
541cdf0e10cSrcweir 
542cdf0e10cSrcweir 	FILE *fp = fopen( filename, "r" );
543cdf0e10cSrcweir 	if ( fp )
544cdf0e10cSrcweir 	{
545cdf0e10cSrcweir 		bSuccess = true;
546cdf0e10cSrcweir 		while (fgets(buf, sizeof(buf), fp) != NULL)
547cdf0e10cSrcweir 		{
548cdf0e10cSrcweir 			rString.append( buf );
549cdf0e10cSrcweir 		}
550cdf0e10cSrcweir 		fclose( fp );
551cdf0e10cSrcweir 	}
552cdf0e10cSrcweir 
553cdf0e10cSrcweir 	return true;
554cdf0e10cSrcweir }
555cdf0e10cSrcweir 
crash_get_details(const hash_map<string,string> & rSettings)556cdf0e10cSrcweir string crash_get_details( const hash_map< string, string >& rSettings )
557cdf0e10cSrcweir {
558cdf0e10cSrcweir     string aRet;
559cdf0e10cSrcweir 
560cdf0e10cSrcweir 	write_description( rSettings );
561cdf0e10cSrcweir 	write_report( rSettings );
562cdf0e10cSrcweir 
563cdf0e10cSrcweir 	aRet.append( rSettings.find( "TITLE" )->second.c_str() );
564cdf0e10cSrcweir 	aRet.append( "\n\n" );
565cdf0e10cSrcweir 	append_file( g_szDescriptionFile, aRet );
566cdf0e10cSrcweir 	aRet.append( "\n\n-------\n\n" );
567cdf0e10cSrcweir 	append_file( g_szReportFile, aRet );
568cdf0e10cSrcweir 	aRet.append( "\n\n-------\n\n" );
569cdf0e10cSrcweir 	append_file( g_szStackFile, aRet );
570cdf0e10cSrcweir 
571cdf0e10cSrcweir 	unlink( g_szDescriptionFile );
572cdf0e10cSrcweir 	unlink( g_szReportFile );
573cdf0e10cSrcweir 
574cdf0e10cSrcweir     return aRet;
575cdf0e10cSrcweir }
576cdf0e10cSrcweir 
577cdf0e10cSrcweir 
578cdf0e10cSrcweir // ensure validity of program relative paths
setup_program_dir(const char * progname)579cdf0e10cSrcweir static void setup_program_dir( const char* progname )
580cdf0e10cSrcweir {
581cdf0e10cSrcweir 	char	szCanonicProgPath[PATH_MAX];
582cdf0e10cSrcweir 
583cdf0e10cSrcweir 
584cdf0e10cSrcweir 	if ( realpath( progname, szCanonicProgPath ) )
585cdf0e10cSrcweir 	{
586cdf0e10cSrcweir 		string aDir = szCanonicProgPath;
587cdf0e10cSrcweir 
588cdf0e10cSrcweir 		size_t pos = aDir.rfind( '/' );
589cdf0e10cSrcweir 		// FIXME: search PATH if necessary
590cdf0e10cSrcweir 		assert( pos != string::npos );
591cdf0e10cSrcweir 
592cdf0e10cSrcweir 		g_strProgramDir = aDir.substr( 0, pos + 1 );
593cdf0e10cSrcweir 		aDir.erase( pos );
594cdf0e10cSrcweir 		chdir( aDir.c_str() );
595cdf0e10cSrcweir 	}
596cdf0e10cSrcweir }
597cdf0e10cSrcweir 
598cdf0e10cSrcweir //*************************************************************************
599cdf0e10cSrcweir 
setup_commandline_arguments(int argc,char ** argv,int * pSignal)600cdf0e10cSrcweir static long setup_commandline_arguments( int argc, char** argv, int *pSignal )
601cdf0e10cSrcweir {
602cdf0e10cSrcweir 	long	pid = 0;
603cdf0e10cSrcweir 	int		signal = 0;
604cdf0e10cSrcweir 
605cdf0e10cSrcweir 	for ( int n = 1; n < argc; n++ )
606cdf0e10cSrcweir 	{
607cdf0e10cSrcweir 		if ( 0 == strcmp( argv[n], "-p" ) )
608cdf0e10cSrcweir 		{
609cdf0e10cSrcweir 			if ( ++n < argc )
610cdf0e10cSrcweir 				pid = strtol( argv[n], NULL, 0 );
611cdf0e10cSrcweir 		}
612cdf0e10cSrcweir 		else if ( 0 == strcmp( argv[n], "-s" ) )
613cdf0e10cSrcweir 		{
614cdf0e10cSrcweir 			if ( ++n < argc )
615cdf0e10cSrcweir 				signal = strtol( argv[n], NULL, 0 );
616cdf0e10cSrcweir 		}
617cdf0e10cSrcweir 		else if ( 0 == strcmp( argv[n], "-debug" ) )
618cdf0e10cSrcweir 		{
619cdf0e10cSrcweir 			g_bDebugMode = true;
620cdf0e10cSrcweir 		}
621cdf0e10cSrcweir 		else if ( 0 == strcmp( argv[n], "-xml" ) )
622cdf0e10cSrcweir 		{
623cdf0e10cSrcweir 			if ( ++n < argc )
624cdf0e10cSrcweir 				g_strXMLFileName = argv[n];
625cdf0e10cSrcweir 		}
626cdf0e10cSrcweir 		else if ( 0 == strcmp( argv[n], "-stack" ) )
627cdf0e10cSrcweir 		{
628cdf0e10cSrcweir 			if ( ++n < argc )
629cdf0e10cSrcweir 				g_strPStackFileName = argv[n];
630cdf0e10cSrcweir 		}
631cdf0e10cSrcweir 		else if ( 0 == strcmp( argv[n], "-chksum" ) )
632cdf0e10cSrcweir 		{
633cdf0e10cSrcweir 			if ( ++n < argc )
634cdf0e10cSrcweir 				g_strChecksumFileName = argv[n];
635cdf0e10cSrcweir 		}
636cdf0e10cSrcweir 		else if ( 0 == strcmp( argv[n], "-noui" ) )
637cdf0e10cSrcweir 		{
638cdf0e10cSrcweir 			g_bNoUI = true;
639cdf0e10cSrcweir 		}
640cdf0e10cSrcweir 		else if ( 0 == strcmp( argv[n], "-send" ) )
641cdf0e10cSrcweir 		{
642cdf0e10cSrcweir 			g_bSendReport = true;
643cdf0e10cSrcweir 		}
644cdf0e10cSrcweir 		else if ( 0 == strcmp( argv[n], "-load" ) )
645cdf0e10cSrcweir 		{
646cdf0e10cSrcweir 			g_bLoadReport = true;
647cdf0e10cSrcweir 		}
648cdf0e10cSrcweir 		else if ( argv[n] && strlen(argv[n]) )
649cdf0e10cSrcweir 		{
650cdf0e10cSrcweir 			printf(
651cdf0e10cSrcweir 				"\n%s crash_report %s\n\n" \
652cdf0e10cSrcweir 				"/?, -h[elp]          %s\n\n" \
653cdf0e10cSrcweir 				"%-20s %s\n\n",
654cdf0e10cSrcweir 				"%MSG_CMDLINE_USAGE%",
655cdf0e10cSrcweir 				"%MSG_PARAM_PROCESSID%",
656cdf0e10cSrcweir 				"%MSG_PARAM_HELP_DESCRIPTION%",
657cdf0e10cSrcweir 				"%MSG_PARAM_PROCESSID%",
658cdf0e10cSrcweir 				"%MSG_PARAM_PROCESSID_DESCRIPTION%"
659cdf0e10cSrcweir 				);
660cdf0e10cSrcweir 			break;
661cdf0e10cSrcweir 		}
662cdf0e10cSrcweir 	}
663cdf0e10cSrcweir 
664cdf0e10cSrcweir 	*pSignal = signal;
665cdf0e10cSrcweir 
666cdf0e10cSrcweir 	return pid;
667cdf0e10cSrcweir }
668cdf0e10cSrcweir 
669cdf0e10cSrcweir //*************************************************************************
670cdf0e10cSrcweir 
read_line(FILE * fp,string & rLine)671cdf0e10cSrcweir static bool read_line( FILE *fp, string& rLine )
672cdf0e10cSrcweir {
673cdf0e10cSrcweir 	char szBuffer[1024];
674cdf0e10cSrcweir 	bool bSuccess = false;
675cdf0e10cSrcweir 	bool bEOL = false;
676cdf0e10cSrcweir 	string	line;
677cdf0e10cSrcweir 
678cdf0e10cSrcweir 
679cdf0e10cSrcweir 	while ( !bEOL && fgets( szBuffer, sizeof(szBuffer), fp ) )
680cdf0e10cSrcweir 	{
681cdf0e10cSrcweir 		int	len = strlen(szBuffer);
682cdf0e10cSrcweir 
683cdf0e10cSrcweir 		bSuccess = true;
684cdf0e10cSrcweir 
685cdf0e10cSrcweir 		while ( len && szBuffer[len - 1] == '\n' )
686cdf0e10cSrcweir 		{
687cdf0e10cSrcweir 			szBuffer[--len] = 0;
688cdf0e10cSrcweir 			bEOL = true;
689cdf0e10cSrcweir 		}
690cdf0e10cSrcweir 
691cdf0e10cSrcweir 		line.append( szBuffer );
692cdf0e10cSrcweir 	}
693cdf0e10cSrcweir 
694cdf0e10cSrcweir 	rLine = line;
695cdf0e10cSrcweir 	return bSuccess;
696cdf0e10cSrcweir }
697cdf0e10cSrcweir 
get_script_string(const char * pFileName,const char * pKeyName)698cdf0e10cSrcweir static string get_script_string( const char *pFileName, const char *pKeyName )
699cdf0e10cSrcweir {
700cdf0e10cSrcweir 	FILE	*fp = fopen( pFileName, "r" );
701cdf0e10cSrcweir 	string	retValue;
702cdf0e10cSrcweir 
703cdf0e10cSrcweir 	if ( fp )
704cdf0e10cSrcweir 	{
705cdf0e10cSrcweir 		string line;
706cdf0e10cSrcweir 		string section;
707cdf0e10cSrcweir 
708cdf0e10cSrcweir 		while ( read_line( fp, line ) )
709cdf0e10cSrcweir 		{
710cdf0e10cSrcweir 			line = trim_string( line );
711cdf0e10cSrcweir 
712cdf0e10cSrcweir 
713cdf0e10cSrcweir 			string::size_type iEqualSign = line.find( '=', 0 );
714cdf0e10cSrcweir 
715cdf0e10cSrcweir 			if ( iEqualSign != string::npos )
716cdf0e10cSrcweir 			{
717cdf0e10cSrcweir 				string	keyname = line.substr( 0, iEqualSign );
718cdf0e10cSrcweir 				keyname = trim_string( keyname );
719cdf0e10cSrcweir 
720cdf0e10cSrcweir 				string	value = line.substr( iEqualSign + 1, string::npos );
721cdf0e10cSrcweir 				value = trim_string( value );
722cdf0e10cSrcweir 
723cdf0e10cSrcweir 				if ( value.length() && '\"' == value[0] )
724cdf0e10cSrcweir 				{
725cdf0e10cSrcweir 					value.erase( 0, 1 );
726cdf0e10cSrcweir 
727cdf0e10cSrcweir 					string::size_type iQuotes = value.find( '"', 0 );
728cdf0e10cSrcweir 
729cdf0e10cSrcweir 					if ( iQuotes != string::npos )
730cdf0e10cSrcweir 						value.erase( iQuotes );
731cdf0e10cSrcweir 				}
732cdf0e10cSrcweir 
733cdf0e10cSrcweir 				if ( 0 == strcasecmp( keyname.c_str(), pKeyName ) )
734cdf0e10cSrcweir 				{
735cdf0e10cSrcweir 					retValue = value;
736cdf0e10cSrcweir 					break;
737cdf0e10cSrcweir 				}
738cdf0e10cSrcweir 			}
739cdf0e10cSrcweir 		}
740cdf0e10cSrcweir 
741cdf0e10cSrcweir 		fclose( fp );
742cdf0e10cSrcweir 	}
743cdf0e10cSrcweir 
744cdf0e10cSrcweir 	return retValue;
745cdf0e10cSrcweir }
746cdf0e10cSrcweir 
get_profile_string(const char * pFileName,const char * pSectionName,const char * pKeyName,const char * pDefault=NULL)747cdf0e10cSrcweir static string get_profile_string( const char *pFileName, const char *pSectionName, const char *pKeyName, const char *pDefault = NULL )
748cdf0e10cSrcweir {
749cdf0e10cSrcweir 	FILE	*fp = fopen( pFileName, "r" );
750cdf0e10cSrcweir 	string	retValue = pDefault ? pDefault : "";
751cdf0e10cSrcweir 
752cdf0e10cSrcweir 	if ( fp )
753cdf0e10cSrcweir 	{
754cdf0e10cSrcweir 		string line;
755cdf0e10cSrcweir 		string section;
756cdf0e10cSrcweir 
757cdf0e10cSrcweir 		while ( read_line( fp, line ) )
758cdf0e10cSrcweir 		{
759cdf0e10cSrcweir 			line = trim_string( line );
760cdf0e10cSrcweir 
761cdf0e10cSrcweir 			if ( line.length() && line[0] == '[' )
762cdf0e10cSrcweir 			{
763cdf0e10cSrcweir 				line.erase( 0, 1 );
764cdf0e10cSrcweir 				string::size_type end = line.find( ']', 0 );
765cdf0e10cSrcweir 
766cdf0e10cSrcweir 				if ( string::npos != end )
767cdf0e10cSrcweir 					section = trim_string( line.substr( 0, end ) );
768cdf0e10cSrcweir 			}
769cdf0e10cSrcweir 			else
770cdf0e10cSrcweir 			{
771cdf0e10cSrcweir 
772cdf0e10cSrcweir 				string::size_type iEqualSign = line.find( '=', 0 );
773cdf0e10cSrcweir 
774cdf0e10cSrcweir 				if ( iEqualSign != string::npos )
775cdf0e10cSrcweir 				{
776cdf0e10cSrcweir 					string	keyname = line.substr( 0, iEqualSign );
777cdf0e10cSrcweir 					keyname = trim_string( keyname );
778cdf0e10cSrcweir 
779cdf0e10cSrcweir 					string	value = line.substr( iEqualSign + 1, string::npos );
780cdf0e10cSrcweir 					value = trim_string( value );
781cdf0e10cSrcweir 
782cdf0e10cSrcweir 					if (
783cdf0e10cSrcweir 						0 == strcasecmp( section.c_str(), pSectionName ) &&
784cdf0e10cSrcweir 						0 == strcasecmp( keyname.c_str(), pKeyName )
785cdf0e10cSrcweir 						 )
786cdf0e10cSrcweir 					{
787cdf0e10cSrcweir 						retValue = value;
788cdf0e10cSrcweir 						break;
789cdf0e10cSrcweir 					}
790cdf0e10cSrcweir 				}
791cdf0e10cSrcweir 			}
792cdf0e10cSrcweir 		}
793cdf0e10cSrcweir 
794cdf0e10cSrcweir 		fclose( fp );
795cdf0e10cSrcweir 	}
796cdf0e10cSrcweir 
797cdf0e10cSrcweir 	return retValue;
798cdf0e10cSrcweir }
799cdf0e10cSrcweir 
get_environment_string(const char * pEnvName)800cdf0e10cSrcweir static string get_environment_string( const char *pEnvName )
801cdf0e10cSrcweir {
802cdf0e10cSrcweir 	const char *pEnvValue = getenv( pEnvName );
803cdf0e10cSrcweir 
804cdf0e10cSrcweir 	if ( pEnvValue )
805cdf0e10cSrcweir 		return pEnvValue;
806cdf0e10cSrcweir 	else
807cdf0e10cSrcweir 		return "";
808cdf0e10cSrcweir }
809cdf0e10cSrcweir 
read_from_file(const string & rFileName)810cdf0e10cSrcweir static string read_from_file( const string& rFileName )
811cdf0e10cSrcweir {
812cdf0e10cSrcweir 	string	content;
813cdf0e10cSrcweir 	FILE *fp = fopen( rFileName.c_str(), "r" );
814cdf0e10cSrcweir 
815cdf0e10cSrcweir 	if ( fp )
816cdf0e10cSrcweir 	{
817cdf0e10cSrcweir 		char	buffer[256 + 1];
818cdf0e10cSrcweir 		size_t	nBytesRead;
819cdf0e10cSrcweir 
820cdf0e10cSrcweir 		while( 0 != ( nBytesRead = fread( buffer, 1, sizeof(buffer) - 1,  fp ) ) )
821cdf0e10cSrcweir 		{
822cdf0e10cSrcweir 			buffer[nBytesRead] = 0;
823cdf0e10cSrcweir 			content += buffer;
824cdf0e10cSrcweir 		}
825cdf0e10cSrcweir 
826cdf0e10cSrcweir 		fclose( fp );
827cdf0e10cSrcweir 	}
828cdf0e10cSrcweir 
829cdf0e10cSrcweir 	return content;
830cdf0e10cSrcweir }
831cdf0e10cSrcweir 
832cdf0e10cSrcweir #define RCFILE ".crash_reportrc"
833cdf0e10cSrcweir #define XMLFILE ".crash_report_frames"
834cdf0e10cSrcweir #define CHKFILE ".crash_report_checksum"
835cdf0e10cSrcweir #define LCKFILE ".crash_report_unsent"
836cdf0e10cSrcweir #define PRVFILE ".crash_report_preview"
837cdf0e10cSrcweir 
load_crash_data()838cdf0e10cSrcweir static void load_crash_data()
839cdf0e10cSrcweir {
840cdf0e10cSrcweir 	g_strXMLFileName = get_home_dir();
841cdf0e10cSrcweir 	g_strXMLFileName += "/";
842cdf0e10cSrcweir 	g_strXMLFileName += string(XMLFILE);
843cdf0e10cSrcweir 
844cdf0e10cSrcweir 	g_strChecksumFileName = get_home_dir();
845cdf0e10cSrcweir 	g_strChecksumFileName += "/";
846cdf0e10cSrcweir 	g_strChecksumFileName += string(CHKFILE);
847cdf0e10cSrcweir }
848cdf0e10cSrcweir 
write_crash_data()849cdf0e10cSrcweir static bool write_crash_data()
850cdf0e10cSrcweir {
851cdf0e10cSrcweir 	bool success = true;
852cdf0e10cSrcweir 	string	sFile = get_home_dir();
853cdf0e10cSrcweir 
854cdf0e10cSrcweir 	sFile += "/";
855cdf0e10cSrcweir 	sFile += string(XMLFILE);
856cdf0e10cSrcweir 
857cdf0e10cSrcweir 	FILE *fp = fopen( sFile.c_str(), "w" );
858cdf0e10cSrcweir 
859cdf0e10cSrcweir 	if ( fp )
860cdf0e10cSrcweir 	{
861cdf0e10cSrcweir 		FILE	*fpin = fopen( g_strXMLFileName.c_str(), "r" );
862cdf0e10cSrcweir 
863cdf0e10cSrcweir 		if ( fpin )
864cdf0e10cSrcweir 		{
865cdf0e10cSrcweir 			fcopy( fp, fpin );
866cdf0e10cSrcweir 			fclose( fpin );
867cdf0e10cSrcweir 		}
868cdf0e10cSrcweir 
869cdf0e10cSrcweir 		fclose( fp );
870cdf0e10cSrcweir 	}
871cdf0e10cSrcweir 
872cdf0e10cSrcweir 	sFile = get_home_dir();
873cdf0e10cSrcweir 
874cdf0e10cSrcweir 	sFile += "/";
875cdf0e10cSrcweir 	sFile += string(CHKFILE);
876cdf0e10cSrcweir 
877cdf0e10cSrcweir 	fp = fopen( sFile.c_str(), "w" );
878cdf0e10cSrcweir 
879cdf0e10cSrcweir 	if ( fp )
880cdf0e10cSrcweir 	{
881cdf0e10cSrcweir 		FILE	*fpin = fopen( g_strChecksumFileName.c_str(), "r" );
882cdf0e10cSrcweir 
883cdf0e10cSrcweir 		if ( fpin )
884cdf0e10cSrcweir 		{
885cdf0e10cSrcweir 			fcopy( fp, fpin );
886cdf0e10cSrcweir 			fclose( fpin );
887cdf0e10cSrcweir 		}
888cdf0e10cSrcweir 
889cdf0e10cSrcweir 		fclose( fp );
890cdf0e10cSrcweir 	}
891cdf0e10cSrcweir 
892cdf0e10cSrcweir 	sFile = get_home_dir();
893cdf0e10cSrcweir 
894cdf0e10cSrcweir 	sFile += "/";
895cdf0e10cSrcweir 	sFile += string(LCKFILE);
896cdf0e10cSrcweir 
897cdf0e10cSrcweir 	fp = fopen( sFile.c_str(), "w" );
898cdf0e10cSrcweir 
899cdf0e10cSrcweir 	if ( fp )
900cdf0e10cSrcweir 	{
901cdf0e10cSrcweir 		fprintf( fp, "Unsent\n" );
902cdf0e10cSrcweir 		fclose( fp );
903cdf0e10cSrcweir 	}
904cdf0e10cSrcweir 
905cdf0e10cSrcweir 	return success;
906cdf0e10cSrcweir }
907cdf0e10cSrcweir 
908cdf0e10cSrcweir #if 0
909cdf0e10cSrcweir // unused
910cdf0e10cSrcweir static bool write_settings( const hash_map< string, string >& rSettings )
911cdf0e10cSrcweir {
912cdf0e10cSrcweir 	bool success = false;
913cdf0e10cSrcweir 	string	sRCFile = get_home_dir();
914cdf0e10cSrcweir 
915cdf0e10cSrcweir 	sRCFile += "/";
916cdf0e10cSrcweir 	sRCFile += string(RCFILE);
917cdf0e10cSrcweir 
918cdf0e10cSrcweir 	FILE *fp = fopen( sRCFile.c_str(), "w" );
919cdf0e10cSrcweir 
920cdf0e10cSrcweir 	if ( fp )
921cdf0e10cSrcweir 	{
922cdf0e10cSrcweir 		fprintf( fp, "[Options]\n" );
923cdf0e10cSrcweir 		fprintf( fp, "UseProxy=%s\n", rSettings.find( "USEPROXY" )->second.c_str() );
924cdf0e10cSrcweir 		fprintf( fp, "ProxyServer=%s\n", rSettings.find( "SERVER" )->second.c_str() );
925cdf0e10cSrcweir 		fprintf( fp, "ProxyPort=%s\n", rSettings.find( "PORT" )->second.c_str() );
926cdf0e10cSrcweir 		fprintf( fp, "ReturnAddress=%s\n", rSettings.find( "EMAIL" )->second.c_str() );
927cdf0e10cSrcweir 		fprintf( fp, "AllowContact=%s\n", rSettings.find( "CONTACT" )->second.c_str() );
928cdf0e10cSrcweir 		fclose( fp );
929cdf0e10cSrcweir 	}
930cdf0e10cSrcweir 
931cdf0e10cSrcweir 	return success;
932cdf0e10cSrcweir }
933cdf0e10cSrcweir #endif
934cdf0e10cSrcweir 
read_settings(hash_map<string,string> & rSettings)935cdf0e10cSrcweir static void read_settings( hash_map< string, string >& rSettings )
936cdf0e10cSrcweir {
937cdf0e10cSrcweir 	string	sRCFile = get_home_dir();
938cdf0e10cSrcweir 
939cdf0e10cSrcweir 	sRCFile += "/";
940cdf0e10cSrcweir 	sRCFile += string(RCFILE);
941cdf0e10cSrcweir 
942cdf0e10cSrcweir 	rSettings[ "EMAIL" ] = get_profile_string( sRCFile.c_str(), "Options", "ReturnAddress" );
943cdf0e10cSrcweir 	rSettings[ "SERVER" ] = get_profile_string( sRCFile.c_str(), "Options", "ProxyServer" );
944cdf0e10cSrcweir 	rSettings[ "PORT" ] = get_profile_string( sRCFile.c_str(), "Options", "ProxyPort" );
945cdf0e10cSrcweir 	rSettings[ "USEPROXY" ] = get_profile_string( sRCFile.c_str(), "Options", "UseProxy" );
946cdf0e10cSrcweir 	rSettings[ "CONTACT" ] = get_profile_string( sRCFile.c_str(), "Options", "AllowContact" );
947cdf0e10cSrcweir 	rSettings[ "DESCRIPTION" ] = "";
948cdf0e10cSrcweir 	rSettings[ "TITLE" ] = "";
949cdf0e10cSrcweir }
950cdf0e10cSrcweir 
read_settings_from_environment(hash_map<string,string> & rSettings)951cdf0e10cSrcweir static void read_settings_from_environment( hash_map< string, string >& rSettings )
952cdf0e10cSrcweir {
953cdf0e10cSrcweir 	string	strEnv;
954cdf0e10cSrcweir 
955cdf0e10cSrcweir 	strEnv = get_environment_string( "ERRORREPORT_RETURNADDRESS" );
956cdf0e10cSrcweir 	if ( strEnv.length() )
957cdf0e10cSrcweir 	{
958cdf0e10cSrcweir 		rSettings[ "EMAIL" ] = strEnv;
959cdf0e10cSrcweir 		if ( !(rSettings.find( "CONTACT" )->second).length() )
960cdf0e10cSrcweir 			rSettings[ "CONTACT" ] = "true";
961cdf0e10cSrcweir 	}
962cdf0e10cSrcweir 	else if ( !(rSettings.find( "CONTACT" )->second).length() )
963cdf0e10cSrcweir 		rSettings[ "CONTACT" ] = "false";
964cdf0e10cSrcweir 
965cdf0e10cSrcweir 
966cdf0e10cSrcweir 	strEnv = get_environment_string( "ERRORREPORT_HTTPPROXYSERVER" );
967cdf0e10cSrcweir 	if ( strEnv.length() )
968cdf0e10cSrcweir 		rSettings[ "SERVER" ] = strEnv;
969cdf0e10cSrcweir 
970cdf0e10cSrcweir 	strEnv = get_environment_string( "ERRORREPORT_HTTPPROXYPORT" );
971cdf0e10cSrcweir 	if ( strEnv.length() )
972cdf0e10cSrcweir 		rSettings[ "PORT" ] = strEnv;
973cdf0e10cSrcweir 
974cdf0e10cSrcweir 	strEnv = get_environment_string( "ERRORREPORT_HTTPCONNECTIONTYPE" );
975cdf0e10cSrcweir 	if ( strEnv.length() )
976cdf0e10cSrcweir 		rSettings[ "USEPROXY" ] = 0 == strcasecmp( strEnv.c_str(), "MANUALPROXY" ) ? "true" : "false";
977cdf0e10cSrcweir 
978cdf0e10cSrcweir 	strEnv = get_environment_string( "ERRORREPORT_BODYFILE" );
979cdf0e10cSrcweir 	if ( strEnv.length() )
980cdf0e10cSrcweir 		rSettings[ "DESCRIPTION" ] = read_from_file( strEnv );
981cdf0e10cSrcweir 
982cdf0e10cSrcweir 	strEnv = get_environment_string( "ERRORREPORT_SUBJECT" );
983cdf0e10cSrcweir 	if ( strEnv.length() )
984cdf0e10cSrcweir 		rSettings[ "TITLE" ] = strEnv;
985cdf0e10cSrcweir }
986cdf0e10cSrcweir 
setup_version()987cdf0e10cSrcweir static bool	setup_version()
988cdf0e10cSrcweir {
989cdf0e10cSrcweir 	if ( !getenv( "PRODUCTNAME" ) )
990cdf0e10cSrcweir 	{
991cdf0e10cSrcweir 		string productkey = get_profile_string( "bootstraprc", "Bootstrap", "ProductKey" );
992cdf0e10cSrcweir 
993cdf0e10cSrcweir 		g_strProductKey = productkey;
994cdf0e10cSrcweir 
995cdf0e10cSrcweir 		if ( productkey.length() )
996cdf0e10cSrcweir 		{
997cdf0e10cSrcweir 			static string productname;
998cdf0e10cSrcweir 			static string productversion;
999cdf0e10cSrcweir 			string::size_type	iSpace = productkey.find( ' ', 0 );
1000cdf0e10cSrcweir 
1001cdf0e10cSrcweir 			if ( string::npos != iSpace )
1002cdf0e10cSrcweir 			{
1003cdf0e10cSrcweir 				productname = productkey.substr( 0, iSpace );
1004cdf0e10cSrcweir 				productversion = productkey.substr( iSpace + 1, string::npos );
1005cdf0e10cSrcweir 			}
1006cdf0e10cSrcweir 			else
1007cdf0e10cSrcweir 				productname = productkey;
1008cdf0e10cSrcweir 
1009cdf0e10cSrcweir 			productname.insert( 0, "PRODUCTNAME=" );
1010cdf0e10cSrcweir             putenv( (char *)productname.c_str() );
1011cdf0e10cSrcweir 
1012cdf0e10cSrcweir 			productversion.insert( 0, "PRODUCTVERSION=" );
1013cdf0e10cSrcweir             putenv( (char *)productversion.c_str() );
1014cdf0e10cSrcweir 		}
1015cdf0e10cSrcweir 	}
1016cdf0e10cSrcweir 
1017cdf0e10cSrcweir 	g_buildid =	get_profile_string( "versionrc", "Version", "BuildId" );
1018cdf0e10cSrcweir 	g_strDefaultLanguage = get_script_string( "instdb.ins", "DefaultLanguage"  );
1019cdf0e10cSrcweir 
1020cdf0e10cSrcweir 	g_strReportServer = get_profile_string( "bootstraprc", "ErrorReport", "ErrorReportServer" );
1021cdf0e10cSrcweir 
1022cdf0e10cSrcweir 	string strReportPort = get_profile_string( "bootstraprc", "ErrorReport", "ErrorReportPort", "80" );
1023cdf0e10cSrcweir 	char *endptr = NULL;
1024cdf0e10cSrcweir 	unsigned short uReportPort = (unsigned short)strtoul( strReportPort.c_str(), &endptr, 10 );
1025cdf0e10cSrcweir 	g_uReportPort = uReportPort ? uReportPort : 80;
1026cdf0e10cSrcweir 
1027cdf0e10cSrcweir 	return 0 != g_strReportServer.length();
1028cdf0e10cSrcweir }
1029cdf0e10cSrcweir 
1030cdf0e10cSrcweir #if 0
1031cdf0e10cSrcweir // Use gconftool-2 to determine if gnome accessiblity is enabled
1032cdf0e10cSrcweir // unused
1033cdf0e10cSrcweir static bool get_accessibility_state()
1034cdf0e10cSrcweir {
1035cdf0e10cSrcweir 	bool bAccessible = false;
1036cdf0e10cSrcweir 	FILE *fin = popen( "gconftool-2 -g /desktop/gnome/interface/accessibility", "r");
1037cdf0e10cSrcweir 
1038cdf0e10cSrcweir 	if ( fin )
1039cdf0e10cSrcweir 	{
1040cdf0e10cSrcweir 		char buffer[sizeof("true")];
1041cdf0e10cSrcweir 
1042cdf0e10cSrcweir 		bAccessible = fgets( buffer, sizeof(buffer), fin ) && 0 == strcmp( buffer, "true" );
1043cdf0e10cSrcweir 
1044cdf0e10cSrcweir 		pclose( fin );
1045cdf0e10cSrcweir 	}
1046cdf0e10cSrcweir 
1047cdf0e10cSrcweir 	return bAccessible;
1048cdf0e10cSrcweir }
1049cdf0e10cSrcweir #endif
1050cdf0e10cSrcweir 
main(int argc,char ** argv)1051cdf0e10cSrcweir int main( int argc, char** argv )
1052cdf0e10cSrcweir {
1053cdf0e10cSrcweir 	freopen( "/dev/null", "w", stderr );
1054cdf0e10cSrcweir 
1055cdf0e10cSrcweir 	setup_program_dir( argv[0] );
1056cdf0e10cSrcweir 
1057cdf0e10cSrcweir 	// Don't start if accessiblity is enabled or report server is not given
1058cdf0e10cSrcweir 
1059cdf0e10cSrcweir 	if ( setup_version() )
1060cdf0e10cSrcweir 	{
1061cdf0e10cSrcweir 		/*long pid =*/ setup_commandline_arguments( argc, argv, &g_signal );
1062cdf0e10cSrcweir 
1063cdf0e10cSrcweir 		if ( g_bLoadReport )
1064cdf0e10cSrcweir 		{
1065cdf0e10cSrcweir 			load_crash_data();
1066cdf0e10cSrcweir 		}
1067cdf0e10cSrcweir 
1068cdf0e10cSrcweir 		if ( g_bSendReport )
1069cdf0e10cSrcweir 		{
1070cdf0e10cSrcweir 			hash_map< string, string > aDialogSettings;
1071cdf0e10cSrcweir 
1072cdf0e10cSrcweir 			read_settings( aDialogSettings );
1073cdf0e10cSrcweir 			read_settings_from_environment( aDialogSettings );
1074cdf0e10cSrcweir 
1075cdf0e10cSrcweir 			send_crash_report( aDialogSettings );
1076cdf0e10cSrcweir 		}
1077cdf0e10cSrcweir 		else
1078cdf0e10cSrcweir 		{
1079cdf0e10cSrcweir 			hash_map< string, string > aDialogSettings;
1080cdf0e10cSrcweir 
1081cdf0e10cSrcweir 			read_settings( aDialogSettings );
1082cdf0e10cSrcweir 			read_settings_from_environment( aDialogSettings );
1083cdf0e10cSrcweir 
1084cdf0e10cSrcweir 			write_crash_data();
1085cdf0e10cSrcweir 			write_report( aDialogSettings );
1086cdf0e10cSrcweir 
1087cdf0e10cSrcweir 			string	sPreviewFile = get_home_dir();
1088cdf0e10cSrcweir 			sPreviewFile += "/";
1089cdf0e10cSrcweir 			sPreviewFile += string(PRVFILE);
1090cdf0e10cSrcweir 
1091cdf0e10cSrcweir 			FILE *fpout = fopen( sPreviewFile.c_str(), "w+" );
1092cdf0e10cSrcweir 			if ( fpout )
1093cdf0e10cSrcweir 			{
1094cdf0e10cSrcweir 				FILE *fpin = fopen( g_szReportFile, "r" );
1095cdf0e10cSrcweir 				if ( fpin )
1096cdf0e10cSrcweir 				{
1097cdf0e10cSrcweir 					fcopy( fpout, fpin );
1098cdf0e10cSrcweir 					fclose( fpin );
1099cdf0e10cSrcweir 				}
1100cdf0e10cSrcweir 				fclose( fpout );
1101cdf0e10cSrcweir 			}
1102cdf0e10cSrcweir 
1103cdf0e10cSrcweir 			unlink( g_szReportFile );
1104cdf0e10cSrcweir 		}
1105cdf0e10cSrcweir 
1106cdf0e10cSrcweir 		if ( g_bLoadReport )
1107cdf0e10cSrcweir 		{
1108cdf0e10cSrcweir 			unlink( g_strXMLFileName.c_str() );
1109cdf0e10cSrcweir 			unlink( g_strChecksumFileName.c_str() );
1110cdf0e10cSrcweir 		}
1111cdf0e10cSrcweir 
1112cdf0e10cSrcweir 		unlink( g_szStackFile );
1113cdf0e10cSrcweir 
1114cdf0e10cSrcweir     	return 0;
1115cdf0e10cSrcweir 	}
1116cdf0e10cSrcweir 
1117cdf0e10cSrcweir 	return -1;
1118cdf0e10cSrcweir }
1119