Exemplo n.º 1
0
// return NULL + set pItem->m_bIsFolder to remove it completely from list.
IFileDirectory* CFileDirectoryFactory::Create(const CURL& url, CFileItem* pItem, const std::string& strMask)
{
  if (url.IsProtocol("stack")) // disqualify stack as we need to work with each of the parts instead
    return NULL;

  std::string strExtension=URIUtils::GetExtension(url);
  StringUtils::ToLower(strExtension);
  if (!strExtension.empty())
  {
    VECADDONS codecs;
    CBinaryAddonCache &addonCache = CServiceBroker::GetBinaryAddonCache();
    addonCache.GetAddons(codecs, ADDON_AUDIODECODER);
    for (size_t i=0;i<codecs.size();++i)
    {
      std::shared_ptr<CAudioDecoder> dec(std::static_pointer_cast<CAudioDecoder>(codecs[i]));
      if (dec->HasTracks() && dec->GetExtensions().find(strExtension) != std::string::npos)
      {
        CAudioDecoder* result = new CAudioDecoder(*dec);
        result->Create();
        if (result->ContainsFiles(url))
          return result;
        delete result;
        return NULL;
      }
    }
  }

  if (CServiceBroker::IsBinaryAddonCacheUp())
  {
    VECADDONS vfs;
    CBinaryAddonCache &addonCache = CServiceBroker::GetBinaryAddonCache();
    addonCache.GetAddons(vfs, ADDON_VFS);
    for (size_t i=0;i<vfs.size();++i)
    {
      std::shared_ptr<CVFSEntry> dec(std::static_pointer_cast<CVFSEntry>(vfs[i]));
      if (!strExtension.empty() && dec->HasFileDirectories() &&
          dec->GetExtensions().find(strExtension) != std::string::npos)
      {
        CVFSEntryIFileDirectoryWrapper* wrap = new CVFSEntryIFileDirectoryWrapper(dec);
        if (wrap->ContainsFiles(url))
        {
          if (wrap->m_items.Size() == 1)
          {
            // one STORED file - collapse it down
            *pItem = *wrap->m_items[0];
          }
          else
          { // compressed or more than one file -> create a dir
            pItem->SetPath(wrap->m_items.GetPath());
            return wrap;
          }
        }
        else
          pItem->m_bIsFolder = true;

        delete wrap;
        return NULL;
      }
    }
  }

  if (pItem->IsRSS())
    return new CRSSDirectory();

  if (pItem->IsDiscImage())
    return new CUDFDirectory();

#if defined(TARGET_ANDROID)
  if (url.IsFileType("apk"))
  {
    CURL zipURL = URIUtils::CreateArchivePath("apk", url);

    CFileItemList items;
    CDirectory::GetDirectory(zipURL, items, strMask);
    if (items.Size() == 0) // no files
      pItem->m_bIsFolder = true;
    else if (items.Size() == 1 && items[0]->m_idepth == 0 && !items[0]->m_bIsFolder)
    {
      // one STORED file - collapse it down
      *pItem = *items[0];
    }
    else
    { // compressed or more than one file -> create a apk dir
      pItem->SetURL(zipURL);
      return new CAPKDirectory;
    }
    return NULL;
  }
#endif
  if (url.IsFileType("zip"))
  {
    CURL zipURL = URIUtils::CreateArchivePath("zip", url);

    CFileItemList items;
    CDirectory::GetDirectory(zipURL, items, strMask);
    if (items.Size() == 0) // no files
      pItem->m_bIsFolder = true;
    else if (items.Size() == 1 && items[0]->m_idepth == 0 && !items[0]->m_bIsFolder)
    {
      // one STORED file - collapse it down
      *pItem = *items[0];
    }
    else
    { // compressed or more than one file -> create a zip dir
      pItem->SetURL(zipURL);
      return new CZipDirectory;
    }
    return NULL;
  }
  if (url.IsFileType("rar") || url.IsFileType("001"))
  {
    std::vector<std::string> tokens;
    const std::string strPath = url.Get();
    StringUtils::Tokenize(strPath,tokens,".");
    if (tokens.size() > 2)
    {
      if (url.IsFileType("001"))
      {
        if (StringUtils::EqualsNoCase(tokens[tokens.size()-2], "ts")) // .ts.001 - treat as a movie file to scratch some users itch
          return NULL;
      }
      std::string token = tokens[tokens.size()-2];
      if (StringUtils::StartsWith(token, "part")) // only list '.part01.rar'
      {
        // need this crap to avoid making mistakes - yeyh for the new rar naming scheme :/
        struct __stat64 stat;
        int digits = token.size()-4;
        std::string strFormat = StringUtils::Format("part%%0%ii", digits);
        std::string strNumber = StringUtils::Format(strFormat.c_str(), 1);
        std::string strPath2 = strPath;
        StringUtils::Replace(strPath2,token,strNumber);
        if (atoi(token.substr(4).c_str()) > 1 && CFile::Stat(strPath2,&stat) == 0)
        {
          pItem->m_bIsFolder = true;
          return NULL;
        }
      }
    }

    CURL rarURL = URIUtils::CreateArchivePath("rar", url);

    CFileItemList items;
    CDirectory::GetDirectory(rarURL, items, strMask);
    if (items.Size() == 0) // no files - hide this
      pItem->m_bIsFolder = true;
    else if (items.Size() == 1 && items[0]->m_idepth == 0x30 && !items[0]->m_bIsFolder)
    {
      // one STORED file - collapse it down
      *pItem = *items[0];
    }
    else
    {
#ifdef HAS_FILESYSTEM_RAR
      // compressed or more than one file -> create a rar dir
      pItem->SetURL(rarURL);
      return new CRarDirectory;
#else
      return NULL;
#endif
    }
    return NULL;
  }
  if (url.IsFileType("xbt"))
  {
    CURL xbtUrl = URIUtils::CreateArchivePath("xbt", url);
    pItem->SetURL(xbtUrl);

    return new CXbtDirectory();
  }
  if (url.IsFileType("xsp"))
  { // XBMC Smart playlist - just XML renamed to XSP
    // read the name of the playlist in
    CSmartPlaylist playlist;
    if (playlist.OpenAndReadName(url))
    {
      pItem->SetLabel(playlist.GetName());
      pItem->SetLabelPreformatted(true);
    }
    IFileDirectory* pDir=new CSmartPlaylistDirectory;
    return pDir; // treat as directory
  }
  if (CPlayListFactory::IsPlaylist(url))
  { // Playlist file
    // currently we only return the directory if it contains
    // more than one file.  Reason is that .pls and .m3u may be used
    // for links to http streams etc.
    IFileDirectory *pDir = new CPlaylistFileDirectory();
    CFileItemList items;
    if (pDir->GetDirectory(url, items))
    {
      if (items.Size() > 1)
        return pDir;
    }
    delete pDir;
    return NULL;
  }

  if (pItem->IsAudioBook())
  {
    if (!pItem->HasMusicInfoTag() || pItem->m_lEndOffset <= 0)
    {
      std::unique_ptr<CAudioBookFileDirectory> pDir(new CAudioBookFileDirectory);
      if (pDir->ContainsFiles(url))
        return pDir.release();
    }
    return NULL;
  }
  return NULL;
}
Exemplo n.º 2
0
// return NULL + set pItem->m_bIsFolder to remove it completely from list.
IFileDirectory* CFileDirectoryFactory::Create(const CURL& url, CFileItem* pItem, const std::string& strMask)
{
  if (url.IsProtocol("stack")) // disqualify stack as we need to work with each of the parts instead
    return NULL;

  std::string strExtension=URIUtils::GetExtension(url);
  StringUtils::ToLower(strExtension);
  if (!strExtension.empty() && CServiceBroker::IsBinaryAddonCacheUp())
  {
    BinaryAddonBaseList addonInfos;
    CServiceBroker::GetBinaryAddonManager().GetAddonInfos(addonInfos, true, ADDON_AUDIODECODER);
    for (const auto& addonInfo : addonInfos)
    {
      if (CAudioDecoder::HasTracks(addonInfo) &&
          CAudioDecoder::GetExtensions(addonInfo).find(strExtension) != std::string::npos)
      {
        CAudioDecoder* result = new CAudioDecoder(addonInfo);
        if (!result->CreateDecoder() || !result->ContainsFiles(url))
        {
          delete result;
          return nullptr;
        }
        return result;
      }
    }
  }

  if (!strExtension.empty() && CServiceBroker::IsBinaryAddonCacheUp())
  {
    for (const auto& vfsAddon : CServiceBroker::GetVFSAddonCache().GetAddonInstances())
    {
      if (vfsAddon->HasFileDirectories() &&
          vfsAddon->GetExtensions().find(strExtension) != std::string::npos)
      {
        CVFSEntryIFileDirectoryWrapper* wrap = new CVFSEntryIFileDirectoryWrapper(vfsAddon);
        if (wrap->ContainsFiles(url))
        {
          if (wrap->m_items.Size() == 1)
          {
            // one STORED file - collapse it down
            *pItem = *wrap->m_items[0];
          }
          else
          { // compressed or more than one file -> create a dir
            pItem->SetPath(wrap->m_items.GetPath());
            return wrap;
          }
        }
        else
          pItem->m_bIsFolder = true;

        delete wrap;
        return nullptr;
      }
    }
  }

  if (pItem->IsRSS())
    return new CRSSDirectory();

  if (pItem->IsDiscImage())
    return new CUDFDirectory();

#if defined(TARGET_ANDROID)
  if (url.IsFileType("apk"))
  {
    CURL zipURL = URIUtils::CreateArchivePath("apk", url);

    CFileItemList items;
    CDirectory::GetDirectory(zipURL, items, strMask);
    if (items.Size() == 0) // no files
      pItem->m_bIsFolder = true;
    else if (items.Size() == 1 && items[0]->m_idepth == 0 && !items[0]->m_bIsFolder)
    {
      // one STORED file - collapse it down
      *pItem = *items[0];
    }
    else
    { // compressed or more than one file -> create a apk dir
      pItem->SetURL(zipURL);
      return new CAPKDirectory;
    }
    return NULL;
  }
#endif
  if (url.IsFileType("zip"))
  {
    CURL zipURL = URIUtils::CreateArchivePath("zip", url);

    CFileItemList items;
    CDirectory::GetDirectory(zipURL, items, strMask);
    if (items.Size() == 0) // no files
      pItem->m_bIsFolder = true;
    else if (items.Size() == 1 && items[0]->m_idepth == 0 && !items[0]->m_bIsFolder)
    {
      // one STORED file - collapse it down
      *pItem = *items[0];
    }
    else
    { // compressed or more than one file -> create a zip dir
      pItem->SetURL(zipURL);
      return new CZipDirectory;
    }
    return NULL;
  }
  if (url.IsFileType("xbt"))
  {
    CURL xbtUrl = URIUtils::CreateArchivePath("xbt", url);
    pItem->SetURL(xbtUrl);

    return new CXbtDirectory();
  }
  if (url.IsFileType("xsp"))
  { // XBMC Smart playlist - just XML renamed to XSP
    // read the name of the playlist in
    CSmartPlaylist playlist;
    if (playlist.OpenAndReadName(url))
    {
      pItem->SetLabel(playlist.GetName());
      pItem->SetLabelPreformatted(true);
    }
    IFileDirectory* pDir=new CSmartPlaylistDirectory;
    return pDir; // treat as directory
  }
  if (CPlayListFactory::IsPlaylist(url))
  { // Playlist file
    // currently we only return the directory if it contains
    // more than one file.  Reason is that .pls and .m3u may be used
    // for links to http streams etc.
    IFileDirectory *pDir = new CPlaylistFileDirectory();
    CFileItemList items;
    if (pDir->GetDirectory(url, items))
    {
      if (items.Size() > 1)
        return pDir;
    }
    delete pDir;
    return NULL;
  }

  if (pItem->IsAudioBook())
  {
    if (!pItem->HasMusicInfoTag() || pItem->m_lEndOffset <= 0)
    {
      std::unique_ptr<CAudioBookFileDirectory> pDir(new CAudioBookFileDirectory);
      if (pDir->ContainsFiles(url))
        return pDir.release();
    }
    return NULL;
  }
  return NULL;
}