xbmc
Directorization.h
1 /*
2  * Copyright (C) 2015-2018 Team Kodi
3  * This file is part of Kodi - https://kodi.tv
4  *
5  * SPDX-License-Identifier: GPL-2.0-or-later
6  * See LICENSES/README.md for more information.
7  */
8 
9 #pragma once
10 
11 #include "FileItem.h"
12 #include "URL.h"
13 #include "utils/CharsetConverter.h"
14 #include "utils/StringUtils.h"
15 #include "utils/URIUtils.h"
16 
17 #include <string>
18 #include <utility>
19 #include <vector>
20 
21 namespace XFILE
22 {
32  template<class TEntry>
33  using DirectorizeEntryToFileItemFunction = CFileItemPtr(*)(const TEntry& entry, const std::string& label, const std::string& path, bool isFolder);
34 
35  template<class TEntry>
36  using DirectorizeEntry = std::pair<std::string, TEntry>;
37  template<class TEntry>
38  using DirectorizeEntries = std::vector<DirectorizeEntry<TEntry>>;
39 
48  template<class TEntry>
49  static void Directorize(const CURL& url, const DirectorizeEntries<TEntry>& entries, DirectorizeEntryToFileItemFunction<TEntry> converter, CFileItemList& items)
50  {
51  if (url.Get().empty() || entries.empty())
52  return;
53 
54  const std::string& options = url.GetOptions();
55  const std::string& filePath = url.GetFileName();
56 
57  CURL baseUrl(url);
58  baseUrl.SetOptions(""); // delete options to have a clean path to add stuff too
59  baseUrl.SetFileName(""); // delete filename too as our names later will contain it
60 
61  std::string basePath = baseUrl.Get();
62  URIUtils::AddSlashAtEnd(basePath);
63 
64  std::vector<std::string> filePathTokens;
65  if (!filePath.empty())
66  StringUtils::Tokenize(filePath, filePathTokens, "/");
67 
68  bool fastLookup = items.GetFastLookup();
69  items.SetFastLookup(true);
70  for (const auto& entry : entries)
71  {
72  std::string entryPath = entry.first;
73  std::string entryFileName = entryPath;
74  StringUtils::Replace(entryFileName, '\\', '/');
75 
76  // skip the requested entry
77  if (entryFileName == filePath)
78  continue;
79 
80  // Disregard Apple Resource Fork data
81  std::size_t found = entryPath.find("__MACOSX");
82  if (found != std::string::npos)
83  continue;
84 
85  std::vector<std::string> pathTokens;
86  StringUtils::Tokenize(entryFileName, pathTokens, "/");
87 
88  // ignore any entries in lower directory hierarchies
89  if (pathTokens.size() < filePathTokens.size() + 1)
90  continue;
91 
92  // ignore any entries in different directory hierarchies
93  bool ignoreItem = false;
94  entryFileName.clear();
95  for (auto filePathToken = filePathTokens.begin(); filePathToken != filePathTokens.end(); ++filePathToken)
96  {
97  if (*filePathToken != pathTokens[std::distance(filePathTokens.begin(), filePathToken)])
98  {
99  ignoreItem = true;
100  break;
101  }
102  entryFileName = URIUtils::AddFileToFolder(entryFileName, *filePathToken);
103  }
104  if (ignoreItem)
105  continue;
106 
107  entryFileName = URIUtils::AddFileToFolder(entryFileName, pathTokens[filePathTokens.size()]);
108  char c = entryPath[entryFileName.size()];
109  if (c == '/' || c == '\\')
110  URIUtils::AddSlashAtEnd(entryFileName);
111 
112  std::string itemPath = URIUtils::AddFileToFolder(basePath, entryFileName) + options;
113  bool isFolder = false;
114  if (URIUtils::HasSlashAtEnd(entryFileName)) // this is a directory
115  {
116  // check if the directory has already been added
117  if (items.Contains(itemPath)) // already added
118  continue;
119 
120  isFolder = true;
121  URIUtils::AddSlashAtEnd(itemPath);
122  }
123 
124  // determine the entry's filename
125  std::string label = pathTokens[filePathTokens.size()];
126  g_charsetConverter.unknownToUTF8(label);
127 
128  // convert the entry into a CFileItem
129  CFileItemPtr item = converter(entry.second, label, itemPath, isFolder);
130  item->SetPath(itemPath);
131  item->m_bIsFolder = isFolder;
132  if (isFolder)
133  item->m_dwSize = 0;
134 
135  items.Add(item);
136  }
137  items.SetFastLookup(fastLookup);
138  }
139 }
Definition: Scraper.h:41
std::shared_ptr< CFileItem > CFileItemPtr
A shared pointer to CFileItem.
Definition: FileItem.h:680
Represents a list of files.
Definition: FileItem.h:713
Definition: URL.h:20
static std::vector< std::string > Tokenize(const std::string &input, const std::string &delimiters)
Split a string by the specified delimiters. Splits a string using one or more delimiting characters...
Definition: StringUtils.cpp:1814