#include <Roster.h>
#include <ctype.h>
#include <new>
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <unistd.h>
#include <AppFileInfo.h>
#include <Application.h>
#include <Bitmap.h>
#include <Directory.h>
#include <File.h>
#include <FindDirectory.h>
#include <fs_index.h>
#include <fs_info.h>
#include <image.h>
#include <List.h>
#include <Mime.h>
#include <Node.h>
#include <NodeInfo.h>
#include <OS.h>
#include <Path.h>
#include <Query.h>
#include <RegistrarDefs.h>
#include <String.h>
#include <Volume.h>
#include <VolumeRoster.h>
#include <locks.h>
#include <AppMisc.h>
#include <DesktopLink.h>
#include <LaunchRoster.h>
#include <MessengerPrivate.h>
#include <PortLink.h>
#include <RosterPrivate.h>
#include <ServerProtocol.h>
using namespace std;
using namespace BPrivate;
#define DBG(x)
#ifdef DEBUG_PRINTF
# define OUT DEBUG_PRINTF
#else
# define OUT printf
#endif
const BRoster* be_roster;
static status_t
find_message_app_info(BMessage* message, app_info* info)
{
status_t error = (message && info ? B_OK : B_BAD_VALUE);
const flat_app_info* flatInfo = NULL;
ssize_t size = 0;
if (error == B_OK) {
error = message->FindData("app_info", B_REG_APP_INFO_TYPE,
(const void**)&flatInfo, &size);
}
if (error == B_OK) {
if (size == sizeof(flat_app_info)) {
info->thread = flatInfo->thread;
info->team = flatInfo->team;
info->port = flatInfo->port;
info->flags = flatInfo->flags;
info->ref.device = flatInfo->ref_device;
info->ref.directory = flatInfo->ref_directory;
info->ref.name = NULL;
memcpy(info->signature, flatInfo->signature, B_MIME_TYPE_LENGTH);
if (strlen(flatInfo->ref_name) > 0)
info->ref.set_name(flatInfo->ref_name);
} else
error = B_ERROR;
}
return error;
}
static status_t
can_app_be_used(const entry_ref* ref)
{
status_t error = (ref ? B_OK : B_BAD_VALUE);
BEntry entry;
if (error == B_OK)
error = entry.SetTo(ref, true);
if (error == B_OK && !entry.Exists())
error = B_ENTRY_NOT_FOUND;
if (error == B_OK && !entry.IsFile())
error = B_IS_A_DIRECTORY;
BPath trashPath;
BDirectory directory;
BVolume volume;
if (error == B_OK
&& volume.SetTo(ref->device) == B_OK
&& find_directory(B_TRASH_DIRECTORY, &trashPath, false, &volume)
== B_OK
&& directory.SetTo(trashPath.Path()) == B_OK
&& directory.Contains(&entry)) {
error = B_LAUNCH_FAILED_APP_IN_TRASH;
}
return error;
}
static int32
compare_version_infos(const version_info& info1, const version_info& info2)
{
int32 result = 0;
if (info1.major < info2.major)
result = -1;
else if (info1.major > info2.major)
result = 1;
else if (info1.middle < info2.middle)
result = -1;
else if (info1.middle > info2.middle)
result = 1;
else if (info1.minor < info2.minor)
result = -1;
else if (info1.minor > info2.minor)
result = 1;
else if (info1.variety < info2.variety)
result = -1;
else if (info1.variety > info2.variety)
result = 1;
else if (info1.internal < info2.internal)
result = -1;
else if (info1.internal > info2.internal)
result = 1;
return result;
}
static int32
compare_queried_apps(const entry_ref* app1, const entry_ref* app2)
{
BPath path1(app1);
BPath path2(app2);
const char* searchPathes = getenv("PATH");
if (searchPathes != NULL) {
char* searchBuffer = strdup(searchPathes);
if (searchBuffer != NULL) {
char* last;
const char* path = strtok_r(searchBuffer, ":", &last);
while (path != NULL) {
size_t length = strlen(path);
bool found1 = !strncmp(path, path1.Path(), length)
&& path1.Path()[length] == '/';
bool found2 = !strncmp(path, path2.Path(), length)
&& path2.Path()[length] == '/';;
if (found1 != found2) {
free(searchBuffer);
return found1 ? 1 : -1;
}
path = strtok_r(NULL, ":", &last);
}
free(searchBuffer);
}
}
BPath path;
find_directory(B_SYSTEM_SERVERS_DIRECTORY, &path);
BString serverPath(path.Path());
serverPath << '/';
size_t length = serverPath.Length();
bool inSystem1 = !strncmp(serverPath.String(), path1.Path(), length);
bool inSystem2 = !strncmp(serverPath.String(), path2.Path(), length);
if (inSystem1 != inSystem2)
return inSystem1 ? 1 : -1;
BFile file1;
file1.SetTo(app1, B_READ_ONLY);
BFile file2;
file2.SetTo(app2, B_READ_ONLY);
BAppFileInfo appFileInfo1;
appFileInfo1.SetTo(&file1);
BAppFileInfo appFileInfo2;
appFileInfo2.SetTo(&file2);
time_t modificationTime1 = 0;
time_t modificationTime2 = 0;
file1.GetModificationTime(&modificationTime1);
file2.GetModificationTime(&modificationTime2);
int32 result = 0;
version_info versionInfo1;
version_info versionInfo2;
bool hasVersionInfo1 = (appFileInfo1.GetVersionInfo(
&versionInfo1, B_APP_VERSION_KIND) == B_OK);
bool hasVersionInfo2 = (appFileInfo2.GetVersionInfo(
&versionInfo2, B_APP_VERSION_KIND) == B_OK);
if (hasVersionInfo1) {
if (hasVersionInfo2)
result = compare_version_infos(versionInfo1, versionInfo2);
else
result = 1;
} else {
if (hasVersionInfo2)
result = -1;
else if (modificationTime1 < modificationTime2)
result = -1;
else if (modificationTime1 > modificationTime2)
result = 1;
}
return result;
}
static status_t
query_for_app(const char* signature, entry_ref* appRef)
{
if (signature == NULL || appRef == NULL)
return B_BAD_VALUE;
status_t error = B_LAUNCH_FAILED_APP_NOT_FOUND;
bool caseInsensitive = false;
while (true) {
BVolumeRoster volumeRoster;
BVolume volume;
while (volumeRoster.GetNextVolume(&volume) == B_OK) {
if (!volume.KnowsQuery())
continue;
index_info info;
if (fs_stat_index(volume.Device(), "BEOS:APP_SIG", &info) != 0) {
continue;
}
BQuery query;
query.SetVolume(&volume);
query.PushAttr("BEOS:APP_SIG");
if (!caseInsensitive)
query.PushString(signature);
else {
char string[B_MIME_TYPE_LENGTH * 4];
strlcpy(string, "application/", sizeof(string));
int32 length = strlen(string);
const char* from = signature + length;
char* to = string + length;
for (; from[0]; from++) {
if (isalpha(from[0])) {
*to++ = '[';
*to++ = tolower(from[0]);
*to++ = toupper(from[0]);
*to++ = ']';
} else
*to++ = from[0];
}
to[0] = '\0';
query.PushString(string);
}
query.PushOp(B_EQ);
query.Fetch();
bool appFound = false;
status_t foundAppError = B_OK;
entry_ref ref;
while (query.GetNextRef(&ref) == B_OK) {
if ((!appFound || compare_queried_apps(appRef, &ref) < 0)
&& (foundAppError = can_app_be_used(&ref)) == B_OK) {
*appRef = ref;
appFound = true;
}
}
if (!appFound) {
error = foundAppError != B_OK
? foundAppError : B_LAUNCH_FAILED_APP_NOT_FOUND;
} else
return B_OK;
}
if (!caseInsensitive)
caseInsensitive = true;
else
break;
}
return error;
}
app_info::app_info()
:
thread(-1),
team(-1),
port(-1),
flags(B_REG_DEFAULT_APP_FLAGS),
ref()
{
signature[0] = '\0';
}
app_info::~app_info()
{
}
class BRoster::ArgVector {
public:
ArgVector();
~ArgVector();
status_t Init(int argc, const char* const* args,
const entry_ref* appRef,
const entry_ref* docRef);
void Unset();
inline int Count() const { return fArgc; }
inline const char* const* Args() const { return fArgs; }
private:
int fArgc;
const char** fArgs;
BPath fAppPath;
BPath fDocPath;
};
BRoster::ArgVector::ArgVector()
:
fArgc(0),
fArgs(NULL),
fAppPath(),
fDocPath()
{
}
BRoster::ArgVector::~ArgVector()
{
Unset();
}
status_t
BRoster::ArgVector::Init(int argc, const char* const* args,
const entry_ref* appRef, const entry_ref* docRef)
{
Unset();
status_t error = appRef ? B_OK : B_BAD_VALUE;
if (error == B_OK)
error = fAppPath.SetTo(appRef);
bool hasDocArg = false;
if (error == B_OK) {
fArgc = 1;
if (argc > 0 && args) {
fArgc += argc;
if (docRef != NULL && fDocPath.SetTo(docRef) == B_OK) {
fArgc++;
hasDocArg = true;
}
}
fArgs = new(nothrow) const char*[fArgc + 1];
if (!fArgs)
error = B_NO_MEMORY;
}
if (error == B_OK) {
fArgs[0] = fAppPath.Path();
if (argc > 0 && args != NULL) {
for (int i = 0; i < argc; i++)
fArgs[i + 1] = args[i];
if (hasDocArg)
fArgs[fArgc - 1] = fDocPath.Path();
}
fArgs[fArgc] = NULL;
}
return error;
}
void
BRoster::ArgVector::Unset()
{
fArgc = 0;
delete[] fArgs;
fArgs = NULL;
fAppPath.Unset();
fDocPath.Unset();
}
BRoster::BRoster()
:
fMessenger(),
fMimeMessenger(),
fMimeMessengerInitOnce(INIT_ONCE_UNINITIALIZED),
fNoRegistrar(false)
{
_InitMessenger();
}
BRoster::~BRoster()
{
}
bool
BRoster::IsRunning(const char* signature) const
{
return (TeamFor(signature) >= 0);
}
bool
BRoster::IsRunning(entry_ref* ref) const
{
return (TeamFor(ref) >= 0);
}
team_id
BRoster::TeamFor(const char* signature) const
{
team_id team;
app_info info;
status_t error = GetAppInfo(signature, &info);
if (error == B_OK)
team = info.team;
else
team = error;
return team;
}
team_id
BRoster::TeamFor(entry_ref* ref) const
{
team_id team;
app_info info;
status_t error = GetAppInfo(ref, &info);
if (error == B_OK)
team = info.team;
else
team = error;
return team;
}
void
BRoster::GetAppList(BList* teamIDList) const
{
status_t error = (teamIDList ? B_OK : B_BAD_VALUE);
BMessage request(B_REG_GET_APP_LIST);
BMessage reply;
if (error == B_OK)
error = fMessenger.SendMessage(&request, &reply);
if (error == B_OK) {
if (reply.what == B_REG_SUCCESS) {
team_id team;
for (int32 i = 0; reply.FindInt32("teams", i, &team) == B_OK; i++)
teamIDList->AddItem((void*)(addr_t)team);
} else {
if (reply.FindInt32("error", &error) != B_OK)
error = B_ERROR;
DBG(OUT("Roster request unsuccessful: %s\n", strerror(error)));
DBG(reply.PrintToStream());
}
} else {
DBG(OUT("Sending message to roster failed: %s\n", strerror(error)));
}
}
void
BRoster::GetAppList(const char* signature, BList* teamIDList) const
{
status_t error = B_OK;
if (signature == NULL || teamIDList == NULL)
error = B_BAD_VALUE;
BMessage request(B_REG_GET_APP_LIST);
if (error == B_OK)
error = request.AddString("signature", signature);
BMessage reply;
if (error == B_OK)
error = fMessenger.SendMessage(&request, &reply);
if (error == B_OK) {
if (reply.what == B_REG_SUCCESS) {
team_id team;
for (int32 i = 0; reply.FindInt32("teams", i, &team) == B_OK; i++)
teamIDList->AddItem((void*)(addr_t)team);
} else if (reply.FindInt32("error", &error) != B_OK)
error = B_ERROR;
}
}
status_t
BRoster::GetAppInfo(const char* signature, app_info* info) const
{
status_t error = B_OK;
if (signature == NULL || info == NULL)
error = B_BAD_VALUE;
BMessage request(B_REG_GET_APP_INFO);
if (error == B_OK)
error = request.AddString("signature", signature);
BMessage reply;
if (error == B_OK)
error = fMessenger.SendMessage(&request, &reply);
if (error == B_OK) {
if (reply.what == B_REG_SUCCESS)
error = find_message_app_info(&reply, info);
else if (reply.FindInt32("error", &error) != B_OK)
error = B_ERROR;
}
return error;
}
status_t
BRoster::GetAppInfo(entry_ref* ref, app_info* info) const
{
status_t error = (ref && info ? B_OK : B_BAD_VALUE);
BMessage request(B_REG_GET_APP_INFO);
if (error == B_OK)
error = request.AddRef("ref", ref);
BMessage reply;
if (error == B_OK)
error = fMessenger.SendMessage(&request, &reply);
if (error == B_OK) {
if (reply.what == B_REG_SUCCESS)
error = find_message_app_info(&reply, info);
else if (reply.FindInt32("error", &error) != B_OK)
error = B_ERROR;
}
return error;
}
status_t
BRoster::GetRunningAppInfo(team_id team, app_info* info) const
{
status_t error = (info ? B_OK : B_BAD_VALUE);
if (error == B_OK && team < 0)
error = B_BAD_TEAM_ID;
BMessage request(B_REG_GET_APP_INFO);
if (error == B_OK)
error = request.AddInt32("team", team);
BMessage reply;
if (error == B_OK)
error = fMessenger.SendMessage(&request, &reply);
if (error == B_OK) {
if (reply.what == B_REG_SUCCESS)
error = find_message_app_info(&reply, info);
else if (reply.FindInt32("error", &error) != B_OK)
error = B_ERROR;
}
return error;
}
status_t
BRoster::GetActiveAppInfo(app_info* info) const
{
if (info == NULL)
return B_BAD_VALUE;
BMessage request(B_REG_GET_APP_INFO);
BMessage reply;
status_t error = fMessenger.SendMessage(&request, &reply);
if (error == B_OK) {
if (reply.what == B_REG_SUCCESS)
error = find_message_app_info(&reply, info);
else if (reply.FindInt32("error", &error) != B_OK)
error = B_ERROR;
}
return error;
}
status_t
BRoster::FindApp(const char* mimeType, entry_ref* app) const
{
if (mimeType == NULL || app == NULL)
return B_BAD_VALUE;
return _ResolveApp(mimeType, NULL, app, NULL, NULL, NULL);
}
status_t
BRoster::FindApp(entry_ref* ref, entry_ref* app) const
{
if (ref == NULL || app == NULL)
return B_BAD_VALUE;
entry_ref _ref(*ref);
return _ResolveApp(NULL, &_ref, app, NULL, NULL, NULL);
}
status_t
BRoster::Broadcast(BMessage* message) const
{
return Broadcast(message, be_app_messenger);
}
status_t
BRoster::Broadcast(BMessage* message, BMessenger replyTo) const
{
status_t error = (message ? B_OK : B_BAD_VALUE);
BMessage request(B_REG_BROADCAST);
if (error == B_OK)
error = request.AddInt32("team", BPrivate::current_team());
if (error == B_OK)
error = request.AddMessage("message", message);
if (error == B_OK)
error = request.AddMessenger("reply_target", replyTo);
BMessage reply;
if (error == B_OK)
error = fMessenger.SendMessage(&request, &reply);
if (error == B_OK && reply.what != B_REG_SUCCESS
&& reply.FindInt32("error", &error) != B_OK)
error = B_ERROR;
return error;
}
status_t
BRoster::StartWatching(BMessenger target, uint32 eventMask) const
{
status_t error = B_OK;
BMessage request(B_REG_START_WATCHING);
if (error == B_OK)
error = request.AddMessenger("target", target);
if (error == B_OK)
error = request.AddInt32("events", (int32)eventMask);
BMessage reply;
if (error == B_OK)
error = fMessenger.SendMessage(&request, &reply);
if (error == B_OK && reply.what != B_REG_SUCCESS
&& reply.FindInt32("error", &error) != B_OK)
error = B_ERROR;
return error;
}
status_t
BRoster::StopWatching(BMessenger target) const
{
status_t error = B_OK;
BMessage request(B_REG_STOP_WATCHING);
if (error == B_OK)
error = request.AddMessenger("target", target);
BMessage reply;
if (error == B_OK)
error = fMessenger.SendMessage(&request, &reply);
if (error == B_OK && reply.what != B_REG_SUCCESS
&& reply.FindInt32("error", &error) != B_OK)
error = B_ERROR;
return error;
}
status_t
BRoster::ActivateApp(team_id team) const
{
BPrivate::DesktopLink link;
status_t status = link.InitCheck();
if (status < B_OK)
return status;
status_t error = link.StartMessage(AS_ACTIVATE_APP);
if (error != B_OK)
return error;
error = link.Attach(link.ReceiverPort());
if (error != B_OK)
return error;
error = link.Attach(team);
if (error != B_OK)
return error;
status_t code;
error = link.FlushWithReply(code);
if (error != B_OK)
return error;
return code;
}
status_t
BRoster::Launch(const char* mimeType, BMessage* initialMessage,
team_id* _appTeam) const
{
if (mimeType == NULL)
return B_BAD_VALUE;
BList messageList;
if (initialMessage != NULL)
messageList.AddItem(initialMessage);
return _LaunchApp(mimeType, NULL, &messageList, 0, NULL,
(const char**)environ, _appTeam, NULL, NULL, NULL, false);
}
status_t
BRoster::Launch(const char* mimeType, BList* messageList,
team_id* _appTeam) const
{
if (mimeType == NULL)
return B_BAD_VALUE;
return _LaunchApp(mimeType, NULL, messageList, 0, NULL,
(const char**)environ, _appTeam, NULL, NULL, NULL, false);
}
status_t
BRoster::Launch(const char* mimeType, int argc, const char* const* args,
team_id* _appTeam) const
{
if (mimeType == NULL)
return B_BAD_VALUE;
return _LaunchApp(mimeType, NULL, NULL, argc, args, (const char**)environ,
_appTeam, NULL, NULL, NULL, false);
}
status_t
BRoster::Launch(const entry_ref* ref, const BMessage* initialMessage,
team_id* _appTeam) const
{
if (ref == NULL)
return B_BAD_VALUE;
BList messageList;
if (initialMessage != NULL)
messageList.AddItem(const_cast<BMessage*>(initialMessage));
return _LaunchApp(NULL, ref, &messageList, 0, NULL, (const char**)environ,
_appTeam, NULL, NULL, NULL, false);
}
status_t
BRoster::Launch(const entry_ref* ref, const BList* messageList,
team_id* appTeam) const
{
if (ref == NULL)
return B_BAD_VALUE;
return _LaunchApp(NULL, ref, messageList, 0, NULL, (const char**)environ,
appTeam, NULL, NULL, NULL, false);
}
status_t
BRoster::Launch(const entry_ref* ref, int argc, const char* const* args,
team_id* appTeam) const
{
if (ref == NULL)
return B_BAD_VALUE;
return _LaunchApp(NULL, ref, NULL, argc, args, (const char**)environ,
appTeam, NULL, NULL, NULL, false);
}
#if __GNUC__ == 2
extern "C" status_t
Launch__C7BRosterP9entry_refP8BMessagePl(BRoster* roster, entry_ref* ref,
BMessage* initialMessage)
{
return roster->BRoster::Launch(ref, initialMessage, NULL);
}
extern "C" status_t
Launch__C7BRosterPCciPPcPl(BRoster* roster, const char* mimeType,
int argc, char** args, team_id* _appTeam)
{
return roster->BRoster::Launch(mimeType, argc, args, _appTeam);
}
extern "C" status_t
Launch__C7BRosterP9entry_refiPPcPl(BRoster* roster, entry_ref* ref,
int argc, char* const* args, team_id* _appTeam)
{
return roster->BRoster::Launch(ref, argc, args, _appTeam);
}
#endif
void
BRoster::GetRecentDocuments(BMessage* refList, int32 maxCount,
const char* fileType, const char* signature) const
{
if (refList == NULL)
return;
status_t error = maxCount > 0 ? B_OK : B_BAD_VALUE;
BMessage& message = *refList;
BMessage& reply = *refList;
status_t result;
if (error == B_OK) {
message.what = B_REG_GET_RECENT_DOCUMENTS;
error = message.AddInt32("max count", maxCount);
}
if (error == B_OK && fileType)
error = message.AddString("file type", fileType);
if (error == B_OK && signature)
error = message.AddString("app sig", signature);
fMessenger.SendMessage(&message, &reply);
if (error == B_OK) {
error = reply.what == B_REG_RESULT
? (status_t)B_OK : (status_t)B_BAD_REPLY;
}
if (error == B_OK)
error = reply.FindInt32("result", &result);
if (error == B_OK)
error = result;
if (error != B_OK && refList != NULL)
refList->MakeEmpty();
}
void
BRoster::GetRecentDocuments(BMessage* refList, int32 maxCount,
const char* fileTypes[], int32 fileTypesCount,
const char* signature) const
{
if (refList == NULL)
return;
status_t error = maxCount > 0 ? B_OK : B_BAD_VALUE;
BMessage& message = *refList;
BMessage& reply = *refList;
status_t result;
if (error == B_OK) {
message.what = B_REG_GET_RECENT_DOCUMENTS;
error = message.AddInt32("max count", maxCount);
}
if (error == B_OK && fileTypes) {
for (int i = 0; i < fileTypesCount && error == B_OK; i++)
error = message.AddString("file type", fileTypes[i]);
}
if (error == B_OK && signature)
error = message.AddString("app sig", signature);
fMessenger.SendMessage(&message, &reply);
if (error == B_OK) {
error = reply.what == B_REG_RESULT
? (status_t)B_OK : (status_t)B_BAD_REPLY;
}
if (error == B_OK)
error = reply.FindInt32("result", &result);
if (error == B_OK)
error = result;
if (error != B_OK && refList != NULL)
refList->MakeEmpty();
}
void
BRoster::GetRecentFolders(BMessage* refList, int32 maxCount,
const char* signature) const
{
if (refList == NULL)
return;
status_t error = maxCount > 0 ? B_OK : B_BAD_VALUE;
BMessage& message = *refList;
BMessage& reply = *refList;
status_t result;
if (error == B_OK) {
message.what = B_REG_GET_RECENT_FOLDERS;
error = message.AddInt32("max count", maxCount);
}
if (error == B_OK && signature)
error = message.AddString("app sig", signature);
fMessenger.SendMessage(&message, &reply);
if (error == B_OK) {
error = reply.what == B_REG_RESULT
? (status_t)B_OK : (status_t)B_BAD_REPLY;
}
if (error == B_OK)
error = reply.FindInt32("result", &result);
if (error == B_OK)
error = result;
if (error != B_OK && refList != NULL)
refList->MakeEmpty();
}
void
BRoster::GetRecentApps(BMessage* refList, int32 maxCount) const
{
if (refList == NULL)
return;
status_t err = maxCount > 0 ? B_OK : B_BAD_VALUE;
BMessage& message = *refList;
BMessage& reply = *refList;
status_t result;
if (!err) {
message.what = B_REG_GET_RECENT_APPS;
err = message.AddInt32("max count", maxCount);
}
fMessenger.SendMessage(&message, &reply);
if (!err) {
err = reply.what == B_REG_RESULT
? (status_t)B_OK : (status_t)B_BAD_REPLY;
}
if (!err)
err = reply.FindInt32("result", &result);
if (!err)
err = result;
if (err && refList)
refList->MakeEmpty();
}
void
BRoster::AddToRecentDocuments(const entry_ref* document,
const char* signature) const
{
status_t error = document ? B_OK : B_BAD_VALUE;
BMessage message(B_REG_ADD_TO_RECENT_DOCUMENTS);
BMessage reply;
status_t result;
char* callingApplicationSignature = NULL;
if (error == B_OK && signature == NULL) {
app_info info;
error = GetRunningAppInfo(be_app->Team(), &info);
if (error == B_OK)
callingApplicationSignature = info.signature;
}
if (error == B_OK)
error = message.AddRef("ref", document);
if (error == B_OK) {
error = message.AddString("app sig", signature != NULL
? signature : callingApplicationSignature);
}
fMessenger.SendMessage(&message, &reply);
if (error == B_OK) {
error = reply.what == B_REG_RESULT
? (status_t)B_OK : (status_t)B_BAD_REPLY;
}
if (error == B_OK)
error = reply.FindInt32("result", &result);
if (error == B_OK)
error = result;
if (error != B_OK) {
DBG(OUT("WARNING: BRoster::AddToRecentDocuments() failed with error "
"0x%" B_PRIx32 "\n", error));
}
}
void
BRoster::AddToRecentFolders(const entry_ref* folder,
const char* signature) const
{
status_t error = folder ? B_OK : B_BAD_VALUE;
BMessage message(B_REG_ADD_TO_RECENT_FOLDERS);
BMessage reply;
status_t result;
char* callingApplicationSignature = NULL;
if (error == B_OK && signature == NULL) {
app_info info;
error = GetRunningAppInfo(be_app->Team(), &info);
if (error == B_OK)
callingApplicationSignature = info.signature;
}
if (error == B_OK)
error = message.AddRef("ref", folder);
if (error == B_OK) {
error = message.AddString("app sig",
signature != NULL ? signature : callingApplicationSignature);
}
fMessenger.SendMessage(&message, &reply);
if (error == B_OK) {
error = reply.what == B_REG_RESULT
? (status_t)B_OK : (status_t)B_BAD_REPLY;
}
if (error == B_OK)
error = reply.FindInt32("result", &result);
if (error == B_OK)
error = result;
if (error != B_OK) {
DBG(OUT("WARNING: BRoster::AddToRecentDocuments() failed with error "
"0x%" B_PRIx32 "\n", error));
}
}
status_t
BRoster::_ShutDown(bool reboot, bool confirm, bool synchronous)
{
status_t error = B_OK;
BMessage request(B_REG_SHUT_DOWN);
if (error == B_OK)
error = request.AddBool("reboot", reboot);
if (error == B_OK)
error = request.AddBool("confirm", confirm);
if (error == B_OK)
error = request.AddBool("synchronous", synchronous);
BMessage reply;
if (error == B_OK)
error = fMessenger.SendMessage(&request, &reply);
if (error == B_OK && reply.what != B_REG_SUCCESS
&& reply.FindInt32("error", &error) != B_OK) {
error = B_ERROR;
}
return error;
}
status_t
BRoster::_IsShutDownInProgress(bool* inProgress)
{
status_t error = B_OK;
BMessage request(B_REG_IS_SHUT_DOWN_IN_PROGRESS);
BMessage reply;
if (error == B_OK)
error = fMessenger.SendMessage(&request, &reply);
if (error == B_OK) {
if (reply.what == B_REG_SUCCESS) {
if (inProgress != NULL
&& reply.FindBool("in-progress", inProgress) != B_OK) {
error = B_ERROR;
}
} else if (reply.FindInt32("error", &error) != B_OK)
error = B_ERROR;
}
return error;
}
status_t
BRoster::_AddApplication(const char* signature, const entry_ref* ref,
uint32 flags, team_id team, thread_id thread, port_id port,
bool fullRegistration, uint32* pToken, team_id* otherTeam) const
{
status_t error = B_OK;
BMessage request(B_REG_ADD_APP);
if (error == B_OK && signature != NULL)
error = request.AddString("signature", signature);
if (error == B_OK && ref != NULL)
error = request.AddRef("ref", ref);
if (error == B_OK)
error = request.AddInt32("flags", (int32)flags);
if (error == B_OK && team >= 0)
error = request.AddInt32("team", team);
if (error == B_OK && thread >= 0)
error = request.AddInt32("thread", thread);
if (error == B_OK && port >= 0)
error = request.AddInt32("port", port);
if (error == B_OK)
error = request.AddBool("full_registration", fullRegistration);
BMessage reply;
if (error == B_OK)
error = fMessenger.SendMessage(&request, &reply);
if (error == B_OK) {
if (reply.what == B_REG_SUCCESS) {
if (!fullRegistration && team < 0) {
uint32 token;
if (reply.FindInt32("token", (int32*)&token) == B_OK) {
if (pToken != NULL)
*pToken = token;
} else
error = B_ERROR;
}
} else {
if (reply.FindInt32("error", &error) != B_OK)
error = B_ERROR;
if (otherTeam != NULL
&& reply.FindInt32("other_team", otherTeam) != B_OK) {
*otherTeam = -1;
}
if (pToken != NULL
&& reply.FindInt32("token", (int32*)pToken) != B_OK) {
*pToken = 0;
}
}
}
return error;
}
status_t
BRoster::_SetSignature(team_id team, const char* signature) const
{
status_t error = B_OK;
BMessage request(B_REG_SET_SIGNATURE);
if (team >= 0)
error = request.AddInt32("team", team);
if (error == B_OK && signature)
error = request.AddString("signature", signature);
BMessage reply;
if (error == B_OK)
error = fMessenger.SendMessage(&request, &reply);
if (error == B_OK && reply.what != B_REG_SUCCESS
&& reply.FindInt32("error", &error) != B_OK) {
error = B_ERROR;
}
return error;
}
void
BRoster::_SetThread(team_id team, thread_id thread) const
{
}
status_t
BRoster::_SetThreadAndTeam(uint32 entryToken, thread_id thread,
team_id team, port_id* _port) const
{
status_t error = B_OK;
BMessage request(B_REG_SET_THREAD_AND_TEAM);
if (error == B_OK)
error = request.AddInt32("token", (int32)entryToken);
if (error == B_OK && team >= 0)
error = request.AddInt32("team", team);
if (error == B_OK && thread >= 0)
error = request.AddInt32("thread", thread);
BMessage reply;
if (error == B_OK)
error = fMessenger.SendMessage(&request, &reply);
if (error == B_OK && reply.what != B_REG_SUCCESS
&& reply.FindInt32("error", &error) != B_OK)
error = B_ERROR;
if (error == B_OK && _port != NULL)
*_port = reply.GetInt32("port", -1);
return error;
}
status_t
BRoster::_CompleteRegistration(team_id team, thread_id thread,
port_id port) const
{
status_t error = B_OK;
BMessage request(B_REG_COMPLETE_REGISTRATION);
if (team >= 0)
error = request.AddInt32("team", team);
if (error == B_OK && thread >= 0)
error = request.AddInt32("thread", thread);
if (error == B_OK && port >= 0)
error = request.AddInt32("port", port);
BMessage reply;
if (error == B_OK)
error = fMessenger.SendMessage(&request, &reply);
if (error == B_OK && reply.what != B_REG_SUCCESS
&& reply.FindInt32("error", &error) != B_OK) {
error = B_ERROR;
}
return error;
}
status_t
BRoster::_IsAppRegistered(const entry_ref* ref, team_id team,
uint32 token, bool* preRegistered, app_info* info) const
{
status_t error = B_OK;
BMessage request(B_REG_IS_APP_REGISTERED);
if (ref)
error = request.AddRef("ref", ref);
if (error == B_OK && team >= 0)
error = request.AddInt32("team", team);
if (error == B_OK && token > 0)
error = request.AddInt32("token", (int32)token);
BMessage reply;
if (error == B_OK)
error = fMessenger.SendMessage(&request, &reply);
bool isRegistered = false;
bool isPreRegistered = false;
if (error == B_OK) {
if (reply.what == B_REG_SUCCESS) {
if (reply.FindBool("registered", &isRegistered) != B_OK
|| !isRegistered
|| reply.FindBool("pre-registered", &isPreRegistered) != B_OK) {
error = B_ERROR;
}
if (error == B_OK && preRegistered)
*preRegistered = isPreRegistered;
if (error == B_OK && info)
error = find_message_app_info(&reply, info);
} else if (reply.FindInt32("error", &error) != B_OK)
error = B_ERROR;
}
return error;
}
status_t
BRoster::_RemovePreRegApp(uint32 entryToken) const
{
status_t error = B_OK;
BMessage request(B_REG_REMOVE_PRE_REGISTERED_APP);
if (error == B_OK)
error = request.AddInt32("token", (int32)entryToken);
BMessage reply;
if (error == B_OK)
error = fMessenger.SendMessage(&request, &reply);
if (error == B_OK && reply.what != B_REG_SUCCESS
&& reply.FindInt32("error", &error) != B_OK) {
error = B_ERROR;
}
return error;
}
status_t
BRoster::_RemoveApp(team_id team) const
{
status_t error = B_OK;
BMessage request(B_REG_REMOVE_APP);
if (team >= 0)
error = request.AddInt32("team", team);
BMessage reply;
if (error == B_OK)
error = fMessenger.SendMessage(&request, &reply);
if (error == B_OK && reply.what != B_REG_SUCCESS
&& reply.FindInt32("error", &error) != B_OK) {
error = B_ERROR;
}
return error;
}
void
BRoster::_ApplicationCrashed(team_id team)
{
BPrivate::DesktopLink link;
if (link.InitCheck() != B_OK)
return;
if (link.StartMessage(AS_APP_CRASHED) == B_OK
&& link.Attach(team) == B_OK) {
link.Flush();
}
}
status_t
BRoster::_UpdateActiveApp(team_id team) const
{
if (team < B_OK)
return B_BAD_TEAM_ID;
BMessage request(B_REG_UPDATE_ACTIVE_APP);
status_t status = request.AddInt32("team", team);
if (status < B_OK)
return status;
return fMessenger.SendMessage(&request);
}
status_t
BRoster::_LaunchApp(const char* mimeType, const entry_ref* ref,
const BList* messageList, int argc, const char* const* args,
const char** environment, team_id* _appTeam, thread_id* _appThread,
port_id* _appPort, uint32* _appToken, bool launchSuspended) const
{
DBG(OUT("BRoster::_LaunchApp()"));
if (_appTeam != NULL) {
*_appTeam = -1;
}
if (mimeType == NULL && ref == NULL)
return B_BAD_VALUE;
entry_ref _docRef;
entry_ref* docRef = NULL;
if (ref != NULL) {
_docRef = *ref;
docRef = &_docRef;
}
uint32 otherAppFlags = B_REG_DEFAULT_APP_FLAGS;
uint32 appFlags = B_REG_DEFAULT_APP_FLAGS;
bool alreadyRunning = false;
bool wasDocument = true;
status_t error = B_OK;
ArgVector argVector;
team_id team = -1;
thread_id appThread = -1;
port_id appPort = -1;
uint32 appToken = 0;
entry_ref hintRef;
while (true) {
entry_ref appRef;
char signature[B_MIME_TYPE_LENGTH];
error = _ResolveApp(mimeType, docRef, &appRef, signature,
&appFlags, &wasDocument);
DBG(OUT(" find app: %s (%" B_PRIx32 ") %s \n", strerror(error), error,
signature));
if (error != B_OK)
return error;
error = argVector.Init(argc, args, &appRef,
wasDocument ? docRef : NULL);
DBG(OUT(" build argv: %s (%" B_PRIx32 ")\n", strerror(error), error));
if (error != B_OK)
return error;
app_info appInfo;
bool isScript = wasDocument && docRef != NULL && *docRef == appRef;
if (!isScript && !fNoRegistrar) {
error = _AddApplication(signature, &appRef, appFlags, -1, -1, -1,
false, &appToken, &team);
if (error == B_ALREADY_RUNNING) {
DBG(OUT(" already running\n"));
alreadyRunning = true;
error = _IsAppRegistered(&appRef, team, appToken, NULL,
&appInfo);
if (error == B_OK) {
otherAppFlags = appInfo.flags;
appPort = appInfo.port;
team = appInfo.team;
}
}
DBG(OUT(" pre-register: %s (%" B_PRIx32 ")\n", strerror(error),
error));
}
if (error == B_OK && !alreadyRunning) {
DBG(OUT(" token: %" B_PRIu32 "\n", appToken));
appThread = load_image(argVector.Count(),
const_cast<const char**>(argVector.Args()), environment);
if (appThread >= 0) {
thread_info threadInfo;
error = get_thread_info(appThread, &threadInfo);
if (error == B_OK)
team = threadInfo.team;
} else if (wasDocument && appThread == B_NOT_AN_EXECUTABLE)
error = B_LAUNCH_FAILED_EXECUTABLE;
else
error = appThread;
DBG(OUT(" load image: %s (%" B_PRIx32 ")\n", strerror(error),
error));
if (error == B_OK && !isScript && !fNoRegistrar)
error = _SetThreadAndTeam(appToken, appThread, team, &appPort);
DBG(OUT(" set thread and team: %s (%" B_PRIx32 ")\n",
strerror(error), error));
if (error == B_OK && !launchSuspended)
error = resume_thread(appThread);
DBG(OUT(" resume thread: %s (%" B_PRIx32 ")\n", strerror(error),
error));
if (error != B_OK) {
if (appThread >= 0)
kill_thread(appThread);
if (!isScript) {
if (!fNoRegistrar)
_RemovePreRegApp(appToken);
if (!wasDocument) {
if (appRef == hintRef)
break;
BMimeType appType(signature);
if (appType.InitCheck() == B_OK
&& appType.GetAppHint(&hintRef) == B_OK
&& appRef == hintRef) {
appType.SetAppHint(NULL);
continue;
}
}
}
}
}
break;
}
if (alreadyRunning && current_team() == team) {
error = B_BAD_VALUE;
}
if (error == B_OK && !fNoRegistrar) {
bool argvOnly = (appFlags & B_ARGV_ONLY) != 0
|| (alreadyRunning && (otherAppFlags & B_ARGV_ONLY) != 0);
const BList* _messageList = (argvOnly ? NULL : messageList);
const entry_ref* _ref = argvOnly || !wasDocument
|| argVector.Count() > 1 ? NULL : docRef;
if (!(argvOnly && alreadyRunning)) {
_SendToRunning(team, argVector.Count(), argVector.Args(),
_messageList, _ref, alreadyRunning);
}
}
if (error == B_OK) {
if (alreadyRunning)
error = B_ALREADY_RUNNING;
else if (_appTeam)
*_appTeam = team;
if (_appThread != NULL)
*_appThread = appThread;
if (_appPort != NULL)
*_appPort = appPort;
if (_appToken != NULL)
*_appToken = appToken;
}
DBG(OUT("BRoster::_LaunchApp() done: %s (%" B_PRIx32 ")\n",
strerror(error), error));
return error;
}
void
BRoster::_SetAppFlags(team_id team, uint32 flags) const
{
}
void
BRoster::_DumpRoster() const
{
}
status_t
BRoster::_ResolveApp(const char* inType, entry_ref* ref,
entry_ref* _appRef, char* _signature, uint32* _appFlags,
bool* _wasDocument) const
{
if ((inType == NULL && ref == NULL)
|| (inType != NULL && strlen(inType) >= B_MIME_TYPE_LENGTH))
return B_BAD_VALUE;
BMimeType appMeta;
BFile appFile;
entry_ref appRef;
status_t error;
if (inType != NULL) {
error = _TranslateType(inType, &appMeta, &appRef, &appFile);
if (_wasDocument != NULL)
*_wasDocument = !(appMeta == inType);
} else {
error = _TranslateRef(ref, &appMeta, &appRef, &appFile,
_wasDocument);
}
if (!fNoRegistrar && error == B_OK) {
BPath path;
if (path.SetTo(&appRef) == B_OK)
create_app_meta_mime(path.Path(), false, true, false);
}
BAppFileInfo appFileInfo;
if (!fNoRegistrar && error == B_OK) {
char signature[B_MIME_TYPE_LENGTH];
if (appFileInfo.SetTo(&appFile) == B_OK
&& appFileInfo.GetSignature(signature) == B_OK) {
if (!strcasecmp(appMeta.Type(), signature)) {
entry_ref dummyRef;
if (appMeta.GetAppHint(&dummyRef) != B_OK)
appMeta.SetAppHint(&appRef);
} else {
appMeta.SetAppHint(NULL);
appMeta.SetTo(signature);
}
} else
appMeta.SetAppHint(NULL);
}
if (error == B_OK) {
if (_appRef)
*_appRef = appRef;
if (_signature != NULL) {
if (appMeta.IsValid()) {
strlcpy(_signature, appMeta.Type(),
B_MIME_TYPE_LENGTH);
} else
_signature[0] = '\0';
}
if (_appFlags != NULL) {
if (appFileInfo.InitCheck() != B_OK
|| appFileInfo.GetAppFlags(_appFlags) != B_OK) {
*_appFlags = B_REG_DEFAULT_APP_FLAGS;
}
}
} else {
if (_appRef != NULL)
*_appRef = appRef;
}
return error;
}
status_t
BRoster::_TranslateRef(entry_ref* ref, BMimeType* appMeta,
entry_ref* appRef, BFile* appFile, bool* _wasDocument) const
{
if (ref == NULL || appMeta == NULL || appRef == NULL || appFile == NULL)
return B_BAD_VALUE;
entry_ref originalRef = *ref;
BEntry entry;
status_t error = entry.SetTo(ref, false);
if (error != B_OK)
return error;
if (entry.IsSymLink()) {
if (entry.SetTo(ref, true) != B_OK || entry.GetRef(ref) != B_OK)
return B_LAUNCH_FAILED_NO_RESOLVE_LINK;
}
BNode node;
error = node.SetTo(ref);
if (error != B_OK)
return error;
mode_t permissions;
error = node.GetPermissions(&permissions);
if (error != B_OK)
return error;
if ((permissions & S_IXUSR) != 0 && node.IsFile()) {
error = appFile->SetTo(ref, B_READ_ONLY);
if (error != B_OK)
return error;
BAppFileInfo appFileInfo;
error = appFileInfo.SetTo(appFile);
if (error != B_OK)
return error;
char type[B_MIME_TYPE_LENGTH];
if (appFileInfo.GetSignature(type) == B_OK) {
error = appMeta->SetTo(type);
if (error != B_OK)
return error;
} else
appMeta->Unset();
bool isDocument = true;
if (_GetFileType(ref, &appFileInfo, type) == B_OK
&& strcasecmp(type, B_APP_MIME_TYPE) == 0) {
isDocument = false;
}
char preferredApp[B_MIME_TYPE_LENGTH];
if (!isDocument || appFileInfo.GetPreferredApp(preferredApp) != B_OK) {
*appRef = originalRef;
if (_wasDocument != NULL)
*_wasDocument = isDocument;
return B_OK;
}
}
BNodeInfo nodeInfo;
error = nodeInfo.SetTo(&node);
if (error != B_OK)
return error;
char preferredApp[B_MIME_TYPE_LENGTH];
if (nodeInfo.GetPreferredApp(preferredApp) == B_OK
&& _TranslateType(preferredApp, appMeta, appRef, appFile) == B_OK) {
if (_wasDocument != NULL)
*_wasDocument = true;
return B_OK;
}
char fileType[B_MIME_TYPE_LENGTH];
error = _GetFileType(ref, &nodeInfo, fileType);
if (error != B_OK)
return error;
error = _TranslateType(fileType, appMeta, appRef, appFile);
if (error != B_OK)
return error;
if (_wasDocument != NULL)
*_wasDocument = true;
return B_OK;
}
status_t
BRoster::_TranslateType(const char* mimeType, BMimeType* appMeta,
entry_ref* appRef, BFile* appFile) const
{
if (mimeType == NULL || appMeta == NULL || appRef == NULL
|| appFile == NULL || strlen(mimeType) >= B_MIME_TYPE_LENGTH) {
return B_BAD_VALUE;
}
BMimeType type;
status_t error = type.SetTo(mimeType);
char primarySignature[B_MIME_TYPE_LENGTH];
char secondarySignature[B_MIME_TYPE_LENGTH];
primarySignature[0] = '\0';
secondarySignature[0] = '\0';
if (error == B_OK) {
BMimeType superType;
if (type.GetSupertype(&superType) == B_OK)
superType.GetPreferredApp(secondarySignature);
if (type.IsInstalled()) {
if (type.GetPreferredApp(primarySignature) != B_OK) {
primarySignature[0] = '\0';
} else if (!strcmp(primarySignature, secondarySignature)) {
secondarySignature[0] = '\0';
}
} else {
strlcpy(primarySignature, mimeType, sizeof(primarySignature));
}
}
const char* kSigField = "applications";
BMessage signatures;
bool addedSecondarySignature = false;
if (error == B_OK) {
if (primarySignature[0] != '\0')
error = signatures.AddString(kSigField, primarySignature);
else {
if (secondarySignature[0] != '\0') {
error = signatures.AddString(kSigField, secondarySignature);
addedSecondarySignature = true;
}
}
}
BMessage supportingSignatures;
if (error == B_OK
&& type.GetSupportingApps(&supportingSignatures) == B_OK) {
int32 subCount;
if (supportingSignatures.FindInt32("be:sub", &subCount) != B_OK)
subCount = 0;
const char* supportingType;
if (!addedSecondarySignature) {
for (int32 i = 0; error == B_OK && i < subCount
&& supportingSignatures.FindString(kSigField, i,
&supportingType) == B_OK; i++) {
if (strcmp(primarySignature, supportingType) != 0
&& strcmp(secondarySignature, supportingType) == 0) {
error = signatures.AddString(kSigField, supportingType);
addedSecondarySignature = true;
break;
}
}
}
for (int32 i = 0; error == B_OK && i < subCount
&& supportingSignatures.FindString(kSigField, i,
&supportingType) == B_OK; i++) {
if (strcmp(primarySignature, supportingType) != 0
&& strcmp(secondarySignature, supportingType) != 0) {
error = signatures.AddString(kSigField, supportingType);
}
}
if (error == B_OK && !addedSecondarySignature
&& secondarySignature[0] != '\0') {
error = signatures.AddString(kSigField, secondarySignature);
}
for (int32 i = subCount; error == B_OK
&& supportingSignatures.FindString(kSigField, i,
&supportingType) == B_OK; i++) {
if (strcmp(primarySignature, supportingType) != 0
&& strcmp(secondarySignature, supportingType) != 0) {
error = signatures.AddString(kSigField, supportingType);
}
}
} else {
if (error == B_OK && secondarySignature[0] != '\0')
error = signatures.AddString(kSigField, secondarySignature);
}
if (error != B_OK)
return error;
error = B_LAUNCH_FAILED_NO_PREFERRED_APP;
const char* signature;
for (int32 i = 0;
signatures.FindString(kSigField, i, &signature) == B_OK; i++) {
if (signature[0] == '\0')
continue;
error = appMeta->SetTo(signature);
bool appFound = false;
if (error == B_OK && appMeta->GetAppHint(appRef) == B_OK) {
BEntry entry;
if (entry.SetTo(appRef, true) == B_OK && entry.IsFile()
&& entry.GetRef(appRef) == B_OK) {
appFound = true;
} else {
appMeta->SetAppHint(NULL);
}
}
if (error == B_OK && !appFound)
error = query_for_app(appMeta->Type(), appRef);
if (error == B_OK)
error = appFile->SetTo(appRef, B_READ_ONLY);
if (error == B_OK)
error = can_app_be_used(appRef);
if (error == B_OK)
break;
}
return error;
}
status_t
BRoster::_GetFileType(const entry_ref* file, BNodeInfo* nodeInfo,
char* mimeType) const
{
if (nodeInfo->GetType(mimeType) == B_OK)
return B_OK;
if (fNoRegistrar)
return B_NO_INIT;
BPath path;
if (path.SetTo(file) != B_OK
|| update_mime_info(path.Path(), false, true, false) != B_OK
|| nodeInfo->GetType(mimeType) != B_OK) {
BMimeType type;
status_t error = BMimeType::GuessMimeType(file, &type);
if (error != B_OK)
return error;
if (!type.IsValid())
return B_BAD_VALUE;
strlcpy(mimeType, type.Type(), B_MIME_TYPE_LENGTH);
}
return B_OK;
}
status_t
BRoster::_SendToRunning(team_id team, int argc, const char* const* args,
const BList* messageList, const entry_ref* ref,
bool alreadyRunning) const
{
status_t error = B_OK;
app_info info;
error = GetRunningAppInfo(team, &info);
if (error == B_OK) {
BMessenger messenger;
BMessenger::Private(messenger).SetTo(team, info.port,
B_PREFERRED_TOKEN);
if (messageList != NULL) {
for (int32 i = 0;
BMessage* message = (BMessage*)messageList->ItemAt(i);
i++) {
messenger.SendMessage(message);
}
}
if (args != NULL && argc > 1) {
BMessage message(B_ARGV_RECEIVED);
message.AddInt32("argc", argc);
for (int32 i = 0; i < argc; i++)
message.AddString("argv", args[i]);
char cwd[B_PATH_NAME_LENGTH];
if (getcwd(cwd, B_PATH_NAME_LENGTH) != NULL)
message.AddString("cwd", cwd);
messenger.SendMessage(&message);
} else if (ref != NULL) {
DBG(OUT("_SendToRunning : B_REFS_RECEIVED\n"));
BMessage message(B_REFS_RECEIVED);
message.AddRef("refs", ref);
messenger.SendMessage(&message);
} else if (alreadyRunning && (!messageList || messageList->IsEmpty()))
messenger.SendMessage(B_SILENT_RELAUNCH);
if (!alreadyRunning) {
DBG(OUT("_SendToRunning : B_READY_TO_RUN\n"));
messenger.SendMessage(B_READY_TO_RUN);
}
}
return error;
}
void
BRoster::_SetWithoutRegistrar(bool noRegistrar)
{
fNoRegistrar = noRegistrar;
}
void
BRoster::_InitMessenger()
{
DBG(OUT("BRoster::InitMessengers()\n"));
#ifndef HAIKU_TARGET_PLATFORM_LIBBE_TEST
BMessage data;
if (BLaunchRoster().GetData(B_REGISTRAR_SIGNATURE, data) == B_OK) {
port_id port = data.GetInt32("port", -1);
team_id team = data.GetInt32("team", -1);
if (port >= 0 && team != current_team()) {
DBG(OUT(" found roster port\n"));
BMessenger::Private(fMessenger).SetTo(team, port,
B_PREFERRED_TOKEN);
}
}
#else
port_id rosterPort = find_port(B_REGISTRAR_PORT_NAME);
port_info info;
if (rosterPort >= 0 && get_port_info(rosterPort, &info) == B_OK) {
DBG(OUT(" found roster port\n"));
BMessenger::Private(fMessenger).SetTo(info.team, rosterPort,
B_PREFERRED_TOKEN);
}
#endif
DBG(OUT("BRoster::InitMessengers() done\n"));
}
status_t
BRoster::_InitMimeMessenger(void* data)
{
BRoster* roster = (BRoster*)data;
BMessage request(B_REG_GET_MIME_MESSENGER);
BMessage reply;
status_t error = roster->fMessenger.SendMessage(&request, &reply,
1000000LL, 5000000LL);
if (error == B_OK && reply.what == B_REG_SUCCESS) {
DBG(OUT(" got reply from roster\n"));
reply.FindMessenger("messenger", &roster->fMimeMessenger);
} else {
DBG(OUT(" no (useful) reply from roster: error: %" B_PRIx32 ": %s\n",
error, strerror(error)));
if (error == B_OK)
DBG(reply.PrintToStream());
}
return error;
}
BMessenger&
BRoster::_MimeMessenger()
{
__init_once(&fMimeMessengerInitOnce, &_InitMimeMessenger, this);
return fMimeMessenger;
}
void
BRoster::_AddToRecentApps(const char* signature) const
{
status_t error = B_OK;
BMessage request(B_REG_ADD_TO_RECENT_APPS);
if (error == B_OK)
error = request.AddString("app sig", signature);
BMessage reply;
if (error == B_OK)
error = fMessenger.SendMessage(&request, &reply);
status_t result;
if (error == B_OK) {
error = reply.what == B_REG_RESULT
? (status_t)B_OK : (status_t)B_BAD_REPLY;
}
if (error == B_OK)
error = reply.FindInt32("result", &result);
if (error == B_OK)
error = result;
}
void
BRoster::_ClearRecentDocuments() const
{
BMessage request(B_REG_CLEAR_RECENT_DOCUMENTS);
BMessage reply;
fMessenger.SendMessage(&request, &reply);
}
void
BRoster::_ClearRecentFolders() const
{
BMessage request(B_REG_CLEAR_RECENT_FOLDERS);
BMessage reply;
fMessenger.SendMessage(&request, &reply);
}
void
BRoster::_ClearRecentApps() const
{
BMessage request(B_REG_CLEAR_RECENT_APPS);
BMessage reply;
fMessenger.SendMessage(&request, &reply);
}
void
BRoster::_LoadRecentLists(const char* filename) const
{
status_t error = B_OK;
BMessage request(B_REG_LOAD_RECENT_LISTS);
if (error == B_OK)
error = request.AddString("filename", filename);
BMessage reply;
if (error == B_OK)
error = fMessenger.SendMessage(&request, &reply);
status_t result;
if (error == B_OK) {
error = reply.what == B_REG_RESULT
? (status_t)B_OK : (status_t)B_BAD_REPLY;
}
if (error == B_OK)
error = reply.FindInt32("result", &result);
if (error == B_OK)
error = result;
}
void
BRoster::_SaveRecentLists(const char* filename) const
{
status_t error = B_OK;
BMessage request(B_REG_SAVE_RECENT_LISTS);
if (error == B_OK)
error = request.AddString("filename", filename);
BMessage reply;
if (error == B_OK)
error = fMessenger.SendMessage(&request, &reply);
status_t result;
if (error == B_OK) {
error = reply.what == B_REG_RESULT
? (status_t)B_OK : (status_t)B_BAD_REPLY;
}
if (error == B_OK)
error = reply.FindInt32("result", &result);
if (error == B_OK)
error = result;
}