2 * Copyright (C) 2013 Arne Morten Kvarving
4 * SPDX-License-Identifier: GPL-2.0-or-later
5 * See LICENSES/README.md for more information.
10 #include "ServiceBroker.h"
12 #include "addons/AddonEvents.h"
13 #include "addons/AddonManager.h"
14 #include "addons/addoninfo/AddonInfo.h"
15 #include "addons/addoninfo/AddonType.h"
16 #include "addons/interfaces/Filesystem.h"
17 #include "network/ZeroconfBrowser.h"
18 #include "utils/StringUtils.h"
19 #include "utils/log.h"
24 #if defined(TARGET_WINDOWS)
26 #define S_IFLNK 0120000
35 #define S_IFREG _S_IFREG
38 #define S_IFCHR _S_IFCHR
41 #define S_IFDIR _S_IFDIR
44 #define S_IFIFO _S_IFIFO
51 CVFSAddonCache::~CVFSAddonCache()
56 void CVFSAddonCache::Init()
58 CServiceBroker::GetAddonMgr().Events().Subscribe(this, &CVFSAddonCache::OnEvent
);
60 // Load all available VFS addons during Kodi start
61 std::vector
<AddonInfoPtr
> addonInfos
;
62 CServiceBroker::GetAddonMgr().GetAddonInfos(addonInfos
, true, AddonType::VFS
);
64 std::unique_lock
<CCriticalSection
> lock(m_critSection
);
65 for (const auto& addonInfo
: addonInfos
)
67 VFSEntryPtr vfs
= std::make_shared
<CVFSEntry
>(addonInfo
);
68 vfs
->Addon()->RegisterInformer(this);
70 m_addonsInstances
.emplace_back(vfs
);
72 if (!vfs
->GetZeroconfType().empty())
73 CZeroconfBrowser::GetInstance()->AddServiceType(vfs
->GetZeroconfType());
77 void CVFSAddonCache::Deinit()
79 CServiceBroker::GetAddonMgr().Events().Unsubscribe(this);
82 const std::vector
<VFSEntryPtr
> CVFSAddonCache::GetAddonInstances()
84 std::unique_lock
<CCriticalSection
> lock(m_critSection
);
85 return m_addonsInstances
;
88 VFSEntryPtr
CVFSAddonCache::GetAddonInstance(const std::string
& strId
)
92 std::unique_lock
<CCriticalSection
> lock(m_critSection
);
94 const auto& itAddon
= std::find_if(m_addonsInstances
.begin(), m_addonsInstances
.end(),
95 [&strId
](const VFSEntryPtr
& addon
)
97 return addon
->ID() == strId
;
100 if (itAddon
!= m_addonsInstances
.end())
106 void CVFSAddonCache::OnEvent(const AddonEvent
& event
)
108 if (typeid(event
) == typeid(AddonEvents::Disabled
))
110 for (const auto& vfs
: m_addonsInstances
)
112 if (vfs
->ID() == event
.addonId
&& !vfs
->GetZeroconfType().empty())
113 CZeroconfBrowser::GetInstance()->RemoveServiceType(vfs
->GetZeroconfType());
117 if (typeid(event
) == typeid(AddonEvents::Enabled
) ||
118 typeid(event
) == typeid(AddonEvents::Disabled
) ||
119 typeid(event
) == typeid(AddonEvents::ReInstalled
))
121 if (CServiceBroker::GetAddonMgr().HasType(event
.addonId
, AddonType::VFS
))
122 Update(event
.addonId
);
124 else if (typeid(event
) == typeid(AddonEvents::UnInstalled
))
126 Update(event
.addonId
);
130 bool CVFSAddonCache::IsInUse(const std::string
& id
)
132 std::unique_lock
<CCriticalSection
> lock(m_critSection
);
134 const auto& itAddon
= std::find_if(m_addonsInstances
.begin(), m_addonsInstances
.end(),
135 [&id
](const VFSEntryPtr
& addon
) { return addon
->ID() == id
; });
136 if (itAddon
!= m_addonsInstances
.end() && (*itAddon
).use_count() > 1)
141 void CVFSAddonCache::Update(const std::string
& id
)
143 std::vector
<VFSEntryPtr
> addonmap
;
145 // Stop used instance if present, otherwise the new becomes created on already created addon base one.
147 std::unique_lock
<CCriticalSection
> lock(m_critSection
);
149 const auto& itAddon
=
150 std::find_if(m_addonsInstances
.begin(), m_addonsInstances
.end(),
151 [&id
](const VFSEntryPtr
& addon
) { return addon
->ID() == id
; });
153 if (itAddon
!= m_addonsInstances
.end())
155 (*itAddon
)->Addon()->RegisterInformer(nullptr);
156 m_addonsInstances
.erase(itAddon
);
160 // Create and init the new VFS addon instance
161 AddonInfoPtr addonInfo
= CServiceBroker::GetAddonMgr().GetAddonInfo(id
, AddonType::VFS
);
162 if (addonInfo
&& !CServiceBroker::GetAddonMgr().IsAddonDisabled(id
))
164 VFSEntryPtr vfs
= std::make_shared
<CVFSEntry
>(addonInfo
);
166 if (!vfs
->GetZeroconfType().empty())
167 CZeroconfBrowser::GetInstance()->AddServiceType(vfs
->GetZeroconfType());
169 std::unique_lock
<CCriticalSection
> lock(m_critSection
);
170 m_addonsInstances
.emplace_back(vfs
);
177 explicit CVFSURLWrapper(const CURL
& url2
)
179 m_strings
.push_back(url2
.Get());
180 m_strings
.push_back(url2
.GetDomain());
181 m_strings
.push_back(url2
.GetHostName());
182 m_strings
.push_back(url2
.GetFileName());
183 m_strings
.push_back(url2
.GetOptions());
184 m_strings
.push_back(url2
.GetUserName());
185 m_strings
.push_back(url2
.GetPassWord());
186 m_strings
.push_back(url2
.GetRedacted());
187 m_strings
.push_back(url2
.GetShareName());
188 m_strings
.push_back(url2
.GetProtocol());
190 url
.url
= m_strings
[0].c_str();
191 url
.domain
= m_strings
[1].c_str();
192 url
.hostname
= m_strings
[2].c_str();
193 url
.filename
= m_strings
[3].c_str();
194 url
.port
= url2
.GetPort();
195 url
.options
= m_strings
[4].c_str();
196 url
.username
= m_strings
[5].c_str();
197 url
.password
= m_strings
[6].c_str();
198 url
.redacted
= m_strings
[7].c_str();
199 url
.sharename
= m_strings
[8].c_str();
200 url
.protocol
= m_strings
[9].c_str();
205 std::vector
<std::string
> m_strings
;
208 CVFSEntry::ProtocolInfo::ProtocolInfo(const AddonInfoPtr
& addonInfo
)
209 : supportPath(addonInfo
->Type(AddonType::VFS
)->GetValue("@supportPath").asBoolean()),
210 supportUsername(addonInfo
->Type(AddonType::VFS
)->GetValue("@supportUsername").asBoolean()),
211 supportPassword(addonInfo
->Type(AddonType::VFS
)->GetValue("@supportPassword").asBoolean()),
212 supportPort(addonInfo
->Type(AddonType::VFS
)->GetValue("@supportPort").asBoolean()),
213 supportBrowsing(addonInfo
->Type(AddonType::VFS
)->GetValue("@supportBrowsing").asBoolean()),
214 supportWrite(addonInfo
->Type(AddonType::VFS
)->GetValue("@supportWrite").asBoolean()),
215 defaultPort(addonInfo
->Type(AddonType::VFS
)->GetValue("@defaultPort").asInteger()),
216 type(addonInfo
->Type(AddonType::VFS
)->GetValue("@protocols").asString()),
217 label(addonInfo
->Type(AddonType::VFS
)->GetValue("@label").asInteger())
221 CVFSEntry::CVFSEntry(const AddonInfoPtr
& addonInfo
)
222 : IAddonInstanceHandler(ADDON_INSTANCE_VFS
, addonInfo
),
223 m_protocols(addonInfo
->Type(AddonType::VFS
)->GetValue("@protocols").asString()),
224 m_extensions(addonInfo
->Type(AddonType::VFS
)->GetValue("@extensions").asString()),
225 m_zeroconf(addonInfo
->Type(AddonType::VFS
)->GetValue("@zeroconf").asString()),
226 m_files(addonInfo
->Type(AddonType::VFS
)->GetValue("@files").asBoolean()),
227 m_directories(addonInfo
->Type(AddonType::VFS
)->GetValue("@directories").asBoolean()),
228 m_filedirectories(addonInfo
->Type(AddonType::VFS
)->GetValue("@filedirectories").asBoolean()),
229 m_protocolInfo(addonInfo
)
231 if (!addonInfo
->Type(AddonType::VFS
)->GetValue("@supportDialog").asBoolean())
232 m_protocolInfo
.type
.clear();
234 // Create "C" interface structures, used as own parts to prevent API problems on update
235 m_ifc
.vfs
= new AddonInstance_VFSEntry
;
236 m_ifc
.vfs
->props
= new AddonProps_VFSEntry();
237 m_ifc
.vfs
->toAddon
= new KodiToAddonFuncTable_VFSEntry();
238 m_ifc
.vfs
->toKodi
= new AddonToKodiFuncTable_VFSEntry();
240 m_ifc
.vfs
->toKodi
->kodiInstance
= this;
241 if (CreateInstance() != ADDON_STATUS_OK
)
242 CLog::Log(LOGFATAL
, "CVFSEntry - Couldn't create instance on add-on '{}'", addonInfo
->Name());
245 CVFSEntry::~CVFSEntry()
249 // Delete "C" interface structures
250 delete m_ifc
.vfs
->toAddon
;
251 delete m_ifc
.vfs
->toKodi
;
252 delete m_ifc
.vfs
->props
;
256 void* CVFSEntry::Open(const CURL
& url
)
258 if (!m_ifc
.vfs
->toAddon
->open
)
261 CVFSURLWrapper
url2(url
);
262 return m_ifc
.vfs
->toAddon
->open(m_ifc
.vfs
, &url2
.url
);
265 void* CVFSEntry::OpenForWrite(const CURL
& url
, bool bOverWrite
)
267 if (!m_ifc
.vfs
->toAddon
->open_for_write
)
270 CVFSURLWrapper
url2(url
);
271 return m_ifc
.vfs
->toAddon
->open_for_write(m_ifc
.vfs
, &url2
.url
, bOverWrite
);
274 bool CVFSEntry::Exists(const CURL
& url
)
276 if (!m_ifc
.vfs
->toAddon
->exists
)
279 CVFSURLWrapper
url2(url
);
280 return m_ifc
.vfs
->toAddon
->exists(m_ifc
.vfs
, &url2
.url
);
283 int CVFSEntry::Stat(const CURL
& url
, struct __stat64
* buffer
)
286 if (!m_ifc
.vfs
->toAddon
->stat
)
289 CVFSURLWrapper
url2(url
);
290 STAT_STRUCTURE statBuffer
= {};
291 ret
= m_ifc
.vfs
->toAddon
->stat(m_ifc
.vfs
, &url2
.url
, &statBuffer
);
294 buffer
->st_dev
= statBuffer
.deviceId
;
295 buffer
->st_ino
= statBuffer
.fileSerialNumber
;
296 buffer
->st_size
= statBuffer
.size
;
297 buffer
->st_atime
= statBuffer
.accessTime
;
298 buffer
->st_mtime
= statBuffer
.modificationTime
;
299 buffer
->st_ctime
= statBuffer
.statusTime
;
301 if (statBuffer
.isDirectory
)
302 buffer
->st_mode
|= S_IFDIR
;
303 if (statBuffer
.isSymLink
)
304 buffer
->st_mode
|= S_IFLNK
;
305 if (statBuffer
.isBlock
)
306 buffer
->st_mode
|= S_IFBLK
;
307 if (statBuffer
.isCharacter
)
308 buffer
->st_mode
|= S_IFCHR
;
309 if (statBuffer
.isFifo
)
310 buffer
->st_mode
|= S_IFIFO
;
311 if (statBuffer
.isRegular
)
312 buffer
->st_mode
|= S_IFREG
;
313 if (statBuffer
.isSocket
)
314 buffer
->st_mode
|= S_IFSOCK
;
319 ssize_t
CVFSEntry::Read(void* ctx
, void* lpBuf
, size_t uiBufSize
)
321 if (!m_ifc
.vfs
->toAddon
->read
)
324 return m_ifc
.vfs
->toAddon
->read(m_ifc
.vfs
, ctx
, static_cast<uint8_t*>(lpBuf
), uiBufSize
);
327 ssize_t
CVFSEntry::Write(void* ctx
, const void* lpBuf
, size_t uiBufSize
)
329 if (!m_ifc
.vfs
->toAddon
->write
)
332 return m_ifc
.vfs
->toAddon
->write(m_ifc
.vfs
, ctx
, static_cast<const uint8_t*>(lpBuf
), uiBufSize
);
335 int64_t CVFSEntry::Seek(void* ctx
, int64_t position
, int whence
)
337 if (!m_ifc
.vfs
->toAddon
->seek
)
340 return m_ifc
.vfs
->toAddon
->seek(m_ifc
.vfs
, ctx
, position
, whence
);
343 int CVFSEntry::Truncate(void* ctx
, int64_t size
)
345 if (!m_ifc
.vfs
->toAddon
->truncate
)
348 return m_ifc
.vfs
->toAddon
->truncate(m_ifc
.vfs
, ctx
, size
);
351 void CVFSEntry::Close(void* ctx
)
353 if (m_ifc
.vfs
->toAddon
->close
)
354 m_ifc
.vfs
->toAddon
->close(m_ifc
.vfs
, ctx
);
357 int64_t CVFSEntry::GetPosition(void* ctx
)
359 if (!m_ifc
.vfs
->toAddon
->get_position
)
362 return m_ifc
.vfs
->toAddon
->get_position(m_ifc
.vfs
, ctx
);
365 int CVFSEntry::GetChunkSize(void* ctx
)
367 if (!m_ifc
.vfs
->toAddon
->get_chunk_size
)
370 return m_ifc
.vfs
->toAddon
->get_chunk_size(m_ifc
.vfs
, ctx
);
373 int64_t CVFSEntry::GetLength(void* ctx
)
375 if (!m_ifc
.vfs
->toAddon
->get_length
)
378 return m_ifc
.vfs
->toAddon
->get_length(m_ifc
.vfs
, ctx
);
381 int CVFSEntry::IoControl(void* ctx
, XFILE::EIoControl request
, void* param
)
385 case XFILE::EIoControl::IOCTRL_SEEK_POSSIBLE
:
387 if (!m_ifc
.vfs
->toAddon
->io_control_get_seek_possible
)
389 return m_ifc
.vfs
->toAddon
->io_control_get_seek_possible(m_ifc
.vfs
, ctx
) ? 1 : 0;
391 case XFILE::EIoControl::IOCTRL_CACHE_STATUS
:
393 if (!m_ifc
.vfs
->toAddon
->io_control_get_cache_status
)
396 XFILE::SCacheStatus
* kodiData
= static_cast<XFILE::SCacheStatus
*>(param
);
400 VFS_CACHE_STATUS_DATA status
;
401 int ret
= m_ifc
.vfs
->toAddon
->io_control_get_cache_status(m_ifc
.vfs
, ctx
, &status
) ? 0 : -1;
404 kodiData
->forward
= status
.forward
;
405 kodiData
->maxrate
= status
.maxrate
;
406 kodiData
->currate
= status
.currate
;
407 kodiData
->lowrate
= status
.lowrate
;
411 case XFILE::EIoControl::IOCTRL_CACHE_SETRATE
:
413 if (!m_ifc
.vfs
->toAddon
->io_control_set_cache_rate
)
416 uint32_t& iParam
= *static_cast<uint32_t*>(param
);
417 return m_ifc
.vfs
->toAddon
->io_control_set_cache_rate(m_ifc
.vfs
, ctx
, iParam
) ? 1 : 0;
419 case XFILE::EIoControl::IOCTRL_SET_RETRY
:
421 if (!m_ifc
.vfs
->toAddon
->io_control_set_retry
)
424 bool& bParam
= *static_cast<bool*>(param
);
425 return m_ifc
.vfs
->toAddon
->io_control_set_retry(m_ifc
.vfs
, ctx
, bParam
) ? 0 : -1;
428 // Not by addon supported io's
429 case XFILE::EIoControl::IOCTRL_SET_CACHE
:
430 case XFILE::EIoControl::IOCTRL_NATIVE
:
438 bool CVFSEntry::Delete(const CURL
& url
)
440 if (!m_ifc
.vfs
->toAddon
->delete_it
)
443 CVFSURLWrapper
url2(url
);
444 return m_ifc
.vfs
->toAddon
->delete_it(m_ifc
.vfs
, &url2
.url
);
447 bool CVFSEntry::Rename(const CURL
& url
, const CURL
& url2
)
449 if (!m_ifc
.vfs
->toAddon
->rename
)
452 CVFSURLWrapper
url3(url
);
453 CVFSURLWrapper
url4(url2
);
454 return m_ifc
.vfs
->toAddon
->rename(m_ifc
.vfs
, &url3
.url
, &url4
.url
);
457 void CVFSEntry::ClearOutIdle()
459 if (m_ifc
.vfs
->toAddon
->clear_out_idle
)
460 m_ifc
.vfs
->toAddon
->clear_out_idle(m_ifc
.vfs
);
463 void CVFSEntry::DisconnectAll()
465 if (m_ifc
.vfs
->toAddon
->disconnect_all
)
466 m_ifc
.vfs
->toAddon
->disconnect_all(m_ifc
.vfs
);
469 bool CVFSEntry::DirectoryExists(const CURL
& url
)
471 if (!m_ifc
.vfs
->toAddon
->directory_exists
)
474 CVFSURLWrapper
url2(url
);
475 return m_ifc
.vfs
->toAddon
->directory_exists(m_ifc
.vfs
, &url2
.url
);
478 bool CVFSEntry::RemoveDirectory(const CURL
& url
)
480 if (!m_ifc
.vfs
->toAddon
->remove_directory
)
483 CVFSURLWrapper
url2(url
);
484 return m_ifc
.vfs
->toAddon
->remove_directory(m_ifc
.vfs
, &url2
.url
);
487 bool CVFSEntry::CreateDirectory(const CURL
& url
)
489 if (!m_ifc
.vfs
->toAddon
->create_directory
)
492 CVFSURLWrapper
url2(url
);
493 return m_ifc
.vfs
->toAddon
->create_directory(m_ifc
.vfs
, &url2
.url
);
496 static void VFSDirEntriesToCFileItemList(int num_entries
,
497 VFSDirEntry
* entries
,
498 CFileItemList
& items
)
500 for (int i
=0;i
<num_entries
;++i
)
502 CFileItemPtr
item(new CFileItem());
503 item
->SetLabel(entries
[i
].label
);
504 item
->SetPath(entries
[i
].path
);
505 item
->m_dwSize
= entries
[i
].size
;
506 item
->m_dateTime
= entries
[i
].date_time
;
507 item
->m_bIsFolder
= entries
[i
].folder
;
508 if (entries
[i
].title
)
509 item
->m_strTitle
= entries
[i
].title
;
510 for (unsigned int j
=0;j
<entries
[i
].num_props
;++j
)
512 if (StringUtils::CompareNoCase(entries
[i
].properties
[j
].name
, "propmisusepreformatted") == 0)
514 if (StringUtils::CompareNoCase(entries
[i
].properties
[j
].name
, "true") == 0)
515 item
->SetLabelPreformatted(true);
517 item
->SetLabelPreformatted(false);
519 item
->SetProperty(entries
[i
].properties
[j
].name
,
520 entries
[i
].properties
[j
].val
);
526 bool CVFSEntry::GetDirectory(const CURL
& url
, CFileItemList
& items
,
529 if (!m_ifc
.vfs
->toAddon
->get_directory
|| !m_ifc
.vfs
->toAddon
->free_directory
)
532 VFSGetDirectoryCallbacks callbacks
;
534 callbacks
.get_keyboard_input
= CVFSEntryIDirectoryWrapper::DoGetKeyboardInput
;
535 callbacks
.set_error_dialog
= CVFSEntryIDirectoryWrapper::DoSetErrorDialog
;
536 callbacks
.require_authentication
= CVFSEntryIDirectoryWrapper::DoRequireAuthentication
;
538 VFSDirEntry
* entries
= nullptr;
540 CVFSURLWrapper
url2(url
);
542 m_ifc
.vfs
->toAddon
->get_directory(m_ifc
.vfs
, &url2
.url
, &entries
, &num_entries
, &callbacks
);
545 VFSDirEntriesToCFileItemList(num_entries
, entries
, items
);
546 m_ifc
.vfs
->toAddon
->free_directory(m_ifc
.vfs
, entries
, num_entries
);
552 bool CVFSEntry::ContainsFiles(const CURL
& url
, CFileItemList
& items
)
554 if (!m_ifc
.vfs
->toAddon
->contains_files
|| !m_ifc
.vfs
->toAddon
->free_directory
)
557 VFSDirEntry
* entries
= nullptr;
560 CVFSURLWrapper
url2(url
);
561 char rootpath
[ADDON_STANDARD_STRING_LENGTH
];
564 m_ifc
.vfs
->toAddon
->contains_files(m_ifc
.vfs
, &url2
.url
, &entries
, &num_entries
, rootpath
);
568 VFSDirEntriesToCFileItemList(num_entries
, entries
, items
);
569 m_ifc
.vfs
->toAddon
->free_directory(m_ifc
.vfs
, entries
, num_entries
);
570 if (strlen(rootpath
))
571 items
.SetPath(rootpath
);
576 CVFSEntryIFileWrapper::CVFSEntryIFileWrapper(VFSEntryPtr ptr
)
577 : m_context(nullptr), m_addon(std::move(ptr
))
581 CVFSEntryIFileWrapper::~CVFSEntryIFileWrapper()
586 bool CVFSEntryIFileWrapper::Open(const CURL
& url
)
588 m_context
= m_addon
->Open(url
);
589 return m_context
!= nullptr;
592 bool CVFSEntryIFileWrapper::OpenForWrite(const CURL
& url
, bool bOverWrite
)
594 m_context
= m_addon
->OpenForWrite(url
, bOverWrite
);
595 return m_context
!= nullptr;
598 bool CVFSEntryIFileWrapper::Exists(const CURL
& url
)
600 return m_addon
->Exists(url
);
603 int CVFSEntryIFileWrapper::Stat(const CURL
& url
, struct __stat64
* buffer
)
605 return m_addon
->Stat(url
, buffer
);
608 int CVFSEntryIFileWrapper::Truncate(int64_t size
)
610 return m_addon
->Truncate(m_context
, size
);
613 ssize_t
CVFSEntryIFileWrapper::Read(void* lpBuf
, size_t uiBufSize
)
618 return m_addon
->Read(m_context
, lpBuf
, uiBufSize
);
621 ssize_t
CVFSEntryIFileWrapper::Write(const void* lpBuf
, size_t uiBufSize
)
626 return m_addon
->Write(m_context
, lpBuf
, uiBufSize
);
629 int64_t CVFSEntryIFileWrapper::Seek(int64_t iFilePosition
, int whence
)
634 return m_addon
->Seek(m_context
, iFilePosition
, whence
);
637 void CVFSEntryIFileWrapper::Close()
641 m_addon
->Close(m_context
);
646 int64_t CVFSEntryIFileWrapper::GetPosition()
651 return m_addon
->GetPosition(m_context
);
654 int CVFSEntryIFileWrapper::GetChunkSize()
659 return m_addon
->GetChunkSize(m_context
);
662 int64_t CVFSEntryIFileWrapper::GetLength()
667 return m_addon
->GetLength(m_context
);
670 int CVFSEntryIFileWrapper::IoControl(XFILE::EIoControl request
, void* param
)
675 return m_addon
->IoControl(m_context
, request
, param
);
678 bool CVFSEntryIFileWrapper::Delete(const CURL
& url
)
680 return m_addon
->Delete(url
);
683 bool CVFSEntryIFileWrapper::Rename(const CURL
& url
, const CURL
& url2
)
685 return m_addon
->Rename(url
, url2
);
688 CVFSEntryIDirectoryWrapper::CVFSEntryIDirectoryWrapper(VFSEntryPtr ptr
) : m_addon(std::move(ptr
))
692 bool CVFSEntryIDirectoryWrapper::Exists(const CURL
& url
)
694 return m_addon
->DirectoryExists(url
);
697 bool CVFSEntryIDirectoryWrapper::Remove(const CURL
& url
)
699 return m_addon
->RemoveDirectory(url
);
702 bool CVFSEntryIDirectoryWrapper::Create(const CURL
& url
)
704 return m_addon
->CreateDirectory(url
);
707 bool CVFSEntryIDirectoryWrapper::GetDirectory(const CURL
& url
,
708 CFileItemList
& items
)
710 return m_addon
->GetDirectory(url
, items
, this);
713 bool CVFSEntryIDirectoryWrapper::DoGetKeyboardInput(void* ctx
,
718 return static_cast<CVFSEntryIDirectoryWrapper
*>(ctx
)->GetKeyboardInput2(heading
, input
, hidden_input
);
721 bool CVFSEntryIDirectoryWrapper::GetKeyboardInput2(const char* heading
,
727 if ((result
=GetKeyboardInput(CVariant(std::string(heading
)), inp
, hidden_input
)))
728 *input
= strdup(inp
.c_str());
733 void CVFSEntryIDirectoryWrapper::DoSetErrorDialog(void* ctx
, const char* heading
,
738 static_cast<CVFSEntryIDirectoryWrapper
*>(ctx
)->SetErrorDialog2(heading
, line1
,
742 void CVFSEntryIDirectoryWrapper::SetErrorDialog2(const char* heading
,
749 l2
= std::string(line2
);
751 l3
= std::string(line3
);
752 if (m_flags
& XFILE::DIR_FLAG_ALLOW_PROMPT
)
753 SetErrorDialog(CVariant(std::string(heading
)),
754 CVariant(std::string(line1
)), l2
, l3
);
757 void CVFSEntryIDirectoryWrapper::DoRequireAuthentication(void* ctx
,
760 static_cast<CVFSEntryIDirectoryWrapper
*>(ctx
)->RequireAuthentication2(CURL(url
));
763 void CVFSEntryIDirectoryWrapper::RequireAuthentication2(const CURL
& url
)
765 if (m_flags
& XFILE::DIR_FLAG_ALLOW_PROMPT
)
766 RequireAuthentication(url
);
769 } /*namespace ADDON*/