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