diff options
| author | Josh Ferrell <josh@vector35.com> | 2024-04-08 14:13:16 -0400 |
|---|---|---|
| committer | Josh Ferrell <josh@vector35.com> | 2024-05-13 15:06:53 -0400 |
| commit | 3c28d7e6eaa84041ec0fe5352a618759c13e6cb3 (patch) | |
| tree | d4115c3e663b30ea388c35add6e5fc7dbd835c11 /collaboration.cpp | |
| parent | 0ace079eb70b0c999914a1e95a3eb1324a3b19d8 (diff) | |
Move collaboration to core
Diffstat (limited to 'collaboration.cpp')
| -rw-r--r-- | collaboration.cpp | 2550 |
1 files changed, 2550 insertions, 0 deletions
diff --git a/collaboration.cpp b/collaboration.cpp new file mode 100644 index 00000000..3361890b --- /dev/null +++ b/collaboration.cpp @@ -0,0 +1,2550 @@ +// Copyright (c) 2015-2024 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> database) +{ + return BNCollaborationIsCollaborationDatabase(database->m_object); +} + + +Ref<Remote> BinaryNinja::Collaboration::GetRemoteForLocalDatabase(Ref<Database> 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<RemoteProject> BinaryNinja::Collaboration::GetRemoteProjectForLocalDatabase(Ref<Database> 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<RemoteFile> BinaryNinja::Collaboration::GetRemoteFileForLocalDatabase(Ref<Database> 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> database, Ref<RemoteFile> 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> 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> database, Ref<RemoteFile> 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> database) +{ + BNCollaborationDumpDatabase(database->m_object); +} + + +void BinaryNinja::Collaboration::IgnoreSnapshot(Ref<Database> database, Ref<Snapshot> snapshot) +{ + BNCollaborationIgnoreSnapshot(database->m_object, snapshot->m_object); +} + + +bool BinaryNinja::Collaboration::IsSnapshotIgnored(Ref<Database> database, Ref<Snapshot> snapshot) +{ + return BNCollaborationIsSnapshotIgnored(database->m_object, snapshot->m_object); +} + + +Ref<CollabSnapshot> BinaryNinja::Collaboration::GetRemoteSnapshotFromLocal(Ref<Snapshot> 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<Snapshot> BinaryNinja::Collaboration::GetLocalSnapshotFromRemote(Ref<CollabSnapshot> snapshot, Ref<Database> 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<TypeArchive> archive) +{ + return BNCollaborationIsCollaborationTypeArchive(archive->m_object); +} + + +Ref<Remote> BinaryNinja::Collaboration::GetRemoteForLocalTypeArchive(Ref<TypeArchive> archive) +{ + BNRemote* val = BNCollaborationGetRemoteForLocalTypeArchive(archive->m_object); + if (val == nullptr) + return nullptr; + return new Remote(val); +} + + +Ref<RemoteProject> BinaryNinja::Collaboration::GetRemoteProjectForLocalTypeArchive(Ref<TypeArchive> archive) +{ + BNRemoteProject* val = BNCollaborationGetRemoteProjectForLocalTypeArchive(archive->m_object); + if (val == nullptr) + return nullptr; + return new RemoteProject(val); +} + + +Ref<RemoteFile> BinaryNinja::Collaboration::GetRemoteFileForLocalTypeArchive(Ref<TypeArchive> archive) +{ + BNRemoteFile* val = BNCollaborationGetRemoteFileForLocalTypeArchive(archive->m_object); + if (val == nullptr) + return nullptr; + return new RemoteFile(val); +} + + +Ref<CollabSnapshot> BinaryNinja::Collaboration::GetRemoteSnapshotFromLocalTypeArchive(Ref<TypeArchive> 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<std::string> BinaryNinja::Collaboration::GetLocalSnapshotFromRemoteTypeArchive(Ref<CollabSnapshot> snapshot, Ref<TypeArchive> 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<TypeArchive> archive, const std::string& snapshot) +{ + return BNCollaborationIsTypeArchiveSnapshotIgnored(archive->m_object, snapshot.c_str()); +} + + +Ref<TypeArchive> BinaryNinja::Collaboration::DownloadTypeArchive(Ref<RemoteFile> 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<RemoteFile> BinaryNinja::Collaboration::UploadTypeArchive(Ref<TypeArchive> archive, Ref<RemoteProject> project, Ref<RemoteFolder> folder, ProgressFunction progress, Ref<ProjectFile> 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<TypeArchive> archive, Ref<RemoteFile> 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<TypeArchive> archive, Ref<RemoteFile> file, std::function<bool(const std::vector<Ref<TypeArchiveMergeConflict>>)> 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<RemoteFile> 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> database, Ref<Snapshot> snapshot, const std::string& author) +{ + BNCollaborationSetSnapshotAuthor(database->m_object, snapshot->m_object, author.c_str()); +} + + +Ref<Remote> BinaryNinja::Collaboration::GetActiveRemote() +{ + BNRemote* remote = BNCollaborationGetActiveRemote(); + if (remote == nullptr) + return nullptr; + return new Remote(remote); +} + + +void BinaryNinja::Collaboration::SetActiveRemote(Ref<Remote> remote) +{ + BNCollaborationSetActiveRemote(remote ? remote->m_object : nullptr); +} + + +bool BinaryNinja::Collaboration::StoreDataInKeychain(const std::string& key, const std::map<std::string, std::string>& 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<std::map<std::string, std::string>> 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<std::string, std::string> 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<Ref<Remote>> BinaryNinja::Collaboration::GetRemotes() +{ + size_t count = 0; + BNRemote** remotes = BNCollaborationGetRemotes(&count); + std::vector<Ref<Remote>> 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<Remote> BinaryNinja::Collaboration::GetRemoteById(const std::string& remoteId) +{ + BNRemote* remote = BNCollaborationGetRemoteById(remoteId.c_str()); + if (!remote) + return nullptr; + return new Remote(remote); +} + + +Ref<Remote> BinaryNinja::Collaboration::GetRemoteByAddress(const std::string& remoteAddress) +{ + BNRemote* remote = BNCollaborationGetRemoteByAddress(remoteAddress.c_str()); + if (!remote) + return nullptr; + return new Remote(remote); +} + + +Ref<Remote> BinaryNinja::Collaboration::GetRemoteByName(const std::string& name) +{ + BNRemote* remote = BNCollaborationGetRemoteByName(name.c_str()); + if (!remote) + return nullptr; + return new Remote(remote); +} + + +Ref<Remote> 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>& remote) +{ + BNCollaborationRemoveRemote(remote->m_object); +} + + +bool BinaryNinja::Collaboration::DatabaseConflictHandlerCallback(void* ctxt, const char** keys, BNAnalysisMergeConflict** conflicts, size_t count) +{ + DatabaseConflictHandlerContext* chctxt = reinterpret_cast<DatabaseConflictHandlerContext*>(ctxt); + if (!chctxt->callback) + return true; + std::unordered_map<std::string, Ref<AnalysisMergeConflict>> 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<TypeArchiveConflictHandlerContext*>(ctxt); + if (!chctxt->callback) + return true; + std::vector<Ref<TypeArchiveMergeConflict>> conflictVec; + 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<NameChangesetContext*>(ctxt); + if (!ncctxt->callback) + return true; + return ncctxt->callback(new CollabChangeset(changeset)); +}; + + +void BinaryNinja::Collaboration::SyncDatabase(Ref<Database> database, Ref<RemoteFile> file, std::function<bool(const std::unordered_map<std::string, Ref<AnalysisMergeConflict>>& conflicts)> conflictHandler, std::function<bool(size_t, size_t)> 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<TypeArchive> archive, Ref<RemoteFile> file, std::function<bool(const std::vector<Ref<TypeArchiveMergeConflict>>& 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<Snapshot> BinaryNinja::Collaboration::MergeSnapshots(Ref<Snapshot> first, Ref<Snapshot> second, std::function<bool(const std::unordered_map<std::string, Ref<AnalysisMergeConflict>>& 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<RemoteProject> project) +{ + char* path = BNCollaborationDefaultProjectPath(project->m_object); + std::string result = path; + BNFreeString(path); + return result; +} + + +std::string BinaryNinja::Collaboration::DefaultFilePath(Ref<RemoteFile> file) +{ + char* path = BNCollaborationDefaultFilePath(file->m_object); + std::string result = path; + BNFreeString(path); + return result; +} + + +Ref<FileMetadata> BinaryNinja::Collaboration::DownloadFile(Ref<RemoteFile> 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<RemoteFile> BinaryNinja::Collaboration::UploadDatabase(Ref<FileMetadata> metadata, Ref<RemoteProject> project, Ref<RemoteFolder> 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<Snapshot> localSnapshot, Ref<CollabSnapshot> 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::GetServerBuildId() +{ + char* buildId = BNRemoteGetServerBuildId(m_object); + std::string result = buildId; + BNFreeString(buildId); + return result; +} + + +std::vector<std::pair<std::string, std::string>> 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<std::pair<std::string, std::string>> results; + 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()); + 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<Ref<RemoteProject>> Remote::GetProjects() +{ + size_t count = 0; + BNRemoteProject** projects = BNRemoteGetProjects(m_object, &count); + std::vector<Ref<RemoteProject>> 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<RemoteProject> Remote::GetProjectById(const std::string& id) +{ + BNRemoteProject* project = BNRemoteGetProjectById(m_object, id.c_str()); + if (project == nullptr) + return nullptr; + return new RemoteProject(project); +} + + +Ref<RemoteProject> 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(std::function<bool(size_t, size_t)> progress) +{ + ProgressContext pctxt; + pctxt.callback = progress; + BNRemotePullProjects(m_object, ProgressCallback, &pctxt); +} + + +Ref<RemoteProject> 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<RemoteProject> Remote::ImportLocalProject(Ref<Project> localProject, std::function<bool(size_t, size_t)> 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<RemoteProject> project, const std::vector<std::pair<std::string, std::string>>& 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<RemoteProject> project) +{ + BNRemoteDeleteProject(m_object, project->m_object); +} + + +std::vector<Ref<CollabGroup>> Remote::GetGroups() +{ + size_t count = 0; + BNCollaborationGroup** groups = BNRemoteGetGroups(m_object, &count); + std::vector<Ref<CollabGroup>> 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<CollabGroup> Remote::GetGroupById(uint64_t id) +{ + BNCollaborationGroup* group = BNRemoteGetGroupById(m_object, id); + if (group == nullptr) + return nullptr; + return new CollabGroup(group); +} + + +Ref<CollabGroup> 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<std::pair<uint64_t, std::string>> 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<std::pair<uint64_t, std::string>> results; + 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(std::function<bool(size_t, size_t)> progress) +{ + ProgressContext pctxt; + pctxt.callback = progress; + BNRemotePullGroups(m_object, ProgressCallback, &pctxt); +} + + +Ref<CollabGroup> Remote::CreateGroup(const std::string& name, const std::vector<std::string>& 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<CollabGroup> group, const std::vector<std::pair<std::string, std::string>>& 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<CollabGroup> group) +{ + BNRemoteDeleteGroup(m_object, group->m_object); +} + + +std::vector<Ref<CollabUser>> Remote::GetUsers() +{ + size_t count = 0; + BNCollaborationUser** users = BNRemoteGetUsers(m_object, &count); + std::vector<Ref<CollabUser>> 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<CollabUser> Remote::GetUserById(const std::string& id) +{ + BNCollaborationUser* user = BNRemoteGetUserById(m_object, id.c_str()); + if (user == nullptr) + return nullptr; + return new CollabUser(user); +} + + +Ref<CollabUser> Remote::GetUserByUsername(const std::string& username) +{ + BNCollaborationUser* user = BNRemoteGetUserByUsername(m_object, username.c_str()); + if (user == nullptr) + return nullptr; + return new CollabUser(user); +} + + +Ref<CollabUser> Remote::GetCurrentUser() +{ + BNCollaborationUser* user = BNRemoteGetCurrentUser(m_object); + if (user == nullptr) + return nullptr; + return new CollabUser(user); +} + + +std::vector<std::pair<std::string, std::string>> 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<std::pair<std::string, std::string>> results; + for (size_t i = 0; i < count; i++) + { + results.push_back({ids[i], names[i]}); + } + + BNFreeStringList(ids, count); + BNFreeStringList(names, count); + + return results; +} + + +void Remote::PullUsers(std::function<bool(size_t, size_t)> progress) +{ + ProgressContext pctxt; + pctxt.callback = progress; + BNRemotePullUsers(m_object, ProgressCallback, &pctxt); +} + + +Ref<CollabUser> Remote::CreateUser(const std::string& username, const std::string& email, bool is_active, const std::string& password, const std::vector<uint64_t>& groupIds, const std::vector<uint64_t>& 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<CollabUser> user, const std::vector<std::pair<std::string, std::string>>& 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<std::string>& 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<Remote> 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<Project> 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(std::function<bool(size_t, size_t)> progress) +{ + ProgressContext pctxt; + pctxt.callback = progress; + return BNRemoteProjectOpen(m_object, ProgressCallback, &pctxt); +} + + +void RemoteProject::Close() +{ + BNRemoteProjectClose(m_object); +} + + +Ref<Remote> 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<Ref<RemoteFile>> RemoteProject::GetFiles() +{ + size_t count; + BNRemoteFile** files = BNRemoteProjectGetFiles(m_object, &count); + + std::vector<Ref<RemoteFile>> 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<Ref<RemoteFolder>> RemoteProject::GetFolders() +{ + size_t count; + BNRemoteFolder** folders = BNRemoteProjectGetFolders(m_object, &count); + + std::vector<Ref<RemoteFolder>> 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<RemoteFile> RemoteProject::GetFileById(const std::string& id) +{ + BNRemoteFile* file = BNRemoteProjectGetFileById(m_object, id.c_str()); + if (file == nullptr) + return nullptr; + return new RemoteFile(file); +} + + +Ref<RemoteFile> 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(std::function<bool(size_t, size_t)> progress) +{ + ProgressContext pctxt; + pctxt.callback = progress; + BNRemoteProjectPullFiles(m_object, ProgressCallback, &pctxt); +} + + +void RemoteProject::PullFolders(std::function<bool(size_t, size_t)> progress) +{ + ProgressContext pctxt; + pctxt.callback = progress; + + BNRemoteProjectPullFolders(m_object, ProgressCallback, &pctxt); +} + + +Ref<RemoteFile> RemoteProject::CreateFile(const std::string& filename, std::vector<uint8_t>& contents, const std::string& name, const std::string& description, Ref<RemoteFolder> folder, BNRemoteFileType type, std::function<bool(size_t, size_t)> progress, Ref<ProjectFile> 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<RemoteFolder> RemoteProject::CreateFolder(const std::string& name, const std::string& description, Ref<RemoteFolder> parent, std::function<bool(size_t, size_t)> progress, Ref<ProjectFolder> 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<RemoteFile> file, const std::vector<std::pair<std::string, std::string>>& 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<RemoteFolder> folder, const std::vector<std::pair<std::string, std::string>>& 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<RemoteFolder> folder) +{ + BNRemoteProjectDeleteFolder(m_object, folder->m_object); +} + + +void RemoteProject::DeleteFile(const Ref<RemoteFile> file) +{ + BNRemoteProjectDeleteFile(m_object, file->m_object); +} + + +Ref<RemoteFolder> 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<Ref<CollabPermission>> RemoteProject::GetGroupPermissions() +{ + size_t count; + BNCollaborationPermission** perms = BNRemoteProjectGetGroupPermissions(m_object, &count); + + std::vector<Ref<CollabPermission>> 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<Ref<CollabPermission>> RemoteProject::GetUserPermissions() +{ + size_t count; + BNCollaborationPermission** perms = BNRemoteProjectGetUserPermissions(m_object, &count); + + std::vector<Ref<CollabPermission>> 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<CollabPermission> 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(std::function<bool(size_t, size_t)> progress) +{ + ProgressContext pctxt; + pctxt.callback = progress; + BNRemoteProjectPullGroupPermissions(m_object, ProgressCallback, &pctxt); +} + + +void RemoteProject::PullUserPermissions(std::function<bool(size_t, size_t)> progress) +{ + ProgressContext pctxt; + pctxt.callback = progress; + BNRemoteProjectPullUserPermissions(m_object, ProgressCallback, &pctxt); +} + + +Ref<CollabPermission> RemoteProject::CreateGroupPermission(int groupId, BNCollaborationPermissionLevel level, std::function<bool(size_t, size_t)> 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<CollabPermission> RemoteProject::CreateUserPermission(const std::string& userId, BNCollaborationPermissionLevel level, std::function<bool(size_t, size_t)> 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<CollabPermission> permission, const std::vector<std::pair<std::string, std::string>>& 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<CollabPermission> 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<ProjectFile> RemoteFile::GetCoreFile() +{ + BNProjectFile* res = BNRemoteFileGetCoreFile(m_object); + if (!res) + return nullptr; + return new ProjectFile(res); +} + + +Ref<RemoteProject> RemoteFile::GetProject() +{ + BNRemoteProject* res = BNRemoteFileGetProject(m_object); + if (!res) + return nullptr; + return new RemoteProject(res); +} + + +Ref<RemoteFolder> RemoteFile::GetFolder() +{ + BNRemoteFolder* res = BNRemoteFileGetFolder(m_object); + if (!res) + return nullptr; + return new RemoteFolder(res); +} + + +Ref<Remote> 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<RemoteFolder>& folder) +{ + BNRemoteFileSetFolder(m_object, folder ? folder->m_object : nullptr); +} + + +void RemoteFile::SetMetadata(const std::string& metadata) +{ + BNRemoteFileSetMetadata(m_object, metadata.c_str()); +} + + +std::vector<Ref<CollabSnapshot>> RemoteFile::GetSnapshots() +{ + size_t count = 0; + BNCollaborationSnapshot** collabSnapshots = BNRemoteFileGetSnapshots(m_object, &count); + std::vector<Ref<CollabSnapshot>> 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<CollabSnapshot> 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(std::function<bool(size_t, size_t)> progress) +{ + ProgressContext pctxt; + pctxt.callback = progress; + BNRemoteFilePullSnapshots(m_object, ProgressCallback, &pctxt); +} + + +Ref<CollabSnapshot> RemoteFile::CreateSnapshot(std::string name, std::vector<uint8_t> contents, std::vector<uint8_t> analysisCacheContents, std::optional<std::vector<uint8_t>> fileContents, std::vector<std::string> parentIds, std::function<bool(size_t, size_t)> 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<CollabSnapshot> snapshot) +{ + BNRemoteFileDeleteSnapshot(m_object, snapshot->m_object); +} + + +std::vector<uint8_t> RemoteFile::Download(std::function<bool(size_t, size_t)> progress) +{ + ProgressContext pctxt; + pctxt.callback = progress; + size_t size = 0; + uint8_t* data; + if (!BNRemoteFileDownload(m_object, ProgressCallback, &pctxt, &data, &size)) + throw SyncException("Failed to download file"); + + std::vector<uint8_t> 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<Json::CharReader> 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<Json::CharReader> 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; +} + + +CollabPermission::CollabPermission(BNCollaborationPermission* permission) +{ + m_object = permission; +} + + +Ref<RemoteProject> CollabPermission::GetProject() +{ + BNRemoteProject* project = BNCollaborationPermissionGetProject(m_object); + if (project == nullptr) + return nullptr; + return new RemoteProject(project); +} + + +Ref<Remote> 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<std::string> BinaryNinja::Collaboration::GetSnapshotAuthor(Ref<Database> database, Ref<Snapshot> 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<nlohmann::json> AnalysisMergeConflict::GetBase() +{ + char* val = BNAnalysisMergeConflictGetBase(m_object); + if (val == nullptr) + return {}; + return nlohmann::json::parse(val); + BNFreeString(val); +} + + +std::optional<nlohmann::json> AnalysisMergeConflict::GetFirst() +{ + char* val = BNAnalysisMergeConflictGetFirst(m_object); + if (val == nullptr) + return {}; + return nlohmann::json::parse(val); + BNFreeString(val); +} + + +std::optional<nlohmann::json> AnalysisMergeConflict::GetSecond() +{ + char* val = BNAnalysisMergeConflictGetSecond(m_object); + if (val == nullptr) + return {}; + return nlohmann::json::parse(val); + BNFreeString(val); +} + + +Ref<FileMetadata> AnalysisMergeConflict::GetBaseFile() +{ + BNFileMetadata* val = BNAnalysisMergeConflictGetBaseFile(m_object); + if (val == nullptr) + return nullptr; + return new FileMetadata(val); +} + + +Ref<FileMetadata> AnalysisMergeConflict::GetFirstFile() +{ + BNFileMetadata* val = BNAnalysisMergeConflictGetFirstFile(m_object); + if (val == nullptr) + return nullptr; + return new FileMetadata(val); +} + + +Ref<FileMetadata> AnalysisMergeConflict::GetSecondFile() +{ + BNFileMetadata* val = BNAnalysisMergeConflictGetSecondFile(m_object); + if (val == nullptr) + return nullptr; + return new FileMetadata(val); +} + + +Ref<Snapshot> AnalysisMergeConflict::GetBaseSnapshot() +{ + BNSnapshot* val = BNAnalysisMergeConflictGetBaseSnapshot(m_object); + if (val == nullptr) + return nullptr; + return new Snapshot(val); +} + + +Ref<Snapshot> AnalysisMergeConflict::GetFirstSnapshot() +{ + BNSnapshot* val = BNAnalysisMergeConflictGetFirstSnapshot(m_object); + if (val == nullptr) + return nullptr; + return new Snapshot(val); +} + + +Ref<Snapshot> AnalysisMergeConflict::GetSecondSnapshot() +{ + BNSnapshot* val = BNAnalysisMergeConflictGetSecondSnapshot(m_object); + if (val == nullptr) + return nullptr; + return new Snapshot(val); +} + + +std::any AnalysisMergeConflict::GetPathItem(const std::string& path) +{ + void* val = BNAnalysisMergeConflictGetPathItem(m_object, path.c_str()); + if (val == nullptr) + return {}; + return *(std::any*)val; +} + + +bool AnalysisMergeConflict::Success(std::nullopt_t value) +{ + return BNAnalysisMergeConflictSuccess(m_object, nullptr); +} + + +bool AnalysisMergeConflict::Success(std::optional<const nlohmann::json*> value) +{ + return BNAnalysisMergeConflictSuccess(m_object, value.has_value() ? (*value)->dump().c_str() : nullptr); +} + + +bool AnalysisMergeConflict::Success(const std::optional<nlohmann::json>& value) +{ + return BNAnalysisMergeConflictSuccess(m_object, value.has_value() ? value->dump().c_str() : nullptr); +} + + +TypeArchiveMergeConflict::TypeArchiveMergeConflict(BNTypeArchiveMergeConflict* conflict) +{ + m_object = conflict; +} + + +Ref<TypeArchive> 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<Database> CollabChangeset::GetDatabase() +{ + BNDatabase* database = BNCollaborationChangesetGetDatabase(m_object); + if (database == nullptr) + return nullptr; + return new Database(database); +} + + +Ref<RemoteFile> CollabChangeset::GetFile() +{ + BNRemoteFile* file = BNCollaborationChangesetGetFile(m_object); + if (file == nullptr) + return nullptr; + return new RemoteFile(file); +} + + +std::vector<int64_t> CollabChangeset::GetSnapshotIds() +{ + size_t count = 0; + int64_t* ids = BNCollaborationChangesetGetSnapshotIds(m_object, &count); + std::vector<int64_t> result; + result.insert(result.end(), ids, &ids[count]); + delete[] ids; + return result; +} + + +Ref<CollabUser> 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<RemoteFile> CollabSnapshot::GetFile() +{ + BNRemoteFile* file = BNCollaborationSnapshotGetFile(m_object); + if (file == nullptr) + return nullptr; + return new RemoteFile(file); +} + + +Ref<RemoteProject> CollabSnapshot::GetProject() +{ + BNRemoteProject* project = BNCollaborationSnapshotGetProject(m_object); + if (project == nullptr) + return nullptr; + return new RemoteProject(project); +} + + +Ref<Remote> 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<std::string> CollabSnapshot::GetParentIds() +{ + size_t count = 0; + char** strs = BNCollaborationSnapshotGetParentIds(m_object, &count); + std::vector<std::string> result; + for (size_t i = 0; i < count; i++) + { + result.push_back(strs[i]); + } + BNFreeStringList(strs, count); + return result; +} + + +std::vector<std::string> CollabSnapshot::GetChildIds() +{ + size_t count = 0; + char** strs = BNCollaborationSnapshotGetParentIds(m_object, &count); + std::vector<std::string> result; + 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<Ref<CollabSnapshot>> CollabSnapshot::GetParents() +{ + size_t count = 0; + BNCollaborationSnapshot** snapshots = BNCollaborationSnapshotGetParents(m_object, &count); + std::vector<Ref<CollabSnapshot>> 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<Ref<CollabSnapshot>> CollabSnapshot::GetChildren() +{ + size_t count = 0; + BNCollaborationSnapshot** snapshots = BNCollaborationSnapshotGetChildren(m_object, &count); + std::vector<Ref<CollabSnapshot>> 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<Ref<CollabUndoEntry>> CollabSnapshot::GetUndoEntries() +{ + size_t count = 0; + BNCollaborationUndoEntry** entries = BNCollaborationSnapshotGetUndoEntries(m_object, &count); + std::vector<Ref<CollabUndoEntry>> 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<CollabUndoEntry> CollabSnapshot::GetUndoEntryById(uint64_t id) +{ + BNCollaborationUndoEntry* entry = BNCollaborationSnapshotGetUndoEntryById(m_object, id); + if (entry == nullptr) + return nullptr; + return new CollabUndoEntry(entry); +} + + +void CollabSnapshot::PullUndoEntries(std::function<bool(size_t, size_t)> progress) +{ + ProgressContext pctxt; + pctxt.callback = progress; + BNCollaborationSnapshotPullUndoEntries(m_object, ProgressCallback, &pctxt); +} + + +Ref<CollabUndoEntry> CollabSnapshot::CreateUndoEntry(std::optional<uint64_t> 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<uint8_t> CollabSnapshot::DownloadSnapshotFile(std::function<bool(size_t, size_t)> 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<uint8_t> out; + out.insert(out.end(), data, &data[size]); + delete[] data; + return out; +} + + +std::vector<uint8_t> CollabSnapshot::Download(std::function<bool(size_t, size_t)> 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<uint8_t> out; + out.insert(out.end(), data, &data[size]); + delete[] data; + return out; +} + + +std::vector<uint8_t> CollabSnapshot::DownloadAnalysisCache(std::function<bool(size_t, size_t)> 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<uint8_t> out; + out.insert(out.end(), data, &data[size]); + delete[] data; + return out; +} + + +CollabUndoEntry::CollabUndoEntry(BNCollaborationUndoEntry* entry) +{ + m_object = entry; +} + |
