bool CResourceDirectory::GetDirectory(const CURL& url, CFileItemList &items) { const std::string pathToUrl(url.Get()); std::string translatedPath; if (!CResourceFile::TranslatePath(url, translatedPath)) return false; if (CDirectory::GetDirectory(translatedPath, items, m_strFileMask, m_flags | DIR_FLAG_GET_HIDDEN)) { // replace our paths as necessary items.SetURL(url); for (int i = 0; i < items.Size(); i++) { CFileItemPtr item = items[i]; if (StringUtils::StartsWith(item->GetPath(), translatedPath)) item->SetPath(URIUtils::AddFileToFolder(pathToUrl, item->GetPath().substr(translatedPath.size()))); } return true; } return false; }
bool CDirectory::GetDirectory(const CURL& url, CFileItemList &items, const CHints &hints, bool allowThreads) { try { CURL realURL = URIUtils::SubstitutePath(url); std::shared_ptr<IDirectory> pDirectory(CDirectoryFactory::Create(realURL)); if (!pDirectory.get()) return false; // check our cache for this path if (g_directoryCache.GetDirectory(realURL.Get(), items, (hints.flags & DIR_FLAG_READ_CACHE) == DIR_FLAG_READ_CACHE)) items.SetURL(url); else { // need to clear the cache (in case the directory fetch fails) // and (re)fetch the folder if (!(hints.flags & DIR_FLAG_BYPASS_CACHE)) g_directoryCache.ClearDirectory(realURL.Get()); pDirectory->SetFlags(hints.flags); bool result = false, cancel = false; while (!result && !cancel) { const std::string pathToUrl(url.Get()); if (g_application.IsCurrentThread() && allowThreads && !URIUtils::IsSpecial(pathToUrl)) { CSingleExit ex(g_graphicsContext); CGetDirectory get(pDirectory, realURL, url); if(!get.Wait(TIME_TO_BUSY_DIALOG)) { CGUIDialogBusy* dialog = (CGUIDialogBusy*)g_windowManager.GetWindow(WINDOW_DIALOG_BUSY); if (dialog) { dialog->Open(); while(!get.Wait(10)) { CSingleLock lock(g_graphicsContext); // update progress float progress = pDirectory->GetProgress(); if (progress > 0) dialog->SetProgress(progress); if (dialog->IsCanceled()) { cancel = true; pDirectory->CancelDirectory(); break; } lock.Leave(); // prevent an occasional deadlock on exit g_windowManager.ProcessRenderLoop(false); } dialog->Close(); } } result = get.GetDirectory(items); } else { items.SetURL(url); result = pDirectory->GetDirectory(realURL, items); } if (!result) { if (!cancel && g_application.IsCurrentThread() && pDirectory->ProcessRequirements()) continue; CLog::Log(LOGERROR, "%s - Error getting %s", __FUNCTION__, url.GetRedacted().c_str()); return false; } } // cache the directory, if necessary if (!(hints.flags & DIR_FLAG_BYPASS_CACHE)) g_directoryCache.SetDirectory(realURL.Get(), items, pDirectory->GetCacheType(url)); } // now filter for allowed files if (!pDirectory->AllowAll()) { pDirectory->SetMask(hints.mask); for (int i = 0; i < items.Size(); ++i) { CFileItemPtr item = items[i]; if (!item->m_bIsFolder && !pDirectory->IsAllowed(item->GetURL())) { items.Remove(i); i--; // don't confuse loop } } } // filter hidden files // TODO: we shouldn't be checking the gui setting here, callers should use getHidden instead if (!CSettings::Get().GetBool("filelists.showhidden") && !(hints.flags & DIR_FLAG_GET_HIDDEN)) { for (int i = 0; i < items.Size(); ++i) { if (items[i]->GetProperty("file:hidden").asBoolean()) { items.Remove(i); i--; // don't confuse loop } } } // Should any of the files we read be treated as a directory? // Disable for database folders, as they already contain the extracted items if (!(hints.flags & DIR_FLAG_NO_FILE_DIRS) && !items.IsMusicDb() && !items.IsVideoDb() && !items.IsSmartPlayList()) FilterFileDirectories(items, hints.mask); // Correct items for path substitution const std::string pathToUrl(url.Get()); const std::string pathToUrl2(realURL.Get()); if (pathToUrl != pathToUrl2) { for (int i = 0; i < items.Size(); ++i) { CFileItemPtr item = items[i]; item->SetPath(URIUtils::SubstitutePath(item->GetPath(), true)); } } return true; } XBMCCOMMONS_HANDLE_UNCHECKED catch (...) { CLog::Log(LOGERROR, "%s - Unhandled exception", __FUNCTION__); } CLog::Log(LOGERROR, "%s - Error getting %s", __FUNCTION__, url.GetRedacted().c_str()); return false; }