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