00001
00033 #include "llcrashloggermac.h"
00034
00035 #include <Carbon/Carbon.h>
00036 #include <iostream>
00037 #include <sstream>
00038
00039 #include "boost/tokenizer.hpp"
00040
00041 #include "indra_constants.h"
00042 #include "llerror.h"
00043 #include "llfile.h"
00044 #include "lltimer.h"
00045 #include "llstring.h"
00046 #include "lldir.h"
00047 #include "llsdserialize.h"
00048
00049 #define MAX_LOADSTRING 100
00050 const char* const SETTINGS_FILE_HEADER = "version";
00051 const S32 SETTINGS_FILE_VERSION = 101;
00052
00053
00054
00055 BOOL gFirstDialog = TRUE;
00056 LLFILE *gDebugFile = NULL;
00057
00058 WindowRef gWindow = NULL;
00059 EventHandlerRef gEventHandler = NULL;
00060 LLString gUserNotes = "";
00061 bool gSendReport = false;
00062 bool gRememberChoice = false;
00063 IBNibRef nib = NULL;
00064
00065 OSStatus dialogHandler(EventHandlerCallRef handler, EventRef event, void *userdata)
00066 {
00067 OSStatus result = eventNotHandledErr;
00068 OSStatus err;
00069 UInt32 evtClass = GetEventClass(event);
00070 UInt32 evtKind = GetEventKind(event);
00071 if((evtClass == kEventClassCommand) && (evtKind == kEventCommandProcess))
00072 {
00073 HICommand cmd;
00074 err = GetEventParameter(event, kEventParamDirectObject, typeHICommand, NULL, sizeof(cmd), NULL, &cmd);
00075
00076
00077
00078 if(err == noErr)
00079 {
00080
00081 ControlID id;
00082 ControlRef checkBox = NULL;
00083 id.signature = 'remb';
00084 id.id = 0;
00085 err = GetControlByID(gWindow, &id, &checkBox);
00086
00087 if(err == noErr)
00088 {
00089 if(GetControl32BitValue(checkBox) == kControlCheckBoxCheckedValue)
00090 {
00091 gRememberChoice = true;
00092 }
00093 else
00094 {
00095 gRememberChoice = false;
00096 }
00097 }
00098 switch(cmd.commandID)
00099 {
00100 case kHICommandOK:
00101 {
00102 char buffer[65535];
00103 Size size = sizeof(buffer) - 1;
00104 ControlRef textField = NULL;
00105
00106 id.signature = 'text';
00107 id.id = 0;
00108
00109 err = GetControlByID(gWindow, &id, &textField);
00110 if(err == noErr)
00111 {
00112
00113 err = GetControlData(textField, kControlNoPart, kControlEditTextTextTag, size, (Ptr)buffer, &size);
00114 }
00115 if(err == noErr)
00116 {
00117
00118 buffer[size] = 0;
00119 gUserNotes = buffer;
00120
00121 llinfos << buffer << llendl;
00122 }
00123
00124
00125
00126 QuitAppModalLoopForWindow(gWindow);
00127 gSendReport = true;
00128 result = noErr;
00129 }
00130 break;
00131
00132 case kHICommandCancel:
00133 QuitAppModalLoopForWindow(gWindow);
00134 result = noErr;
00135 break;
00136 }
00137 }
00138 }
00139
00140 return(result);
00141 }
00142
00143
00144 LLCrashLoggerMac::LLCrashLoggerMac(void)
00145 {
00146 }
00147
00148 LLCrashLoggerMac::~LLCrashLoggerMac(void)
00149 {
00150 }
00151
00152 bool LLCrashLoggerMac::init(void)
00153 {
00154 bool ok = LLCrashLogger::init();
00155 if(!ok) return false;
00156 if(mCrashBehavior != CRASH_BEHAVIOR_ASK) return true;
00157
00158
00159 OSStatus err;
00160
00161 err = CreateNibReference(CFSTR("CrashReporter"), &nib);
00162
00163 if(err == noErr)
00164 {
00165 err = CreateWindowFromNib(nib, CFSTR("CrashReporter"), &gWindow);
00166 }
00167
00168 if(err == noErr)
00169 {
00170
00171 ControlRef textField = NULL;
00172 ControlID id;
00173
00174 id.signature = 'text';
00175 id.id = 0;
00176
00177
00178 if(GetControlByID(gWindow, &id, &textField) == noErr)
00179 {
00180 SetKeyboardFocus(gWindow, textField, kControlFocusNextPart);
00181 }
00182 }
00183
00184 if(err == noErr)
00185 {
00186 ShowWindow(gWindow);
00187 }
00188
00189 if(err == noErr)
00190 {
00191
00192 EventTypeSpec handlerEvents[] =
00193 {
00194 { kEventClassCommand, kEventCommandProcess }
00195 };
00196
00197 InstallWindowEventHandler(
00198 gWindow,
00199 NewEventHandlerUPP(dialogHandler),
00200 GetEventTypeCount (handlerEvents),
00201 handlerEvents,
00202 0,
00203 &gEventHandler);
00204 }
00205 return true;
00206 }
00207
00208 void LLCrashLoggerMac::gatherPlatformSpecificFiles()
00209 {
00210 updateApplication("Gathering hardware information...");
00211 char path[MAX_PATH];
00212 FSRef folder;
00213
00214 if(FSFindFolder(kUserDomain, kLogsFolderType, false, &folder) == noErr)
00215 {
00216
00217 if(FSRefMakePath(&folder, (UInt8*)&path, sizeof(path)) == noErr)
00218 {
00219 struct stat dw_stat;
00220 LLString mBuf;
00221 bool isLeopard = false;
00222
00223 LLString dw_file_name = LLString(path) + LLString("/CrashReporter/Second Life.crash.log");
00224 int res = stat(dw_file_name.c_str(), &dw_stat);
00225
00226 if (res)
00227 {
00228
00229 dw_file_name = LLString(path) + LLString("/Second Life.crash.log");
00230 res = stat(dw_file_name.c_str(), &dw_stat);
00231 }
00232
00233 if(res)
00234 {
00235
00236
00237
00238 LLString old_file_name, current_file_name, pathname, mask;
00239 pathname = LLString(path) + LLString("/CrashReporter/");
00240 mask = "Second Life*";
00241 while(gDirUtilp->getNextFileInDir(pathname, mask, current_file_name, false))
00242 {
00243 old_file_name = current_file_name;
00244 }
00245 if(old_file_name != "")
00246 {
00247 dw_file_name = pathname + old_file_name;
00248 res=stat(dw_file_name.c_str(), &dw_stat);
00249 isLeopard = true;
00250 }
00251 }
00252
00253 if (!res)
00254 {
00255 std::ifstream fp(dw_file_name.c_str());
00256 std::stringstream str;
00257 if(!fp.is_open()) return;
00258 str << fp.rdbuf();
00259 mBuf = str.str();
00260
00261 if(!isLeopard)
00262 {
00263
00264
00265
00266 const char *sep = "**********";
00267 const char *start = mBuf.c_str();
00268 const char *cur = start;
00269 const char *temp = strstr(cur, sep);
00270
00271 while(temp != NULL)
00272 {
00273
00274 cur = temp + strlen(sep);
00275
00276
00277 temp = strstr(cur, sep);
00278 }
00279
00280
00281 if(cur != start)
00282 {
00283 mBuf.erase(0, cur - start);
00284 }
00285 }
00286 mCrashInfo["CrashLog"] = mBuf;
00287 }
00288 else
00289 {
00290 llwarns << "Couldn't find any CrashReporter files..." << llendl;
00291 }
00292 }
00293 }
00294 }
00295
00296 bool LLCrashLoggerMac::mainLoop()
00297 {
00298 OSStatus err = noErr;
00299
00300 if(err == noErr && mCrashBehavior == CRASH_BEHAVIOR_ASK)
00301 {
00302 RunAppModalLoopForWindow(gWindow);
00303 }
00304 else if (mCrashBehavior == CRASH_BEHAVIOR_ALWAYS_SEND)
00305 {
00306 gSendReport = true;
00307 }
00308
00309 if(gRememberChoice)
00310 {
00311 if(gSendReport) saveCrashBehaviorSetting(CRASH_BEHAVIOR_ALWAYS_SEND);
00312 else saveCrashBehaviorSetting(CRASH_BEHAVIOR_NEVER_SEND);
00313 }
00314
00315 if(gSendReport)
00316 {
00317 setUserText(gUserNotes);
00318 sendCrashLogs();
00319 }
00320
00321 if(gWindow != NULL)
00322 {
00323 DisposeWindow(gWindow);
00324 }
00325
00326 if(nib != NULL)
00327 {
00328 DisposeNibReference(nib);
00329 }
00330
00331 return true;
00332 }
00333
00334 void LLCrashLoggerMac::updateApplication(LLString message)
00335 {
00336 LLCrashLogger::updateApplication();
00337 }
00338
00339 bool LLCrashLoggerMac::cleanup()
00340 {
00341 return true;
00342 }