1/* PoorManWindow.cpp
2 *
3 *	Philip Harrison
4 *	Started: 4/25/2004
5 *	Version: 0.1
6 */
7
8#include "PoorManWindow.h"
9
10#include <string.h>
11#include <time.h>
12#include <arpa/inet.h>
13
14#include <Alert.h>
15#include <Box.h>
16#include <Catalog.h>
17#include <Directory.h>
18#include <File.h>
19#include <FindDirectory.h>
20#include <LayoutBuilder.h>
21#include <Locale.h>
22#include <Menu.h>
23#include <MenuBar.h>
24#include <MenuItem.h>
25#include <OS.h>
26#include <Path.h>
27#include <ScrollBar.h>
28#include <ScrollView.h>
29#include <StringView.h>
30#include <TypeConstants.h>
31
32#include "PoorManApplication.h"
33#include "PoorManPreferencesWindow.h"
34#include "PoorManView.h"
35#include "PoorManServer.h"
36#include "PoorManLogger.h"
37#include "constants.h"
38
39
40#undef B_TRANSLATION_CONTEXT
41#define B_TRANSLATION_CONTEXT "PoorMan"
42#define DATE_FORMAT B_SHORT_DATE_FORMAT
43#define TIME_FORMAT B_MEDIUM_TIME_FORMAT
44
45
46PoorManWindow::PoorManWindow(BRect frame)
47	:
48	BWindow(frame, STR_APP_NAME, B_TITLED_WINDOW, 0),
49	fStatus(false),
50	fHits(0),
51	fPrefWindow(NULL),
52	fLogFile(NULL),
53	fServer(NULL)
54{
55	//preferences init
56	fWebDirectory.SetTo(STR_DEFAULT_WEB_DIRECTORY);
57	fIndexFileName.SetTo("index.html");
58	fDirListFlag = false;
59
60	fLogConsoleFlag = true;
61	fLogFileFlag = false;
62	fLogPath.SetTo("");
63
64	fMaxConnections = (int16)32;
65
66	fIsZoomed = true;
67	fLastWidth = 318.0f;
68	fLastHeight = 320.0f;
69	this->fFrame = frame;
70	fSetwindowFrame.Set(112.0f, 60.0f, 492.0f, 340.0f);
71
72	// PoorMan Window
73	SetSizeLimits(318, 1600, 53, 1200);
74	// limit the size of the size of the window
75
76	// -----------------------------------------------------------------
77	// Three Labels
78
79	// Status String
80	fStatusView = new BStringView("Status View", B_TRANSLATE("Status: Stopped"));
81
82	// Directory String
83	fDirView = new BStringView("Dir View", B_TRANSLATE("Directory: (none)"));
84
85	// Hits String
86	fHitsView = new BStringView("Hit View", B_TRANSLATE("Hits: 0"));
87
88	// -----------------------------------------------------------------
89	// Logging View
90
91	fLoggingView = new BTextView(STR_TXT_VIEW, B_WILL_DRAW );
92
93	fLoggingView->MakeEditable(false);	// user cannot change the text
94	fLoggingView->MakeSelectable(true);
95	fLoggingView->SetViewColor(WHITE);
96	fLoggingView->SetStylable(true);
97
98	// create the scroll view
99	fScrollView = new BScrollView("Scroll View", fLoggingView,
100					B_WILL_DRAW | B_FRAME_EVENTS | B_FOLLOW_ALL_SIDES,
101					// Make sure articles on border do not occur when resizing
102					false, true);
103	fLoggingView->MakeFocus(true);
104
105
106	// -----------------------------------------------------------------
107	// menu bar
108	fFileMenuBar = new BMenuBar("File Menu Bar");
109
110	// menus
111	fFileMenu = BuildFileMenu();
112	if (fFileMenu)
113		fFileMenuBar->AddItem(fFileMenu);
114
115	fEditMenu = BuildEditMenu();
116	if (fEditMenu)
117		fFileMenuBar->AddItem(fEditMenu);
118
119	fControlsMenu = BuildControlsMenu();
120	if (fControlsMenu)
121		fFileMenuBar->AddItem(fControlsMenu);
122
123	// File Panels
124	BWindow* change_title;
125
126	fSaveConsoleFilePanel = new BFilePanel(B_SAVE_PANEL, new BMessenger(this),
127						NULL, B_FILE_NODE, false,
128						new BMessage(MSG_FILE_PANEL_SAVE_CONSOLE));
129	change_title = fSaveConsoleFilePanel->Window();
130	change_title->SetTitle(STR_FILEPANEL_SAVE_CONSOLE);
131
132	fSaveConsoleSelectionFilePanel = new BFilePanel(B_SAVE_PANEL,
133						new BMessenger(this), NULL, B_FILE_NODE, false,
134						new BMessage(MSG_FILE_PANEL_SAVE_CONSOLE_SELECTION));
135	change_title = fSaveConsoleSelectionFilePanel->Window();
136	change_title->SetTitle(STR_FILEPANEL_SAVE_CONSOLE_SELECTION);
137
138	BLayoutBuilder::Group<>(this, B_VERTICAL, 0)
139		.SetInsets(0)
140		.Add(fFileMenuBar)
141		.AddGroup(B_VERTICAL, B_USE_SMALL_SPACING)
142			.SetInsets(B_USE_WINDOW_INSETS)
143			.AddGroup(B_HORIZONTAL)
144				.Add(fStatusView)
145				.AddGlue()
146				.Add(fHitsView)
147				.End()
148			.AddGroup(B_HORIZONTAL)
149				.Add(fDirView)
150				.AddGlue()
151				.End()
152			.Add(fScrollView);
153
154	pthread_rwlock_init(&fLogFileLock, NULL);
155}
156
157
158PoorManWindow::~PoorManWindow()
159{
160	delete fServer;
161	delete fLogFile;
162	pthread_rwlock_destroy(&fLogFileLock);
163}
164
165
166void
167PoorManWindow::MessageReceived(BMessage* message)
168{
169	switch (message->what) {
170		case MSG_MENU_FILE_SAVE_AS:
171			fSaveConsoleFilePanel->Show();
172			break;
173		case MSG_FILE_PANEL_SAVE_CONSOLE:
174			printf("FilePanel: Save console\n");
175			SaveConsole(message, false);
176			break;
177		case MSG_MENU_FILE_SAVE_SELECTION:
178			fSaveConsoleSelectionFilePanel->Show();
179			break;
180		case MSG_FILE_PANEL_SAVE_CONSOLE_SELECTION:
181			printf("FilePanel: Save console selection\n");
182			SaveConsole(message, true);
183			break;
184		case MSG_FILE_PANEL_SELECT_WEB_DIR:
185			fPrefWindow->MessageReceived(message);
186			break;
187		case MSG_MENU_EDIT_PREF:
188			fPrefWindow = new PoorManPreferencesWindow(fSetwindowFrame,
189				STR_WIN_NAME_PREF);
190			fPrefWindow->Show();
191			break;
192		case MSG_MENU_CTRL_RUN:
193			if (fStatus)
194				StopServer();
195			else
196				StartServer();
197			break;
198		case MSG_MENU_CTRL_CLEAR_HIT:
199			SetHits(0);
200			//UpdateHitsLabel();
201			break;
202		case MSG_MENU_CTRL_CLEAR_CONSOLE:
203			fLoggingView->SelectAll();
204			fLoggingView->Delete();
205			break;
206		case MSG_MENU_CTRL_CLEAR_LOG:
207			FILE* f;
208			f = fopen(fLogPath.String(), "w");
209			fclose(f);
210			break;
211		case MSG_LOG: {
212			if (!fLogConsoleFlag && !fLogFileFlag)
213				break;
214
215			time_t time;
216			in_addr_t address;
217			rgb_color color;
218			const void* pointer;
219			ssize_t size;
220			const char* msg;
221			BString line;
222
223			if (message->FindString("cstring", &msg) != B_OK)
224				break;
225			if (message->FindData("time_t", B_TIME_TYPE, &pointer, &size) != B_OK)
226				time = -1;
227			else
228				time = *static_cast<const time_t*>(pointer);
229
230			if (message->FindData("in_addr_t", B_ANY_TYPE, &pointer, &size) != B_OK)
231				address = INADDR_NONE;
232			else
233				address = *static_cast<const in_addr_t*>(pointer);
234
235			if (message->FindData("rgb_color", B_RGB_COLOR_TYPE, &pointer, &size) != B_OK)
236				color = BLACK;
237			else
238				color = *static_cast<const rgb_color*>(pointer);
239
240			if (time != -1) {
241				BString timeString;
242				if (BLocale::Default()->FormatDateTime(&timeString, time,
243						DATE_FORMAT, TIME_FORMAT) == B_OK) {
244					line << '[' << timeString << "]: ";
245				}
246			}
247
248			if (address != INADDR_NONE) {
249				char addr[INET_ADDRSTRLEN];
250				struct in_addr sin_addr;
251				sin_addr.s_addr = address;
252				if (inet_ntop(AF_INET, &sin_addr, addr, sizeof(addr)) != NULL) {
253					addr[strlen(addr)] = '\0';
254					line << '(' << addr << ") ";
255				}
256			}
257
258			line << msg;
259
260			text_run run;
261			text_run_array runs;
262
263			run.offset = 0;
264			run.color = color;
265
266			runs.count = 1;
267			runs.runs[0] = run;
268
269			if (Lock()) {
270				if (fLogConsoleFlag) {
271					fLoggingView->Insert(fLoggingView->TextLength(),
272						line.String(), line.Length(), &runs);
273					fLoggingView->ScrollToOffset(fLoggingView->TextLength());
274				}
275
276				if (fLogFileFlag) {
277					if (pthread_rwlock_rdlock(&fLogFileLock) == 0) {
278						fLogFile->Write(line.String(), line.Length());
279						pthread_rwlock_unlock(&fLogFileLock);
280					}
281				}
282
283				Unlock();
284			}
285
286			break;
287		}
288		default:
289			BWindow::MessageReceived(message);
290			break;
291	}
292}
293
294
295void
296PoorManWindow::FrameMoved(BPoint origin)
297{
298	fFrame.left = origin.x;
299	fFrame.top = origin.y;
300}
301
302
303void
304PoorManWindow::FrameResized(float width, float height)
305{
306	if (fIsZoomed) {
307		fLastWidth  = width;
308		fLastHeight = height;
309	}
310}
311
312
313bool
314PoorManWindow::QuitRequested()
315{
316	if (fStatus) {
317		time_t now = time(NULL);
318		BString timeString;
319		BLocale::Default()->FormatDateTime(&timeString, now,
320			DATE_FORMAT, TIME_FORMAT);
321
322		BString line;
323		line << "[" << timeString << "]: " << B_TRANSLATE("Shutting down.")
324			<< "\n";
325
326		if (fLogConsoleFlag) {
327			fLoggingView->Insert(fLoggingView->TextLength(),
328				line, line.Length());
329			fLoggingView->ScrollToOffset(fLoggingView->TextLength());
330		}
331
332		if (fLogFileFlag) {
333			if (pthread_rwlock_rdlock(&fLogFileLock) == 0) {
334				fLogFile->Write(line, line.Length());
335				pthread_rwlock_unlock(&fLogFileLock);
336			}
337		}
338
339		fServer->Stop();
340		fStatus = false;
341		UpdateStatusLabelAndMenuItem();
342	}
343
344	SaveSettings();
345	be_app_messenger.SendMessage(B_QUIT_REQUESTED);
346	return true;
347}
348
349
350void
351PoorManWindow::Zoom(BPoint origin, float width, float height)
352{
353	if (fIsZoomed) {
354		// Change to the Minimal size
355		fIsZoomed = false;
356		ResizeTo(318, 53);
357	} else {
358		// Change to the Zoomed size
359		fIsZoomed = true;
360		ResizeTo(fLastWidth, fLastHeight);
361	}
362}
363
364
365void
366PoorManWindow::SetHits(uint32 num)
367{
368	fHits = num;
369	UpdateHitsLabel();
370}
371
372
373// Private: Methods ------------------------------------------
374
375
376BMenu*
377PoorManWindow::BuildFileMenu() const
378{
379	BMenu* ptrFileMenu = new BMenu(STR_MNU_FILE);
380
381	ptrFileMenu->AddItem(new BMenuItem(STR_MNU_FILE_SAVE_AS,
382		new BMessage(MSG_MENU_FILE_SAVE_AS), CMD_FILE_SAVE_AS));
383
384	ptrFileMenu->AddItem(new BMenuItem(STR_MNU_FILE_SAVE_SELECTION,
385		new BMessage(MSG_MENU_FILE_SAVE_SELECTION)));
386
387	ptrFileMenu->AddSeparatorItem();
388
389	ptrFileMenu->AddItem(new BMenuItem(STR_MNU_FILE_QUIT,
390		new BMessage(B_QUIT_REQUESTED), CMD_FILE_QUIT));
391
392	return ptrFileMenu;
393}
394
395
396BMenu*
397PoorManWindow::BuildEditMenu() const
398{
399	BMenu* ptrEditMenu = new BMenu(STR_MNU_EDIT);
400
401	BMenuItem* CopyMenuItem = new BMenuItem(STR_MNU_EDIT_COPY,
402		new BMessage(B_COPY), CMD_EDIT_COPY);
403
404	ptrEditMenu->AddItem(CopyMenuItem);
405	CopyMenuItem->SetTarget(fLoggingView, NULL);
406
407	ptrEditMenu->AddSeparatorItem();
408
409	BMenuItem* SelectAllMenuItem = new BMenuItem(STR_MNU_EDIT_SELECT_ALL,
410	new BMessage(B_SELECT_ALL), CMD_EDIT_SELECT_ALL);
411
412	ptrEditMenu->AddItem(SelectAllMenuItem);
413	SelectAllMenuItem->SetTarget(fLoggingView, NULL);
414
415	ptrEditMenu->AddSeparatorItem();
416
417	BMenuItem* PrefMenuItem = new BMenuItem(STR_MNU_EDIT_PREF,
418		new BMessage(MSG_MENU_EDIT_PREF));
419	ptrEditMenu->AddItem(PrefMenuItem);
420
421	return ptrEditMenu;
422}
423
424
425BMenu*
426PoorManWindow::BuildControlsMenu() const
427{
428	BMenu* ptrControlMenu = new BMenu(STR_MNU_CTRL);
429
430	BMenuItem* RunServerMenuItem = new BMenuItem(STR_MNU_CTRL_RUN_SERVER,
431		new BMessage(MSG_MENU_CTRL_RUN));
432	RunServerMenuItem->SetMarked(false);
433	ptrControlMenu->AddItem(RunServerMenuItem);
434
435	BMenuItem* ClearHitCounterMenuItem = new BMenuItem(STR_MNU_CTRL_CLEAR_HIT_COUNTER,
436		new BMessage(MSG_MENU_CTRL_CLEAR_HIT));
437	ptrControlMenu->AddItem(ClearHitCounterMenuItem);
438
439	ptrControlMenu->AddSeparatorItem();
440
441	BMenuItem* ClearConsoleLogMenuItem = new BMenuItem(STR_MNU_CTRL_CLEAR_CONSOLE,
442		new BMessage(MSG_MENU_CTRL_CLEAR_CONSOLE));
443	ptrControlMenu->AddItem(ClearConsoleLogMenuItem);
444
445	BMenuItem* ClearLogFileMenuItem = new BMenuItem(STR_MNU_CTRL_CLEAR_LOG_FILE,
446		new BMessage(MSG_MENU_CTRL_CLEAR_LOG));
447	ptrControlMenu->AddItem(ClearLogFileMenuItem);
448
449	return ptrControlMenu;
450}
451
452
453void
454PoorManWindow::SetDirLabel(const char* name)
455{
456	BString dirPath(B_TRANSLATE("Directory: "));
457	dirPath.Append(name);
458
459	if (Lock()) {
460		fDirView->SetText(dirPath.String());
461		Unlock();
462	}
463}
464
465
466void
467PoorManWindow::UpdateStatusLabelAndMenuItem()
468{
469	if (Lock()) {
470		if (fStatus)
471			fStatusView->SetText(B_TRANSLATE("Status: Running"));
472		else
473			fStatusView->SetText(B_TRANSLATE("Status: Stopped"));
474		fControlsMenu->FindItem(STR_MNU_CTRL_RUN_SERVER)->SetMarked(fStatus);
475		Unlock();
476	}
477}
478
479
480void
481PoorManWindow::UpdateHitsLabel()
482{
483	if (Lock()) {
484		sprintf(fHitsLabel, B_TRANSLATE("Hits: %lu"), GetHits());
485		fHitsView->SetText(fHitsLabel);
486
487		Unlock();
488	}
489}
490
491
492status_t
493PoorManWindow::SaveConsole(BMessage* message, bool selection)
494{
495	entry_ref	ref;
496	const char* name;
497	BPath		path;
498	BEntry		entry;
499	status_t	err = B_OK;
500	FILE*		f;
501
502	err = message->FindRef("directory", &ref);
503	if (err != B_OK)
504		return err;
505
506	err = message->FindString("name", &name);
507	if (err != B_OK)
508		return err;
509
510	err = entry.SetTo(&ref);
511	if (err != B_OK)
512		return err;
513
514	entry.GetPath(&path);
515	path.Append(name);
516
517	if (!(f = fopen(path.Path(), "w")))
518		return B_ERROR;
519
520	if (!selection) {
521		// write the data to the file
522		err = fwrite(fLoggingView->Text(), 1, fLoggingView->TextLength(), f);
523	} else {
524		// find the selected text and write it to a file
525		int32 start = 0, end = 0;
526		fLoggingView->GetSelection(&start, &end);
527
528		BString buffer;
529		char * buffData = buffer.LockBuffer(end - start + 1);
530		// copy the selected text from the TextView to the buffer
531		fLoggingView->GetText(start, end - start, buffData);
532		buffer.UnlockBuffer(end - start + 1);
533
534		err = fwrite(buffer.String(), 1, end - start + 1, f);
535	}
536
537	fclose(f);
538
539	return err;
540}
541
542
543void
544PoorManWindow::DefaultSettings()
545{
546	BAlert* serverAlert = new BAlert(B_TRANSLATE("Error Server"),
547		STR_ERR_CANT_START, B_TRANSLATE("OK"));
548	serverAlert->SetFlags(serverAlert->Flags() | B_CLOSE_ON_ESCAPE);
549	BAlert* dirAlert = new BAlert(B_TRANSLATE("Error Dir"),
550		STR_ERR_WEB_DIR, B_TRANSLATE("Cancel"), B_TRANSLATE("Select"),
551		B_TRANSLATE("Default"), B_WIDTH_AS_USUAL, B_OFFSET_SPACING);
552	dirAlert->SetShortcut(0, B_ESCAPE);
553	int32 buttonIndex = dirAlert->Go();
554
555	switch (buttonIndex) {
556		case 0:
557			if (Lock())
558				Quit();
559			be_app_messenger.SendMessage(B_QUIT_REQUESTED);
560			break;
561
562		case 1:
563			fPrefWindow = new PoorManPreferencesWindow(
564					fSetwindowFrame,
565					STR_WIN_NAME_PREF);
566			fPrefWindow->ShowWebDirFilePanel();
567			break;
568
569		case 2:
570			if (create_directory(STR_DEFAULT_WEB_DIRECTORY, 0755) != B_OK) {
571				serverAlert->Go();
572				if (Lock())
573					Quit();
574				be_app_messenger.SendMessage(B_QUIT_REQUESTED);
575				break;
576			}
577			BAlert* dirCreatedAlert =
578				new BAlert(B_TRANSLATE("Dir Created"), STR_DIR_CREATED,
579					B_TRANSLATE("OK"));
580			dirCreatedAlert->SetFlags(dirCreatedAlert->Flags() | B_CLOSE_ON_ESCAPE);
581			dirCreatedAlert->Go();
582			SetWebDir(STR_DEFAULT_WEB_DIRECTORY);
583			be_app->PostMessage(kStartServer);
584			break;
585	}
586}
587
588
589status_t
590PoorManWindow::ReadSettings()
591{
592	BPath p;
593	BFile f;
594	BMessage m;
595
596	if (find_directory(B_USER_SETTINGS_DIRECTORY, &p) != B_OK)
597		return B_ERROR;
598	p.Append(STR_SETTINGS_FILE_NAME);
599
600	f.SetTo(p.Path(), B_READ_ONLY);
601	if (f.InitCheck() != B_OK)
602		return B_ERROR;
603
604	if (m.Unflatten(&f) != B_OK)
605		return B_ERROR;
606
607	if (MSG_PREF_FILE != m.what)
608		return B_ERROR;
609
610	//site tab
611	if (m.FindString("fWebDirectory", &fWebDirectory) != B_OK)
612		fWebDirectory.SetTo(STR_DEFAULT_WEB_DIRECTORY);
613	if (m.FindString("fIndexFileName", &fIndexFileName) != B_OK)
614		fIndexFileName.SetTo("index.html");
615	if (m.FindBool("fDirListFlag", &fDirListFlag) != B_OK)
616		fDirListFlag = false;
617
618	//logging tab
619	if (m.FindBool("fLogConsoleFlag", &fLogConsoleFlag) != B_OK)
620		fLogConsoleFlag = true;
621	if (m.FindBool("fLogFileFlag", &fLogFileFlag) != B_OK)
622		fLogFileFlag = false;
623	if (m.FindString("fLogPath", &fLogPath) != B_OK)
624		fLogPath.SetTo("");
625
626	//advance tab
627	if (m.FindInt16("fMaxConnections", &fMaxConnections) != B_OK)
628		fMaxConnections = (int16)32;
629
630	//windows' position and size
631	if (m.FindRect("frame", &fFrame) != B_OK)
632		fFrame.Set(82.0f, 30.0f, 400.0f, 350.0f);
633	if (m.FindRect("fSetwindowFrame", &fSetwindowFrame) != B_OK)
634		fSetwindowFrame.Set(112.0f, 60.0f, 492.0f, 340.0f);
635	if (m.FindBool("fIsZoomed", &fIsZoomed) != B_OK)
636		fIsZoomed = true;
637	if (m.FindFloat("fLastWidth", &fLastWidth) != B_OK)
638		fLastWidth = 318.0f;
639	if (m.FindFloat("fLastHeight", &fLastHeight) != B_OK)
640		fLastHeight = 320.0f;
641
642	fIsZoomed?ResizeTo(fLastWidth, fLastHeight):ResizeTo(318, 53);
643	MoveTo(fFrame.left, fFrame.top);
644
645	fLogFile = new BFile(fLogPath.String(), B_CREATE_FILE | B_WRITE_ONLY
646		| B_OPEN_AT_END);
647	if (fLogFile->InitCheck() != B_OK) {
648		fLogFileFlag = false;
649		//log it to console, "log to file unavailable."
650		return B_OK;
651	}
652
653	SetDirLabel(fWebDirectory.String());
654
655	return B_OK;
656}
657
658
659status_t
660PoorManWindow::SaveSettings()
661{
662	BPath p;
663	BFile f;
664	BMessage m(MSG_PREF_FILE);
665
666	//site tab
667	m.AddString("fWebDirectory", fWebDirectory);
668	m.AddString("fIndexFileName", fIndexFileName);
669	m.AddBool("fDirListFlag", fDirListFlag);
670
671	//logging tab
672	m.AddBool("fLogConsoleFlag", fLogConsoleFlag);
673	m.AddBool("fLogFileFlag", fLogFileFlag);
674	m.AddString("fLogPath", fLogPath);
675
676	//advance tab
677	m.AddInt16("fMaxConnections", fMaxConnections);
678
679	//windows' position and size
680	m.AddRect("frame", fFrame);
681	m.AddRect("fSetwindowFrame", fSetwindowFrame);
682	m.AddBool("fIsZoomed", fIsZoomed);
683	m.AddFloat("fLastWidth", fLastWidth);
684	m.AddFloat("fLastHeight", fLastHeight);
685
686	if (find_directory(B_USER_SETTINGS_DIRECTORY, &p) != B_OK)
687		return B_ERROR;
688	p.Append(STR_SETTINGS_FILE_NAME);
689
690	f.SetTo(p.Path(), B_WRITE_ONLY | B_ERASE_FILE | B_CREATE_FILE);
691	if (f.InitCheck() != B_OK)
692		return B_ERROR;
693
694	if (m.Flatten(&f) != B_OK)
695		return B_ERROR;
696
697	return B_OK;
698}
699
700
701status_t
702PoorManWindow::StartServer()
703{
704	if (fServer == NULL)
705		fServer = new PoorManServer(fWebDirectory.String(), fMaxConnections,
706			fDirListFlag, fIndexFileName.String());
707
708	poorman_log(B_TRANSLATE("Starting up... "));
709	if (fServer->Run() != B_OK) {
710		return B_ERROR;
711	}
712
713	fStatus = true;
714	UpdateStatusLabelAndMenuItem();
715	poorman_log(B_TRANSLATE("done.\n"), false, INADDR_NONE, GREEN);
716
717	return B_OK;
718}
719
720
721status_t
722PoorManWindow::StopServer()
723{
724	if (fServer == NULL)
725		return B_ERROR;
726
727	poorman_log(B_TRANSLATE("Shutting down.\n"));
728	fServer->Stop();
729	fStatus = false;
730	UpdateStatusLabelAndMenuItem();
731	return B_OK;
732}
733
734
735void
736PoorManWindow::SetLogPath(const char* str)
737{
738	if (!strcmp(fLogPath, str))
739		return;
740
741	BFile* temp = new BFile(str, B_CREATE_FILE | B_WRITE_ONLY | B_OPEN_AT_END);
742
743	if (temp->InitCheck() != B_OK) {
744		delete temp;
745		return;
746	}
747
748	if (pthread_rwlock_wrlock(&fLogFileLock) == 0) {
749		delete fLogFile;
750		fLogFile = temp;
751		pthread_rwlock_unlock(&fLogFileLock);
752	} else {
753		delete temp;
754		return;
755	}
756
757	fLogPath.SetTo(str);
758}
759