summaryrefslogtreecommitdiffstats
path: root/xbmc/addons/VFSEntry.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--xbmc/addons/VFSEntry.cpp770
1 files changed, 770 insertions, 0 deletions
diff --git a/xbmc/addons/VFSEntry.cpp b/xbmc/addons/VFSEntry.cpp
new file mode 100644
index 0000000..063ba25
--- /dev/null
+++ b/xbmc/addons/VFSEntry.cpp
@@ -0,0 +1,770 @@
+/*
+ * Copyright (C) 2013 Arne Morten Kvarving
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * See LICENSES/README.md for more information.
+ */
+
+#include "VFSEntry.h"
+
+#include "ServiceBroker.h"
+#include "URL.h"
+#include "addons/AddonEvents.h"
+#include "addons/AddonManager.h"
+#include "addons/addoninfo/AddonInfo.h"
+#include "addons/addoninfo/AddonType.h"
+#include "addons/interfaces/Filesystem.h"
+#include "network/ZeroconfBrowser.h"
+#include "utils/StringUtils.h"
+#include "utils/log.h"
+
+#include <mutex>
+#include <utility>
+
+#if defined(TARGET_WINDOWS)
+#ifndef S_IFLNK
+#define S_IFLNK 0120000
+#endif
+#ifndef S_IFBLK
+#define S_IFBLK 0
+#endif
+#ifndef S_IFSOCK
+#define S_IFSOCK 0
+#endif
+#ifndef S_IFREG
+#define S_IFREG _S_IFREG
+#endif
+#ifndef S_IFCHR
+#define S_IFCHR _S_IFCHR
+#endif
+#ifndef S_IFDIR
+#define S_IFDIR _S_IFDIR
+#endif
+#ifndef S_IFIFO
+#define S_IFIFO _S_IFIFO
+#endif
+#endif
+
+namespace ADDON
+{
+
+CVFSAddonCache::~CVFSAddonCache()
+{
+ Deinit();
+}
+
+void CVFSAddonCache::Init()
+{
+ CServiceBroker::GetAddonMgr().Events().Subscribe(this, &CVFSAddonCache::OnEvent);
+
+ // Load all available VFS addons during Kodi start
+ std::vector<AddonInfoPtr> addonInfos;
+ CServiceBroker::GetAddonMgr().GetAddonInfos(addonInfos, true, AddonType::VFS);
+
+ std::unique_lock<CCriticalSection> lock(m_critSection);
+ for (const auto& addonInfo : addonInfos)
+ {
+ VFSEntryPtr vfs = std::make_shared<CVFSEntry>(addonInfo);
+ vfs->Addon()->RegisterInformer(this);
+
+ m_addonsInstances.emplace_back(vfs);
+
+ if (!vfs->GetZeroconfType().empty())
+ CZeroconfBrowser::GetInstance()->AddServiceType(vfs->GetZeroconfType());
+ }
+}
+
+void CVFSAddonCache::Deinit()
+{
+ CServiceBroker::GetAddonMgr().Events().Unsubscribe(this);
+}
+
+const std::vector<VFSEntryPtr> CVFSAddonCache::GetAddonInstances()
+{
+ std::unique_lock<CCriticalSection> lock(m_critSection);
+ return m_addonsInstances;
+}
+
+VFSEntryPtr CVFSAddonCache::GetAddonInstance(const std::string& strId)
+{
+ VFSEntryPtr addon;
+
+ std::unique_lock<CCriticalSection> lock(m_critSection);
+
+ const auto& itAddon = std::find_if(m_addonsInstances.begin(), m_addonsInstances.end(),
+ [&strId](const VFSEntryPtr& addon)
+ {
+ return addon->ID() == strId;
+ });
+
+ if (itAddon != m_addonsInstances.end())
+ addon = *itAddon;
+
+ return addon;
+}
+
+void CVFSAddonCache::OnEvent(const AddonEvent& event)
+{
+ if (typeid(event) == typeid(AddonEvents::Disabled))
+ {
+ for (const auto& vfs : m_addonsInstances)
+ {
+ if (vfs->ID() == event.addonId && !vfs->GetZeroconfType().empty())
+ CZeroconfBrowser::GetInstance()->RemoveServiceType(vfs->GetZeroconfType());
+ }
+ }
+
+ if (typeid(event) == typeid(AddonEvents::Enabled) ||
+ typeid(event) == typeid(AddonEvents::Disabled) ||
+ typeid(event) == typeid(AddonEvents::ReInstalled))
+ {
+ if (CServiceBroker::GetAddonMgr().HasType(event.addonId, AddonType::VFS))
+ Update(event.addonId);
+ }
+ else if (typeid(event) == typeid(AddonEvents::UnInstalled))
+ {
+ Update(event.addonId);
+ }
+}
+
+bool CVFSAddonCache::IsInUse(const std::string& id)
+{
+ std::unique_lock<CCriticalSection> lock(m_critSection);
+
+ const auto& itAddon = std::find_if(m_addonsInstances.begin(), m_addonsInstances.end(),
+ [&id](const VFSEntryPtr& addon) { return addon->ID() == id; });
+ if (itAddon != m_addonsInstances.end() && (*itAddon).use_count() > 1)
+ return true;
+ return false;
+}
+
+void CVFSAddonCache::Update(const std::string& id)
+{
+ std::vector<VFSEntryPtr> addonmap;
+
+ // Stop used instance if present, otherwise the new becomes created on already created addon base one.
+ {
+ std::unique_lock<CCriticalSection> lock(m_critSection);
+
+ const auto& itAddon =
+ std::find_if(m_addonsInstances.begin(), m_addonsInstances.end(),
+ [&id](const VFSEntryPtr& addon) { return addon->ID() == id; });
+
+ if (itAddon != m_addonsInstances.end())
+ {
+ (*itAddon)->Addon()->RegisterInformer(nullptr);
+ m_addonsInstances.erase(itAddon);
+ }
+ }
+
+ // Create and init the new VFS addon instance
+ AddonInfoPtr addonInfo = CServiceBroker::GetAddonMgr().GetAddonInfo(id, AddonType::VFS);
+ if (addonInfo && !CServiceBroker::GetAddonMgr().IsAddonDisabled(id))
+ {
+ VFSEntryPtr vfs = std::make_shared<CVFSEntry>(addonInfo);
+
+ if (!vfs->GetZeroconfType().empty())
+ CZeroconfBrowser::GetInstance()->AddServiceType(vfs->GetZeroconfType());
+
+ std::unique_lock<CCriticalSection> lock(m_critSection);
+ m_addonsInstances.emplace_back(vfs);
+ }
+}
+
+class CVFSURLWrapper
+{
+ public:
+ explicit CVFSURLWrapper(const CURL& url2)
+ {
+ m_strings.push_back(url2.Get());
+ m_strings.push_back(url2.GetDomain());
+ m_strings.push_back(url2.GetHostName());
+ m_strings.push_back(url2.GetFileName());
+ m_strings.push_back(url2.GetOptions());
+ m_strings.push_back(url2.GetUserName());
+ m_strings.push_back(url2.GetPassWord());
+ m_strings.push_back(url2.GetRedacted());
+ m_strings.push_back(url2.GetShareName());
+ m_strings.push_back(url2.GetProtocol());
+
+ url.url = m_strings[0].c_str();
+ url.domain = m_strings[1].c_str();
+ url.hostname = m_strings[2].c_str();
+ url.filename = m_strings[3].c_str();
+ url.port = url2.GetPort();
+ url.options = m_strings[4].c_str();
+ url.username = m_strings[5].c_str();
+ url.password = m_strings[6].c_str();
+ url.redacted = m_strings[7].c_str();
+ url.sharename = m_strings[8].c_str();
+ url.protocol = m_strings[9].c_str();
+ }
+
+ VFSURL url;
+ protected:
+ std::vector<std::string> m_strings;
+};
+
+CVFSEntry::ProtocolInfo::ProtocolInfo(const AddonInfoPtr& addonInfo)
+ : supportPath(addonInfo->Type(AddonType::VFS)->GetValue("@supportPath").asBoolean()),
+ supportUsername(addonInfo->Type(AddonType::VFS)->GetValue("@supportUsername").asBoolean()),
+ supportPassword(addonInfo->Type(AddonType::VFS)->GetValue("@supportPassword").asBoolean()),
+ supportPort(addonInfo->Type(AddonType::VFS)->GetValue("@supportPort").asBoolean()),
+ supportBrowsing(addonInfo->Type(AddonType::VFS)->GetValue("@supportBrowsing").asBoolean()),
+ supportWrite(addonInfo->Type(AddonType::VFS)->GetValue("@supportWrite").asBoolean()),
+ defaultPort(addonInfo->Type(AddonType::VFS)->GetValue("@defaultPort").asInteger()),
+ type(addonInfo->Type(AddonType::VFS)->GetValue("@protocols").asString()),
+ label(addonInfo->Type(AddonType::VFS)->GetValue("@label").asInteger())
+{
+}
+
+CVFSEntry::CVFSEntry(const AddonInfoPtr& addonInfo)
+ : IAddonInstanceHandler(ADDON_INSTANCE_VFS, addonInfo),
+ m_protocols(addonInfo->Type(AddonType::VFS)->GetValue("@protocols").asString()),
+ m_extensions(addonInfo->Type(AddonType::VFS)->GetValue("@extensions").asString()),
+ m_zeroconf(addonInfo->Type(AddonType::VFS)->GetValue("@zeroconf").asString()),
+ m_files(addonInfo->Type(AddonType::VFS)->GetValue("@files").asBoolean()),
+ m_directories(addonInfo->Type(AddonType::VFS)->GetValue("@directories").asBoolean()),
+ m_filedirectories(addonInfo->Type(AddonType::VFS)->GetValue("@filedirectories").asBoolean()),
+ m_protocolInfo(addonInfo)
+{
+ if (!addonInfo->Type(AddonType::VFS)->GetValue("@supportDialog").asBoolean())
+ m_protocolInfo.type.clear();
+
+ // Create "C" interface structures, used as own parts to prevent API problems on update
+ m_ifc.vfs = new AddonInstance_VFSEntry;
+ m_ifc.vfs->props = new AddonProps_VFSEntry();
+ m_ifc.vfs->toAddon = new KodiToAddonFuncTable_VFSEntry();
+ m_ifc.vfs->toKodi = new AddonToKodiFuncTable_VFSEntry();
+
+ m_ifc.vfs->toKodi->kodiInstance = this;
+ if (CreateInstance() != ADDON_STATUS_OK)
+ CLog::Log(LOGFATAL, "CVFSEntry - Couldn't create instance on add-on '{}'", addonInfo->Name());
+}
+
+CVFSEntry::~CVFSEntry()
+{
+ DestroyInstance();
+
+ // Delete "C" interface structures
+ delete m_ifc.vfs->toAddon;
+ delete m_ifc.vfs->toKodi;
+ delete m_ifc.vfs->props;
+ delete m_ifc.vfs;
+}
+
+void* CVFSEntry::Open(const CURL& url)
+{
+ if (!m_ifc.vfs->toAddon->open)
+ return nullptr;
+
+ CVFSURLWrapper url2(url);
+ return m_ifc.vfs->toAddon->open(m_ifc.vfs, &url2.url);
+}
+
+void* CVFSEntry::OpenForWrite(const CURL& url, bool bOverWrite)
+{
+ if (!m_ifc.vfs->toAddon->open_for_write)
+ return nullptr;
+
+ CVFSURLWrapper url2(url);
+ return m_ifc.vfs->toAddon->open_for_write(m_ifc.vfs, &url2.url, bOverWrite);
+}
+
+bool CVFSEntry::Exists(const CURL& url)
+{
+ if (!m_ifc.vfs->toAddon->exists)
+ return false;
+
+ CVFSURLWrapper url2(url);
+ return m_ifc.vfs->toAddon->exists(m_ifc.vfs, &url2.url);
+}
+
+int CVFSEntry::Stat(const CURL& url, struct __stat64* buffer)
+{
+ int ret = -1;
+ if (!m_ifc.vfs->toAddon->stat)
+ return ret;
+
+ CVFSURLWrapper url2(url);
+ STAT_STRUCTURE statBuffer = {};
+ ret = m_ifc.vfs->toAddon->stat(m_ifc.vfs, &url2.url, &statBuffer);
+
+ *buffer = {};
+ buffer->st_dev = statBuffer.deviceId;
+ buffer->st_ino = statBuffer.fileSerialNumber;
+ buffer->st_size = statBuffer.size;
+ buffer->st_atime = statBuffer.accessTime;
+ buffer->st_mtime = statBuffer.modificationTime;
+ buffer->st_ctime = statBuffer.statusTime;
+ buffer->st_mode = 0;
+ if (statBuffer.isDirectory)
+ buffer->st_mode |= S_IFDIR;
+ if (statBuffer.isSymLink)
+ buffer->st_mode |= S_IFLNK;
+ if (statBuffer.isBlock)
+ buffer->st_mode |= S_IFBLK;
+ if (statBuffer.isCharacter)
+ buffer->st_mode |= S_IFCHR;
+ if (statBuffer.isFifo)
+ buffer->st_mode |= S_IFIFO;
+ if (statBuffer.isRegular)
+ buffer->st_mode |= S_IFREG;
+ if (statBuffer.isSocket)
+ buffer->st_mode |= S_IFSOCK;
+
+ return ret;
+}
+
+ssize_t CVFSEntry::Read(void* ctx, void* lpBuf, size_t uiBufSize)
+{
+ if (!m_ifc.vfs->toAddon->read)
+ return 0;
+
+ return m_ifc.vfs->toAddon->read(m_ifc.vfs, ctx, static_cast<uint8_t*>(lpBuf), uiBufSize);
+}
+
+ssize_t CVFSEntry::Write(void* ctx, const void* lpBuf, size_t uiBufSize)
+{
+ if (!m_ifc.vfs->toAddon->write)
+ return 0;
+
+ return m_ifc.vfs->toAddon->write(m_ifc.vfs, ctx, static_cast<const uint8_t*>(lpBuf), uiBufSize);
+}
+
+int64_t CVFSEntry::Seek(void* ctx, int64_t position, int whence)
+{
+ if (!m_ifc.vfs->toAddon->seek)
+ return 0;
+
+ return m_ifc.vfs->toAddon->seek(m_ifc.vfs, ctx, position, whence);
+}
+
+int CVFSEntry::Truncate(void* ctx, int64_t size)
+{
+ if (!m_ifc.vfs->toAddon->truncate)
+ return 0;
+
+ return m_ifc.vfs->toAddon->truncate(m_ifc.vfs, ctx, size);
+}
+
+void CVFSEntry::Close(void* ctx)
+{
+ if (m_ifc.vfs->toAddon->close)
+ m_ifc.vfs->toAddon->close(m_ifc.vfs, ctx);
+}
+
+int64_t CVFSEntry::GetPosition(void* ctx)
+{
+ if (!m_ifc.vfs->toAddon->get_position)
+ return 0;
+
+ return m_ifc.vfs->toAddon->get_position(m_ifc.vfs, ctx);
+}
+
+int CVFSEntry::GetChunkSize(void* ctx)
+{
+ if (!m_ifc.vfs->toAddon->get_chunk_size)
+ return 0;
+
+ return m_ifc.vfs->toAddon->get_chunk_size(m_ifc.vfs, ctx);
+}
+
+int64_t CVFSEntry::GetLength(void* ctx)
+{
+ if (!m_ifc.vfs->toAddon->get_length)
+ return 0;
+
+ return m_ifc.vfs->toAddon->get_length(m_ifc.vfs, ctx);
+}
+
+int CVFSEntry::IoControl(void* ctx, XFILE::EIoControl request, void* param)
+{
+ switch (request)
+ {
+ case XFILE::EIoControl::IOCTRL_SEEK_POSSIBLE:
+ {
+ if (!m_ifc.vfs->toAddon->io_control_get_seek_possible)
+ return -1;
+ return m_ifc.vfs->toAddon->io_control_get_seek_possible(m_ifc.vfs, ctx) ? 1 : 0;
+ }
+ case XFILE::EIoControl::IOCTRL_CACHE_STATUS:
+ {
+ if (!m_ifc.vfs->toAddon->io_control_get_cache_status)
+ return -1;
+
+ XFILE::SCacheStatus* kodiData = static_cast<XFILE::SCacheStatus*>(param);
+ if (!kodiData)
+ return -1;
+
+ VFS_CACHE_STATUS_DATA status;
+ int ret = m_ifc.vfs->toAddon->io_control_get_cache_status(m_ifc.vfs, ctx, &status) ? 0 : -1;
+ if (ret >= 0)
+ {
+ kodiData->forward = status.forward;
+ kodiData->maxrate = status.maxrate;
+ kodiData->currate = status.currate;
+ kodiData->lowrate = status.lowrate;
+ }
+ return ret;
+ }
+ case XFILE::EIoControl::IOCTRL_CACHE_SETRATE:
+ {
+ if (!m_ifc.vfs->toAddon->io_control_set_cache_rate)
+ return -1;
+
+ uint32_t& iParam = *static_cast<uint32_t*>(param);
+ return m_ifc.vfs->toAddon->io_control_set_cache_rate(m_ifc.vfs, ctx, iParam) ? 1 : 0;
+ }
+ case XFILE::EIoControl::IOCTRL_SET_RETRY:
+ {
+ if (!m_ifc.vfs->toAddon->io_control_set_retry)
+ return -1;
+
+ bool& bParam = *static_cast<bool*>(param);
+ return m_ifc.vfs->toAddon->io_control_set_retry(m_ifc.vfs, ctx, bParam) ? 0 : -1;
+ }
+
+ // Not by addon supported io's
+ case XFILE::EIoControl::IOCTRL_SET_CACHE:
+ case XFILE::EIoControl::IOCTRL_NATIVE:
+ default:
+ break;
+ }
+
+ return -1;
+}
+
+bool CVFSEntry::Delete(const CURL& url)
+{
+ if (!m_ifc.vfs->toAddon->delete_it)
+ return false;
+
+ CVFSURLWrapper url2(url);
+ return m_ifc.vfs->toAddon->delete_it(m_ifc.vfs, &url2.url);
+}
+
+bool CVFSEntry::Rename(const CURL& url, const CURL& url2)
+{
+ if (!m_ifc.vfs->toAddon->rename)
+ return false;
+
+ CVFSURLWrapper url3(url);
+ CVFSURLWrapper url4(url2);
+ return m_ifc.vfs->toAddon->rename(m_ifc.vfs, &url3.url, &url4.url);
+}
+
+void CVFSEntry::ClearOutIdle()
+{
+ if (m_ifc.vfs->toAddon->clear_out_idle)
+ m_ifc.vfs->toAddon->clear_out_idle(m_ifc.vfs);
+}
+
+void CVFSEntry::DisconnectAll()
+{
+ if (m_ifc.vfs->toAddon->disconnect_all)
+ m_ifc.vfs->toAddon->disconnect_all(m_ifc.vfs);
+}
+
+bool CVFSEntry::DirectoryExists(const CURL& url)
+{
+ if (!m_ifc.vfs->toAddon->directory_exists)
+ return false;
+
+ CVFSURLWrapper url2(url);
+ return m_ifc.vfs->toAddon->directory_exists(m_ifc.vfs, &url2.url);
+}
+
+bool CVFSEntry::RemoveDirectory(const CURL& url)
+{
+ if (!m_ifc.vfs->toAddon->remove_directory)
+ return false;
+
+ CVFSURLWrapper url2(url);
+ return m_ifc.vfs->toAddon->remove_directory(m_ifc.vfs, &url2.url);
+}
+
+bool CVFSEntry::CreateDirectory(const CURL& url)
+{
+ if (!m_ifc.vfs->toAddon->create_directory)
+ return false;
+
+ CVFSURLWrapper url2(url);
+ return m_ifc.vfs->toAddon->create_directory(m_ifc.vfs, &url2.url);
+}
+
+static void VFSDirEntriesToCFileItemList(int num_entries,
+ VFSDirEntry* entries,
+ CFileItemList& items)
+{
+ for (int i=0;i<num_entries;++i)
+ {
+ CFileItemPtr item(new CFileItem());
+ item->SetLabel(entries[i].label);
+ item->SetPath(entries[i].path);
+ item->m_dwSize = entries[i].size;
+ item->m_dateTime = entries[i].date_time;
+ item->m_bIsFolder = entries[i].folder;
+ if (entries[i].title)
+ item->m_strTitle = entries[i].title;
+ for (unsigned int j=0;j<entries[i].num_props;++j)
+ {
+ if (StringUtils::CompareNoCase(entries[i].properties[j].name, "propmisusepreformatted") == 0)
+ {
+ if (StringUtils::CompareNoCase(entries[i].properties[j].name, "true") == 0)
+ item->SetLabelPreformatted(true);
+ else
+ item->SetLabelPreformatted(false);
+ } else
+ item->SetProperty(entries[i].properties[j].name,
+ entries[i].properties[j].val);
+ }
+ items.Add(item);
+ }
+}
+
+bool CVFSEntry::GetDirectory(const CURL& url, CFileItemList& items,
+ void* ctx)
+{
+ if (!m_ifc.vfs->toAddon->get_directory || !m_ifc.vfs->toAddon->free_directory)
+ return false;
+
+ VFSGetDirectoryCallbacks callbacks;
+ callbacks.ctx = ctx;
+ callbacks.get_keyboard_input = CVFSEntryIDirectoryWrapper::DoGetKeyboardInput;
+ callbacks.set_error_dialog = CVFSEntryIDirectoryWrapper::DoSetErrorDialog;
+ callbacks.require_authentication = CVFSEntryIDirectoryWrapper::DoRequireAuthentication;
+
+ VFSDirEntry* entries = nullptr;
+ int num_entries = 0;
+ CVFSURLWrapper url2(url);
+ bool ret =
+ m_ifc.vfs->toAddon->get_directory(m_ifc.vfs, &url2.url, &entries, &num_entries, &callbacks);
+ if (ret)
+ {
+ VFSDirEntriesToCFileItemList(num_entries, entries, items);
+ m_ifc.vfs->toAddon->free_directory(m_ifc.vfs, entries, num_entries);
+ }
+
+ return ret;
+}
+
+bool CVFSEntry::ContainsFiles(const CURL& url, CFileItemList& items)
+{
+ if (!m_ifc.vfs->toAddon->contains_files || !m_ifc.vfs->toAddon->free_directory)
+ return false;
+
+ VFSDirEntry* entries = nullptr;
+ int num_entries = 0;
+
+ CVFSURLWrapper url2(url);
+ char rootpath[ADDON_STANDARD_STRING_LENGTH];
+ rootpath[0] = 0;
+ bool ret =
+ m_ifc.vfs->toAddon->contains_files(m_ifc.vfs, &url2.url, &entries, &num_entries, rootpath);
+ if (!ret)
+ return false;
+
+ VFSDirEntriesToCFileItemList(num_entries, entries, items);
+ m_ifc.vfs->toAddon->free_directory(m_ifc.vfs, entries, num_entries);
+ if (strlen(rootpath))
+ items.SetPath(rootpath);
+
+ return true;
+}
+
+CVFSEntryIFileWrapper::CVFSEntryIFileWrapper(VFSEntryPtr ptr)
+ : m_context(nullptr), m_addon(std::move(ptr))
+{
+}
+
+CVFSEntryIFileWrapper::~CVFSEntryIFileWrapper()
+{
+ Close();
+}
+
+bool CVFSEntryIFileWrapper::Open(const CURL& url)
+{
+ m_context = m_addon->Open(url);
+ return m_context != nullptr;
+}
+
+bool CVFSEntryIFileWrapper::OpenForWrite(const CURL& url, bool bOverWrite)
+{
+ m_context = m_addon->OpenForWrite(url, bOverWrite);
+ return m_context != nullptr;
+}
+
+bool CVFSEntryIFileWrapper::Exists(const CURL& url)
+{
+ return m_addon->Exists(url);
+}
+
+int CVFSEntryIFileWrapper::Stat(const CURL& url, struct __stat64* buffer)
+{
+ return m_addon->Stat(url, buffer);
+}
+
+int CVFSEntryIFileWrapper::Truncate(int64_t size)
+{
+ return m_addon->Truncate(m_context, size);
+}
+
+ssize_t CVFSEntryIFileWrapper::Read(void* lpBuf, size_t uiBufSize)
+{
+ if (!m_context)
+ return 0;
+
+ return m_addon->Read(m_context, lpBuf, uiBufSize);
+}
+
+ssize_t CVFSEntryIFileWrapper::Write(const void* lpBuf, size_t uiBufSize)
+{
+ if (!m_context)
+ return 0;
+
+ return m_addon->Write(m_context, lpBuf, uiBufSize);
+}
+
+int64_t CVFSEntryIFileWrapper::Seek(int64_t iFilePosition, int whence)
+{
+ if (!m_context)
+ return 0;
+
+ return m_addon->Seek(m_context, iFilePosition, whence);
+}
+
+void CVFSEntryIFileWrapper::Close()
+{
+ if (m_context)
+ {
+ m_addon->Close(m_context);
+ m_context = nullptr;
+ }
+}
+
+int64_t CVFSEntryIFileWrapper::GetPosition()
+{
+ if (!m_context)
+ return 0;
+
+ return m_addon->GetPosition(m_context);
+}
+
+int CVFSEntryIFileWrapper::GetChunkSize()
+{
+ if (!m_context)
+ return 0;
+
+ return m_addon->GetChunkSize(m_context);
+}
+
+int64_t CVFSEntryIFileWrapper::GetLength()
+{
+ if (!m_context)
+ return 0;
+
+ return m_addon->GetLength(m_context);
+}
+
+int CVFSEntryIFileWrapper::IoControl(XFILE::EIoControl request, void* param)
+{
+ if (!m_context)
+ return 0;
+
+ return m_addon->IoControl(m_context, request, param);
+}
+
+bool CVFSEntryIFileWrapper::Delete(const CURL& url)
+{
+ return m_addon->Delete(url);
+}
+
+bool CVFSEntryIFileWrapper::Rename(const CURL& url, const CURL& url2)
+{
+ return m_addon->Rename(url, url2);
+}
+
+CVFSEntryIDirectoryWrapper::CVFSEntryIDirectoryWrapper(VFSEntryPtr ptr) : m_addon(std::move(ptr))
+{
+}
+
+bool CVFSEntryIDirectoryWrapper::Exists(const CURL& url)
+{
+ return m_addon->DirectoryExists(url);
+}
+
+bool CVFSEntryIDirectoryWrapper::Remove(const CURL& url)
+{
+ return m_addon->RemoveDirectory(url);
+}
+
+bool CVFSEntryIDirectoryWrapper::Create(const CURL& url)
+{
+ return m_addon->CreateDirectory(url);
+}
+
+bool CVFSEntryIDirectoryWrapper::GetDirectory(const CURL& url,
+ CFileItemList& items)
+{
+ return m_addon->GetDirectory(url, items, this);
+}
+
+bool CVFSEntryIDirectoryWrapper::DoGetKeyboardInput(void* ctx,
+ const char* heading,
+ char** input,
+ bool hidden_input)
+{
+ return static_cast<CVFSEntryIDirectoryWrapper*>(ctx)->GetKeyboardInput2(heading, input, hidden_input);
+}
+
+bool CVFSEntryIDirectoryWrapper::GetKeyboardInput2(const char* heading,
+ char** input,
+ bool hidden_input)
+{
+ std::string inp;
+ bool result;
+ if ((result=GetKeyboardInput(CVariant(std::string(heading)), inp, hidden_input)))
+ *input = strdup(inp.c_str());
+
+ return result;
+}
+
+void CVFSEntryIDirectoryWrapper::DoSetErrorDialog(void* ctx, const char* heading,
+ const char* line1,
+ const char* line2,
+ const char* line3)
+{
+ static_cast<CVFSEntryIDirectoryWrapper*>(ctx)->SetErrorDialog2(heading, line1,
+ line2, line3);
+}
+
+void CVFSEntryIDirectoryWrapper::SetErrorDialog2(const char* heading,
+ const char* line1,
+ const char* line2,
+ const char* line3)
+{
+ CVariant l2=0, l3=0;
+ if (line2)
+ l2 = std::string(line2);
+ if (line3)
+ l3 = std::string(line3);
+ if (m_flags & XFILE::DIR_FLAG_ALLOW_PROMPT)
+ SetErrorDialog(CVariant(std::string(heading)),
+ CVariant(std::string(line1)), l2, l3);
+}
+
+void CVFSEntryIDirectoryWrapper::DoRequireAuthentication(void* ctx,
+ const char* url)
+{
+ static_cast<CVFSEntryIDirectoryWrapper*>(ctx)->RequireAuthentication2(CURL(url));
+}
+
+void CVFSEntryIDirectoryWrapper::RequireAuthentication2(const CURL& url)
+{
+ if (m_flags & XFILE::DIR_FLAG_ALLOW_PROMPT)
+ RequireAuthentication(url);
+}
+
+} /*namespace ADDON*/
+