// Copyright (c) 2015-2026 Vector 35 Inc // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to // deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. #include "binaryninjaapi.h" #include "binaryninjacore.h" #include "http.h" using namespace BinaryNinja; using namespace BinaryNinja::Collaboration; //TODO: this should really be split up and put in a collaboration directory bool BinaryNinja::Collaboration::IsCollaborationDatabase(Ref database) { return BNCollaborationIsCollaborationDatabase(database->m_object); } Ref BinaryNinja::Collaboration::GetRemoteForLocalDatabase(Ref database) { BNRemote* val; if (!BNCollaborationGetRemoteForLocalDatabase(database->m_object, &val)) throw RemoteException("Failed to get remote for local database"); if (val == nullptr) return nullptr; return new Remote(val); } Ref BinaryNinja::Collaboration::GetRemoteProjectForLocalDatabase(Ref database) { BNRemoteProject* val; if (!BNCollaborationGetRemoteProjectForLocalDatabase(database->m_object, &val)) throw RemoteException("Failed to get remote project for local database"); if (val == nullptr) return nullptr; return new RemoteProject(val); } Ref BinaryNinja::Collaboration::GetRemoteFileForLocalDatabase(Ref database) { BNRemoteFile* val; if (!BNCollaborationGetRemoteFileForLocalDatabase(database->m_object, &val)) throw RemoteException("Failed to get remote file for local database"); if (val == nullptr) return nullptr; return new RemoteFile(val); } size_t BinaryNinja::Collaboration::PullDatabase(Ref database, Ref file, AnalysisConflictHandler conflictHandler, ProgressFunction progress, NameChangesetFunction nameChangeset) { ProgressContext pctxt; pctxt.callback = progress; DatabaseConflictHandlerContext chctxt; chctxt.callback = conflictHandler; NameChangesetContext ncctxt; ncctxt.callback = nameChangeset; size_t count = 0; if (!BNCollaborationPullDatabase(database->m_object, file->m_object, &count, DatabaseConflictHandlerCallback, &chctxt, ProgressCallback, &pctxt, NameChangesetCallback, &ncctxt) ) throw SyncException("Failed to pull database"); return count; } void BinaryNinja::Collaboration::MergeDatabase(Ref database, AnalysisConflictHandler conflictHandler, ProgressFunction progress) { ProgressContext pctxt; pctxt.callback = progress; DatabaseConflictHandlerContext chctxt; chctxt.callback = conflictHandler; if (!BNCollaborationMergeDatabase(database->m_object, DatabaseConflictHandlerCallback, &chctxt, ProgressCallback, &pctxt)) throw SyncException("Failed to merge database"); } size_t BinaryNinja::Collaboration::PushDatabase(Ref database, Ref file, ProgressFunction progress) { ProgressContext pctxt; pctxt.callback = progress; size_t count = 0; if (!BNCollaborationPushDatabase(database->m_object, file->m_object, &count, ProgressCallback, &pctxt)) throw SyncException("Failed to push database"); return count; } void BinaryNinja::Collaboration::DumpDatabase(Ref database) { BNCollaborationDumpDatabase(database->m_object); } void BinaryNinja::Collaboration::IgnoreSnapshot(Ref database, Ref snapshot) { BNCollaborationIgnoreSnapshot(database->m_object, snapshot->m_object); } bool BinaryNinja::Collaboration::IsSnapshotIgnored(Ref database, Ref snapshot) { return BNCollaborationIsSnapshotIgnored(database->m_object, snapshot->m_object); } Ref BinaryNinja::Collaboration::GetRemoteSnapshotFromLocal(Ref snapshot) { BNCollaborationSnapshot* val; if (!BNCollaborationGetRemoteSnapshotFromLocal(snapshot->m_object, &val)) throw RemoteException("Failed to get remote snapshot for local snapshot"); if (val == nullptr) return nullptr; return new CollabSnapshot(val); } Ref BinaryNinja::Collaboration::GetLocalSnapshotFromRemote(Ref snapshot, Ref database) { BNSnapshot* val; if (!BNCollaborationGetLocalSnapshotFromRemote(snapshot->m_object, database->m_object, &val)) throw RemoteException("Failed to get local snapshot for remote snapshot"); if (val == nullptr) return nullptr; return new Snapshot(val); } bool BinaryNinja::Collaboration::IsCollaborationTypeArchive(Ref archive) { return BNCollaborationIsCollaborationTypeArchive(archive->m_object); } Ref BinaryNinja::Collaboration::GetRemoteForLocalTypeArchive(Ref archive) { BNRemote* val = BNCollaborationGetRemoteForLocalTypeArchive(archive->m_object); if (val == nullptr) return nullptr; return new Remote(val); } Ref BinaryNinja::Collaboration::GetRemoteProjectForLocalTypeArchive(Ref archive) { BNRemoteProject* val = BNCollaborationGetRemoteProjectForLocalTypeArchive(archive->m_object); if (val == nullptr) return nullptr; return new RemoteProject(val); } Ref BinaryNinja::Collaboration::GetRemoteFileForLocalTypeArchive(Ref archive) { BNRemoteFile* val = BNCollaborationGetRemoteFileForLocalTypeArchive(archive->m_object); if (val == nullptr) return nullptr; return new RemoteFile(val); } Ref BinaryNinja::Collaboration::GetRemoteSnapshotFromLocalTypeArchive(Ref archive, const std::string& snapshotId) { BNCollaborationSnapshot* val = BNCollaborationGetRemoteSnapshotFromLocalTypeArchive(archive->m_object, snapshotId.c_str()); if (val == nullptr) return nullptr; return new CollabSnapshot(val); } std::optional BinaryNinja::Collaboration::GetLocalSnapshotFromRemoteTypeArchive(Ref snapshot, Ref archive) { char* val = BNCollaborationGetLocalSnapshotFromRemoteTypeArchive(snapshot->m_object, archive->m_object); if (val == nullptr) return {}; std::string out = val; BNFreeString(val); return out; } bool BinaryNinja::Collaboration::IsTypeArchiveSnapshotIgnored(Ref archive, const std::string& snapshot) { return BNCollaborationIsTypeArchiveSnapshotIgnored(archive->m_object, snapshot.c_str()); } Ref BinaryNinja::Collaboration::DownloadTypeArchive(Ref file, const std::string& dbPath, ProgressFunction progress) { ProgressContext pctxt; pctxt.callback = progress; BNTypeArchive* val; if (!BNCollaborationDownloadTypeArchive(file->m_object, dbPath.c_str(), ProgressCallback, &pctxt, &val)) throw RemoteException("Failed to download type archive"); if (val == nullptr) return nullptr; return new TypeArchive(val); } Ref BinaryNinja::Collaboration::UploadTypeArchive(Ref archive, Ref project, Ref folder, ProgressFunction progress, Ref coreFile) { ProgressContext pctxt; pctxt.callback = progress; BNRemoteFile* val; if (!BNCollaborationUploadTypeArchive(archive->m_object, project->m_object, folder ? folder->m_object : nullptr, ProgressCallback, &pctxt, coreFile ? coreFile->m_object : nullptr, &val)) throw RemoteException("Failed to upload type archive"); if (val == nullptr) return nullptr; return new RemoteFile(val); } size_t BinaryNinja::Collaboration::PushTypeArchive(Ref archive, Ref file, ProgressFunction progress) { ProgressContext pctxt; pctxt.callback = progress; size_t count = 0; if (!BNCollaborationPushTypeArchive(archive->m_object, file->m_object, &count, ProgressCallback, &pctxt)) throw RemoteException("Failed to push type archive for file"); return count; } size_t BinaryNinja::Collaboration::PullTypeArchive(Ref archive, Ref file, std::function>)> conflictHandler, ProgressFunction progress) { ProgressContext pctxt; pctxt.callback = progress; TypeArchiveConflictHandlerContext chctxt; chctxt.callback = conflictHandler; size_t count = 0; if (!BNCollaborationPullTypeArchive(archive->m_object, file->m_object, &count, TypeArchiveConflictHandlerCallback, &chctxt, ProgressCallback, &pctxt)) throw RemoteException("Failed to pull type archive for file"); return count; } void BinaryNinja::Collaboration::DownloadDatabaseForFile(Ref file, const std::string& dbPath, bool force, ProgressFunction progress) { ProgressContext pctxt; pctxt.callback = progress; if (!BNCollaborationDownloadDatabaseForFile(file->m_object, dbPath.c_str(), force, ProgressCallback, &pctxt)) throw RemoteException("Failed to download database for file"); } void BinaryNinja::Collaboration::SetSnapshotAuthor(Ref database, Ref snapshot, const std::string& author) { BNCollaborationSetSnapshotAuthor(database->m_object, snapshot->m_object, author.c_str()); } Ref BinaryNinja::Collaboration::GetActiveRemote() { BNRemote* remote = BNCollaborationGetActiveRemote(); if (remote == nullptr) return nullptr; return new Remote(remote); } void BinaryNinja::Collaboration::SetActiveRemote(Ref remote) { BNCollaborationSetActiveRemote(remote ? remote->m_object : nullptr); } bool BinaryNinja::Collaboration::StoreDataInKeychain(const std::string& key, const std::map& data) { const char** dataKeys = new const char*[data.size()]; const char** dataValues = new const char*[data.size()]; size_t i = 0; for (const auto& entry : data) { dataKeys[i] = entry.first.c_str(); dataValues[i] = entry.second.c_str(); i++; } bool result = BNCollaborationStoreDataInKeychain(key.c_str(), dataKeys, dataValues, data.size()); delete[] dataKeys; delete[] dataValues; return result; } bool BinaryNinja::Collaboration::HasDataInKeychain(const std::string& key) { return BNCollaborationHasDataInKeychain(key.c_str()); } std::optional> BinaryNinja::Collaboration::GetDataFromKeychain(const std::string& key) { char** keys; char** values; size_t count = BNCollaborationGetDataFromKeychain(key.c_str(), &keys, &values); if (count == 0) return {}; std::map results; for (size_t i = 0; i < count; i++) { results[keys[i]] = values[i]; } BNFreeStringList(keys, count); BNFreeStringList(values, count); return results; } bool BinaryNinja::Collaboration::DeleteDataFromKeychain(const std::string& key) { return BNCollaborationDeleteDataFromKeychain(key.c_str()); } void BinaryNinja::Collaboration::LoadRemotes() { BNCollaborationLoadRemotes(); } std::vector> BinaryNinja::Collaboration::GetRemotes() { size_t count = 0; BNRemote** remotes = BNCollaborationGetRemotes(&count); std::vector> out; out.reserve(count); for (size_t i = 0; i < count; i++) { out.push_back(new Remote(BNNewRemoteReference(remotes[i]))); } BNFreeRemoteList(remotes, count); return out; } Ref BinaryNinja::Collaboration::GetRemoteById(const std::string& remoteId) { BNRemote* remote = BNCollaborationGetRemoteById(remoteId.c_str()); if (!remote) return nullptr; return new Remote(remote); } Ref BinaryNinja::Collaboration::GetRemoteByAddress(const std::string& remoteAddress) { BNRemote* remote = BNCollaborationGetRemoteByAddress(remoteAddress.c_str()); if (!remote) return nullptr; return new Remote(remote); } Ref BinaryNinja::Collaboration::GetRemoteByName(const std::string& name) { BNRemote* remote = BNCollaborationGetRemoteByName(name.c_str()); if (!remote) return nullptr; return new Remote(remote); } Ref BinaryNinja::Collaboration::CreateRemote(const std::string& name, const std::string& address) { BNRemote* remote = BNCollaborationCreateRemote(name.c_str(), address.c_str()); if (!remote) return nullptr; return new Remote(remote); } void BinaryNinja::Collaboration::RemoveRemote(const Ref& remote) { BNCollaborationRemoveRemote(remote->m_object); } bool BinaryNinja::Collaboration::DatabaseConflictHandlerCallback(void* ctxt, const char** keys, BNAnalysisMergeConflict** conflicts, size_t count) { DatabaseConflictHandlerContext* chctxt = reinterpret_cast(ctxt); if (!chctxt->callback) return true; std::unordered_map> conflictMap; for (size_t i = 0; i < count; i++) { conflictMap[keys[i]] = new AnalysisMergeConflict(conflicts[i]); } return chctxt->callback(conflictMap); }; bool BinaryNinja::Collaboration::TypeArchiveConflictHandlerCallback(void* ctxt, BNTypeArchiveMergeConflict** conflicts, size_t count) { TypeArchiveConflictHandlerContext* chctxt = reinterpret_cast(ctxt); if (!chctxt->callback) return true; std::vector> conflictVec; conflictVec.reserve(count); for (size_t i = 0; i < count; i++) { conflictVec.push_back(new TypeArchiveMergeConflict(conflicts[i])); } return chctxt->callback(conflictVec); } bool BinaryNinja::Collaboration::NameChangesetCallback(void* ctxt, BNCollaborationChangeset* changeset) { NameChangesetContext* ncctxt = reinterpret_cast(ctxt); if (!ncctxt->callback) return true; return ncctxt->callback(new CollabChangeset(changeset)); }; void BinaryNinja::Collaboration::SyncDatabase(Ref database, Ref file, std::function>& conflicts)> conflictHandler, ProgressFunction progress, NameChangesetFunction nameChangeset) { ProgressContext pctxt; pctxt.callback = progress; DatabaseConflictHandlerContext chctxt; chctxt.callback = conflictHandler; NameChangesetContext ncctxt; ncctxt.callback = nameChangeset; BNCollaborationSyncDatabase(database->m_object, file->m_object, DatabaseConflictHandlerCallback, &chctxt, ProgressCallback, &pctxt, NameChangesetCallback, &ncctxt ); } void BinaryNinja::Collaboration::SyncTypeArchive(Ref archive, Ref file, std::function>& conflicts)> conflictHandler, ProgressFunction progress) { ProgressContext pctxt; pctxt.callback = progress; TypeArchiveConflictHandlerContext chctxt; chctxt.callback = conflictHandler; BNCollaborationSyncTypeArchive(archive->m_object, file->m_object, TypeArchiveConflictHandlerCallback, &chctxt, ProgressCallback, &pctxt ); } Ref BinaryNinja::Collaboration::MergeSnapshots(Ref first, Ref second, std::function>& conflicts)> conflictHandler, ProgressFunction progress) { ProgressContext pctxt; pctxt.callback = progress; DatabaseConflictHandlerContext chctxt; chctxt.callback = conflictHandler; BNSnapshot* snapshot = BNCollaborationMergeSnapshots(first->m_object, second->m_object, DatabaseConflictHandlerCallback, &chctxt, ProgressCallback, &pctxt); if (snapshot == nullptr) throw SyncException("Failed to merge snapshots"); return new Snapshot(snapshot); } std::string BinaryNinja::Collaboration::DefaultProjectPath(Ref project) { char* path = BNCollaborationDefaultProjectPath(project->m_object); std::string result = path; BNFreeString(path); return result; } std::string BinaryNinja::Collaboration::DefaultFilePath(Ref file) { char* path = BNCollaborationDefaultFilePath(file->m_object); std::string result = path; BNFreeString(path); return result; } Ref BinaryNinja::Collaboration::DownloadFile(Ref file, const std::string& dbPath, ProgressFunction progress) { ProgressContext pctxt; pctxt.callback = progress; BNFileMetadata* metadata = BNCollaborationDownloadFile(file->m_object, dbPath.c_str(), ProgressCallback, &pctxt); if (metadata == nullptr) return nullptr; return new FileMetadata(metadata); } Ref BinaryNinja::Collaboration::UploadDatabase(Ref metadata, Ref project, Ref folder, ProgressFunction progress, NameChangesetFunction nameChangeset) { ProgressContext pctxt; pctxt.callback = progress; NameChangesetContext ncctxt; ncctxt.callback = nameChangeset; BNRemoteFile* file = BNCollaborationUploadDatabase( metadata->m_object, project->m_object, folder ? folder->m_object : nullptr, ProgressCallback, &pctxt, NameChangesetCallback, &ncctxt ); if (file == nullptr) return nullptr; return new RemoteFile(file); } void BinaryNinja::Collaboration::AssignSnapshotMap(Ref localSnapshot, Ref remoteSnapshot) { if (!BNCollaborationAssignSnapshotMap(localSnapshot->m_object, remoteSnapshot->m_object)) throw SyncException("Failed to assign snapshot map"); } Remote::Remote(BNRemote* remote) { m_object = remote; } std::string Remote::GetUniqueId() { char* id = BNRemoteGetUniqueId(m_object); std::string result = id; BNFreeString(id); return result; } std::string Remote::GetName() { char* name = BNRemoteGetName(m_object); std::string result = name; BNFreeString(name); return result; } std::string Remote::GetAddress() { char* addr = BNRemoteGetAddress(m_object); std::string result = addr; BNFreeString(addr); return result; } bool Remote::HasLoadedMetadata() { return BNRemoteHasLoadedMetadata(m_object); } bool Remote::IsConnected() { return BNRemoteIsConnected(m_object); } std::string Remote::GetUsername() { char* username = BNRemoteGetUsername(m_object); std::string result = username; BNFreeString(username); return result; } std::string Remote::GetToken() { char* username = BNRemoteGetToken(m_object); std::string result = username; BNFreeString(username); return result; } int Remote::GetServerVersion() { return BNRemoteGetServerVersion(m_object); } std::string Remote::GetServerBuildVersion() { char* buildVersion = BNRemoteGetServerBuildVersion(m_object); std::string result = buildVersion; BNFreeString(buildVersion); return result; } std::string Remote::GetServerBuildId() { char* buildId = BNRemoteGetServerBuildId(m_object); std::string result = buildId; BNFreeString(buildId); return result; } std::vector> Remote::GetAuthBackends() { char** methods; char** names; size_t count; if (!BNRemoteGetAuthBackends(m_object, &methods, &names, &count)) throw RemoteException("Failed to get authentication backends"); std::vector> results; results.reserve(count); for (size_t i = 0; i < count; i++) { results.push_back({methods[i], names[i]}); } BNFreeStringList(methods, count); BNFreeStringList(names, count); return results; } bool Remote::HasPulledProjects() { return BNRemoteHasPulledProjects(m_object); } bool Remote::HasPulledUsers() { return BNRemoteHasPulledUsers(m_object); } bool Remote::HasPulledGroups() { return BNRemoteHasPulledGroups(m_object); } bool Remote::IsAdmin() { return BNRemoteIsAdmin(m_object); } bool Remote::IsEnterprise() { return BNRemoteIsEnterprise(m_object); } bool Remote::LoadMetadata() { return BNRemoteLoadMetadata(m_object); } std::string Remote::RequestAuthenticationToken(const std::string& username, const std::string& password) { char* token = BNRemoteRequestAuthenticationToken(m_object, username.c_str(), password.c_str()); if (token == nullptr) throw RemoteException("Failed to authenticate"); std::string result = token; BNFreeString(token); return result; } void Remote::Connect(const std::string& username, const std::string& token) { BNRemoteConnect(m_object, username.c_str(), token.c_str()); } void Remote::Disconnect() { BNRemoteDisconnect(m_object); } std::vector> Remote::GetProjects() { size_t count = 0; BNRemoteProject** projects = BNRemoteGetProjects(m_object, &count); std::vector> out; out.reserve(count); for (size_t i = 0; i < count; i++) { out.push_back(new RemoteProject(BNNewRemoteProjectReference(projects[i]))); } BNFreeRemoteProjectList(projects, count); return out; } Ref Remote::GetProjectById(const std::string& id) { BNRemoteProject* project = BNRemoteGetProjectById(m_object, id.c_str()); if (project == nullptr) return nullptr; return new RemoteProject(project); } Ref Remote::GetProjectByName(const std::string& name) { BNRemoteProject* project = BNRemoteGetProjectByName(m_object, name.c_str()); if (project == nullptr) return nullptr; return new RemoteProject(project); } void Remote::PullProjects(ProgressFunction progress) { ProgressContext pctxt; pctxt.callback = progress; BNRemotePullProjects(m_object, ProgressCallback, &pctxt); } Ref Remote::CreateProject(const std::string& name, const std::string& description) { BNRemoteProject* project = BNRemoteCreateProject(m_object, name.c_str(), description.c_str()); if (project == nullptr) return nullptr; return new RemoteProject(project); } Ref Remote::ImportLocalProject(Ref localProject, ProgressFunction progress) { ProgressContext pctxt; pctxt.callback = progress; BNRemoteProject* project = BNRemoteImportLocalProject(m_object, localProject->m_object, ProgressCallback, &pctxt); if (project == nullptr) return nullptr; return new RemoteProject(project); } void Remote::PushProject(Ref project, const std::vector>& extraFields) { const char** fieldKeys = new const char*[extraFields.size()]; const char** fieldValues = new const char*[extraFields.size()]; for (size_t i = 0; i < extraFields.size(); i++) { auto& field = extraFields[i]; fieldKeys[i] = field.first.c_str(); fieldValues[i] = field.second.c_str(); } BNRemotePushProject(m_object, project->m_object, fieldKeys, fieldValues, extraFields.size()); delete[] fieldKeys; delete[] fieldValues; } void Remote::DeleteProject(const Ref project) { BNRemoteDeleteProject(m_object, project->m_object); } std::vector> Remote::GetGroups() { size_t count = 0; BNCollaborationGroup** groups = BNRemoteGetGroups(m_object, &count); std::vector> out; out.reserve(count); for (size_t i = 0; i < count; i++) { out.push_back(new CollabGroup(BNNewCollaborationGroupReference(groups[i]))); } BNFreeCollaborationGroupList(groups, count); return out; } Ref Remote::GetGroupById(uint64_t id) { BNCollaborationGroup* group = BNRemoteGetGroupById(m_object, id); if (group == nullptr) return nullptr; return new CollabGroup(group); } Ref Remote::GetGroupByName(const std::string& name) { BNCollaborationGroup* group = BNRemoteGetGroupByName(m_object, name.c_str()); if (group == nullptr) return nullptr; return new CollabGroup(group); } std::vector> Remote::SearchGroups(const std::string& prefix) { uint64_t* ids; char** names; size_t count; if (!BNRemoteSearchGroups(m_object, prefix.c_str(), &ids, &names, &count)) throw RemoteException("Failed to search groups"); std::vector> results; results.reserve(count); for (size_t i = 0; i < count; i++) { results.push_back({ids[i], names[i]}); } delete[] ids; BNFreeStringList(names, count); return results; } void Remote::PullGroups(ProgressFunction progress) { ProgressContext pctxt; pctxt.callback = progress; BNRemotePullGroups(m_object, ProgressCallback, &pctxt); } Ref Remote::CreateGroup(const std::string& name, const std::vector& usernames) { const char** cstrNames = new const char*[usernames.size()]; for (size_t i = 0; i < usernames.size(); i++) { cstrNames[i] = usernames[i].c_str(); } BNCollaborationGroup* group = BNRemoteCreateGroup(m_object, name.c_str(), cstrNames, usernames.size()); delete[] cstrNames; if (!group) return nullptr; return new CollabGroup(group); } void Remote::PushGroup(Ref group, const std::vector>& extraFields) { const char** fieldKeys = new const char*[extraFields.size()]; const char** fieldValues = new const char*[extraFields.size()]; for (size_t i = 0; i < extraFields.size(); i++) { auto& field = extraFields[i]; fieldKeys[i] = field.first.c_str(); fieldValues[i] = field.second.c_str(); } BNRemotePushGroup(m_object, group->m_object, fieldKeys, fieldValues, extraFields.size()); delete[] fieldKeys; delete[] fieldValues; } void Remote::DeleteGroup(Ref group) { BNRemoteDeleteGroup(m_object, group->m_object); } std::vector> Remote::GetUsers() { size_t count = 0; BNCollaborationUser** users = BNRemoteGetUsers(m_object, &count); std::vector> out; out.reserve(count); for (size_t i = 0; i < count; i++) { out.push_back(new CollabUser(BNNewCollaborationUserReference(users[i]))); } BNFreeCollaborationUserList(users, count); return out; } Ref Remote::GetUserById(const std::string& id) { BNCollaborationUser* user = BNRemoteGetUserById(m_object, id.c_str()); if (user == nullptr) return nullptr; return new CollabUser(user); } Ref Remote::GetUserByUsername(const std::string& username) { BNCollaborationUser* user = BNRemoteGetUserByUsername(m_object, username.c_str()); if (user == nullptr) return nullptr; return new CollabUser(user); } Ref Remote::GetCurrentUser() { BNCollaborationUser* user = BNRemoteGetCurrentUser(m_object); if (user == nullptr) return nullptr; return new CollabUser(user); } std::vector> Remote::SearchUsers(const std::string& prefix) { char** ids; char** names; size_t count; if (!BNRemoteSearchUsers(m_object, prefix.c_str(), &ids, &names, &count)) throw RemoteException("Failed to search users"); std::vector> results; results.reserve(count); for (size_t i = 0; i < count; i++) { results.push_back({ids[i], names[i]}); } BNFreeStringList(ids, count); BNFreeStringList(names, count); return results; } std::vector Remote::FindFiles(const std::string& name) { size_t count = 0; BNRemoteFileSearchMatch* matches = BNRemoteFindFiles(m_object, name.c_str(), &count); std::vector results; if (!matches) return results; results.reserve(count); for (size_t i = 0; i < count; i++) { FileSearchMatch match; if (matches[i].projectId) match.projectId = matches[i].projectId; if (matches[i].projectName) match.projectName = matches[i].projectName; if (matches[i].fileId) match.fileId = matches[i].fileId; if (matches[i].fileName) match.fileName = matches[i].fileName; results.push_back(std::move(match)); } BNFreeRemoteFileSearchMatchList(matches, count); return results; } void Remote::PullUsers(ProgressFunction progress) { ProgressContext pctxt; pctxt.callback = progress; BNRemotePullUsers(m_object, ProgressCallback, &pctxt); } Ref Remote::CreateUser(const std::string& username, const std::string& email, bool is_active, const std::string& password, const std::vector& groupIds, const std::vector& userPermissionIds) { BNCollaborationUser* user = BNRemoteCreateUser(m_object, username.c_str(), email.c_str(), is_active, password.c_str(), groupIds.data(), groupIds.size(), userPermissionIds.data(), userPermissionIds.size()); if (user == nullptr) return nullptr; return new CollabUser(user); } void Remote::PushUser(Ref user, const std::vector>& extraFields) { const char** fieldKeys = new const char*[extraFields.size()]; const char** fieldValues = new const char*[extraFields.size()]; for (size_t i = 0; i < extraFields.size(); i++) { auto& field = extraFields[i]; fieldKeys[i] = field.first.c_str(); fieldValues[i] = field.second.c_str(); } BNRemotePushUser(m_object, user->m_object, fieldKeys, fieldValues, extraFields.size()); delete[] fieldKeys; delete[] fieldValues; } int Remote::Request(Http::Request request, Http::Response& ret) { return BNRemoteRequest(m_object, &request, &ret); } CollabGroup::CollabGroup(BNCollaborationGroup* group) { m_object = group; } uint64_t CollabGroup::GetId() { return BNCollaborationGroupGetId(m_object); } std::string CollabGroup::GetName() { char* name = BNCollaborationGroupGetName(m_object); std::string result = name; BNFreeString(name); return result; } void CollabGroup::SetName(const std::string& name) { BNCollaborationGroupSetName(m_object, name.c_str()); } void CollabGroup::SetUsernames(const std::vector& usernames) { const char** cNames = new const char*[usernames.size()]; for (size_t i = 0; i < usernames.size(); i++) { cNames[i] = usernames[i].c_str(); } BNCollaborationGroupSetUsernames(m_object, cNames, usernames.size()); delete[] cNames; } bool CollabGroup::ContainsUser(const std::string& username) { return BNCollaborationGroupContainsUser(m_object, username.c_str()); } CollabUser::CollabUser(BNCollaborationUser* user) { m_object = user; } Ref CollabUser::GetRemote() { BNRemote* remote = BNCollaborationUserGetRemote(m_object); if (remote == nullptr) return nullptr; return new Remote(remote); } std::string CollabUser::GetUrl() { char* url = BNCollaborationUserGetUrl(m_object); std::string result = url; BNFreeString(url); return result; } std::string CollabUser::GetId() { char* id = BNCollaborationUserGetId(m_object); std::string result = id; BNFreeString(id); return result; } std::string CollabUser::GetUsername() { char* username = BNCollaborationUserGetUsername(m_object); std::string result = username; BNFreeString(username); return result; } std::string CollabUser::GetEmail() { char* email = BNCollaborationUserGetEmail(m_object); std::string result = email; BNFreeString(email); return result; } std::string CollabUser::GetLastLogin() { char* lastLogin = BNCollaborationUserGetLastLogin(m_object); std::string result = lastLogin; BNFreeString(lastLogin); return result; } bool CollabUser::IsActive() { return BNCollaborationUserIsActive(m_object); } void CollabUser::SetUsername(const std::string& username) { BNCollaborationUserSetUsername(m_object, username.c_str()); } void CollabUser::SetEmail(const std::string& email) { BNCollaborationUserSetEmail(m_object, email.c_str()); } void CollabUser::SetIsActive(bool isActive) { BNCollaborationUserSetIsActive(m_object, isActive); } RemoteProject::RemoteProject(BNRemoteProject* project) { m_object = project; } Ref RemoteProject::GetCoreProject() { BNProject* project = BNRemoteProjectGetCoreProject(m_object); if (project == nullptr) return nullptr; return new Project(project); } bool RemoteProject::IsOpen() { return BNRemoteProjectIsOpen(m_object); } bool RemoteProject::Open(ProgressFunction progress) { ProgressContext pctxt; pctxt.callback = progress; return BNRemoteProjectOpen(m_object, ProgressCallback, &pctxt); } void RemoteProject::Close() { BNRemoteProjectClose(m_object); } Ref RemoteProject::GetRemote() { return new Remote(BNRemoteProjectGetRemote(m_object)); } std::string RemoteProject::GetUrl() { char* url = BNRemoteProjectGetUrl(m_object); std::string result = url; BNFreeString(url); return result; } int64_t RemoteProject::GetCreated() { return BNRemoteProjectGetCreated(m_object); } int64_t RemoteProject::GetLastModified() { return BNRemoteProjectGetLastModified(m_object); } std::string RemoteProject::GetId() { char* id = BNRemoteProjectGetId(m_object); std::string result = id; BNFreeString(id); return result; } std::string RemoteProject::GetName() { char* name = BNRemoteProjectGetName(m_object); std::string result = name; BNFreeString(name); return result; } void RemoteProject::SetName(const std::string& name) { BNRemoteProjectSetName(m_object, name.c_str()); } std::string RemoteProject::GetDescription() { char* desc = BNRemoteProjectGetDescription(m_object); std::string result = desc; BNFreeString(desc); return result; } void RemoteProject::SetDescription(const std::string& description) { BNRemoteProjectSetDescription(m_object, description.c_str()); } uint64_t RemoteProject::GetReceivedFileCount() { return BNRemoteProjectGetReceivedFileCount(m_object); } uint64_t RemoteProject::GetReceivedFolderCount() { return BNRemoteProjectGetReceivedFolderCount(m_object); } bool RemoteProject::HasPulledFiles() { return BNRemoteProjectHasPulledFiles(m_object); } bool RemoteProject::HasPulledGroupPermissions() { return BNRemoteProjectHasPulledGroupPermissions(m_object); } bool RemoteProject::HasPulledUserPermissions() { return BNRemoteProjectHasPulledUserPermissions(m_object); } bool RemoteProject::IsAdmin() { return BNRemoteProjectIsAdmin(m_object); } std::vector> RemoteProject::GetFiles() { size_t count; BNRemoteFile** files = BNRemoteProjectGetFiles(m_object, &count); std::vector> result; result.reserve(count); for (size_t i = 0; i < count; i++) { result.push_back(new RemoteFile(BNNewRemoteFileReference(files[i]))); } BNFreeRemoteFileList(files, count); return result; } std::vector> RemoteProject::GetFolders() { size_t count; BNRemoteFolder** folders = BNRemoteProjectGetFolders(m_object, &count); std::vector> result; result.reserve(count); for (size_t i = 0; i < count; i++) { result.push_back(new RemoteFolder(BNNewRemoteFolderReference(folders[i]))); } BNFreeRemoteFolderList(folders, count); return result; } Ref RemoteProject::GetFileById(const std::string& id) { BNRemoteFile* file = BNRemoteProjectGetFileById(m_object, id.c_str()); if (file == nullptr) return nullptr; return new RemoteFile(file); } Ref RemoteProject::GetFileByName(const std::string& name) { BNRemoteFile* file = BNRemoteProjectGetFileByName(m_object, name.c_str()); if (file == nullptr) return nullptr; return new RemoteFile(file); } void RemoteProject::PullFiles(ProgressFunction progress) { ProgressContext pctxt; pctxt.callback = progress; BNRemoteProjectPullFiles(m_object, ProgressCallback, &pctxt); } void RemoteProject::PullFolders(ProgressFunction progress) { ProgressContext pctxt; pctxt.callback = progress; BNRemoteProjectPullFolders(m_object, ProgressCallback, &pctxt); } Ref RemoteProject::CreateFile(const std::string& filename, std::vector& contents, const std::string& name, const std::string& description, Ref folder, BNRemoteFileType type, ProgressFunction progress, Ref coreFile) { ProgressContext pctxt; pctxt.callback = progress; BNRemoteFile* file = BNRemoteProjectCreateFile(m_object, filename.c_str(), contents.data(), contents.size(), name.c_str(), description.c_str(), folder ? folder->m_object : nullptr, type, ProgressCallback, &pctxt); if (file == nullptr) return nullptr; return new RemoteFile(file); } Ref RemoteProject::CreateFolder(const std::string& name, const std::string& description, Ref parent, ProgressFunction progress, Ref coreFolder) { ProgressContext pctxt; pctxt.callback = progress; BNRemoteFolder* folder = BNRemoteProjectCreateFolder(m_object, name.c_str(), description.c_str(), parent ? parent->m_object : nullptr, ProgressCallback, &pctxt); if (folder == nullptr) return nullptr; return new RemoteFolder(folder); } void RemoteProject::PushFile(Ref file, const std::vector>& extraFields) { const char** fieldKeys = new const char*[extraFields.size()]; const char** fieldValues = new const char*[extraFields.size()]; for (size_t i = 0; i < extraFields.size(); i++) { auto& field = extraFields[i]; fieldKeys[i] = field.first.c_str(); fieldValues[i] = field.second.c_str(); } BNRemoteProjectPushFile(m_object, file->m_object, fieldKeys, fieldValues, extraFields.size()); delete[] fieldKeys; delete[] fieldValues; } void RemoteProject::PushFolder(Ref folder, const std::vector>& extraFields) { const char** fieldKeys = new const char*[extraFields.size()]; const char** fieldValues = new const char*[extraFields.size()]; for (size_t i = 0; i < extraFields.size(); i++) { auto& field = extraFields[i]; fieldKeys[i] = field.first.c_str(); fieldValues[i] = field.second.c_str(); } BNRemoteProjectPushFolder(m_object, folder->m_object, fieldKeys, fieldValues, extraFields.size()); delete[] fieldKeys; delete[] fieldValues; } void RemoteProject::DeleteFolder(const Ref folder) { BNRemoteProjectDeleteFolder(m_object, folder->m_object); } void RemoteProject::DeleteFile(const Ref file) { BNRemoteProjectDeleteFile(m_object, file->m_object); } Ref RemoteProject::GetFolderById(const std::string& id) { BNRemoteFolder* folder = BNRemoteProjectGetFolderById(m_object, id.c_str()); if (folder == nullptr) return nullptr; return new RemoteFolder(folder); } std::vector> RemoteProject::GetGroupPermissions() { size_t count; BNCollaborationPermission** perms = BNRemoteProjectGetGroupPermissions(m_object, &count); std::vector> result; result.reserve(count); for (size_t i = 0; i < count; i++) { result.push_back(new CollabPermission(BNNewCollaborationPermissionReference(perms[i]))); } BNFreeCollaborationPermissionList(perms, count); return result; } std::vector> RemoteProject::GetUserPermissions() { size_t count; BNCollaborationPermission** perms = BNRemoteProjectGetUserPermissions(m_object, &count); std::vector> result; result.reserve(count); for (size_t i = 0; i < count; i++) { result.push_back(new CollabPermission(BNNewCollaborationPermissionReference(perms[i]))); } BNFreeCollaborationPermissionList(perms, count); return result; } Ref RemoteProject::GetPermissionById(const std::string& id) { BNCollaborationPermission* perm = BNRemoteProjectGetPermissionById(m_object, id.c_str()); if (perm == nullptr) return nullptr; return new CollabPermission(perm); } void RemoteProject::PullGroupPermissions(ProgressFunction progress) { ProgressContext pctxt; pctxt.callback = progress; BNRemoteProjectPullGroupPermissions(m_object, ProgressCallback, &pctxt); } void RemoteProject::PullUserPermissions(ProgressFunction progress) { ProgressContext pctxt; pctxt.callback = progress; BNRemoteProjectPullUserPermissions(m_object, ProgressCallback, &pctxt); } Ref RemoteProject::CreateGroupPermission(int groupId, BNCollaborationPermissionLevel level, ProgressFunction progress) { ProgressContext pctxt; pctxt.callback = progress; BNCollaborationPermission* perm = BNRemoteProjectCreateGroupPermission(m_object, groupId, level, ProgressCallback, &pctxt); if (perm == nullptr) return nullptr; return new CollabPermission(perm); } Ref RemoteProject::CreateUserPermission(const std::string& userId, BNCollaborationPermissionLevel level, ProgressFunction progress) { ProgressContext pctxt; pctxt.callback = progress; BNCollaborationPermission* perm = BNRemoteProjectCreateUserPermission(m_object, userId.c_str(), level, ProgressCallback, &pctxt); if (perm == nullptr) return nullptr; return new CollabPermission(perm); } void RemoteProject::PushPermission(Ref permission, const std::vector>& extraFields) { const char** fieldKeys = new const char*[extraFields.size()]; const char** fieldValues = new const char*[extraFields.size()]; for (size_t i = 0; i < extraFields.size(); i++) { auto& field = extraFields[i]; fieldKeys[i] = field.first.c_str(); fieldValues[i] = field.second.c_str(); } BNRemoteProjectPushPermission(m_object, permission->m_object, fieldKeys, fieldValues, extraFields.size()); delete[] fieldKeys; delete[] fieldValues; } void RemoteProject::DeletePermission(Ref permission) { BNRemoteProjectDeletePermission(m_object, permission->m_object); } bool RemoteProject::CanUserView(const std::string& username) { return BNRemoteProjectCanUserView(m_object, username.c_str()); } bool RemoteProject::CanUserEdit(const std::string& username) { return BNRemoteProjectCanUserEdit(m_object, username.c_str()); } bool RemoteProject::CanUserAdmin(const std::string& username) { return BNRemoteProjectCanUserAdmin(m_object, username.c_str()); } RemoteFile::RemoteFile(BNRemoteFile* file) { m_object = file; } Ref RemoteFile::GetCoreFile() { BNProjectFile* res = BNRemoteFileGetCoreFile(m_object); if (!res) return nullptr; return new ProjectFile(res); } Ref RemoteFile::GetProject() { BNRemoteProject* res = BNRemoteFileGetProject(m_object); if (!res) return nullptr; return new RemoteProject(res); } Ref RemoteFile::GetFolder() { BNRemoteFolder* res = BNRemoteFileGetFolder(m_object); if (!res) return nullptr; return new RemoteFolder(res); } Ref RemoteFile::GetRemote() { BNRemote* res = BNRemoteFileGetRemote(m_object); if (!res) return nullptr; return new Remote(res); } std::string RemoteFile::GetUrl() { char* res = BNRemoteFileGetUrl(m_object); std::string out = res; BNFreeString(res); return out; } std::string RemoteFile::GetChatLogUrl() { char* res = BNRemoteFileGetChatLogUrl(m_object); std::string out = res; BNFreeString(res); return out; } std::string RemoteFile::GetUserPositionsUrl() { char* res = BNRemoteFileGetUserPositionsUrl(m_object); std::string out = res; BNFreeString(res); return out; } std::string RemoteFile::GetId() { char* res = BNRemoteFileGetId(m_object); std::string out = res; BNFreeString(res); return out; } BNRemoteFileType RemoteFile::GetType() { return BNRemoteFileGetType(m_object); } int64_t RemoteFile::GetCreated() { return BNRemoteFileGetCreated(m_object); } std::string RemoteFile::GetCreatedBy() { char* res = BNRemoteFileGetCreatedBy(m_object); std::string out = res; BNFreeString(res); return out; } int64_t RemoteFile::GetLastModified() { return BNRemoteFileGetLastModified(m_object); } int64_t RemoteFile::GetLastSnapshot() { return BNRemoteFileGetLastSnapshot(m_object); } std::string RemoteFile::GetLastSnapshotBy() { char* res = BNRemoteFileGetLastSnapshotBy(m_object); std::string out = res; BNFreeString(res); return out; } std::string RemoteFile::GetLastSnapshotName() { char* res = BNRemoteFileGetLastSnapshotName(m_object); std::string out = res; BNFreeString(res); return out; } std::string RemoteFile::GetHash() { char* res = BNRemoteFileGetHash(m_object); std::string out = res; BNFreeString(res); return out; } std::string RemoteFile::GetName() { char* res = BNRemoteFileGetName(m_object); std::string out = res; BNFreeString(res); return out; } std::string RemoteFile::GetDescription() { char* res = BNRemoteFileGetDescription(m_object); std::string out = res; BNFreeString(res); return out; } std::string RemoteFile::GetMetadata() { char* res = BNRemoteFileGetMetadata(m_object); std::string out = res; BNFreeString(res); return out; } uint64_t RemoteFile::GetSize() { return BNRemoteFileGetSize(m_object); } bool RemoteFile::HasPulledSnapshots() { return BNRemoteFileHasPulledSnapshots(m_object); } void RemoteFile::SetName(const std::string& name) { BNRemoteFileSetName(m_object, name.c_str()); } void RemoteFile::SetDescription(const std::string& description) { BNRemoteFileSetDescription(m_object, description.c_str()); } void RemoteFile::SetFolder(const Ref& folder) { BNRemoteFileSetFolder(m_object, folder ? folder->m_object : nullptr); } void RemoteFile::SetMetadata(const std::string& metadata) { BNRemoteFileSetMetadata(m_object, metadata.c_str()); } std::vector> RemoteFile::GetSnapshots() { size_t count = 0; BNCollaborationSnapshot** collabSnapshots = BNRemoteFileGetSnapshots(m_object, &count); std::vector> out; out.reserve(count); for (size_t i = 0; i < count; i++) { out.push_back(new CollabSnapshot(BNNewCollaborationSnapshotReference(collabSnapshots[i]))); } BNFreeCollaborationSnapshotList(collabSnapshots, count); return out; } Ref RemoteFile::GetSnapshotById(const std::string& id) { BNCollaborationSnapshot* snapshot = BNRemoteFileGetSnapshotById(m_object, id.c_str()); if (snapshot == nullptr) return nullptr; return new CollabSnapshot(snapshot); } void RemoteFile::PullSnapshots(ProgressFunction progress) { ProgressContext pctxt; pctxt.callback = progress; BNRemoteFilePullSnapshots(m_object, ProgressCallback, &pctxt); } Ref RemoteFile::CreateSnapshot(std::string name, std::vector contents, std::vector analysisCacheContents, std::optional> fileContents, std::vector parentIds, ProgressFunction progress) { ProgressContext pctxt; pctxt.callback = progress; const char** cParentIds = new const char*[parentIds.size()]; for (size_t i = 0; i < parentIds.size(); i++) { cParentIds[i] = parentIds[i].c_str(); } BNCollaborationSnapshot* snapshot = BNRemoteFileCreateSnapshot(m_object, name.c_str(), contents.data(), contents.size(), analysisCacheContents.data(), analysisCacheContents.size(), fileContents.has_value() ? fileContents->data() : nullptr, fileContents.has_value() ? fileContents->size() : 0, cParentIds, parentIds.size(), ProgressCallback, &pctxt ); delete[] cParentIds; if (snapshot == nullptr) return nullptr; return new CollabSnapshot(snapshot); } void RemoteFile::DeleteSnapshot(const Ref snapshot) { BNRemoteFileDeleteSnapshot(m_object, snapshot->m_object); } void RemoteFile::Download(ProgressFunction progress) { ProgressContext pctxt; pctxt.callback = progress; if (!BNRemoteFileDownload(m_object, ProgressCallback, &pctxt)) throw RemoteException("Failed to download file"); } std::vector RemoteFile::DownloadContents(ProgressFunction progress) { ProgressContext pctxt; pctxt.callback = progress; size_t size = 0; uint8_t* data; if (!BNRemoteFileDownloadContents(m_object, ProgressCallback, &pctxt, &data, &size)) throw SyncException("Failed to download file contents"); std::vector out; out.insert(out.end(), &data[0], &data[size]); delete[] data; return out; } Json::Value RemoteFile::RequestUserPositions() { char* value = BNRemoteFileRequestUserPositions(m_object); if (value == nullptr) throw RemoteException("Failed to load user positions"); Json::Value json; std::unique_ptr reader(Json::CharReaderBuilder().newCharReader()); std::string errors; if (!reader->parse(value, value + strlen(value), &json, &errors)) { throw RemoteException(errors); } BNFreeString(value); return json; } Json::Value RemoteFile::RequestChatLog() { char* value = BNRemoteFileRequestChatLog(m_object); if (value == nullptr) throw RemoteException("Failed to load user positions"); Json::Value json; std::unique_ptr reader(Json::CharReaderBuilder().newCharReader()); std::string errors; if (!reader->parse(value, value + strlen(value), &json, &errors)) { throw RemoteException(errors); } BNFreeString(value); return json; } RemoteFolder::RemoteFolder(BNRemoteFolder* folder) { m_object = folder; } Ref RemoteFolder::GetCoreFolder() { BNProjectFolder* res = BNRemoteFolderGetCoreFolder(m_object); if (!res) return nullptr; return new ProjectFolder(res); } Ref RemoteFolder::GetProject() { BNRemoteProject* res = BNRemoteFolderGetProject(m_object); if (!res) return nullptr; return new RemoteProject(res); } Ref RemoteFolder::GetParent() { BNRemoteFolder* res = nullptr; if (!BNRemoteFolderGetParent(m_object, &res)) return nullptr; if (!res) return nullptr; return new RemoteFolder(res); } Ref RemoteFolder::GetRemote() { BNRemote* res = BNRemoteFolderGetRemote(m_object); if (!res) return nullptr; return new Remote(res); } std::string RemoteFolder::GetId() { char* res = BNRemoteFolderGetId(m_object); std::string out = res; BNFreeString(res); return out; } std::string RemoteFolder::GetUrl() { char* res = BNRemoteFolderGetUrl(m_object); std::string out = res; BNFreeString(res); return out; } std::string RemoteFolder::GetName() { char* res = BNRemoteFolderGetName(m_object); std::string out = res; BNFreeString(res); return out; } std::string RemoteFolder::GetDescription() { char* res = BNRemoteFolderGetDescription(m_object); std::string out = res; BNFreeString(res); return out; } CollabPermission::CollabPermission(BNCollaborationPermission* permission) { m_object = permission; } Ref CollabPermission::GetProject() { BNRemoteProject* project = BNCollaborationPermissionGetProject(m_object); if (project == nullptr) return nullptr; return new RemoteProject(project); } Ref CollabPermission::GetRemote() { BNRemote* remote = BNCollaborationPermissionGetRemote(m_object); if (remote == nullptr) return nullptr; return new Remote(remote); } std::string CollabPermission::GetId() { char* id = BNCollaborationPermissionGetId(m_object); std::string result = id; BNFreeString(id); return result; } std::string CollabPermission::GetUrl() { char* url = BNCollaborationPermissionGetUrl(m_object); std::string result = url; BNFreeString(url); return result; } uint64_t CollabPermission::GetGroupId() { return BNCollaborationPermissionGetGroupId(m_object); } std::string CollabPermission::GetGroupName() { char* name = BNCollaborationPermissionGetGroupName(m_object); std::string result = name; BNFreeString(name); return result; } std::string CollabPermission::GetUserId() { char* id = BNCollaborationPermissionGetUserId(m_object); std::string result = id; BNFreeString(id); return result; } std::string CollabPermission::GetUsername() { char* username = BNCollaborationPermissionGetUsername(m_object); std::string result = username; BNFreeString(username); return result; } BNCollaborationPermissionLevel CollabPermission::GetLevel() { return BNCollaborationPermissionGetLevel(m_object); } void CollabPermission::SetLevel(BNCollaborationPermissionLevel level) { BNCollaborationPermissionSetLevel(m_object, level); } bool CollabPermission::CanView() { return BNCollaborationPermissionCanView(m_object); } bool CollabPermission::CanEdit() { return BNCollaborationPermissionCanEdit(m_object); } bool CollabPermission::CanAdmin() { return BNCollaborationPermissionCanAdmin(m_object); } std::optional BinaryNinja::Collaboration::GetSnapshotAuthor(Ref database, Ref snapshot) { char* cAuthor = nullptr; if (!BNCollaborationGetSnapshotAuthor(database->m_object, snapshot->m_object, &cAuthor)) throw RemoteException("Failed to get snapshot author"); if (cAuthor == nullptr) return {}; std::string author = cAuthor; BNFreeString(cAuthor); return author; } AnalysisMergeConflict::AnalysisMergeConflict(BNAnalysisMergeConflict* conflict) { m_object = conflict; } std::string AnalysisMergeConflict::GetType() { char* val = BNAnalysisMergeConflictGetType(m_object); std::string result = val; BNFreeString(val); return result; } BNMergeConflictDataType AnalysisMergeConflict::GetDataType() { return BNAnalysisMergeConflictGetDataType(m_object); } std::optional AnalysisMergeConflict::GetBase() { char* val = BNAnalysisMergeConflictGetBase(m_object); if (val == nullptr) return {}; return nlohmann::json::parse(val); BNFreeString(val); } std::optional AnalysisMergeConflict::GetFirst() { char* val = BNAnalysisMergeConflictGetFirst(m_object); if (val == nullptr) return {}; return nlohmann::json::parse(val); BNFreeString(val); } std::optional AnalysisMergeConflict::GetSecond() { char* val = BNAnalysisMergeConflictGetSecond(m_object); if (val == nullptr) return {}; return nlohmann::json::parse(val); BNFreeString(val); } Ref AnalysisMergeConflict::GetBaseFile() { BNFileMetadata* val = BNAnalysisMergeConflictGetBaseFile(m_object); if (val == nullptr) return nullptr; return new FileMetadata(val); } Ref AnalysisMergeConflict::GetFirstFile() { BNFileMetadata* val = BNAnalysisMergeConflictGetFirstFile(m_object); if (val == nullptr) return nullptr; return new FileMetadata(val); } Ref AnalysisMergeConflict::GetSecondFile() { BNFileMetadata* val = BNAnalysisMergeConflictGetSecondFile(m_object); if (val == nullptr) return nullptr; return new FileMetadata(val); } Ref AnalysisMergeConflict::GetBaseSnapshot() { BNSnapshot* val = BNAnalysisMergeConflictGetBaseSnapshot(m_object); if (val == nullptr) return nullptr; return new Snapshot(val); } Ref AnalysisMergeConflict::GetFirstSnapshot() { BNSnapshot* val = BNAnalysisMergeConflictGetFirstSnapshot(m_object); if (val == nullptr) return nullptr; return new Snapshot(val); } Ref AnalysisMergeConflict::GetSecondSnapshot() { BNSnapshot* val = BNAnalysisMergeConflictGetSecondSnapshot(m_object); if (val == nullptr) return nullptr; return new Snapshot(val); } template <> std::any AnalysisMergeConflict::GetPathItem(const std::string& path) { void* val = BNAnalysisMergeConflictGetPathItem(m_object, path.c_str()); if (val == nullptr) throw SyncException(fmt::format("Failed to find merge conflict path item \"{}\"", path)); return *(std::any*)val; } template <> uint64_t AnalysisMergeConflict::GetPathItem(const std::string& path) { std::any anyVal = GetPathItem(path); try { return std::any_cast(anyVal); } catch (const std::exception& e) { throw SyncException(fmt::format( "Failed to cast merge conflict path item \"{}\" from \"{}\" to \"{}\": {}", path, anyVal.type().name(), typeid(uint64_t).name(), e.what() )); } } template <> std::string AnalysisMergeConflict::GetPathItem(const std::string& path) { char* val = BNAnalysisMergeConflictGetPathItemString(m_object, path.c_str()); if (val == nullptr) throw SyncException(fmt::format("Failed to find merge conflict path item \"{}\"", path)); std::string strVal = val; BNFreeString(val); return strVal; } template <> nlohmann::json AnalysisMergeConflict::GetPathItem(const std::string& path) { char* val = BNAnalysisMergeConflictGetPathItemSerialized(m_object, path.c_str()); if (val == nullptr) throw SyncException(fmt::format("Failed to find merge conflict path item \"{}\"", path)); std::string strVal = val; BNFreeString(val); return nlohmann::json::parse(strVal); } bool AnalysisMergeConflict::Success(std::nullopt_t value) { return BNAnalysisMergeConflictSuccess(m_object, nullptr); } bool AnalysisMergeConflict::Success(std::optional value) { return BNAnalysisMergeConflictSuccess(m_object, value.has_value() ? (*value)->dump().c_str() : nullptr); } bool AnalysisMergeConflict::Success(const std::optional& value) { return BNAnalysisMergeConflictSuccess(m_object, value.has_value() ? value->dump().c_str() : nullptr); } TypeArchiveMergeConflict::TypeArchiveMergeConflict(BNTypeArchiveMergeConflict* conflict) { m_object = conflict; } Ref TypeArchiveMergeConflict::GetTypeArchive() { BNTypeArchive* archive = BNTypeArchiveMergeConflictGetTypeArchive(m_object); if (archive == nullptr) return nullptr; return new TypeArchive(archive); } std::string TypeArchiveMergeConflict::GetTypeId() { char* val = BNTypeArchiveMergeConflictGetTypeId(m_object); std::string out = val; BNFreeString(val); return out; } std::string TypeArchiveMergeConflict::GetBaseSnapshotId() { char* val = BNTypeArchiveMergeConflictGetBaseSnapshotId(m_object); std::string out = val; BNFreeString(val); return out; } std::string TypeArchiveMergeConflict::GetFirstSnapshotId() { char* val = BNTypeArchiveMergeConflictGetFirstSnapshotId(m_object); std::string out = val; BNFreeString(val); return out; } std::string TypeArchiveMergeConflict::GetSecondSnapshotId() { char* val = BNTypeArchiveMergeConflictGetSecondSnapshotId(m_object); std::string out = val; BNFreeString(val); return out; } bool TypeArchiveMergeConflict::Success(const std::string& value) { return BNTypeArchiveMergeConflictSuccess(m_object, value.c_str()); } CollabChangeset::CollabChangeset(BNCollaborationChangeset* changeset) { m_object = changeset; } Ref CollabChangeset::GetDatabase() { BNDatabase* database = BNCollaborationChangesetGetDatabase(m_object); if (database == nullptr) return nullptr; return new Database(database); } Ref CollabChangeset::GetFile() { BNRemoteFile* file = BNCollaborationChangesetGetFile(m_object); if (file == nullptr) return nullptr; return new RemoteFile(file); } std::vector CollabChangeset::GetSnapshotIds() { size_t count = 0; int64_t* ids = BNCollaborationChangesetGetSnapshotIds(m_object, &count); std::vector result; result.insert(result.end(), ids, &ids[count]); delete[] ids; return result; } Ref CollabChangeset::GetAuthor() { BNCollaborationUser* author = BNCollaborationChangesetGetAuthor(m_object); if (author == nullptr) return nullptr; return new CollabUser(author); } std::string CollabChangeset::GetName() { char* val = BNCollaborationChangesetGetName(m_object); std::string out = val; BNFreeString(val); return out; } void CollabChangeset::SetName(const std::string& name) { BNCollaborationChangesetSetName(m_object, name.c_str()); } CollabSnapshot::CollabSnapshot(BNCollaborationSnapshot* snapshot) { m_object = snapshot; } Ref CollabSnapshot::GetFile() { BNRemoteFile* file = BNCollaborationSnapshotGetFile(m_object); if (file == nullptr) return nullptr; return new RemoteFile(file); } Ref CollabSnapshot::GetProject() { BNRemoteProject* project = BNCollaborationSnapshotGetProject(m_object); if (project == nullptr) return nullptr; return new RemoteProject(project); } Ref CollabSnapshot::GetRemote() { BNRemote* remote = BNCollaborationSnapshotGetRemote(m_object); if (remote == nullptr) return nullptr; return new Remote(remote); } std::string CollabSnapshot::GetUrl() { char* val = BNCollaborationSnapshotGetUrl(m_object); std::string out = val; BNFreeString(val); return out; } std::string CollabSnapshot::GetId() { char* val = BNCollaborationSnapshotGetId(m_object); std::string out = val; BNFreeString(val); return out; } std::string CollabSnapshot::GetName() { char* val = BNCollaborationSnapshotGetName(m_object); std::string out = val; BNFreeString(val); return out; } std::string CollabSnapshot::GetAuthor() { char* val = BNCollaborationSnapshotGetAuthor(m_object); std::string out = val; BNFreeString(val); return out; } int64_t CollabSnapshot::GetCreated() { return BNCollaborationSnapshotGetCreated(m_object); } int64_t CollabSnapshot::GetLastModified() { return BNCollaborationSnapshotGetLastModified(m_object); } std::string CollabSnapshot::GetHash() { char* val = BNCollaborationSnapshotGetHash(m_object); std::string out = val; BNFreeString(val); return out; } std::string CollabSnapshot::GetSnapshotFileHash() { char* val = BNCollaborationSnapshotGetSnapshotFileHash(m_object); std::string out = val; BNFreeString(val); return out; } bool CollabSnapshot::HasPulledUndoEntries() { return BNCollaborationSnapshotHasPulledUndoEntries(m_object); } bool CollabSnapshot::IsFinalized() { return BNCollaborationSnapshotIsFinalized(m_object); } std::vector CollabSnapshot::GetParentIds() { size_t count = 0; char** strs = BNCollaborationSnapshotGetParentIds(m_object, &count); std::vector result; result.reserve(count); for (size_t i = 0; i < count; i++) { result.push_back(strs[i]); } BNFreeStringList(strs, count); return result; } std::vector CollabSnapshot::GetChildIds() { size_t count = 0; char** strs = BNCollaborationSnapshotGetParentIds(m_object, &count); std::vector result; result.reserve(count); for (size_t i = 0; i < count; i++) { result.push_back(strs[i]); } BNFreeStringList(strs, count); return result; } uint64_t CollabSnapshot::GetAnalysisCacheBuildId() { return BNCollaborationSnapshotGetAnalysisCacheBuildId(m_object); } std::string CollabSnapshot::GetTitle() { char* val = BNCollaborationSnapshotGetTitle(m_object); std::string out = val; BNFreeString(val); return out; } std::string CollabSnapshot::GetDescription() { char* val = BNCollaborationSnapshotGetDescription(m_object); std::string out = val; BNFreeString(val); return out; } std::string CollabSnapshot::GetAuthorUsername() { char* val = BNCollaborationSnapshotGetAuthorUsername(m_object); std::string out = val; BNFreeString(val); return out; } std::vector> CollabSnapshot::GetParents() { size_t count = 0; BNCollaborationSnapshot** snapshots = BNCollaborationSnapshotGetParents(m_object, &count); std::vector> out; out.reserve(count); for (size_t i = 0; i < count; i++) { out.push_back(new CollabSnapshot(BNNewCollaborationSnapshotReference(snapshots[i]))); } BNFreeCollaborationSnapshotList(snapshots, count); return out; } std::vector> CollabSnapshot::GetChildren() { size_t count = 0; BNCollaborationSnapshot** snapshots = BNCollaborationSnapshotGetChildren(m_object, &count); std::vector> out; out.reserve(count); for (size_t i = 0; i < count; i++) { out.push_back(new CollabSnapshot(BNNewCollaborationSnapshotReference(snapshots[i]))); } BNFreeCollaborationSnapshotList(snapshots, count); return out; } std::vector> CollabSnapshot::GetUndoEntries() { size_t count = 0; BNCollaborationUndoEntry** entries = BNCollaborationSnapshotGetUndoEntries(m_object, &count); std::vector> out; out.reserve(count); for (size_t i = 0; i < count; i++) { out.push_back(new CollabUndoEntry(BNNewCollaborationUndoEntryReference(entries[i]))); } BNFreeCollaborationUndoEntryList(entries, count); return out; } Ref CollabSnapshot::GetUndoEntryById(uint64_t id) { BNCollaborationUndoEntry* entry = BNCollaborationSnapshotGetUndoEntryById(m_object, id); if (entry == nullptr) return nullptr; return new CollabUndoEntry(entry); } void CollabSnapshot::PullUndoEntries(ProgressFunction progress) { ProgressContext pctxt; pctxt.callback = progress; BNCollaborationSnapshotPullUndoEntries(m_object, ProgressCallback, &pctxt); } Ref CollabSnapshot::CreateUndoEntry(std::optional parent, std::string data) { BNCollaborationUndoEntry* entry = BNCollaborationSnapshotCreateUndoEntry(m_object, parent.has_value(), parent.has_value() ? *parent : 0, data.c_str()); if (entry == nullptr) return nullptr; return new CollabUndoEntry(entry); } void CollabSnapshot::Finalize() { BNCollaborationSnapshotFinalize(m_object); } std::vector CollabSnapshot::DownloadSnapshotFile(ProgressFunction progress) { ProgressContext pctxt; pctxt.callback = progress; size_t size = 0; uint8_t* data; if (!BNCollaborationSnapshotDownloadSnapshotFile(m_object, ProgressCallback, &pctxt, &data, &size)) throw SyncException("Failed to download snapshot file"); std::vector out; out.insert(out.end(), data, &data[size]); delete[] data; return out; } std::vector CollabSnapshot::Download(ProgressFunction progress) { ProgressContext pctxt; pctxt.callback = progress; size_t size = 0; uint8_t* data; if (!BNCollaborationSnapshotDownload(m_object, ProgressCallback, &pctxt, &data, &size)) throw SyncException("Failed to download snapshot"); std::vector out; out.insert(out.end(), data, &data[size]); delete[] data; return out; } std::vector CollabSnapshot::DownloadAnalysisCache(ProgressFunction progress) { ProgressContext pctxt; pctxt.callback = progress; size_t size = 0; uint8_t* data; if (!BNCollaborationSnapshotDownloadAnalysisCache(m_object, ProgressCallback, &pctxt, &data, &size)) throw SyncException("Failed to download snapshot"); std::vector out; out.insert(out.end(), data, &data[size]); delete[] data; return out; } CollabUndoEntry::CollabUndoEntry(BNCollaborationUndoEntry* entry) { m_object = entry; }