Example #1
0
bool CFile::OpenForWrite(const CURL& file, bool bOverWrite)
{
  try
  {
    CURL url = URIUtils::SubstitutePath(file);
    CURL authUrl = url;
    if (CPasswordManager::GetInstance().IsURLSupported(authUrl) && authUrl.GetUserName().empty())
      CPasswordManager::GetInstance().AuthenticateURL(authUrl);

    m_pFile = CFileFactory::CreateLoader(url);

    if (m_pFile && m_pFile->OpenForWrite(authUrl, bOverWrite))
    {
      // add this file to our directory cache (if it's stored)
      g_directoryCache.AddFile(url.Get());
      return true;
    }
    return false;
  }
  XBMCCOMMONS_HANDLE_UNCHECKED
  catch(...)
  {
    CLog::Log(LOGERROR, "%s - Unhandled exception opening %s", __FUNCTION__, file.GetRedacted().c_str());
  }
  CLog::Log(LOGERROR, "%s - Error opening %s", __FUNCTION__, file.GetRedacted().c_str());
  return false;
}
Example #2
0
File: File.cpp Project: Adeelb/xbmc
bool CFile::Exists(const CURL& file, bool bUseCache /* = true */)
{
  CURL url(URIUtils::SubstitutePath(file));

  try
  {
    if (bUseCache)
    {
      bool bPathInCache;
      if (g_directoryCache.FileExists(url.Get(), bPathInCache))
        return true;
      if (bPathInCache)
        return false;
    }

    std::unique_ptr<IFile> pFile(CFileFactory::CreateLoader(url));
    if (!pFile.get())
      return false;

    return pFile->Exists(url);
  }
  XBMCCOMMONS_HANDLE_UNCHECKED
  catch (CRedirectException *pRedirectEx)
  {
    // the file implementation decided this item should use a different implementation.
    // the exception will contain the new implementation and optional a redirected URL.
    CLog::Log(LOGDEBUG,"File::Exists - redirecting implementation for %s", file.GetRedacted().c_str());
    if (pRedirectEx && pRedirectEx->m_pNewFileImp)
    {
      std::unique_ptr<IFile> pImp(pRedirectEx->m_pNewFileImp);
      std::unique_ptr<CURL> pNewUrl(pRedirectEx->m_pNewUrl);
      delete pRedirectEx;

      if (pImp.get())
      {
        if (pNewUrl.get())
        {
          if (bUseCache)
          {
            bool bPathInCache;
            if (g_directoryCache.FileExists(pNewUrl->Get(), bPathInCache))
              return true;
            if (bPathInCache)
              return false;
          }
          return pImp->Exists(*pNewUrl);
        }
        else
          return pImp->Exists(url);
      }
    }
  }
  catch(...)
  {
    CLog::Log(LOGERROR, "%s - Unhandled exception", __FUNCTION__);
  }
  CLog::Log(LOGERROR, "%s - Error checking for %s", __FUNCTION__, file.GetRedacted().c_str());
  return false;
}
Example #3
0
int CFile::Stat(const CURL& file, struct __stat64* buffer)
{
  if (!buffer)
    return -1;

  CURL url(URIUtils::SubstitutePath(file));
  CURL authUrl = url;
  if (CPasswordManager::GetInstance().IsURLSupported(authUrl) && authUrl.GetUserName().empty())
    CPasswordManager::GetInstance().AuthenticateURL(authUrl);

  try
  {
    std::unique_ptr<IFile> pFile(CFileFactory::CreateLoader(url));
    if (!pFile.get())
      return -1;
    return pFile->Stat(authUrl, buffer);
  }
  XBMCCOMMONS_HANDLE_UNCHECKED
  catch (CRedirectException *pRedirectEx)
  {
    // the file implementation decided this item should use a different implementation.
    // the exception will contain the new implementation and optional a redirected URL.
    CLog::Log(LOGDEBUG,"File::Stat - redirecting implementation for %s", file.GetRedacted().c_str());
    if (pRedirectEx && pRedirectEx->m_pNewFileImp)
    {
      std::unique_ptr<IFile> pImp(pRedirectEx->m_pNewFileImp);
      std::unique_ptr<CURL> pNewUrl(pRedirectEx->m_pNewUrl);
      delete pRedirectEx;

      if (pNewUrl.get())
      {
        if (pImp.get())
        {
          CURL newAuthUrl = *pNewUrl;
          if (CPasswordManager::GetInstance().IsURLSupported(newAuthUrl) && newAuthUrl.GetUserName().empty())
            CPasswordManager::GetInstance().AuthenticateURL(newAuthUrl);

          if (!pImp->Stat(newAuthUrl, buffer))
          {
            return 0;
          }
        }
      }
      else
      {
        if (pImp.get() && !pImp->Stat(authUrl, buffer))
        {
          return 0;
        }
      }
    }
  }
  catch(...)
  {
    CLog::Log(LOGERROR, "%s - Unhandled exception", __FUNCTION__);
  }
  CLog::Log(LOGERROR, "%s - Error statting %s", __FUNCTION__, file.GetRedacted().c_str());
  return -1;
}
Example #4
0
bool CFileCache::Open(const CURL& url)
{
	Close();

	XR::CSingleLock lock(m_sync);

	LOGDEBUG("CFileCache::Open - opening <%s> using cache", url.GetRedacted().c_str());

	if (!m_pCache)
	{
		LOGERR("CFileCache::Open - no cache strategy defined");
		return false;
	}

	m_sourcePath = url.Get();

	// open cache strategy
	if (m_pCache->Open() != CACHE_RC_OK)
	{
		LOGERR("CFileCache::Open - failed to open cache");
		Close();
		return false;
	}

	// opening the source file.
	if (!m_source.Open(m_sourcePath, READ_NO_CACHE | READ_TRUNCATED | READ_CHUNKED))
	{
		LOGERR("Failed to open source <%s>", url.GetRedacted().c_str());
		Close();
		return false;
	}

	m_source.IoControl(IOCTRL_SET_CACHE, this);

	// check if source can seek
	m_seekPossible = m_source.IoControl(IOCTRL_SEEK_POSSIBLE, NULL);
	m_chunkSize = CFile::GetChunkSize(m_source.GetChunkSize(), READ_CACHE_CHUNK_SIZE);

	m_readPos = 0;
	m_writePos = 0;
	m_writeRate = 1024 * 1024;
	m_writeRateActual = 0;
	m_cacheFull = false;
	m_seekEvent.Reset();
	m_seekEnded.Reset();

	CThread::Create(false);

	return true;
}
Example #5
0
bool CSMBFile::Open(const CURL& url)
{
  Close();

  // we can't open files like smb://file.f or smb://server/file.f
  // if a file matches the if below return false, it can't exist on a samba share.
  if (!IsValidFile(url.GetFileName()))
  {
      CLog::Log(LOGNOTICE,"SMBFile->Open: Bad URL : '%s'",url.GetRedacted().c_str());
      return false;
  }
  m_url = url;

  // opening a file to another computer share will create a new session
  // when opening smb://server xbms will try to find folder.jpg in all shares
  // listed, which will create lot's of open sessions.

  std::string strFileName;
  m_fd = OpenFile(url, strFileName);

  CLog::Log(LOGDEBUG,"CSMBFile::Open - opened %s, fd=%d",url.GetRedacted().c_str(), m_fd);
  if (m_fd == -1)
  {
    // write error to logfile
    CLog::Log(LOGINFO, "SMBFile->Open: Unable to open file : '%s'\nunix_err:'%x' error : '%s'", CURL::GetRedacted(strFileName).c_str(), errno, strerror(errno));
    return false;
  }

  CSingleLock lock(smb);
  struct stat tmpBuffer;
  if (smbc_stat(strFileName.c_str(), &tmpBuffer) < 0)
  {
    smbc_close(m_fd);
    m_fd = -1;
    return false;
  }

  m_fileSize = tmpBuffer.st_size;

  int64_t ret = smbc_lseek(m_fd, 0, SEEK_SET);
  if ( ret < 0 )
  {
    smbc_close(m_fd);
    m_fd = -1;
    return false;
  }
  // We've successfully opened the file!
  return true;
}
Example #6
0
bool CDAVFile::Rename(const CURL& url, const CURL& urlnew)
{
  if (m_opened)
    return false;

  CDAVFile dav;

  CURL url2(urlnew);
  std::string strProtocol = url2.GetTranslatedProtocol();
  url2.SetProtocol(strProtocol);

  std::string strRequest = "MOVE";
  dav.SetCustomRequest(strRequest);
  dav.SetRequestHeader("Destination", url2.GetWithoutUserDetails());

  CLog::Log(LOGDEBUG, "CDAVFile::Rename - Execute MOVE (%s -> %s)", url.GetRedacted().c_str(), url2.GetRedacted().c_str());
  if (!dav.Execute(url))
  {
    CLog::Log(LOGERROR, "CDAVFile::Rename - Unable to rename dav resource (%s -> %s)", url.GetRedacted().c_str(), url2.GetRedacted().c_str());
    return false;
  }

  dav.Close();

  return true;
}
Example #7
0
bool CFile::Delete(const CURL& file)
{
  try
  {
    CURL url(URIUtils::SubstitutePath(file));

    unique_ptr<IFile> pFile(CFileFactory::CreateLoader(url));
    if (!pFile.get())
      return false;

    if(pFile->Delete(url))
    {
      g_directoryCache.ClearFile(url.Get());
      return true;
    }
  }
  XBMCCOMMONS_HANDLE_UNCHECKED
  catch(...)
  {
    CLog::Log(LOGERROR, "%s - Unhandled exception", __FUNCTION__);
  }
  if (Exists(file))
    CLog::Log(LOGERROR, "%s - Error deleting file %s", __FUNCTION__, file.GetRedacted().c_str());
  return false;
}
Example #8
0
StorageFolder CWinLibraryDirectory::GetFolder(const CURL& url)
{
  StorageFolder rootFolder = GetRootFolder(url);
  if (!rootFolder)
    return nullptr;

  // find inner folder
  std::string folderPath = URIUtils::FixSlashesAndDups(url.GetFileName(), '\\');
  if (!folderPath.empty())
  {
    try
    {
      std::wstring wStrPath = ToW(folderPath);

      auto item = Wait(rootFolder.TryGetItemAsync(wStrPath));
      if (item && item.IsOfType(StorageItemTypes::Folder))
        return item.as<StorageFolder>();

      return nullptr;
    }
    catch (const winrt::hresult_error& ex)
    {
      std::string error = FromW(ex.message().c_str());
      CLog::LogF(LOGERROR, "unable to get folder '%s' with error", url.GetRedacted().c_str(),
                 error.c_str());
    }
    return nullptr;
  }

  return rootFolder;
}
Example #9
0
bool CFile::Rename(const CURL& file, const CURL& newFile)
{
  try
  {
    CURL url(URIUtils::SubstitutePath(file));
    CURL urlnew(URIUtils::SubstitutePath(newFile));

    CURL authUrl = url;
    if (CPasswordManager::GetInstance().IsURLSupported(authUrl) && authUrl.GetUserName().empty())
      CPasswordManager::GetInstance().AuthenticateURL(authUrl);
    CURL authUrlNew = urlnew;
    if (CPasswordManager::GetInstance().IsURLSupported(authUrlNew) && authUrlNew.GetUserName().empty())
      CPasswordManager::GetInstance().AuthenticateURL(authUrlNew);

    std::unique_ptr<IFile> pFile(CFileFactory::CreateLoader(url));
    if (!pFile.get())
      return false;

    if(pFile->Rename(authUrl, authUrlNew))
    {
      g_directoryCache.ClearFile(url.Get());
      g_directoryCache.AddFile(urlnew.Get());
      return true;
    }
  }
  XBMCCOMMONS_HANDLE_UNCHECKED
  catch(...)
  {
    CLog::Log(LOGERROR, "%s - Unhandled exception ", __FUNCTION__);
  }
  CLog::Log(LOGERROR, "%s - Error renaming file %s", __FUNCTION__, file.GetRedacted().c_str());
  return false;
}
Example #10
0
bool CDirectory::Exists(const CURL& url, bool bUseCache /* = true */)
{
  try
  {
    CURL realURL = URIUtils::SubstitutePath(url);
    if (bUseCache)
    {
      bool bPathInCache;
      std::string realPath(realURL.Get());
      URIUtils::AddSlashAtEnd(realPath);
      if (g_directoryCache.FileExists(realPath, bPathInCache))
        return true;
      if (bPathInCache)
        return false;
    }
    unique_ptr<IDirectory> pDirectory(CDirectoryFactory::Create(realURL));
    if (pDirectory.get())
      return pDirectory->Exists(realURL);
  }
  XBMCCOMMONS_HANDLE_UNCHECKED
  catch (...)
  {
    CLog::Log(LOGERROR, "%s - Unhandled exception", __FUNCTION__);
  }
  CLog::Log(LOGERROR, "%s - Error checking for %s", __FUNCTION__, url.GetRedacted().c_str());
  return false;
}
Example #11
0
File: File.cpp Project: Adeelb/xbmc
bool CFile::Rename(const CURL& file, const CURL& newFile)
{
  try
  {
    CURL url(URIUtils::SubstitutePath(file));
    CURL urlnew(URIUtils::SubstitutePath(newFile));

    std::unique_ptr<IFile> pFile(CFileFactory::CreateLoader(url));
    if (!pFile.get())
      return false;

    if(pFile->Rename(url, urlnew))
    {
      g_directoryCache.ClearFile(url.Get());
      g_directoryCache.AddFile(urlnew.Get());
      return true;
    }
  }
  XBMCCOMMONS_HANDLE_UNCHECKED
  catch(...)
  {
    CLog::Log(LOGERROR, "%s - Unhandled exception ", __FUNCTION__);
  }
  CLog::Log(LOGERROR, "%s - Error renaming file %s", __FUNCTION__, file.GetRedacted().c_str());
  return false;
}
Example #12
0
int CDAVFile::Stat(const CURL& url, struct __stat64* buffer)
{
  CDAVFile dav;
  std::string strRequest = "PROPFIND";
  dav.SetCustomRequest(strRequest);
  dav.SetRequestHeader("depth", 0);
  dav.SetMimeType("text/xml; charset=\"utf-8\"");

  if (buffer)
  {
    CLog::Log(LOGDEBUG, "CDAVFile::Stat - Execute STAT (%s)", url.GetRedacted().c_str());

    dav.SetPostData(
      "<?xml version=\"1.0\" encoding=\"utf-8\" ?>"
      " <D:propfind xmlns:D=\"DAV:\">"
      "   <D:prop>"
      "     <D:resourcetype/>"
      "     <D:getcontentlength/>"
      "     <D:getlastmodified/>"
      "     <D:creationdate/>"
      "     <D:displayname/>"
      "    </D:prop>"
      "  </D:propfind>");
  }
  else
  {
    dav.SetPostData(
      "<?xml version=\"1.0\" encoding=\"utf-8\" ?>");
  }

  if (!dav.Execute(url))
  {
    if (buffer)
      CLog::Log(LOGERROR, "CDAVFile::Stat - Unable to stat resource (%s) with code %i", url.GetRedacted().c_str(), m_lastResponseCode);

    return -1;
  }

  dav.Close();

  // Iterate over all responses
  for (TiXmlNode *pChild = m_davResponse.RootElement()->FirstChild(); pChild != 0; pChild = pChild->NextSibling())
  {
    if (CDAVCommon::ValueWithoutNamespace(pChild, "response"))
    {
      if (ParseResponse(pChild->ToElement(), buffer))
        return 0;
      else
        return -1;
    }
  }

  return -1;
}
Example #13
0
bool CDAVFile::Delete(const CURL& url)
{
  if (m_opened)
    return false;

  CDAVFile dav;
  std::string strRequest = "DELETE";

  dav.SetCustomRequest(strRequest);

  CLog::Log(LOGDEBUG, "CDAVFile::Delete - Execute DELETE (%s)", url.GetRedacted().c_str());
  if (!dav.Execute(url))
  {
    CLog::Log(LOGERROR, "CDAVFile::Delete - Unable to delete dav resource (%s)", url.GetRedacted().c_str());
    return false;
  }

  dav.Close();

  return true;
}
Example #14
0
bool CFile::OpenForWrite(const CURL& file, bool bOverWrite)
{
  try
  {
    CURL url = URIUtils::SubstitutePath(file);

    m_pFile = CFileFactory::CreateLoader(url);
    if (m_pFile && m_pFile->OpenForWrite(url, bOverWrite))
    {
      // add this file to our directory cache (if it's stored)
      g_directoryCache.AddFile(url.Get());
      return true;
    }
    return false;
  }
  XBMCCOMMONS_HANDLE_UNCHECKED
  catch(...)
  {
    CLog::Log(LOGERROR, "%s - Unhandled exception opening %s", __FUNCTION__, file.GetRedacted().c_str());
  }
  CLog::Log(LOGERROR, "%s - Error opening %s", __FUNCTION__, file.GetRedacted().c_str());
  return false;
}
Example #15
0
bool CMultiPathDirectory::Exists(const CURL& url)
{
  CLog::Log(LOGDEBUG,"Testing Existence (%s)", url.GetRedacted().c_str());

  std::vector<std::string> vecPaths;
  if (!GetPaths(url, vecPaths))
    return false;

  for (unsigned int i = 0; i < vecPaths.size(); ++i)
  {
    CLog::Log(LOGDEBUG,"Testing Existence (%s)", vecPaths[i].c_str());
    if (CDirectory::Exists(vecPaths[i]))
      return true;
  }
  return false;
}
Example #16
0
StorageFolder^ CWinLibraryDirectory::GetFolder(const CURL& url)
{
  StorageFolder^ rootFolder = GetRootFolder(url);
  if (!rootFolder)
    return nullptr;

  // find inner folder
  std::string folderPath = URIUtils::FixSlashesAndDups(url.GetFileName(), '\\');
  if (url.GetHostName() == "removable")
  {
    // here path has the form e\path where first segment is drive letter
    // we should make path form like regular e:\path
    auto index = folderPath.find('\\');
    if (index != std::string::npos)
    {
      folderPath = folderPath.insert(index, 1, ':');
    }
    // win-lib://removable/F -> folderPath contains only drive letter
    else if (index == std::string::npos && folderPath.length() == 1)
    {
      folderPath += ":\\";
    }
    else
    {
      return nullptr;
    }
  }

  if (!folderPath.empty())
  {
    try
    {
      std::wstring wStrPath = ToW(folderPath);
      Platform::String^ pPath = ref new Platform::String(wStrPath.c_str());
      return Wait(rootFolder->GetFolderAsync(pPath));
    }
    catch (Platform::Exception^ ex)
    {
      std::string error = FromW(std::wstring(ex->Message->Data()));
      CLog::LogF(LOGERROR, "unable to get folder '%s' with error", url.GetRedacted().c_str(), error.c_str());
    }
    return nullptr;
  }

  return rootFolder;
}
Example #17
0
bool CDirectory::Create(const CURL& url)
{
  try
  {
    CURL realURL = URIUtils::SubstitutePath(url);
    unique_ptr<IDirectory> pDirectory(CDirectoryFactory::Create(realURL));
    if (pDirectory.get())
      if(pDirectory->Create(realURL))
        return true;
  }
  XBMCCOMMONS_HANDLE_UNCHECKED
  catch (...)
  {
    CLog::Log(LOGERROR, "%s - Unhandled exception", __FUNCTION__);
  }
  CLog::Log(LOGERROR, "%s - Error creating %s", __FUNCTION__, url.GetRedacted().c_str());
  return false;
}
Example #18
0
File: File.cpp Project: Adeelb/xbmc
bool CFile::SetHidden(const CURL& file, bool hidden)
{
  try
  {
    CURL url(URIUtils::SubstitutePath(file));

    std::unique_ptr<IFile> pFile(CFileFactory::CreateLoader(url));
    if (!pFile.get())
      return false;

    return pFile->SetHidden(url, hidden);
  }
  catch(...)
  {
    CLog::Log(LOGERROR, "%s(%s) - Unhandled exception", __FUNCTION__, file.GetRedacted().c_str());
  }
  return false;
}
Example #19
0
bool CFile::SetHidden(const CURL& file, bool hidden)
{
  try
  {
    CURL url(URIUtils::SubstitutePath(file));
    CURL authUrl = url;
    if (CPasswordManager::GetInstance().IsURLSupported(authUrl) && authUrl.GetUserName().empty())
      CPasswordManager::GetInstance().AuthenticateURL(authUrl);

    std::unique_ptr<IFile> pFile(CFileFactory::CreateLoader(url));
    if (!pFile.get())
      return false;

    return pFile->SetHidden(authUrl, hidden);
  }
  catch(...)
  {
    CLog::Log(LOGERROR, "%s(%s) - Unhandled exception", __FUNCTION__, file.GetRedacted().c_str());
  }
  return false;
}
Example #20
0
    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());

      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();
    }
Example #21
0
bool CFileCache::Open(const CURL& url)
{
  Close();

  CSingleLock lock(m_sync);

  CLog::Log(LOGDEBUG,"CFileCache::Open - opening <%s> using cache", url.GetFileName().c_str());

  m_sourcePath = url.Get();

  // opening the source file.
  if (!m_source.Open(m_sourcePath, READ_NO_CACHE | READ_TRUNCATED | READ_CHUNKED))
  {
    CLog::Log(LOGERROR,"%s - failed to open source <%s>", __FUNCTION__, url.GetRedacted().c_str());
    Close();
    return false;
  }

  m_source.IoControl(IOCTRL_SET_CACHE, this);

  bool retry = false;
  m_source.IoControl(IOCTRL_SET_RETRY, &retry); // We already handle retrying ourselves

  // check if source can seek
  m_seekPossible = m_source.IoControl(IOCTRL_SEEK_POSSIBLE, NULL);
  m_chunkSize = CFile::GetChunkSize(m_source.GetChunkSize(), READ_CACHE_CHUNK_SIZE);
  m_fileSize = m_source.GetLength();

  if (!m_pCache)
  {
    if (g_advancedSettings.m_cacheMemBufferSize == 0)
    {
      // Use cache on disk
      m_pCache = new CSimpleFileCache();
      m_forwardCacheSize = 0;
    }
    else
    {
      size_t cacheSize;
      if (m_fileSize > 0 && m_fileSize < g_advancedSettings.m_cacheMemBufferSize && !(m_flags & READ_AUDIO_VIDEO))
      {
        // NOTE: We don't need to take into account READ_MULTI_STREAM here as it's only used for audio/video
        cacheSize = m_fileSize;
      }
      else
      {
        cacheSize = g_advancedSettings.m_cacheMemBufferSize;
      }

      size_t back = cacheSize / 4;
      size_t front = cacheSize - back;
      
      if (m_flags & READ_MULTI_STREAM)
      {
        // READ_MULTI_STREAM requires double buffering, so use half the amount of memory for each buffer
        front /= 2;
        back /= 2;
      }
      m_pCache = new CCircularCache(front, back);
      m_forwardCacheSize = front;
    }

    if (m_flags & READ_MULTI_STREAM)
    {
      // If READ_MULTI_STREAM flag is set: Double buffering is required
      m_pCache = new CDoubleCache(m_pCache);
    }
  }

  // open cache strategy
  if (!m_pCache || m_pCache->Open() != CACHE_RC_OK)
  {
    CLog::Log(LOGERROR,"CFileCache::Open - failed to open cache");
    Close();
    return false;
  }
  
  m_readPos = 0;
  m_writePos = 0;
  m_writeRate = 1024 * 1024;
  m_writeRateActual = 0;
  m_seekEvent.Reset();
  m_seekEnded.Reset();

  CThread::Create(false);

  return true;
}
Example #22
0
bool CFile::Open(const CURL& file, const unsigned int flags)
{
  if (m_pFile)
  {
    if ((flags & READ_REOPEN) == 0)
    {
      CLog::Log(LOGERROR, "File::Open - already open: %s", file.GetRedacted().c_str());
      return false;
    }
    else
    {
      return m_pFile->ReOpen(URIUtils::SubstitutePath(file));
    }
  }

  m_flags = flags;
  try
  {
    bool bPathInCache;

    CURL url(URIUtils::SubstitutePath(file)), url2(url);

    if (url2.IsProtocol("apk") || url2.IsProtocol("zip") )
      url2.SetOptions("");

    if (!g_directoryCache.FileExists(url2.Get(), bPathInCache) )
    {
      if (bPathInCache)
        return false;
    }

    if (!(m_flags & READ_NO_CACHE))
    {
      const std::string pathToUrl(url.Get());
      if (URIUtils::IsInternetStream(url, true) && !CUtil::IsPicture(pathToUrl) )
        m_flags |= READ_CACHED;

      if (m_flags & READ_CACHED)
      {
        // for internet stream, if it contains multiple stream, file cache need handle it specially.
        m_pFile = new CFileCache(m_flags);

        if (!m_pFile)
          return false;

        return m_pFile->Open(url);
      }
    }
    m_pFile = CFileFactory::CreateLoader(url);

    if (!m_pFile)
      return false;

    CURL authUrl(url);
    if (CPasswordManager::GetInstance().IsURLSupported(authUrl) && authUrl.GetUserName().empty())
      CPasswordManager::GetInstance().AuthenticateURL(authUrl);

    try
    {
      if (!m_pFile->Open(authUrl))
      {
        SAFE_DELETE(m_pFile);
        return false;
      }
    }
    catch (CRedirectException *pRedirectEx)
    {
      // the file implementation decided this item should use a different implementation.
      // the exception will contain the new implementation.
      CLog::Log(LOGDEBUG,"File::Open - redirecting implementation for %s", file.GetRedacted().c_str());
      SAFE_DELETE(m_pFile);
      if (pRedirectEx && pRedirectEx->m_pNewFileImp)
      {
        std::unique_ptr<CURL> pNewUrl(pRedirectEx->m_pNewUrl);
        m_pFile = pRedirectEx->m_pNewFileImp;
        delete pRedirectEx;

        if (pNewUrl.get())
        {
          CURL newAuthUrl(*pNewUrl);
          if (CPasswordManager::GetInstance().IsURLSupported(newAuthUrl) && newAuthUrl.GetUserName().empty())
            CPasswordManager::GetInstance().AuthenticateURL(newAuthUrl);

          if (!m_pFile->Open(newAuthUrl))
          {
            SAFE_DELETE(m_pFile);
            return false;
          }
        }
        else
        {
          if (!m_pFile->Open(authUrl))
          {
            SAFE_DELETE(m_pFile);
            return false;
          }
        }
      }
    }
    catch (...)
    {
      CLog::Log(LOGERROR, "File::Open - unknown exception when opening %s", file.GetRedacted().c_str());
      SAFE_DELETE(m_pFile);
      return false;
    }

    if (m_pFile->GetChunkSize() && !(m_flags & READ_CHUNKED))
    {
      m_pBuffer = new CFileStreamBuffer(0);
      m_pBuffer->Attach(m_pFile);
    }

    if (m_flags & READ_BITRATE)
    {
      m_bitStreamStats = new BitstreamStats();
      m_bitStreamStats->Start();
    }

    return true;
  }
  XBMCCOMMONS_HANDLE_UNCHECKED
  catch(...)
  {
    CLog::Log(LOGERROR, "%s - Unhandled exception", __FUNCTION__);
  }
  CLog::Log(LOGERROR, "%s - Error opening %s", __FUNCTION__, file.GetRedacted().c_str());
  return false;
}
Example #23
0
bool CFile::Copy(const CURL& url2, const CURL& dest, XFILE::IFileCallback* pCallback, void* pContext)
{
  CFile file;

  const std::string pathToUrl(dest.Get());
  if (pathToUrl.empty())
    return false;

  // special case for zips - ignore caching
  CURL url(url2);
  if (URIUtils::IsInZIP(url.Get()) || URIUtils::IsInAPK(url.Get()))
    url.SetOptions("?cache=no");
  if (file.Open(url.Get(), READ_TRUNCATED | READ_CHUNKED))
  {

    CFile newFile;
    if (URIUtils::IsHD(pathToUrl)) // create possible missing dirs
    {
      std::vector<std::string> tokens;
      std::string strDirectory = URIUtils::GetDirectory(pathToUrl);
      URIUtils::RemoveSlashAtEnd(strDirectory);  // for the test below
      if (!(strDirectory.size() == 2 && strDirectory[1] == ':'))
      {
        CURL url(strDirectory);
        std::string pathsep;
#ifndef TARGET_POSIX
        pathsep = "\\";
#else
        pathsep = "/";
#endif
        // Try to use the recursive creation first, if it fails
        // it might not be implemented for that subsystem so let's
        // fall back to the old method in that case
        if (!CDirectory::Create(url))
        {
          StringUtils::Tokenize(url.GetFileName(), tokens, pathsep.c_str());
          std::string strCurrPath;
          // Handle special
          if (!url.GetProtocol().empty())
          {
            pathsep = "/";
            strCurrPath += url.GetProtocol() + "://";
          } // If the directory has a / at the beginning, don't forget it
          else if (strDirectory[0] == pathsep[0])
            strCurrPath += pathsep;

          for (std::vector<std::string>::iterator iter = tokens.begin(); iter != tokens.end(); ++iter)
          {
            strCurrPath += *iter + pathsep;
            CDirectory::Create(strCurrPath);
          }
        }
      }
    }
    if (CFile::Exists(dest))
      CFile::Delete(dest);
    if (!newFile.OpenForWrite(dest, true))  // overwrite always
    {
      file.Close();
      return false;
    }

    int iBufferSize = GetChunkSize(file.GetChunkSize(), 128 * 1024);

    auto_buffer buffer(iBufferSize);
    ssize_t iRead, iWrite;

    unsigned long long llFileSize = file.GetLength();
    unsigned long long llPos = 0;

    CStopWatch timer;
    timer.StartZero();
    float start = 0.0f;
    while (true)
    {
      g_application.ResetScreenSaver();

      iRead = file.Read(buffer.get(), iBufferSize);
      if (iRead == 0) break;
      else if (iRead < 0)
      {
        CLog::Log(LOGERROR, "%s - Failed read from file %s", __FUNCTION__, url.GetRedacted().c_str());
        llFileSize = (uint64_t)-1;
        break;
      }

      /* write data and make sure we managed to write it all */
      iWrite = 0;
      while(iWrite < iRead)
      {
        ssize_t iWrite2 = newFile.Write(buffer.get() + iWrite, iRead - iWrite);
        if(iWrite2 <=0)
          break;
        iWrite+=iWrite2;
      }

      if (iWrite != iRead)
      {
        CLog::Log(LOGERROR, "%s - Failed write to file %s", __FUNCTION__, dest.GetRedacted().c_str());
        llFileSize = (uint64_t)-1;
        break;
      }

      llPos += iRead;

      // calculate the current and average speeds
      float end = timer.GetElapsedSeconds();

      if (pCallback && end - start > 0.5 && end)
      {
        start = end;

        float averageSpeed = llPos / end;
        int ipercent = 0;
        if(llFileSize)
          ipercent = 100 * llPos / llFileSize;

        if(!pCallback->OnFileCallback(pContext, ipercent, averageSpeed))
        {
          CLog::Log(LOGERROR, "%s - User aborted copy", __FUNCTION__);
          llFileSize = (uint64_t)-1;
          break;
        }
      }
    }

    /* close both files */
    newFile.Close();
    file.Close();

    /* verify that we managed to completed the file */
    if (llFileSize && llPos != llFileSize)
    {
      CFile::Delete(dest);
      return false;
    }
    return true;
  }
  return false;
}
Example #24
0
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;
}
Example #25
0
bool CDAVDirectory::Remove(const CURL& url)
{
  CDAVFile dav;
  std::string strRequest = "DELETE";

  dav.SetCustomRequest(strRequest);
 
  if (!dav.Execute(url))
  {
    CLog::Log(LOGERROR, "%s - Unable to delete dav directory (%s) - %d", __FUNCTION__, url.GetRedacted().c_str(), dav.GetLastResponseCode());
    return false;
  }

  dav.Close();

  return true;
}
Example #26
0
bool CDAVDirectory::GetDirectory(const CURL& url, CFileItemList &items)
{
  CCurlFile dav;
  std::string strRequest = "PROPFIND";

  dav.SetCustomRequest(strRequest);
  dav.SetMimeType("text/xml; charset=\"utf-8\"");
  dav.SetRequestHeader("depth", 1);
  dav.SetPostData(
    "<?xml version=\"1.0\" encoding=\"utf-8\" ?>"
    " <D:propfind xmlns:D=\"DAV:\">"
    "   <D:prop>"
    "     <D:resourcetype/>"
    "     <D:getcontentlength/>"
    "     <D:getlastmodified/>"
    "     <D:creationdate/>"
    "     <D:displayname/>"
    "    </D:prop>"
    "  </D:propfind>");

  if (!dav.Open(url))
  {
    CLog::Log(LOGERROR, "%s - Unable to get dav directory (%s)", __FUNCTION__, url.GetRedacted().c_str());
    return false;
  }

  std::string strResponse;
  dav.ReadData(strResponse);

  std::string fileCharset(dav.GetProperty(XFILE::FILE_PROPERTY_CONTENT_CHARSET));
  CXBMCTinyXML davResponse;
  davResponse.Parse(strResponse, fileCharset);

  if (!davResponse.Parse(strResponse))
  {
    CLog::Log(LOGERROR, "%s - Unable to process dav directory (%s)", __FUNCTION__, url.GetRedacted().c_str());
    dav.Close();
    return false;
  }

  TiXmlNode *pChild;
  // Iterate over all responses
  for (pChild = davResponse.RootElement()->FirstChild(); pChild != 0; pChild = pChild->NextSibling())
  {
    if (CDAVCommon::ValueWithoutNamespace(pChild, "response"))
    {
      CFileItem item;
      ParseResponse(pChild->ToElement(), item);
      CURL url2(url);
      CURL url3(item.GetPath());

      std::string itemPath(URIUtils::AddFileToFolder(url2.GetWithoutFilename(), url3.GetFileName()));

      if (item.GetLabel().empty())
      {
        std::string name(itemPath);
        URIUtils::RemoveSlashAtEnd(name);
        item.SetLabel(CURL::Decode(URIUtils::GetFileName(name)));
      }

      if (item.m_bIsFolder)
        URIUtils::AddSlashAtEnd(itemPath);

      // Add back protocol options
      if (!url2.GetProtocolOptions().empty())
        itemPath += "|" + url2.GetProtocolOptions();
      item.SetPath(itemPath);

      if (!item.IsURL(url))
      {
        CFileItemPtr pItem(new CFileItem(item));
        items.Add(pItem);
      }
    }
  }

  dav.Close();

  return true;
}
Example #27
0
bool CDAVFile::Exists(const CURL& url)
{
  if (Stat(url, NULL) != 0)
  {
    if (m_lastResponseCode >= 400 && m_lastResponseCode != 404)
      CLog::Log(LOGERROR, "CDAVFile::Exists - Unable to stat resource (%s) with code %i", url.GetRedacted().c_str(), m_lastResponseCode);

    return false;
  }

  return true;
}
Example #28
0
bool CMultiPathDirectory::GetDirectory(const CURL& url, CFileItemList &items)
{
  CLog::Log(LOGDEBUG,"CMultiPathDirectory::GetDirectory(%s)", url.GetRedacted().c_str());

  std::vector<std::string> vecPaths;
  if (!GetPaths(url, vecPaths))
    return false;

  XbmcThreads::EndTime progressTime(3000); // 3 seconds before showing progress bar
  CGUIDialogProgress* dlgProgress = NULL;

  unsigned int iFailures = 0;
  for (unsigned int i = 0; i < vecPaths.size(); ++i)
  {
    // show the progress dialog if we have passed our time limit
    if (progressTime.IsTimePast() && !dlgProgress)
    {
      dlgProgress = g_windowManager.GetWindow<CGUIDialogProgress>(WINDOW_DIALOG_PROGRESS);
      if (dlgProgress)
      {
        dlgProgress->SetHeading(CVariant{15310});
        dlgProgress->SetLine(0, CVariant{15311});
        dlgProgress->SetLine(1, CVariant{""});
        dlgProgress->SetLine(2, CVariant{""});
        dlgProgress->Open();
        dlgProgress->ShowProgressBar(true);
        dlgProgress->SetProgressMax((int)vecPaths.size()*2);
        dlgProgress->Progress();
      }
    }
    if (dlgProgress)
    {
      CURL url(vecPaths[i]);
      dlgProgress->SetLine(1, CVariant{url.GetWithoutUserDetails()});
      dlgProgress->SetProgressAdvance();
      dlgProgress->Progress();
    }

    CFileItemList tempItems;
    CLog::Log(LOGDEBUG,"Getting Directory (%s)", vecPaths[i].c_str());
    if (CDirectory::GetDirectory(vecPaths[i], tempItems, m_strFileMask, m_flags))
      items.Append(tempItems);
    else
    {
      CLog::Log(LOGERROR,"Error Getting Directory (%s)", vecPaths[i].c_str());
      iFailures++;
    }

    if (dlgProgress)
    {
      dlgProgress->SetProgressAdvance();
      dlgProgress->Progress();
    }
  }

  if (dlgProgress)
    dlgProgress->Close();

  if (iFailures == vecPaths.size())
    return false;

  // merge like-named folders into a sub multipath:// style url
  MergeItems(items);

  return true;
}
Example #29
0
bool CZipManager::GetZipList(const CURL& url, vector<SZipEntry>& items)
{
  CLog::Log(LOGDEBUG, "%s - Processing %s", __FUNCTION__, url.GetRedacted().c_str());

  struct __stat64 m_StatData = {};

  std::string strFile = url.GetHostName();

  if (CFile::Stat(strFile,&m_StatData))
  {
    CLog::Log(LOGDEBUG,"CZipManager::GetZipList: failed to stat file %s", url.GetRedacted().c_str());
    return false;
  }

  map<std::string,vector<SZipEntry> >::iterator it = mZipMap.find(strFile);
  if (it != mZipMap.end()) // already listed, just return it if not changed, else release and reread
  {
    map<std::string,int64_t>::iterator it2=mZipDate.find(strFile);
    CLog::Log(LOGDEBUG,"statdata: %" PRId64" new: %" PRIu64, it2->second, (uint64_t)m_StatData.st_mtime);

      if (m_StatData.st_mtime == it2->second)
      {
        items = it->second;
        return true;
      }
      mZipMap.erase(it);
      mZipDate.erase(it2);
  }

  CFile mFile;
  if (!mFile.Open(strFile))
  {
    CLog::Log(LOGDEBUG,"ZipManager: unable to open file %s!",strFile.c_str());
    return false;
  }

  unsigned int hdr;
  if (mFile.Read(&hdr, 4)!=4 || (Endian_SwapLE32(hdr) != ZIP_LOCAL_HEADER &&
                                 Endian_SwapLE32(hdr) != ZIP_DATA_RECORD_HEADER &&
                                 Endian_SwapLE32(hdr) != ZIP_SPLIT_ARCHIVE_HEADER))
  {
    CLog::Log(LOGDEBUG,"ZipManager: not a zip file!");
    mFile.Close();
    return false;
  }

  if (Endian_SwapLE32(hdr) == ZIP_SPLIT_ARCHIVE_HEADER)
    CLog::LogF(LOGWARNING, "ZIP split archive header found. Trying to process as a single archive..");

  // push date for update detection
  mZipDate.insert(make_pair(strFile,m_StatData.st_mtime));


  // Look for end of central directory record
  // Zipfile comment may be up to 65535 bytes
  // End of central directory record is 22 bytes (ECDREC_SIZE)
  // -> need to check the last 65557 bytes
  int64_t fileSize = mFile.GetLength();
  // Don't need to look in the last 18 bytes (ECDREC_SIZE-4)
  // But as we need to do overlapping between blocks (3 bytes),
  // we start the search at ECDREC_SIZE-1 from the end of file
  int searchSize = (int) min(65557, fileSize-ECDREC_SIZE+1);
  int blockSize = (int) min(1024, searchSize);
  int nbBlock = searchSize / blockSize;
  int extraBlockSize = searchSize % blockSize;
  // Signature is on 4 bytes
  // It could be between 2 blocks, so we need to read 3 extra bytes
  auto_buffer buffer(blockSize + 3);
  bool found = false;

  // Loop through blocks starting at the end of the file (minus ECDREC_SIZE-1)
  for (int nb=1; !found && (nb <= nbBlock); nb++)
  {
    mFile.Seek(fileSize-ECDREC_SIZE+1-(blockSize*nb),SEEK_SET);
    if (mFile.Read(buffer.get(), blockSize + 3) != blockSize + 3)
      return false;
    for (int i=blockSize-1; !found && (i >= 0); i--)
    {
      if ( Endian_SwapLE32(*((unsigned int*)(buffer.get()+i))) == ZIP_END_CENTRAL_HEADER )
      {
        // Set current position to start of end of central directory
        mFile.Seek(fileSize-ECDREC_SIZE+1-(blockSize*nb)+i,SEEK_SET);
        found = true;
      }
    }
  }

  // If not found, look in the last block left...
  if ( !found && (extraBlockSize > 0) )
  {
    mFile.Seek(fileSize-ECDREC_SIZE+1-searchSize,SEEK_SET);
    if (mFile.Read(buffer.get(), extraBlockSize + 3) != extraBlockSize + 3)
      return false;
    for (int i=extraBlockSize-1; !found && (i >= 0); i--)
    {
      if ( Endian_SwapLE32(*((unsigned int*)(buffer.get()+i))) == ZIP_END_CENTRAL_HEADER )
      {
        // Set current position to start of end of central directory
        mFile.Seek(fileSize-ECDREC_SIZE+1-searchSize+i,SEEK_SET);
        found = true;
      }
    }
  }

  buffer.clear();

  if ( !found )
  {
    CLog::Log(LOGDEBUG,"ZipManager: broken file %s!",strFile.c_str());
    mFile.Close();
    return false;
  }

  unsigned int cdirOffset, cdirSize;
  // Get size of the central directory
  mFile.Seek(12,SEEK_CUR);
  if (mFile.Read(&cdirSize, 4) != 4)
    return false;
  cdirSize = Endian_SwapLE32(cdirSize);
  // Get Offset of start of central directory with respect to the starting disk number
  if (mFile.Read(&cdirOffset, 4) != 4)
    return false;
  cdirOffset = Endian_SwapLE32(cdirOffset);

  // Go to the start of central directory
  mFile.Seek(cdirOffset,SEEK_SET);

  char temp[CHDR_SIZE];
  while (mFile.GetPosition() < cdirOffset + cdirSize)
  {
    SZipEntry ze;
    if (mFile.Read(temp, CHDR_SIZE) != CHDR_SIZE)
      return false;
    readCHeader(temp, ze);
    if (ze.header != ZIP_CENTRAL_HEADER)
    {
      CLog::Log(LOGDEBUG,"ZipManager: broken file %s!",strFile.c_str());
      mFile.Close();
      return false;
    }

    // Get the filename just after the central file header
    auto_buffer bufName(ze.flength);
    if (mFile.Read(bufName.get(), ze.flength) != ze.flength)
      return false;
    std::string strName(bufName.get(), bufName.size());
    bufName.clear();
    g_charsetConverter.unknownToUTF8(strName);
    ZeroMemory(ze.name, 255);
    strncpy(ze.name, strName.c_str(), strName.size()>254 ? 254 : strName.size());

    // Jump after central file header extra field and file comment
    mFile.Seek(ze.eclength + ze.clength,SEEK_CUR);

    items.push_back(ze);
  }

  /* go through list and figure out file header lengths */
  for(vector<SZipEntry>::iterator it = items.begin(); it != items.end(); ++it)
  {
    SZipEntry& ze = *it;
    // Go to the local file header to get the extra field length
    // !! local header extra field length != central file header extra field length !!
    mFile.Seek(ze.lhdrOffset+28,SEEK_SET);
    if (mFile.Read(&(ze.elength), 2) != 2)
      return false;
    ze.elength = Endian_SwapLE16(ze.elength);

    // Compressed data offset = local header offset + size of local header + filename length + local file header extra field length
    ze.offset = ze.lhdrOffset + LHDR_SIZE + ze.flength + ze.elength;

  }

  mZipMap.insert(make_pair(strFile,items));
  mFile.Close();
  return true;
}