#include "Application.h"
#include "Window.h"
#include "Region.h"
#include "Alert.h"
#include "CheckBox.h"
#include "Button.h"
#include "TextControl.h"
#include "Menu.h"
#include "PopUpMenu.h"
#include "MenuItem.h"
#include "MenuField.h"
#include "FilePanel.h"
#include "FindDirectory.h"
#include "Path.h"
#include "Mime.h"
#include "Roster.h"
#include "Resources.h"
#include "string.h"
#include "stdio.h"
#include "ctype.h"
#include "signal.h"
#include "unistd.h"
#include "betalk.h"
#include "rpc.h"
#include "ColumnListView.h"
#include "CLVColumn.h"
#include "CLVEasyItem.h"
#include "NewStrings.h"
#define BT_MAX_FILE_SHARES 128
#define MSG_SHARE_INVOKE 'SInv'
#define MSG_PATH_BROWSE 'PBrw'
#define MSG_SHARE_OK 'SOky'
#define MSG_SHARE_CANCEL 'SCan'
#define MSG_SHARE_REFRESH 'SRef'
#define MSG_NEW_SHARE 'SNew'
#define MSG_EDIT_SHARE 'SEdt'
#define MSG_REMOVE_SHARE 'SRem'
#define MSG_SHARE_DEPLOY 'SDep'
#define MSG_SHARE_SELECT 'SSel'
#define MSG_SHARE_PERMS 'SPrm'
#define MSG_EDIT_SECURITY 'ESec'
#define MSG_PICKUSER_SELECT 'MSel'
#define MSG_PICKUSER_ADD 'PAdd'
#define MSG_PICKUSER_REMOVE 'PRem'
#define MSG_DOMUSER_OK 'DOky'
#define MSG_DOMUSER_CANCEL 'DCan'
#define MSG_DOMUSER_SELECT 'DSel'
#define ICON_USER_LARGE 111
#define ICON_USER_SMALL 112
#define ICON_GROUP_LARGE 115
#define ICON_GROUP_SMALL 116
#define ICON_DOMAIN_LARGE 109
#define ICON_DOMAIN_SMALL 110
#define ICON_SWITCH_LARGE 119
#define ICON_SWITCH_SMALL 120
#define ICON_LIGHT_LARGE 121
#define ICON_PADLOCK_LARGE 122
#define ICON_KEY_LARGE 123
#define WARN_REMOVE_SHARE "Removing this file share will prevent other users on your network from accessing certain files on this computer. Are you sure you want to remove this file share?"
#ifndef iswhite
#define iswhite(c) ((c == ' ' || c == '\t'))
#endif
typedef void op_refresh(int share);
typedef struct userRights
{
char *user;
int rights;
bool isGroup;
struct userRights *next;
} bt_user_rights;
typedef struct fileShare
{
char path[B_PATH_NAME_LENGTH];
char name[B_FILE_NAME_LENGTH];
bool used;
bool readOnly;
bool followLinks;
bt_user_rights *rights;
int security;
int index;
struct fileShare *next;
} bt_fileShare_t;
void printString(FILE *fp, const char *str);
bt_fileShare_t fileShares[BT_MAX_FILE_SHARES];
char tokBuffer[B_PATH_NAME_LENGTH], *tokPtr;
char authServerName[B_FILE_NAME_LENGTH], authKey[MAX_KEY_LENGTH + 1];
unsigned int authServerIP = 0;
char *keywords[] =
{
"share",
"as",
"set",
"read",
"write",
"read-write",
"promiscuous",
"on",
"to",
"authenticate",
"with",
"group",
NULL
};
const int32 MSG_LIST_DESELECT = 'CLV0';
class SmartColumnListView : public ColumnListView
{
public:
SmartColumnListView(BRect Frame, CLVContainerView** ContainerView,
const char* Name = NULL, uint32 ResizingMode = B_FOLLOW_LEFT | B_FOLLOW_TOP,
uint32 flags = B_WILL_DRAW | B_FRAME_EVENTS | B_NAVIGABLE,
list_view_type Type = B_SINGLE_SELECTION_LIST,
bool hierarchical = false, bool horizontal = true, bool vertical = true,
bool scroll_view_corner = true, border_style border = B_NO_BORDER,
const BFont* LabelFont = be_plain_font) :
ColumnListView(Frame, ContainerView, Name, ResizingMode, flags, Type, hierarchical,
horizontal, vertical, scroll_view_corner, border, LabelFont)
{
container = *ContainerView;
}
virtual ~SmartColumnListView()
{
}
void MouseDown(BPoint point)
{
ColumnListView::MouseDown(point);
if (CurrentSelection() < 0)
container->Window()->PostMessage(MSG_LIST_DESELECT);
}
private:
CLVContainerView *container;
};
class FileShareItem : public CLVEasyItem
{
public:
FileShareItem(const char *text0, const char *text1, const char *text2) :
CLVEasyItem(0, false, false, 20.0)
{
BRect bmpRect(0.0, 0.0, 15.0, 15.0);
BBitmap *icon = new BBitmap(bmpRect, B_CMAP8);
BMimeType mime("application/x-vnd.BeServed-fileshare");
mime.GetIcon(icon, B_MINI_ICON);
SetColumnContent(0, icon, 2.0);
SetColumnContent(1, text0);
SetColumnContent(2, text1);
SetColumnContent(3, text2);
}
~FileShareItem()
{
}
};
class MilestoneView : public BView
{
public:
MilestoneView(BRect rect, const char *title) :
BView(rect, "MilestoneView", B_FOLLOW_ALL, B_WILL_DRAW)
{
strcpy(heading, title);
rgb_color gray = ui_color(B_PANEL_BACKGROUND_COLOR);
SetViewColor(gray);
BRect bmpRect(0.0, 0.0, 31.0, 31.0);
icon = new BBitmap(bmpRect, B_CMAP8);
BMimeType mime("application/x-vnd.Teldar-FileSharing");
mime.GetIcon(icon, B_LARGE_ICON);
BRect r;
r.Set(120, 48, 190, 68);
okBtn = new BButton(r, "OKBtn", "OK", new BMessage(MSG_SHARE_OK), B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM);
okBtn->MakeDefault(true);
okBtn->SetEnabled(false);
AddChild(okBtn);
}
~MilestoneView()
{
}
void Draw(BRect rect)
{
BRect r = Bounds();
BRect iconRect(13.0, 5.0, 45.0, 37.0);
rgb_color black = { 0, 0, 0, 255 };
rgb_color gray = ui_color(B_PANEL_BACKGROUND_COLOR);
rgb_color light = ui_color(B_MENU_BACKGROUND_COLOR);
SetViewColor(gray);
SetLowColor(gray);
FillRect(r, B_SOLID_LOW);
SetHighColor(black);
SetFont(be_bold_font);
SetFontSize(11);
MovePenTo(55, 20);
DrawString(heading);
SetFont(be_plain_font);
MovePenTo(55, 35);
DrawString(msg);
SetDrawingMode(B_OP_ALPHA);
SetHighColor(0, 0, 0, 180);
SetBlendingMode(B_CONSTANT_ALPHA, B_ALPHA_COMPOSITE);
DrawBitmap(icon, iconRect);
}
void setText(const char *text, bool done)
{
strcpy(msg, text);
LockLooper();
Invalidate(Bounds());
okBtn->SetEnabled(done);
UnlockLooper();
snooze(200000);
}
private:
BButton *okBtn;
BBitmap *icon;
char heading[50];
char msg[256];
};
class MilestonePanel : public BWindow
{
public:
MilestonePanel(BRect frame, const char *title) :
BWindow(frame, "", B_MODAL_WINDOW_LOOK, B_MODAL_APP_WINDOW_FEEL, B_NOT_ZOOMABLE | B_NOT_RESIZABLE)
{
BRect r = Bounds();
milestoneView = new MilestoneView(r, title);
AddChild(milestoneView);
Show();
}
void MessageReceived(BMessage *msg)
{
switch (msg->what)
{
case MSG_SHARE_OK:
BWindow::Quit();
break;
default:
BWindow::MessageReceived(msg);
break;
}
}
void setText(const char *text, bool done)
{
milestoneView->setText(text, done);
}
private:
MilestoneView *milestoneView;
};
class PickUserItem : public CLVEasyItem
{
public:
PickUserItem(bool group, const char *text0, const char *text1) :
CLVEasyItem(0, false, false, 20.0)
{
BBitmap *icon;
BMessage archive;
size_t size;
char *bits = (char *) be_app->AppResources()->LoadResource(type_code('BBMP'), group ? ICON_GROUP_SMALL : ICON_USER_SMALL, &size);
if (bits)
if (archive.Unflatten(bits) == B_OK)
{
icon = new BBitmap(&archive);
SetColumnContent(0, icon, 2.0);
SetColumnContent(1, text0);
SetColumnContent(2, text1);
isGroupItem = group;
}
}
~PickUserItem()
{
}
bool isUser()
{
return !isGroupItem;
}
bool isGroup()
{
return isGroupItem;
}
static int CompareItems(const CLVListItem *item1, const CLVListItem *item2, int32 KeyColumn)
{
const char *str1 = ((PickUserItem *) item1)->GetColumnContentText(1);
const char *str2 = ((PickUserItem *) item2)->GetColumnContentText(1);
return strcasecmp(str1, str2);
}
private:
bool isGroupItem;
};
class SecurityView : public BView
{
public:
SecurityView(BRect rect) :
BView(rect, "DomainUserView", B_FOLLOW_ALL, B_WILL_DRAW)
{
BMessage archive;
size_t size;
char *bits;
rgb_color gray = ui_color(B_PANEL_BACKGROUND_COLOR);
SetViewColor(gray);
bits = (char *) be_app->AppResources()->LoadResource(type_code('BBMP'), ICON_PADLOCK_LARGE, &size);
if (bits)
if (archive.Unflatten(bits) == B_OK)
lockIcon = new BBitmap(&archive);
BRect r;
r.Set(10, 60, 360, 80);
mnuMethod = new BPopUpMenu("");
mnuMethod->AddItem(new BMenuItem("No Authentication Required", NULL));
mnuMethod->AddItem(new BMenuItem("BeSure Authentication Server", NULL));
mnuAccess = new BMenuField(r, "AuthMethod", "Authentication Method:", mnuMethod);
mnuAccess->SetDivider(120);
if (authServerIP)
item = mnuMethod->FindItem("BeSure Authentication Server");
else
item = mnuMethod->FindItem("No Authentication Required");
if (item)
item->SetMarked(true);
AddChild(mnuAccess);
r.Set(10, 85, 360, 105);
editServer = new BTextControl(r, "ServerName", "Server Name:", authServerName, NULL);
editServer->SetDivider(120);
AddChild(editServer);
r.Set(210, 115, 280, 135);
okBtn = new BButton(r, "OkayBtn", "OK", new BMessage(MSG_DOMUSER_OK), B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM);
okBtn->MakeDefault(true);
AddChild(okBtn);
r.Set(290, 115, 360, 135);
AddChild(new BButton(r, "CancelBtn", "Cancel", new BMessage(MSG_DOMUSER_CANCEL), B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM));
}
~SecurityView()
{
}
void Draw(BRect rect)
{
BRect r = Bounds();
BRect iconRect(13.0, 10.0, 45.0, 42.0);
rgb_color black = { 0, 0, 0, 255 };
rgb_color gray = ui_color(B_PANEL_BACKGROUND_COLOR);
SetViewColor(gray);
SetLowColor(gray);
FillRect(r, B_SOLID_LOW);
SetHighColor(black);
SetFont(be_plain_font);
SetFontSize(10);
MovePenTo(55, 17);
DrawString("When users connect to this computer to access shared files,");
MovePenTo(55, 29);
DrawString("the settings here will be used to determine how those users");
MovePenTo(55, 41);
DrawString("are authenticated.");
SetDrawingMode(B_OP_ALPHA);
SetHighColor(0, 0, 0, 180);
SetBlendingMode(B_CONSTANT_ALPHA, B_ALPHA_COMPOSITE);
DrawBitmap(lockIcon, iconRect);
}
void UpdateData()
{
struct hostent *ent;
authServerName[0] = 0;
authServerIP = 0;
BMenuItem *item = mnuMethod->FindMarked();
if (item)
if (strcmp(item->Label(), "BeSure Authentication Server") == 0)
{
strcpy(authServerName, editServer->Text());
ent = gethostbyname(authServerName);
if (ent != NULL)
authServerIP = ntohl(*((unsigned int *) ent->h_addr));
else
authServerIP = 0;
}
}
private:
BButton *okBtn;
BPopUpMenu *mnuMethod;
BMenuField *mnuAccess;
BMenuItem *item;
BTextControl *editServer;
BBitmap *lockIcon;
};
class SecurityPanel : public BWindow
{
public:
SecurityPanel(BRect frame) :
BWindow(frame, "Security", B_TITLED_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL, B_NOT_ZOOMABLE | B_NOT_RESIZABLE)
{
BRect r = Bounds();
infoView = new SecurityView(r);
AddChild(infoView);
Show();
}
void MessageReceived(BMessage *msg)
{
switch (msg->what)
{
case MSG_DOMUSER_OK:
infoView->UpdateData();
BWindow::Quit();
break;
case MSG_DOMUSER_CANCEL:
BWindow::Quit();
break;
default:
BWindow::MessageReceived(msg);
break;
}
}
private:
SecurityView *infoView;
};
class DomainUserView : public BView
{
public:
DomainUserView(BRect rect) :
BView(rect, "DomainUserView", B_FOLLOW_ALL, B_WILL_DRAW)
{
BMessage archive;
size_t size;
char *bits;
rgb_color gray = ui_color(B_PANEL_BACKGROUND_COLOR);
SetViewColor(gray);
bits = (char *) be_app->AppResources()->LoadResource(type_code('BBMP'), ICON_LIGHT_LARGE, &size);
if (bits)
if (archive.Unflatten(bits) == B_OK)
lightIcon = new BBitmap(&archive);
BRect r;
r.Set(10, 240, 200, 260);
mnuRights = new BPopUpMenu("");
mnuRights->AddItem(new BMenuItem("Read-only", NULL));
mnuRights->AddItem(new BMenuItem("Read-write", NULL));
mnuAccess = new BMenuField(r, "AccessRights", "Access Rights:", mnuRights);
mnuAccess->SetDivider(75);
item = mnuRights->FindItem("Read-only");
if (item)
item->SetMarked(true);
AddChild(mnuAccess);
r.Set(210, 320, 280, 340);
okBtn = new BButton(r, "OkayBtn", "OK", new BMessage(MSG_DOMUSER_OK), B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM);
okBtn->MakeDefault(true);
AddChild(okBtn);
r.Set(290, 320, 360, 340);
AddChild(new BButton(r, "CancelBtn", "Cancel", new BMessage(MSG_DOMUSER_CANCEL), B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM));
CLVContainerView *listContView;
r.Set(13, 48, 360 - B_V_SCROLL_BAR_WIDTH, 230);
listView = new SmartColumnListView(r, &listContView, NULL, B_FOLLOW_ALL_SIDES,
B_WILL_DRAW | B_FRAME_EVENTS | B_NAVIGABLE, B_SINGLE_SELECTION_LIST,
false, false, true, false, B_FANCY_BORDER);
listView->AddColumn(new CLVColumn(NULL, 20.0, CLV_LOCK_AT_BEGINNING | CLV_NOT_MOVABLE |
CLV_NOT_RESIZABLE | CLV_PUSH_PASS | CLV_MERGE_WITH_RIGHT));
listView->AddColumn(new CLVColumn("User or Group", 140.0, CLV_SORT_KEYABLE, 50.0));
listView->AddColumn(new CLVColumn("Full Name", 160.0, CLV_SORT_KEYABLE));
AddUserList(listView);
AddGroupList(listView);
listView->SetSortFunction(PickUserItem::CompareItems);
listView->SortItems();
AddChild(listContView);
}
~DomainUserView()
{
}
void Draw(BRect rect)
{
BRect r = Bounds();
rgb_color black = { 0, 0, 0, 255 };
rgb_color gray = ui_color(B_PANEL_BACKGROUND_COLOR);
SetViewColor(gray);
SetLowColor(gray);
FillRect(r, B_SOLID_LOW);
SetHighColor(black);
SetFont(be_plain_font);
SetFontSize(10);
MovePenTo(10, 17);
DrawString("Select a user or group from the list below, select the desired access rights,");
MovePenTo(10, 29);
DrawString("then click the OK button. Click the Cancel button to abort the selection.");
MovePenTo(55, 288);
DrawString("When granting write access to a shared volume, you are by");
MovePenTo(55, 300);
DrawString("definition also granting the ability to rename and delete files.");
SetDrawingMode(B_OP_ALPHA);
SetHighColor(0, 0, 0, 180);
SetBlendingMode(B_CONSTANT_ALPHA, B_ALPHA_COMPOSITE);
r.Set(13, 275, 45, 307);
DrawBitmap(lightIcon, r);
}
void AddUserList(ColumnListView* listView)
{
DIR *dir = NULL;
char user[MAX_USERNAME_LENGTH], fullName[MAX_DESC_LENGTH];
bt_outPacket *outPacket = btRPCPutHeader(BT_CMD_READUSERS, 1, 4);
btRPCPutArg(outPacket, B_INT32_TYPE, &dir, sizeof(int32));
bt_inPacket *inPacket = btRPCSimpleCall(authServerIP, BT_BESURE_PORT, outPacket);
if (inPacket)
{
int error, count = 0;
do
{
error = btRPCGetInt32(inPacket);
if (error == B_OK)
{
memset(user, 0, sizeof(user));
memset(fullName, 0, sizeof(fullName));
btRPCGetString(inPacket, user, sizeof(user));
btRPCGetString(inPacket, fullName, sizeof(fullName));
listView->AddItem(new PickUserItem(false, user, fullName));
}
else break;
} while (++count < 80);
free(inPacket->buffer);
free(inPacket);
}
}
void AddGroupList(ColumnListView* listView)
{
DIR *dir = NULL;
char group[MAX_USERNAME_LENGTH];
bt_outPacket *outPacket = btRPCPutHeader(BT_CMD_READGROUPS, 1, 4);
btRPCPutArg(outPacket, B_INT32_TYPE, &dir, sizeof(int32));
bt_inPacket *inPacket = btRPCSimpleCall(authServerIP, BT_BESURE_PORT, outPacket);
if (inPacket)
{
int error, count = 0;
do
{
error = btRPCGetInt32(inPacket);
if (error == B_OK)
{
memset(group, 0, sizeof(group));
btRPCGetString(inPacket, group, sizeof(group));
listView->AddItem(new PickUserItem(true, group, ""));
}
else break;
} while (++count < 80);
free(inPacket->buffer);
free(inPacket);
}
}
char *GetSelectedUser()
{
if (listView)
{
int index = listView->CurrentSelection();
if (index >= 0)
{
PickUserItem *item = (PickUserItem *) listView->ItemAt(index);
return ((char *) item->GetColumnContentText(1));
}
}
return NULL;
}
int GetRights()
{
BMenuItem *item = mnuRights->FindMarked();
if (item)
if (strcmp(item->Label(), "Read-only") == 0)
return BT_RIGHTS_READ;
else if (strcmp(item->Label(), "Read-write") == 0)
return (BT_RIGHTS_READ | BT_RIGHTS_WRITE);
return 0;
}
bool isGroup()
{
if (listView)
{
int index = listView->CurrentSelection();
if (index >= 0)
{
PickUserItem *item = (PickUserItem *) listView->ItemAt(index);
return item->isGroup();
}
}
return false;
}
private:
SmartColumnListView *listView;
BButton *okBtn;
BPopUpMenu *mnuRights;
BMenuField *mnuAccess;
BMenuItem *item;
BBitmap *lightIcon;
};
class DomainUserPanel : public BWindow
{
public:
DomainUserPanel(BRect frame, bt_fileShare_t *sharePtr) :
BWindow(frame, "Domain Users", B_TITLED_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL, B_NOT_ZOOMABLE | B_NOT_RESIZABLE)
{
share = sharePtr;
BRect r = Bounds();
infoView = new DomainUserView(r);
AddChild(infoView);
Show();
}
void MessageReceived(BMessage *msg)
{
switch (msg->what)
{
case MSG_DOMUSER_OK:
SaveUserRights(infoView->GetSelectedUser(), infoView->GetRights(), infoView->isGroup());
BWindow::Quit();
break;
case MSG_DOMUSER_CANCEL:
BWindow::Quit();
break;
default:
BWindow::MessageReceived(msg);
break;
}
}
void SaveUserRights(char *user, int rights, bool isGroup)
{
bt_user_rights *ur;
if (user == NULL || rights == 0)
return;
for (ur = share->rights; ur; ur = ur->next)
if (strcmp(ur->user, user) == 0)
{
ur->rights = rights;
return;
}
ur = (bt_user_rights *) malloc(sizeof(bt_user_rights));
if (ur)
{
ur->user = (char *) malloc(strlen(user) + 1);
if (ur->user)
{
strcpy(ur->user, user);
ur->rights = rights;
ur->isGroup = isGroup;
ur->next = share->rights;
share->rights = ur;
}
else
free(ur);
}
}
private:
DomainUserView *infoView;
bt_fileShare_t *share;
};
class ShareInfoView : public BView
{
public:
ShareInfoView(BRect rect, bt_fileShare_t *sharePtr) :
BView(rect, "HostInfoView", B_FOLLOW_ALL, B_WILL_DRAW)
{
BMessage archive;
size_t size;
char *bits;
share = sharePtr;
optionIcon = domainIcon = NULL;
rgb_color gray = ui_color(B_PANEL_BACKGROUND_COLOR);
SetViewColor(gray);
BRect bmpRect(0.0, 0.0, 31.0, 31.0);
icon = new BBitmap(bmpRect, B_CMAP8);
BMimeType mime("application/x-vnd.BeServed-fileshare");
mime.GetIcon(icon, B_LARGE_ICON);
bits = (char *) be_app->AppResources()->LoadResource(type_code('BBMP'), ICON_SWITCH_LARGE, &size);
if (bits)
if (archive.Unflatten(bits) == B_OK)
optionIcon = new BBitmap(&archive);
bits = (char *) be_app->AppResources()->LoadResource(type_code('BBMP'), ICON_DOMAIN_LARGE, &size);
if (bits)
if (archive.Unflatten(bits) == B_OK)
domainIcon = new BBitmap(&archive);
BRect r(10, 52, 200, 72);
editName = new BTextControl(r, "ShareName", "Name:", share->name, NULL);
editName->SetDivider(40);
AddChild(editName);
r.top = 77;
r.bottom = r.top + 20;
r.right = 300;
editPath = new BTextControl(r, "SharePath", "Path:", share->path, NULL);
editPath->SetDivider(40);
AddChild(editPath);
r.top = 150;
r.bottom = r.top + 15;
chkReadWrite = new BCheckBox(r, "ReadWrite", "Users can make changes to files and folders", NULL);
chkReadWrite->SetValue(share->readOnly ? B_CONTROL_OFF : B_CONTROL_ON);
AddChild(chkReadWrite);
r.top = 170;
r.bottom = r.top + 15;
chkFollowLinks = new BCheckBox(r, "FollowLinks", "Follow links leading outside the path", NULL);
chkFollowLinks->SetValue(share->followLinks ? B_CONTROL_ON : B_CONTROL_OFF);
chkFollowLinks->SetEnabled(false);
AddChild(chkFollowLinks);
r.Set(310, 75, 390, 95);
AddChild(new BButton(r, "BrowseBtn", "Browse...", new BMessage(MSG_PATH_BROWSE)));
r.Set(325, 235, 400, 255);
btnAdd = new BButton(r, "AddBtn", "Add", new BMessage(MSG_PICKUSER_ADD), B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM);
btnAdd->SetEnabled(authServerIP != 0);
AddChild(btnAdd);
r.Set(325, 265, 400, 285);
btnRemove = new BButton(r, "RemoveBtn", "Remove", new BMessage(MSG_PICKUSER_REMOVE), B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM);
btnRemove->SetEnabled(false);
AddChild(btnRemove);
CLVContainerView *listContView;
r.Set(13, 235, 315 - B_V_SCROLL_BAR_WIDTH, 340);
listView = new SmartColumnListView(r, &listContView, NULL, B_FOLLOW_ALL_SIDES,
B_WILL_DRAW | B_FRAME_EVENTS | B_NAVIGABLE, B_SINGLE_SELECTION_LIST,
false, false, true, false, B_FANCY_BORDER);
listView->AddColumn(new CLVColumn(NULL, 20.0, CLV_LOCK_AT_BEGINNING | CLV_NOT_MOVABLE |
CLV_NOT_RESIZABLE | CLV_PUSH_PASS | CLV_MERGE_WITH_RIGHT));
listView->AddColumn(new CLVColumn("User or Group", 150.0, CLV_SORT_KEYABLE, 50.0));
listView->AddColumn(new CLVColumn("Access", 80.0, CLV_SORT_KEYABLE));
listView->SetSelectionMessage(new BMessage(MSG_PICKUSER_SELECT));
listView->SetInvocationMessage(new BMessage(MSG_LIST_DESELECT));
AddUserList(listView);
listView->SetSortFunction(PickUserItem::CompareItems);
listView->SortItems();
AddChild(listContView);
r.Set(245, 355, 315, 375);
BButton *okBtn = new BButton(r, "OkayBtn", "OK", new BMessage(MSG_SHARE_OK), B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM);
okBtn->MakeDefault(true);
AddChild(okBtn);
r.Set(325, 355, 400, 375);
AddChild(new BButton(r, "CancelBtn", "Cancel", new BMessage(MSG_SHARE_CANCEL), B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM));
}
~ShareInfoView()
{
}
void Draw(BRect rect)
{
BRect r = Bounds();
BRect iconRect(13.0, 5.0, 45.0, 37.0);
rgb_color black = { 0, 0, 0, 255 };
rgb_color gray = ui_color(B_PANEL_BACKGROUND_COLOR);
SetViewColor(gray);
SetLowColor(gray);
FillRect(r, B_SOLID_LOW);
SetHighColor(black);
SetFont(be_bold_font);
SetFontSize(11);
MovePenTo(55, 15);
DrawString(share->name);
MovePenTo(55, 130);
DrawString("General Options");
MovePenTo(55, 212);
DrawString("Domain User Access");
SetFont(be_plain_font);
SetFontSize(10);
MovePenTo(55, 28);
DrawString("Use this properties window to define the parameters under which you will");
MovePenTo(55, 40);
DrawString("allow users to share files on this computer.");
SetDrawingMode(B_OP_ALPHA);
SetHighColor(0, 0, 0, 180);
SetBlendingMode(B_CONSTANT_ALPHA, B_ALPHA_COMPOSITE);
DrawBitmap(icon, iconRect);
r.Set(13, 113, 45, 145);
DrawBitmap(optionIcon, r);
r.Set(13, 195, 45, 227);
DrawBitmap(domainIcon, r);
DrawDivider(10, 107, 390);
DrawDivider(10, 193, 390);
}
void DrawDivider(int left, int top, int width)
{
rgb_color darkGray = { 189, 186, 189, 255 };
rgb_color lightGray = { 239, 239, 239, 255 };
BPoint startPt(left, top);
BPoint endPt(left + width, top);
SetHighColor(darkGray);
StrokeLine(startPt, endPt);
startPt.y += 1;
endPt.y += 1;
SetHighColor(lightGray);
StrokeLine(startPt, endPt);
}
void ItemSelected()
{
if (authServerIP)
btnRemove->SetEnabled(true);
}
void ItemDeselected()
{
btnRemove->SetEnabled(false);
}
void AddUserList(ColumnListView* listView)
{
bt_user_rights *ur;
if (share->security != BT_AUTH_NONE)
for (ur = share->rights; ur; ur = ur->next)
{
char access[50];
access[0] = 0;
if (ur->rights & BT_RIGHTS_READ)
strcat(access, "Read ");
if (ur->rights & BT_RIGHTS_WRITE)
strcat(access, "Write");
listView->AddItem(new PickUserItem(ur->isGroup, ur->user, access));
}
}
void ResetUserList()
{
FileShareItem *item;
listView->LockLooper();
do
{
item = (FileShareItem *) listView->RemoveItem(int32(0));
if (item)
delete item;
} while(item);
AddUserList(listView);
listView->UnlockLooper();
}
void setPath(const char *path)
{
if (editPath)
{
editPath->LockLooper();
editPath->SetText(path);
editPath->UnlockLooper();
}
}
void RemoveSelectedRights()
{
int curItem;
listView->LockLooper();
curItem = listView->CurrentSelection();
if (curItem >= 0)
{
FileShareItem *item = (FileShareItem *) listView->ItemAt(curItem);
if (item)
{
bt_user_rights *ur, *lastUR;
const char *user = item->GetColumnContentText(1);
for (ur = share->rights, lastUR = NULL; ur; ur = ur->next)
{
if (strcmp(ur->user, user) == 0)
{
if (lastUR)
lastUR->next = ur->next;
else
share->rights = ur->next;
free(ur->user);
free(ur);
break;
}
lastUR = ur;
}
}
listView->RemoveItem(curItem);
}
listView->UnlockLooper();
}
bool updateShare()
{
BAlert *alert;
char buf[256];
unsigned int length;
length = sizeof(share->name);
if (strlen(editName->Text()) > length)
{
sprintf(buf, "The name of this share is too long. Please provide a name that is at most %d characters.", length);
alert = new BAlert("Oops!", buf, "OK");
return false;
}
length = sizeof(share->path);
if (strlen(editPath->Text()) > length)
{
sprintf(buf, "The path name is too long. The share path can be at most %d characters.", length);
alert = new BAlert("Oops!", buf, "OK");
return false;
}
strcpy(share->name, editName->Text());
strcpy(share->path, editPath->Text());
share->readOnly = chkReadWrite->Value() == B_CONTROL_OFF;
share->followLinks = chkFollowLinks->Value() == B_CONTROL_ON;
return true;
}
private:
SmartColumnListView *listView;
BBitmap *icon, *optionIcon, *domainIcon;
BTextControl *editName;
BTextControl *editPath;
BCheckBox *chkReadWrite;
BCheckBox *chkFollowLinks;
BButton *btnAdd, *btnRemove;
bt_fileShare_t *share;
};
class ShareInfoPanel : public BWindow
{
public:
ShareInfoPanel(BRect frame, bt_fileShare_t *sharePtr, BWindow *parent) :
BWindow(frame, sharePtr->name, B_TITLED_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL, B_NOT_ZOOMABLE | B_NOT_RESIZABLE)
{
share = sharePtr;
shareWin = parent;
BRect r = Bounds();
infoView = new ShareInfoView(r, share);
AddChild(infoView);
Show();
}
void MessageReceived(BMessage *msg)
{
BFilePanel *filePanel;
entry_ref entryRef;
BRect frame;
DomainUserPanel *picker;
status_t status;
BEntry entry(share->path, false);
entry.GetRef(&entryRef);
switch (msg->what)
{
case MSG_PATH_BROWSE:
filePanel = new BFilePanel(B_OPEN_PANEL, &be_app_messenger, &entryRef, B_DIRECTORY_NODE, false);
filePanel->Show();
filePanel->Window()->SetTitle("Shared Folder");
filePanel->SetButtonLabel(B_DEFAULT_BUTTON, "Select");
break;
case MSG_PICKUSER_ADD:
frame = Frame();
frame.left += 100;
frame.top += 30;
frame.right = frame.left + 370;
frame.bottom = frame.top + 350;
picker = new DomainUserPanel(frame, share);
wait_for_thread(picker->Thread(), &status);
infoView->ResetUserList();
break;
case MSG_PICKUSER_REMOVE:
infoView->RemoveSelectedRights();
break;
case MSG_PICKUSER_SELECT:
infoView->ItemSelected();
break;
case MSG_LIST_DESELECT:
infoView->ItemDeselected();
break;
case MSG_SHARE_OK:
if (!infoView->updateShare())
break;
else
{
BMessage *msg = new BMessage(MSG_SHARE_REFRESH);
msg->AddPointer("share", share);
shareWin->PostMessage(msg);
}
case MSG_SHARE_CANCEL:
BWindow::Quit();
break;
default:
BWindow::MessageReceived(msg);
break;
}
}
void setPath(const char *path)
{
infoView->setPath(path);
}
private:
ShareInfoView *infoView;
BWindow *shareWin;
bt_fileShare_t *share;
};
class FileSharingHeaderView : public BView
{
public:
FileSharingHeaderView(BRect rect) :
BView(rect, "FileSharingHeaderView", B_FOLLOW_TOP | B_FOLLOW_LEFT_RIGHT, B_WILL_DRAW)
{
rgb_color gray = ui_color(B_PANEL_BACKGROUND_COLOR);
SetViewColor(gray);
BRect bmpRect(0.0, 0.0, 31.0, 31.0);
icon = new BBitmap(bmpRect, B_CMAP8);
BMimeType mime("application/x-vnd.Teldar-FileSharing");
mime.GetIcon(icon, B_LARGE_ICON);
BRect r;
r.Set(15, 55, 70, 75);
AddChild(new BButton(r, "NewBtn", "New", new BMessage(MSG_NEW_SHARE)));
r.Set(80, 55, 135, 75);
editBtn = new BButton(r, "EditBtn", "Edit", new BMessage(MSG_EDIT_SHARE));
editBtn->SetEnabled(false);
AddChild(editBtn);
r.Set(145, 55, 210, 75);
removeBtn = new BButton(r, "RemoveBtn", "Remove", new BMessage(MSG_REMOVE_SHARE));
removeBtn->SetEnabled(false);
AddChild(removeBtn);
r.Set(337, 55, 412, 75);
AddChild(new BButton(r, "SecurityBtn", "Security", new BMessage(MSG_EDIT_SECURITY)));
}
~FileSharingHeaderView()
{
}
void Draw(BRect rect)
{
BRect r = Bounds();
BRect iconRect(13.0, 5.0, 45.0, 37.0);
rgb_color black = { 0, 0, 0, 255 };
rgb_color gray = ui_color(B_PANEL_BACKGROUND_COLOR);
SetViewColor(gray);
SetLowColor(gray);
FillRect(r, B_SOLID_LOW);
SetHighColor(black);
SetFont(be_bold_font);
SetFontSize(11);
MovePenTo(55, 15);
DrawString("File Sharing Preferences");
SetFont(be_plain_font);
SetFontSize(10);
MovePenTo(55, 28);
DrawString("Normally, remote computers on your network do not have access to files on");
MovePenTo(55, 40);
DrawString("this computer. You grant them access by explicitly sharing specific folders.");
SetDrawingMode(B_OP_ALPHA);
SetHighColor(0, 0, 0, 180);
SetBlendingMode(B_CONSTANT_ALPHA, B_ALPHA_COMPOSITE);
DrawBitmap(icon, iconRect);
}
BButton *editBtn;
BButton *removeBtn;
private:
BBitmap *icon;
};
class FileSharingFooterView : public BView
{
public:
FileSharingFooterView(BRect rect) :
BView(rect, "FileSharingHeaderView", B_FOLLOW_BOTTOM | B_FOLLOW_LEFT_RIGHT, B_WILL_DRAW)
{
rgb_color gray = ui_color(B_PANEL_BACKGROUND_COLOR);
SetViewColor(gray);
BRect r;
r.Set(177, 52, 247, 72);
BButton *okBtn = new BButton(r, "SaveBtn", "Save", new BMessage(MSG_SHARE_OK), B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM);
okBtn->MakeDefault(true);
AddChild(okBtn);
r.Set(257, 52, 327, 72);
deployBtn = new BButton(r, "DeployBtn", "Deploy", new BMessage(MSG_SHARE_DEPLOY), B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM);
deployBtn->SetEnabled(false);
AddChild(deployBtn);
r.Set(337, 52, 412, 72);
AddChild(new BButton(r, "CancelBtn", "Close", new BMessage(MSG_SHARE_CANCEL), B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM));
}
~FileSharingFooterView()
{
}
void Draw(BRect rect)
{
BRect r = Bounds();
rgb_color black = { 0, 0, 0, 255 };
rgb_color gray = ui_color(B_PANEL_BACKGROUND_COLOR);
SetViewColor(gray);
SetLowColor(gray);
FillRect(r, B_SOLID_LOW);
SetHighColor(black);
SetFont(be_plain_font);
SetFontSize(10);
MovePenTo(15, 15);
DrawString("Save your changes to file sharing preferences by clicking the 'Save' button. This");
MovePenTo(15, 27);
DrawString("will not have an effect on users until you click the 'Deploy' button or manually");
MovePenTo(15, 39);
DrawString("restart the BeServed file serving application.");
}
void SetDeployable(bool deployable)
{
deployBtn->SetEnabled(deployable);
}
private:
BButton *deployBtn;
};
class FileSharingWindow : public BWindow
{
public:
FileSharingWindow() :
BWindow(BRect(50, 50, 475, 460), "File Sharing", B_TITLED_WINDOW, 0)
{
info = NULL;
BRect r = Bounds();
r = Bounds();
r.bottom = 85;
headerView = new FileSharingHeaderView(r);
AddChild(headerView);
CLVContainerView *containerView;
r = Bounds();
r.top = 85;
r.bottom = 325;
MyColumnListView = new SmartColumnListView(r, &containerView, NULL, B_FOLLOW_ALL_SIDES,
B_WILL_DRAW | B_FRAME_EVENTS | B_NAVIGABLE, B_SINGLE_SELECTION_LIST,
false, false, false, false, B_NO_BORDER);
MyColumnListView->AddColumn(new CLVColumn(NULL, 20.0, CLV_LOCK_AT_BEGINNING | CLV_NOT_MOVABLE |
CLV_NOT_RESIZABLE | CLV_PUSH_PASS | CLV_MERGE_WITH_RIGHT));
MyColumnListView->AddColumn(new CLVColumn("Share Name", 130.0, CLV_SORT_KEYABLE, 50.0));
MyColumnListView->AddColumn(new CLVColumn("Access", 75.0, CLV_SORT_KEYABLE));
MyColumnListView->AddColumn(new CLVColumn("Path", 250.0, CLV_SORT_KEYABLE));
MyColumnListView->SetSelectionMessage(new BMessage(MSG_SHARE_SELECT));
MyColumnListView->SetInvocationMessage(new BMessage(MSG_SHARE_INVOKE));
initShares();
AddCLVItems(MyColumnListView);
AddChild(containerView);
r = Bounds();
r.top = 325;
footerView = new FileSharingFooterView(r);
AddChild(footerView);
SetSizeLimits(425, 2000, 250, 2000);
Show();
}
~FileSharingWindow()
{
be_app->PostMessage(B_QUIT_REQUESTED);
}
void AddCLVItems(ColumnListView* MyColumnListView)
{
struct stat st;
int i;
for (i = 0; i < BT_MAX_FILE_SHARES; i++)
if (fileShares[i].used)
MyColumnListView->AddItem(new FileShareItem(fileShares[i].name,
fileShares[i].readOnly ? "Read-only" : "Read-Write",
stat(fileShares[i].path, &st) == 0 ? fileShares[i].path : "--- Invalid Path ---"));
}
void MessageReceived(BMessage *msg)
{
BRect frame;
bt_fileShare_t *share;
struct stat st;
int32 curItem;
switch (msg->what)
{
case MSG_EDIT_SHARE:
case MSG_SHARE_INVOKE:
curItem = MyColumnListView->CurrentSelection();
if (curItem >= 0)
{
FileShareItem *item = (FileShareItem *) MyColumnListView->ItemAt(curItem);
if (item)
{
int index = getShareId((char *) item->GetColumnContentText(1));
if (index >= 0)
{
fileShares[index].index = curItem;
frame = Frame();
frame.left += 100;
frame.top += 100;
frame.right = frame.left + 410;
frame.bottom = frame.top + 390;
info = new ShareInfoPanel(frame, &fileShares[index], this);
}
}
}
break;
case MSG_SHARE_SELECT:
headerView->editBtn->SetEnabled(true);
headerView->removeBtn->SetEnabled(true);
break;
case MSG_LIST_DESELECT:
headerView->editBtn->SetEnabled(false);
headerView->removeBtn->SetEnabled(false);
break;
case MSG_NEW_SHARE:
curItem = MyColumnListView->CountItems();
strcpy(fileShares[curItem].name, "Untitled");
strcpy(fileShares[curItem].path, "/boot/home");
fileShares[curItem].readOnly = true;
fileShares[curItem].followLinks = false;
fileShares[curItem].index = curItem;
frame = Frame();
frame.left += 100;
frame.top += 100;
frame.right = frame.left + 410;
frame.bottom = frame.top + 390;
info = new ShareInfoPanel(frame, &fileShares[curItem], this);
break;
case MSG_REMOVE_SHARE:
curItem = MyColumnListView->CurrentSelection();
if (curItem >= 0)
{
FileShareItem *item = (FileShareItem *) MyColumnListView->ItemAt(curItem);
if (item)
{
curItem = getShareId((char *) item->GetColumnContentText(1));
if (curItem >= 0)
{
BAlert *alert = new BAlert(fileShares[curItem].name, WARN_REMOVE_SHARE, "Yes", "No");
alert->SetShortcut(1, B_ESCAPE);
if (alert->Go() == 0)
{
fileShares[curItem].used = false;
MyColumnListView->LockLooper();
MyColumnListView->RemoveItems(0, MyColumnListView->CountItems());
AddCLVItems(MyColumnListView);
MyColumnListView->UnlockLooper();
}
}
}
}
break;
case MSG_SHARE_REFRESH:
msg->FindPointer("share", (void **) &share);
if (share)
if (share->index >= MyColumnListView->CountItems())
{
share->used = true;
MyColumnListView->LockLooper();
MyColumnListView->AddItem(new FileShareItem(share->name,
share->readOnly ? "Read-only" : "Read-Write",
stat(share->path, &st) == 0 ? share->path : "--- Invalid Path ---"));
MyColumnListView->UnlockLooper();
}
else
refreshShare(share);
break;
case MSG_EDIT_SECURITY:
frame = Frame();
frame.left += 100;
frame.top += 30;
frame.right = frame.left + 370;
frame.bottom = frame.top + 145;
new SecurityPanel(frame);
break;
case MSG_SHARE_OK:
writeShares();
footerView->SetDeployable(true);
break;
case MSG_SHARE_DEPLOY:
footerView->SetDeployable(false);
deployServer();
break;
case MSG_SHARE_CANCEL:
Quit();
break;
default:
BWindow::MessageReceived(msg);
break;
}
}
void Quit()
{
FileShareItem *item;
do
{
item = (FileShareItem *) MyColumnListView->RemoveItem(int32(0));
if (item)
delete item;
} while(item);
BWindow::Quit();
}
void refreshShare(bt_fileShare_t *share)
{
struct stat st;
int curItem = share->index;
FileShareItem *item = (FileShareItem *) MyColumnListView->ItemAt(curItem);
if (item)
{
int index = getShareId((char *) item->GetColumnContentText(1));
if (index >= 0)
{
MyColumnListView->LockLooper();
item->SetColumnContent(1, fileShares[index].name);
item->SetColumnContent(2, fileShares[index].readOnly ? "Read-only" : "Read-Write");
item->SetColumnContent(3, stat(fileShares[index].path, &st) == 0
? fileShares[index].path
: "--- Invalid Path ---");
MyColumnListView->InvalidateItem(index);
MyColumnListView->UnlockLooper();
}
}
}
void setPath(const char *path)
{
if (info)
info->setPath(path);
}
private:
void initShares()
{
FILE *fp;
char path[B_PATH_NAME_LENGTH], buffer[512];
int i, length;
for (i = 0; i < BT_MAX_FILE_SHARES; i++)
{
fileShares[i].name[0] = 0;
fileShares[i].path[0] = 0;
fileShares[i].used = false;
fileShares[i].readOnly = true;
fileShares[i].followLinks = false;
fileShares[i].index = i;
fileShares[i].next = NULL;
}
find_directory(B_COMMON_SETTINGS_DIRECTORY, 0, false, path, sizeof(path));
strcat(path, "/BeServed-Settings");
fp = fopen(path, "r");
if (fp)
{
while (fgets(buffer, sizeof(buffer) - 1, fp))
{
length = strlen(buffer);
if (length <= 1 || buffer[0] == '#')
continue;
if (buffer[length - 1] == '\n')
buffer[--length] = 0;
if (strncmp(buffer, "share ", 6) == 0)
getFileShare(buffer);
else if (strncmp(buffer, "set ", 4) == 0)
getShareProperty(buffer);
else if (strncmp(buffer, "grant ", 6) == 0)
getGrant(buffer);
else if (strncmp(buffer, "authenticate ", 13) == 0)
getAuthenticate(buffer);
}
fclose(fp);
}
}
void getFileShare(const char *buffer)
{
char path[B_PATH_NAME_LENGTH], share[MAX_NAME_LENGTH + 1], *folder;
int i, tok;
tokPtr = (char *) buffer + (6 * sizeof(char));
tok = getToken();
if (tok != BT_TOKEN_STRING)
return;
strcpy(path, tokBuffer);
tok = getToken();
if (tok != BT_TOKEN_AS)
return;
tok = getToken();
if (tok != BT_TOKEN_STRING)
return;
strcpy(share, tokBuffer);
folder = getSharePath(share);
if (folder)
return;
for (i = 0; i < BT_MAX_FILE_SHARES; i++)
if (!fileShares[i].used)
{
strcpy(fileShares[i].name, share);
strcpy(fileShares[i].path, path);
fileShares[i].used = true;
return;
}
}
void getShareProperty(const char *buffer)
{
char share[B_FILE_NAME_LENGTH + 1];
int tok, shareId;
tokPtr = (char *) buffer + (4 * sizeof(char));
tok = getToken();
if (tok != BT_TOKEN_STRING)
return;
strcpy(share, tokBuffer);
shareId = getShareId(share);
if (shareId < 0)
return;
tok = getToken();
if (tok == BT_TOKEN_READWRITE)
fileShares[shareId].readOnly = false;
}
void getGrant(const char *buffer)
{
char share[MAX_NAME_LENGTH + 1];
int tok, rights;
bool isGroup = false;
tokPtr = (char *) buffer + (6 * sizeof(char));
rights = 0;
do
{
tok = getToken();
if (tok == BT_TOKEN_READ)
{
rights |= BT_RIGHTS_READ;
tok = getToken();
}
else if (tok == BT_TOKEN_WRITE)
{
rights |= BT_RIGHTS_WRITE;
tok = getToken();
}
} while (tok == BT_TOKEN_COMMA);
if (tok != BT_TOKEN_ON)
return;
tok = getToken();
if (tok != BT_TOKEN_STRING)
return;
strcpy(share, tokBuffer);
tok = getToken();
if (tok != BT_TOKEN_TO)
return;
tok = getToken();
if (tok == BT_TOKEN_GROUP)
{
isGroup = true;
tok = getToken();
}
if (tok != BT_TOKEN_STRING)
return;
addUserRights(share, tokBuffer, rights, isGroup);
}
void getAuthenticate(const char *buffer)
{
struct hostent *ent;
int i, tok;
tokPtr = (char *) buffer + (13 * sizeof(char));
tok = getToken();
if (tok != BT_TOKEN_WITH)
return;
tok = getToken();
if (tok != BT_TOKEN_STRING)
return;
strcpy(authServerName, tokBuffer);
ent = gethostbyname(tokBuffer);
if (ent != NULL)
authServerIP = ntohl(*((unsigned int *) ent->h_addr));
else
authServerIP = 0;
for (i = 0; i < BT_MAX_FILE_SHARES; i++)
fileShares[i].security = BT_AUTH_BESURE;
}
void addUserRights(char *share, char *user, int rights, bool isGroup)
{
bt_user_rights *ur;
int shareId;
shareId = getShareId(share);
if (shareId < 0)
return;
ur = (bt_user_rights *) malloc(sizeof(bt_user_rights));
if (ur)
{
ur->user = (char *) malloc(strlen(user) + 1);
if (ur->user)
{
strcpy(ur->user, user);
ur->rights = rights;
ur->isGroup = isGroup;
ur->next = fileShares[shareId].rights;
fileShares[shareId].rights = ur;
}
else
free(ur);
}
}
char *getSharePath(char *shareName)
{
int i;
for (i = 0; i < BT_MAX_FILE_SHARES; i++)
if (fileShares[i].used)
if (strcasecmp(fileShares[i].name, shareName) == 0)
return fileShares[i].path;
return NULL;
}
int getToken()
{
bool quoted = false;
tokBuffer[0] = 0;
while (*tokPtr && iswhite(*tokPtr))
tokPtr++;
if (*tokPtr == ',')
{
*tokPtr++;
return BT_TOKEN_COMMA;
}
else if (*tokPtr == '\"')
{
quoted = true;
tokPtr++;
}
if (isalnum(*tokPtr) || *tokPtr == '/')
{
int i = 0;
while (isalnum(*tokPtr) || isValid(*tokPtr) || (quoted && *tokPtr == ' '))
if (i < B_PATH_NAME_LENGTH)
tokBuffer[i++] = *tokPtr++;
else
tokPtr++;
tokBuffer[i] = 0;
if (!quoted)
for (i = 0; keywords[i]; i++)
if (strcasecmp(tokBuffer, keywords[i]) == 0)
return ++i;
if (quoted)
if (*tokPtr != '\"')
return BT_TOKEN_ERROR;
else
tokPtr++;
return BT_TOKEN_STRING;
}
return BT_TOKEN_ERROR;
}
int getShareId(char *shareName)
{
int i;
for (i = 0; i < BT_MAX_FILE_SHARES; i++)
if (fileShares[i].used)
if (strcasecmp(fileShares[i].name, shareName) == 0)
return i;
return -1;
}
void writeShares()
{
FILE *fp;
bt_user_rights *ur;
char path[B_PATH_NAME_LENGTH + 1];
int i;
find_directory(B_COMMON_SETTINGS_DIRECTORY, 0, false, path, sizeof(path));
strcat(path, "/BeServed-Settings");
fp = fopen(path, "w");
if (fp)
{
if (authServerIP)
fprintf(fp, "authenticate with %s\n", authServerName);
for (i = 0; i < BT_MAX_FILE_SHARES; i++)
if (fileShares[i].used)
{
fprintf(fp, "share ");
printString(fp, fileShares[i].path);
fprintf(fp, " as ");
printString(fp, fileShares[i].name);
fputc('\n', fp);
if (!fileShares[i].readOnly)
{
fprintf(fp, "set ");
printString(fp, fileShares[i].name);
fprintf(fp, " read-write\n");
}
if (fileShares[i].followLinks)
{
fprintf(fp, "set ");
printString(fp, fileShares[i].name);
fprintf(fp, " promiscuous\n");
}
for (ur = fileShares[i].rights; ur; ur = ur->next)
{
int rights = ur->rights;
fprintf(fp, "grant ");
do
{
if (rights & BT_RIGHTS_READ)
{
fprintf(fp, "read");
rights &= ~BT_RIGHTS_READ;
}
else if (rights & BT_RIGHTS_WRITE)
{
fprintf(fp, "write");
rights &= ~BT_RIGHTS_WRITE;
}
fprintf(fp, "%c", rights > 0 ? ',' : ' ');
} while (rights > 0);
fprintf(fp, "on ");
printString(fp, fileShares[i].name);
fprintf(fp, " to ");
if (ur->isGroup)
fprintf(fp, "group ");
fprintf(fp, "%s\n", ur->user);
}
}
fclose(fp);
}
}
void deployServer()
{
thread_id serverId;
BRect frame;
frame = Frame();
frame.left += (frame.right - frame.left) / 2 - 100;
frame.top += (frame.bottom - frame.top) / 2 - 40;
frame.right = frame.left + 200;
frame.bottom = frame.top + 80;
MilestonePanel *statusWin = new MilestonePanel(frame, "Deploying...");
statusWin->setText("Connecting to the server", false);
serverId = find_thread("beserved_server");
if (serverId != B_NAME_NOT_FOUND)
{
statusWin->setText("Updating configuration", false);
kill(serverId, SIGHUP);
snooze(500000);
}
statusWin->setText("File sharing deployed", true);
}
FileSharingHeaderView *headerView;
FileSharingFooterView *footerView;
ColumnListView *MyColumnListView;
ShareInfoPanel *info;
};
class FileSharingApp : public BApplication
{
public:
FileSharingApp() :
BApplication("application/x-vnd.Teldar-FileSharing")
{
win = new FileSharingWindow;
}
~FileSharingApp()
{
}
void RefsReceived(BMessage *msg)
{
entry_ref entryRef;
BPath path;
BEntry entry;
switch (msg->what)
{
case B_REFS_RECEIVED:
msg->FindRef("refs", &entryRef);
entry.SetTo(&entryRef, true);
entry.GetPath(&path);
win->setPath(path.Path());
break;
default:
BApplication::RefsReceived(msg);
break;
}
}
private:
void checkMimeTypes()
{
BMimeType mime;
mime.SetTo("application/x-vnd.Teldar-FileSharing");
mime.Delete();
if (!mime.IsInstalled())
{
mime.Install();
mime.SetShortDescription("Network File Server");
mime.SetLongDescription("A network server running BeServed");
}
}
bool setMimeIcon(BMimeType *mime, int32 resourceID, icon_size which)
{
BMessage archive;
size_t size;
char *bits = (char *) be_app->AppResources()->LoadResource(type_code('BBMP'), resourceID, &size);
if (bits)
if (archive.Unflatten(bits) == B_OK)
{
BBitmap *icon = new BBitmap(&archive);
mime->SetIcon(icon, which);
return true;
}
return false;
}
FileSharingWindow *win;
};
int main()
{
new FileSharingApp;
be_app->Run();
delete be_app;
}
void printString(FILE *fp, const char *str)
{
if (strchr(str, ' '))
fprintf(fp, "\"%s\"", str);
else
fprintf(fp, "%s", str);
}