1// MyNetApp.cpp
2
3#include "Application.h"
4#include "Resources.h"
5#include "TabView.h"
6#include "Alert.h"
7#include "Menu.h"
8#include "MenuBar.h"
9#include "MenuItem.h"
10#include "Button.h"
11#include "FilePanel.h"
12#include "FindDirectory.h"
13#include "TextControl.h"
14#include "Path.h"
15#include "Mime.h"
16#include "Roster.h"
17
18#include "assert.h"
19#include "unistd.h"
20#include "socket.h"
21#include "netdb.h"
22#include "time.h"
23
24#include "ColumnListView.h"
25#include "CLVColumn.h"
26#include "CLVEasyItem.h"
27#include "NewStrings.h"
28
29#include "betalk.h"
30#include "besure_auth.h"
31#include "rpc.h"
32#include "BlowFish.h"
33#include "MyNetView.h"
34#include "MyDriveView.h"
35#include "IconListItem.h"
36#include "btAddOn.h"
37#include "LoginPanel.h"
38#include "InstallPrinter.h"
39
40#ifndef BONE_VERSION
41#include "ksocket_internal.h"
42#else
43#include "arpa/inet.h"
44#endif
45
46#define BT_HOST_PATH		"/boot/home/Connections"
47#define IsValid(s)			(strcmp((s), ".") && strcmp((s), ".."))
48
49#define MYNET_ICON_HOST_LARGE		101
50#define MYNET_ICON_SHARE_LARGE		102
51#define MYNET_ICON_HOST_SMALL		103
52#define MYNET_ICON_SHARE_SMALL		104
53#define MYNET_ICON_INETHOST_LARGE	105
54#define MYNET_ICON_INETHOST_SMALL	106
55
56
57// ----- SmartColumnListView ----------------------------------------------------------------
58
59class SmartColumnListView : public ColumnListView
60{
61	public:
62		SmartColumnListView(BRect Frame, CLVContainerView** ContainerView,
63			const char* Name = NULL, uint32 ResizingMode = B_FOLLOW_LEFT | B_FOLLOW_TOP,
64			uint32 flags = B_WILL_DRAW | B_FRAME_EVENTS | B_NAVIGABLE,
65			list_view_type Type = B_SINGLE_SELECTION_LIST,
66			bool hierarchical = false, bool horizontal = true, bool vertical = true,
67			bool scroll_view_corner = true, border_style border = B_NO_BORDER,
68			const BFont* LabelFont = be_plain_font) :
69			  ColumnListView(Frame, ContainerView, Name, ResizingMode, flags, Type, hierarchical,
70				horizontal, vertical, scroll_view_corner, border, LabelFont)
71		{
72			container = *ContainerView;
73		}
74
75		virtual ~SmartColumnListView()
76		{
77		}
78
79		void MouseDown(BPoint point)
80		{
81			ColumnListView::MouseDown(point);
82			if (CurrentSelection() < 0)
83				container->Window()->PostMessage(MSG_LIST_DESELECT);
84		}
85
86	private:
87		CLVContainerView *container;
88};
89
90// ----- MountItem ----------------------------------------------------------------------
91
92class MountItem : public CLVEasyItem
93{
94	public:
95		MountItem(const char *text0, const char *text1, const char *text2) :
96		  CLVEasyItem(0, false, false, 20.0)
97		{
98			// Here we're going to get the mini icon from a specific mime type
99			BRect bmpRect(0.0, 0.0, 15.0, 15.0);
100			BBitmap *icon = new BBitmap(bmpRect, B_CMAP8);
101
102			BMimeType mime("application/x-vnd.BeServed-fileshare");
103			mime.GetIcon(icon, B_MINI_ICON);
104
105			SetColumnContent(0, icon, 2.0);
106			SetColumnContent(1, text0);
107			SetColumnContent(2, text1);
108			SetColumnContent(3, text2);
109		}
110
111		~MountItem()
112		{
113		}
114};
115
116// ----- HostInfoPanel -----------------------------------------------------------------
117
118class HostInfoPanel : public BWindow
119{
120	public:
121		HostInfoPanel(BRect frame, const char *name, uint32 ipAddr) :
122		  BWindow(frame, name, B_TITLED_WINDOW_LOOK, B_MODAL_APP_WINDOW_FEEL, B_NOT_ZOOMABLE | B_NOT_RESIZABLE)
123		{
124			BRect r = Bounds();
125
126			strcpy(host, name);
127			address = ipAddr;
128			AddChild(new HostInfoView(r, name, address));
129
130			Show();
131		}
132
133	private:
134		char host[B_FILE_NAME_LENGTH + 1];
135		uint32 address;
136};
137
138
139class FileShareWindow : public BWindow
140{
141	public:
142		FileShareWindow(BWindow *win, BRect frame, const char *name, uint32 ipAddr) :
143		  BWindow(frame, name, B_TITLED_WINDOW, B_NOT_ZOOMABLE)
144		{
145			parent = win;
146			strcpy(host, name);
147			address = ipAddr;
148
149			CLVContainerView *containerView;
150			BRect r = Bounds();
151
152			MyColumnListView = new SmartColumnListView(r, &containerView, NULL, B_FOLLOW_TOP_BOTTOM | B_FOLLOW_LEFT_RIGHT,
153				B_WILL_DRAW | B_FRAME_EVENTS | B_NAVIGABLE, B_SINGLE_SELECTION_LIST,
154				false, false, false, false, B_NO_BORDER);
155
156			MyColumnListView->AddColumn(new CLVColumn(NULL, 20.0, CLV_LOCK_AT_BEGINNING | CLV_NOT_MOVABLE |
157				CLV_NOT_RESIZABLE | CLV_PUSH_PASS | CLV_MERGE_WITH_RIGHT));
158			MyColumnListView->AddColumn(new CLVColumn("Resource", 140.0, CLV_SORT_KEYABLE, 50.0));
159			MyColumnListView->AddColumn(new CLVColumn("Type", 90.0, CLV_SORT_KEYABLE));
160
161			MyColumnListView->SetSelectionMessage(new BMessage(MSG_SHARE_SELECT));
162			MyColumnListView->SetInvocationMessage(new BMessage(MSG_SHARE_INVOKE));
163
164			AddCLVItems(MyColumnListView);
165			AddChild(containerView);
166
167			SetSizeLimits(260, 2000, 110, 2000);
168			Show();
169		}
170
171		// AddCLVItems()
172		//
173		void AddCLVItems(ColumnListView* MyColumnListView)
174		{
175			extern int32 getShares(void *);
176			ThreadInfo *info = new ThreadInfo();
177			info->SetColumnListView(MyColumnListView);
178			info->SetHostAddress(address);
179			thread_id shareThread = spawn_thread(getShares, "Get Shares", B_NORMAL_PRIORITY, info);
180			resume_thread(shareThread);
181		}
182
183		void MessageReceived(BMessage *msg)
184		{
185			BListView *list;
186			int32 curItem;
187
188			switch (msg->what)
189			{
190				case MSG_SHARE_SELECT:
191					break;
192
193				case MSG_SHARE_INVOKE:
194					msg->FindPointer("source", (void **) &list);
195					curItem = list->CurrentSelection();
196					if (curItem != -1)
197					{
198						CLVEasyItem *item = (CLVEasyItem *) MyColumnListView->ItemAt(curItem);
199						if (item)
200						{
201							const char *share = item->GetColumnContentText(1);
202							const char *type = item->GetColumnContentText(2);
203
204							if (strcmp(type, "Shared Files") == 0)
205								mountToLocalFolder(host, (char *) share);
206							else
207								createSharedPrinter(host, (char *) share, 0);
208						}
209					}
210					break;
211
212				default:
213					BWindow::MessageReceived(msg);
214					break;
215			}
216		}
217
218	private:
219		// mountToLocalFolder()
220		//
221		void mountToLocalFolder(char *host, char *share)
222		{
223			char *folder = makeLocalFolder(host, share);
224			if (folder)
225			{
226				if (dev_for_path("/boot/home") == dev_for_path(folder))
227					if (!mountFileShare(address, share, folder))
228						return;
229
230				updateMountList(host, share, folder);
231				showFolder(folder);
232				free(folder);
233			}
234			else
235			{
236				BAlert *alert = new BAlert("title", "An attempt to create a local mount point to access this shared volume has failed.", "OK");
237				alert->Go();
238			}
239		}
240
241		// makeLocalFolder()
242		//
243		char *makeLocalFolder(char *host, char *share)
244		{
245			char *path = (char *) malloc(B_PATH_NAME_LENGTH);
246			if (!path)
247				return NULL;
248
249			strcpy(path, "/boot/home/Connections");
250			if (access(path, 0) != 0)
251				if (mkdir(path, S_IRWXU | S_IRWXG | S_IRWXO) != 0)
252					return NULL;
253
254			strcat(path, "/");
255			strcat(path, host);
256			if (access(path, 0) != 0)
257				if (mkdir(path, S_IRWXU | S_IRWXG | S_IRWXO) != 0)
258					return NULL;
259
260			strcat(path, "/");
261			strcat(path, share);
262			if (access(path, 0) != 0)
263				if (mkdir(path, S_IRWXU | S_IRWXG | S_IRWXO) != 0)
264					return NULL;
265
266			return path;
267		}
268
269		// getMountFolder()
270		//
271		void getMountFolder()
272		{
273			char path[B_PATH_NAME_LENGTH];
274			entry_ref entryRef;
275
276			find_directory(B_USER_DIRECTORY, 0, false, path, sizeof(path));
277			BEntry entry(path, false);
278			entry.GetRef(&entryRef);
279			BFilePanel *filePanel = new BFilePanel(B_OPEN_PANEL, &be_app_messenger, &entryRef, B_DIRECTORY_NODE, false);
280			filePanel->Show();
281			filePanel->Window()->SetTitle("Mount Location");
282			filePanel->SetButtonLabel(B_DEFAULT_BUTTON, "Mount");
283		}
284
285		bool mountFileShare(uint32 address, char *share, const char *path)
286		{
287			blf_ctx ctx;
288			mount_bt_params params;
289			char hostname[256], msg[512], *folder;
290			int length;
291			port_id port;
292
293			folder = strrchr(path, '/');
294			if (folder)
295				folder++;
296			else
297				folder = (char *) path;
298
299			unsigned int serverIP = ntohl(address);
300
301#ifndef BONE_VERSION
302			if (!be_roster->IsRunning(KSOCKETD_SIGNATURE))
303				if (be_roster->Launch(KSOCKETD_SIGNATURE) < B_NO_ERROR)
304				{
305					printf("Network communications could not be started.  The shared volume cannot be mounted.\n");
306					BAlert *alert = new BAlert("", msg, "OK");
307					alert->Go();
308					return false;
309				}
310
311			for (int32 i = 0; i < 10; i++)
312			{
313				port = find_port(KSOCKET_DAEMON_NAME);
314
315				if (port < B_NO_ERROR)
316					snooze(1000000LL);
317				else
318					break;
319			}
320
321			if (port < B_NO_ERROR)
322			{
323				sprintf(msg, "Network communications are not responding.  The shared volume cannot be mounted.\n");
324				BAlert *alert = new BAlert("", msg, "OK");
325				alert->Go();
326				return false;
327			}
328#endif
329
330			// Handle user authentication
331//			strcpy(user, crypt(user, "u0"));
332//			strcpy(password, crypt(password, "p1"));
333			if (getAuthentication(serverIP, share))
334			{
335				BRect frame = Frame();
336				frame.top += 75;
337				frame.left += 75;
338				frame.bottom = frame.top + 140;
339				frame.right = frame.left + 250;
340				LoginPanel *login = new LoginPanel(frame);
341				status_t loginExit;
342				wait_for_thread(login->Thread(), &loginExit);
343				if (login->IsCancelled())
344					return false;
345
346				// Copy the user name.
347				strcpy(params.user, login->user);
348
349				// Copy the user name and password supplied in the authentication dialog.
350				sprintf(params.password, "%-*s%-*s", B_FILE_NAME_LENGTH, share, MAX_USERNAME_LENGTH, login->user);		//crypt(password, "p1"));
351				length = strlen(params.password);
352				assert(length == BT_AUTH_TOKEN_LENGTH);
353
354				params.password[length] = 0;
355				blf_key(&ctx, (unsigned char *) login->md5passwd, strlen(login->md5passwd));
356				blf_enc(&ctx, (unsigned long *) params.password, length / 4);
357			}
358			else
359				params.user[0] = params.password[0] = 0;
360
361			params.serverIP = serverIP;
362			params.server = host;
363			params._export = share;
364			params.folder = folder;
365			params.uid = 0;
366			params.gid = 0;
367
368			gethostname(hostname, 256);
369			params.hostname = hostname;
370
371			int result = mount("beserved_client", path, NULL, 0, &params, sizeof(params));
372
373			if (result < B_NO_ERROR)
374			{
375				sprintf(msg, "The shared volume could not be mounted (%s).\n", strerror(errno));
376				BAlert *alert = new BAlert("", msg, "OK");
377				alert->Go();
378				return false;
379			}
380
381			return true;
382		}
383
384		bool getAuthentication(unsigned int serverIP, char *shareName)
385		{
386			bt_inPacket *inPacket;
387			bt_outPacket *outPacket;
388			int security;
389
390			security = EHOSTUNREACH;
391
392			outPacket = btRPCPutHeader(BT_CMD_PREMOUNT, 1, strlen(shareName));
393			btRPCPutArg(outPacket, B_STRING_TYPE, shareName, strlen(shareName));
394			inPacket = btRPCSimpleCall(serverIP, BT_TCPIP_PORT, outPacket);
395			if (inPacket)
396			{
397				security = btRPCGetInt32(inPacket);
398				free(inPacket->buffer);
399				free(inPacket);
400			}
401
402			free(outPacket->buffer);
403			free(outPacket);
404
405			return (security == BT_AUTH_BESURE);
406		}
407
408		void updateMountList(char *host, char *share, char *path)
409		{
410			BMessage *relay;
411			relay = new BMessage(MSG_NEW_MOUNT);
412			relay->AddString("host", host);
413			relay->AddString("share", share);
414			relay->AddString("path", path);
415
416			parent->PostMessage(relay);
417		}
418
419		void showFolder(char *path)
420		{
421			char command[512];
422			sprintf(command, "/boot/beos/system/Tracker \"%s\"", path);
423			system(command);
424		}
425
426		bool isSharedPrinterInstalled(char *host, char *printer)
427		{
428			char path[B_PATH_NAME_LENGTH];
429
430			// If a printer by this name already exists, remove the existing configuration
431			// in favor of changes being applied.  If not, just create the printer and move
432			// on.
433			find_directory(B_USER_SETTINGS_DIRECTORY, 0, false, path, sizeof(path));
434			strcat(path, "/printers/");
435			strcat(path, printer);
436			return (access(path, 0) == 0);
437		}
438
439		void createSharedPrinter(char *host, char *printer, int type)
440		{
441			blf_ctx ctx;
442			hostent *ent;
443			char msg[512], user[MAX_USERNAME_LENGTH + 1], password[BT_AUTH_TOKEN_LENGTH * 2 + 1];
444			int length;
445
446			// Abort if the printer type is not valid.
447			if (type < 0 || type > 0)
448				return;
449
450			BRect frame = Frame();
451			frame.top += 75;
452			frame.left += 75;
453			frame.bottom = frame.top + 135;
454			frame.right = frame.left + 350;
455			InstallPrinterPanel *prtPanel = new InstallPrinterPanel(frame, host, printer);
456			status_t loginExit;
457			wait_for_thread(prtPanel->Thread(), &loginExit);
458			if (prtPanel->IsCancelled())
459				return;
460
461			// Get the IP address of the server.
462			ent = gethostbyname(host);
463			if (ent == NULL)
464			{
465				sprintf(msg, "The server %s, which hosts printer %s, cannot be found on the network.", host, printer);
466				BAlert *alert = new BAlert("", msg, "OK");
467				alert->Go();
468				return;
469			}
470
471			unsigned int serverIP = ntohl(*((unsigned int *) ent->h_addr));
472
473			if (getAuthentication(serverIP, printer))
474			{
475				BRect frame = Frame();
476				frame.top += 75;
477				frame.left += 75;
478				frame.bottom = frame.top + 140;
479				frame.right = frame.left + 250;
480				LoginPanel *login = new LoginPanel(frame);
481				status_t loginExit;
482				wait_for_thread(login->Thread(), &loginExit);
483				if (login->IsCancelled())
484					return;
485
486				// Copy the user name.
487				strcpy(user, login->user);
488
489				// Copy the user name and password supplied in the authentication dialog.
490				sprintf(password, "%-*s%-*s", B_FILE_NAME_LENGTH, printer, MAX_USERNAME_LENGTH, login->user);
491				length = strlen(password);
492				assert(length == BT_AUTH_TOKEN_LENGTH);
493
494				password[length] = 0;
495				blf_key(&ctx, (unsigned char *) login->md5passwd, strlen(login->md5passwd));
496				blf_enc(&ctx, (unsigned long *) password, length / 4);
497			}
498			else
499				user[0] = password[0] = 0;
500
501			prtPanel->CreatePrinter(printer, host, type, user, password);
502			if (prtPanel->isDefault())
503				prtPanel->SetDefaultPrinter(printer);
504			if (prtPanel->printTestPage())
505				prtPanel->TestPrinter(printer);
506		}
507
508		BWindow *parent;
509		SmartColumnListView *MyColumnListView;
510		char host[B_FILE_NAME_LENGTH];
511		uint32 address;
512};
513
514// ----- InetHostView -----------------------------------------------------
515
516class InetHostView : public BView
517{
518	public:
519		InetHostView(BRect rect) :
520		  BView(rect, "InetHostView", B_FOLLOW_ALL, B_WILL_DRAW)
521		{
522			rgb_color gray = ui_color(B_PANEL_BACKGROUND_COLOR);
523			SetViewColor(gray);
524
525			BRect bmpRect(0.0, 0.0, 31.0, 31.0);
526			icon = new BBitmap(bmpRect, B_CMAP8);
527			BMimeType mime("application/x-vnd.BeServed-inetserver");
528			mime.GetIcon(icon, B_LARGE_ICON);
529
530			BRect r(10, 52, 310, 72);
531			editName = new BTextControl(r, "ShareName", "Name or Address:", "", NULL);
532			editName->SetDivider(90);
533			AddChild(editName);
534
535			r.Set(155, 97, 225, 117);
536			BButton *okBtn = new BButton(r, "OkayBtn", "OK", new BMessage(MSG_HOST_OK), B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM);
537			okBtn->MakeDefault(true);
538			AddChild(okBtn);
539
540			r.Set(235, 97, 310, 117);
541			AddChild(new BButton(r, "CancelBtn", "Cancel", new BMessage(MSG_HOST_CANCEL), B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM));
542
543			editName->MakeFocus();
544		}
545
546		~InetHostView()
547		{
548		}
549
550		void Draw(BRect rect)
551		{
552			BRect r = Bounds();
553			BRect iconRect(13.0, 5.0, 45.0, 37.0);
554			rgb_color black = { 0, 0, 0, 255 };
555			rgb_color gray = ui_color(B_PANEL_BACKGROUND_COLOR);
556
557			SetViewColor(gray);
558			SetLowColor(gray);
559			FillRect(r, B_SOLID_LOW);
560
561			SetHighColor(black);
562			SetFont(be_bold_font);
563			SetFontSize(11);
564			MovePenTo(55, 15);
565			DrawString("Connect to Internet Host");
566
567			SetFont(be_plain_font);
568			SetFontSize(10);
569			MovePenTo(55, 28);
570			DrawString("Specify the name or address of a computer located");
571			MovePenTo(55, 40);
572			DrawString("outside your network, such as on the Internet.");
573
574			SetDrawingMode(B_OP_ALPHA);
575			SetHighColor(0, 0, 0, 180);
576			SetBlendingMode(B_CONSTANT_ALPHA, B_ALPHA_COMPOSITE);
577			DrawBitmap(icon, iconRect);
578		}
579
580		BTextControl *editName;
581
582	private:
583		BBitmap *icon;
584};
585
586
587// ----- InetHostPanel ----------------------------------------------------------------------
588
589class InetHostPanel : public BWindow
590{
591	public:
592		InetHostPanel(BRect frame, BWindow *win) :
593		  BWindow(frame, "Internet Host", B_TITLED_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL, B_NOT_ZOOMABLE | B_NOT_RESIZABLE)
594		{
595			parent = win;
596
597			BRect r = Bounds();
598			hostView = new InetHostView(r);
599			AddChild(hostView);
600
601			Show();
602		}
603
604		// MessageReceived()
605		//
606		void MessageReceived(BMessage *msg)
607		{
608			BMessage *relay;
609
610			switch (msg->what)
611			{
612				case MSG_HOST_OK:
613					relay = new BMessage(MSG_HOST_OK);
614					relay->AddString("host", hostView->editName->Text());
615					parent->PostMessage(relay);
616
617				case MSG_HOST_CANCEL:
618					BWindow::Quit();
619					break;
620
621				default:
622					BWindow::MessageReceived(msg);
623					break;
624			}
625		}
626
627	private:
628		BWindow *parent;
629		InetHostView *hostView;
630};
631
632// ----- MyNetWindow --------------------------------------------------------------------------
633
634class MyNetWindow : public BWindow
635{
636	public:
637		MyNetWindow(BRect frame) :
638		  BWindow(frame, "My Network", B_TITLED_WINDOW, B_NOT_ZOOMABLE)
639		{
640			BRect r;
641
642			r = Bounds();
643			r.bottom = 85;
644			headerView = new MyNetHeaderView(r);
645			AddChild(headerView);
646
647			CLVContainerView *containerView;
648			r = Bounds();
649			r.top = r.bottom - 140;
650			r.bottom -= 40;
651
652			MyColumnListView = new SmartColumnListView(r, &containerView, NULL, B_FOLLOW_BOTTOM | B_FOLLOW_LEFT_RIGHT,
653				B_WILL_DRAW | B_FRAME_EVENTS | B_NAVIGABLE, B_SINGLE_SELECTION_LIST,
654				false, false, false, false, B_NO_BORDER);
655
656			MyColumnListView->AddColumn(new CLVColumn(NULL, 20.0, CLV_LOCK_AT_BEGINNING | CLV_NOT_MOVABLE |
657				CLV_NOT_RESIZABLE | CLV_PUSH_PASS | CLV_MERGE_WITH_RIGHT));
658			MyColumnListView->AddColumn(new CLVColumn("Computer", 120.0, CLV_SORT_KEYABLE, 50.0));
659			MyColumnListView->AddColumn(new CLVColumn("Share Name", 85.0, CLV_SORT_KEYABLE));
660			MyColumnListView->AddColumn(new CLVColumn("Mounted At", 250.0, CLV_SORT_KEYABLE));
661
662			MyColumnListView->SetSelectionMessage(new BMessage(MSG_SHARE_SELECT));
663			MyColumnListView->SetInvocationMessage(new BMessage(MSG_SHARE_OPEN));
664
665			AddCLVItems(MyColumnListView);
666			AddChild(containerView);
667
668			r = Bounds();
669			r.top = 85;
670			r.bottom -= 140;
671			netView = new MyNetView(r);
672			AddChild(netView);
673
674			r = Bounds();
675			r.top = r.bottom - 40;
676			shareView = new MyShareOptionView(r);
677			AddChild(shareView);
678
679			SetSizeLimits(400, 2000, 270, 2000);
680
681			Show();
682		}
683
684		// AddCLVItems()
685		//
686		void AddCLVItems(ColumnListView* MyColumnListView)
687		{
688			DIR *hosts, *shares;
689			struct dirent *hostInfo, *shareInfo;
690			struct stat st;
691			struct tm *mountTime;
692			char path[B_PATH_NAME_LENGTH];
693
694			hosts = opendir(BT_HOST_PATH);
695			if (hosts)
696			{
697				while ((hostInfo = readdir(hosts)) != NULL)
698					if (IsValid(hostInfo->d_name))
699					{
700						sprintf(path, "%s/%s", BT_HOST_PATH, hostInfo->d_name);
701						shares = opendir(path);
702						if (shares)
703						{
704							while ((shareInfo = readdir(shares)) != NULL)
705								if (IsValid(shareInfo->d_name))
706								{
707									sprintf(path, "%s/%s/%s", BT_HOST_PATH, hostInfo->d_name, shareInfo->d_name);
708									if (dev_for_path("/boot/home") != dev_for_path(path))
709									{
710//										stat(path, &st);
711//										mountTime = localtime(&st.st_ctime);
712//										strftime(path, sizeof(path), "%a, %b %d %Y at %I:%M %p", mountTime);
713										MyColumnListView->AddItem(new MountItem(hostInfo->d_name, shareInfo->d_name, path));
714									}
715									else
716										rmdir(path);
717								}
718
719							closedir(shares);
720						}
721					}
722
723				closedir(hosts);
724			}
725		}
726
727		void MessageReceived(BMessage *msg)
728		{
729			BRect frame;
730			int32 curItem;
731			status_t exitStatus;
732
733			switch (msg->what)
734			{
735				case MSG_HOST_INFO:
736					curItem = netView->list->CurrentSelection();
737					if (curItem != -1)
738					{
739						IconListItem *item = (IconListItem *) netView->list->ItemAt(curItem);
740						if (item)
741						{
742							frame = Frame();
743							frame.left += 100;
744							frame.top += 100;
745							frame.right = frame.left + 260;
746							frame.bottom = frame.top + 310;
747							HostInfoPanel *panel = new HostInfoPanel(frame, item->GetItemText(), item->GetItemData());
748						}
749					}
750					break;
751
752				case MSG_HOST_SELECT:
753					headerView->openBtn->SetEnabled(true);
754					headerView->hostBtn->SetEnabled(true);
755					break;
756
757				case MSG_LIST_DESELECT:
758					if (MyColumnListView->CountItems() > 0 && MyColumnListView->CurrentSelection() == -1)
759					{
760						shareView->openBtn->SetEnabled(false);
761						shareView->unmountBtn->SetEnabled(false);
762					}
763					else
764					{
765						headerView->openBtn->SetEnabled(false);
766						headerView->hostBtn->SetEnabled(false);
767					}
768					break;
769
770				case MSG_SHARE_SELECT:
771					shareView->openBtn->SetEnabled(true);
772					shareView->unmountBtn->SetEnabled(true);
773					break;
774
775				case MSG_HOST_INVOKE:
776					curItem = netView->list->CurrentSelection();
777					if (curItem != -1)
778					{
779						IconListItem *item = (IconListItem *) netView->list->ItemAt(curItem);
780						if (item)
781						{
782							frame = Frame();
783							frame.left += 100;
784							frame.top += 100;
785							frame.right = frame.left + 260;
786							frame.bottom = frame.top + 300;
787							FileShareWindow *win = new FileShareWindow(this, frame, item->GetItemText(), item->GetItemData());
788						}
789					}
790					break;
791
792				case MSG_HOST_REFRESH:
793					netView->Refresh();
794					break;
795
796				case MSG_INET_HOSTS:
797					{
798						frame = Frame();
799						frame.left += 150;
800						frame.top += 50;
801						frame.right = frame.left + 320;
802						frame.bottom = frame.top + 128;
803						InetHostPanel *win = new InetHostPanel(frame, this);
804						wait_for_thread(win->Thread(), &exitStatus);
805					}
806					break;
807
808				case MSG_HOST_OK:
809					{
810						const char *name;
811						msg->FindString("host", &name);
812
813						hostent *ent = gethostbyname(name);
814						if (ent)
815						{
816							char buffer[256];
817							frame = Frame();
818							frame.left += 100;
819							frame.top += 100;
820							frame.right = frame.left + 260;
821							frame.bottom = frame.top + 300;
822							sprintf(buffer, "%d.%d.%d.%d", (uint8) ent->h_addr_list[0][0],
823								(uint8) ent->h_addr_list[0][1], (uint8) ent->h_addr_list[0][2],
824								(uint8) ent->h_addr_list[0][3]);
825							FileShareWindow *win = new FileShareWindow(this, frame, name, (uint32) inet_addr(buffer));
826						}
827						else
828						{
829							BAlert *alert = new BAlert("Error", "The specified name or address cannot be contacted.", "OK", NULL, NULL, B_WIDTH_AS_USUAL, B_WARNING_ALERT);
830							alert->Go();
831						}
832					}
833					break;
834
835				case MSG_NEW_MOUNT:
836					{
837						const char *host, *share, *path;
838						msg->FindString("host", &host);
839						msg->FindString("share", &share);
840						msg->FindString("path", &path);
841						MyColumnListView->LockLooper();
842						MyColumnListView->AddItem(new MountItem(host, share, path));
843						MyColumnListView->UnlockLooper();
844					}
845					break;
846
847				case MSG_SHARE_OPEN:
848					curItem = MyColumnListView->CurrentSelection();
849					if (curItem != -1)
850					{
851						char command[512];
852						MountItem *item = (MountItem *) MyColumnListView->ItemAt(curItem);
853						const char *path = item->GetColumnContentText(3);
854						sprintf(command, "/boot/beos/system/Tracker \"%s\"", path);
855						system(command);
856					}
857					break;
858
859				case MSG_SHARE_UNMOUNT:
860					curItem = MyColumnListView->CurrentSelection();
861					if (curItem != -1)
862					{
863						MountItem *item = (MountItem *) MyColumnListView->ItemAt(curItem);
864						const char *path = item->GetColumnContentText(3);
865						int error = unmount(path);
866						if (error == 0)
867						{
868							MyColumnListView->LockLooper();
869							MyColumnListView->RemoveItems(curItem, 1);
870							MyColumnListView->UnlockLooper();
871
872							shareView->openBtn->SetEnabled(false);
873							shareView->unmountBtn->SetEnabled(false);
874						}
875					}
876					break;
877
878				default:
879					BWindow::MessageReceived(msg);
880					break;
881			}
882		}
883
884		bool QuitRequested()
885		{
886			be_app->PostMessage(B_QUIT_REQUESTED);
887			return true;
888		}
889
890	private:
891		BMenuBar *menuBar;
892		MyNetHeaderView *headerView;
893		MyNetView *netView;
894		MyShareOptionView *shareView;
895		ColumnListView *MyColumnListView;
896};
897
898
899class MyNetApp : public BApplication
900{
901	public:
902		MyNetApp() : BApplication("application/x-vnd.Teldar-MyNetwork")
903		{
904			checkMimeTypes();
905			BRect frame(100, 150, 500, 600);
906			MyNetWindow *win = new MyNetWindow(frame);
907		}
908
909		void RefsReceived(BMessage *msg)
910		{
911			entry_ref entryRef;
912			BPath path;
913			BEntry entry;
914
915			switch (msg->what)
916			{
917				case B_REFS_RECEIVED:
918					msg->FindRef("refs", &entryRef);
919					entry.SetTo(&entryRef, true);
920					entry.GetPath(&path);
921//					mountFileShare(lastHost, lastShare, path.Path());
922					break;
923
924				default:
925					BApplication::RefsReceived(msg);
926					break;
927			}
928		}
929
930	private:
931		void buildMimeDB()
932		{
933			BMimeType mime;
934			BMessage msg;
935			char *data;
936			ssize_t bytes;
937			FILE *fp = fopen("/boot/home/mime.txt", "w");
938			mime.GetInstalledTypes(&msg);
939			for (int i = 0; msg.FindString("types", i, (const char **) &data) == B_OK; i++)
940			{
941				BMimeType t(data);
942				BMessage m;
943				char *ext;
944				if (t.GetFileExtensions(&m) == B_OK)
945				{
946					for (int j = 0; m.FindString("extensions", j, (const char **) &ext) == B_OK; j++)
947						fprintf(fp, "%-6s%s\n", ext, data);
948				}
949			}
950			fclose(fp);
951		}
952
953		void checkMimeTypes()
954		{
955			BMimeType mime;
956			mime.SetTo("application/x-vnd.BeServed-fileserver");
957			mime.Delete();
958			if (!mime.IsInstalled())
959			{
960				mime.Install();
961				mime.SetShortDescription("Network File Server");
962				mime.SetLongDescription("A network server running BeServed");
963				setMimeIcon(&mime, MYNET_ICON_HOST_LARGE, B_LARGE_ICON);
964				setMimeIcon(&mime, MYNET_ICON_HOST_SMALL, B_MINI_ICON);
965			}
966
967			mime.SetTo("application/x-vnd.BeServed-inetserver");
968			mime.Delete();
969			if (!mime.IsInstalled())
970			{
971				mime.Install();
972				mime.SetShortDescription("Public File Server");
973				mime.SetLongDescription("A remote network server running BeServed");
974				setMimeIcon(&mime, MYNET_ICON_INETHOST_LARGE, B_LARGE_ICON);
975				setMimeIcon(&mime, MYNET_ICON_INETHOST_SMALL, B_MINI_ICON);
976			}
977
978			mime.SetTo("application/x-vnd.BeServed-fileshare");
979			mime.Delete();
980			if (!mime.IsInstalled())
981			{
982				mime.Install();
983				mime.SetShortDescription("Shared Volume");
984				mime.SetLongDescription("A BeServed network shared volume");
985				setMimeIcon(&mime, MYNET_ICON_SHARE_LARGE, B_LARGE_ICON);
986				setMimeIcon(&mime, MYNET_ICON_SHARE_SMALL, B_MINI_ICON);
987			}
988		}
989
990		bool setMimeIcon(BMimeType *mime, int32 resourceID, icon_size which)
991		{
992			BMessage archive;
993			size_t size;
994			char *bits = (char *) be_app->AppResources()->LoadResource(type_code('BBMP'), resourceID, &size);
995			if (bits)
996				if (archive.Unflatten(bits) == B_OK)
997				{
998					BBitmap *icon = new BBitmap(&archive);
999					mime->SetIcon(icon, which);
1000					return true;
1001				}
1002
1003			return false;
1004		}
1005};
1006
1007
1008int main()
1009{
1010	MyNetApp *app = new MyNetApp();
1011	app->Run();
1012
1013	return 0;
1014}
1015
1016/*
1017			r = Bounds();
1018			r.bottom = 18.0;
1019			menuBar = new BMenuBar(r, "menu_bar");
1020			BMenu *compMenu = new BMenu("Computer");
1021			compMenu->AddItem(new BMenuItem("Open", new BMessage(MENU_MSG_COPEN), 'O', B_COMMAND_KEY));
1022			compMenu->AddItem(new BMenuItem("Find...", new BMessage(MENU_MSG_CFIND), 'F', B_COMMAND_KEY));
1023			compMenu->AddItem(new BMenuItem("Quit", new BMessage(MENU_MSG_QUIT), 'Q', B_COMMAND_KEY));
1024			menuBar->AddItem(compMenu);
1025
1026			AddChild(menuBar);
1027*/
1028