1 /*
2  *  Copyright (C) 2013 Arne Morten Kvarving
3  *
4  *  SPDX-License-Identifier: GPL-2.0-or-later
5  *  See LICENSES/README.md for more information.
6  */
7 
8 #pragma once
9 
10 #include "addons/binary-addons/AddonInstanceHandler.h"
11 #include "addons/kodi-dev-kit/include/kodi/addon-instance/VFS.h"
12 #include "filesystem/IDirectory.h"
13 #include "filesystem/IFile.h"
14 #include "filesystem/IFileDirectory.h"
15 
16 #include <utility>
17 
18 namespace ADDON
19 {
20 
21   class CVFSEntry;
22   typedef std::shared_ptr<CVFSEntry> VFSEntryPtr;
23 
24   class CVFSAddonCache : public CAddonDllInformer
25   {
26   public:
27     virtual ~CVFSAddonCache();
28     void Init();
29     void Deinit();
30     const std::vector<VFSEntryPtr> GetAddonInstances();
31     VFSEntryPtr GetAddonInstance(const std::string& strId);
32 
33   protected:
34     void Update(const std::string& id);
35     void OnEvent(const AddonEvent& event);
36     bool IsInUse(const std::string& id) override;
37 
38     CCriticalSection m_critSection;
39     std::vector<VFSEntryPtr> m_addonsInstances;
40   };
41 
42   //! \brief A virtual filesystem entry add-on.
43   class CVFSEntry : public IAddonInstanceHandler
44   {
45   public:
46     //! \brief A structure encapsulating properties of supplied protocol.
47     struct ProtocolInfo
48     {
49       bool supportPath;      //!< Protocol has path in addition to server name
50       bool supportUsername;  //!< Protocol uses logins
51       bool supportPassword;  //!< Protocol supports passwords
52       bool supportPort;      //!< Protocol supports port customization
53       bool supportBrowsing;  //!< Protocol supports server browsing
54       bool supportWrite;     //!< Protocol supports write operations
55       int defaultPort;       //!< Default port to use for protocol
56       std::string type;      //!< URL type for protocol
57       int label;             //!< String ID to use as label in dialog
58 
59       //! \brief The constructor reads the info from an add-on info structure.
60       ProtocolInfo(const AddonInfoPtr& addonInfo);
61     };
62 
63     //! \brief Construct from add-on properties.
64     //! \param addonInfo General addon properties
65     explicit CVFSEntry(const AddonInfoPtr& addonInfo);
66     ~CVFSEntry() override;
67 
68     // Things that MUST be supplied by the child classes
69     void* Open(const CURL& url);
70     void* OpenForWrite(const CURL& url, bool bOverWrite);
71     bool Exists(const CURL& url);
72     int Stat(const CURL& url, struct __stat64* buffer);
73     ssize_t Read(void* ctx, void* lpBuf, size_t uiBufSize);
74     ssize_t Write(void* ctx, const void* lpBuf, size_t uiBufSize);
75     int64_t Seek(void* ctx, int64_t iFilePosition, int iWhence = SEEK_SET);
76     int Truncate(void* ctx, int64_t size);
77     void Close(void* ctx);
78     int64_t GetPosition(void* ctx);
79     int64_t GetLength(void* ctx);
80     int GetChunkSize(void* ctx);
81     int IoControl(void* ctx, XFILE::EIoControl request, void* param);
82     bool Delete(const CURL& url);
83     bool Rename(const CURL& url, const CURL& url2);
84 
85     bool GetDirectory(const CURL& url, CFileItemList& items, void* ctx);
86     bool DirectoryExists(const CURL& url);
87     bool RemoveDirectory(const CURL& url);
88     bool CreateDirectory(const CURL& url);
89     void ClearOutIdle();
90     void DisconnectAll();
91 
92     bool ContainsFiles(const CURL& url, CFileItemList& items);
93 
GetProtocols()94     const std::string& GetProtocols() const { return m_protocols; }
GetExtensions()95     const std::string& GetExtensions() const { return m_extensions; }
HasFiles()96     bool HasFiles() const { return m_files; }
HasDirectories()97     bool HasDirectories() const { return m_directories; }
HasFileDirectories()98     bool HasFileDirectories() const { return m_filedirectories; }
GetZeroconfType()99     const std::string& GetZeroconfType() const { return m_zeroconf; }
GetProtocolInfo()100     const ProtocolInfo& GetProtocolInfo() const { return m_protocolInfo; }
101   protected:
102     std::string m_protocols;  //!< Protocols for VFS entry.
103     std::string m_extensions; //!< Extensions for VFS entry.
104     std::string m_zeroconf;   //!< Zero conf announce string for VFS protocol.
105     bool m_files;             //!< Vfs entry can read files.
106     bool m_directories;       //!< VFS entry can list directories.
107     bool m_filedirectories;   //!< VFS entry contains file directories.
108     ProtocolInfo m_protocolInfo; //!< Info about protocol for network dialog.
109     AddonInstance_VFSEntry m_struct; //!< VFS callback table
110   };
111 
112   //! \brief Wrapper equipping a CVFSEntry with an IFile interface.
113   //! \details Needed as CVFSEntry implements several VFS interfaces
114   //!          with overlapping methods.
115   class CVFSEntryIFileWrapper : public XFILE::IFile
116   {
117   public:
118     //! \brief The constructor initializes the reference to the wrapped CVFSEntry.
119     //! \param ptr The CVFSEntry to wrap.
120     explicit CVFSEntryIFileWrapper(VFSEntryPtr ptr);
121 
122     //! \brief Empty destructor.
123     ~CVFSEntryIFileWrapper() override;
124 
125     //! \brief Open a file.
126     //! \param[in] url URL to open.
127     //! \returns True if file was opened, false otherwise.
128     bool Open(const CURL& url) override;
129 
130     //! \brief Open a file for writing.
131     //! \param[in] url URL to open.
132     //! \param[in] bOverWrite If true, overwrite an existing file.
133     //! \returns True if file was opened, false otherwise.
134     bool OpenForWrite(const CURL& url, bool bOverWrite) override;
135 
136     //! \brief Check for file existence.
137     //! \param[in] url URL of file.
138     bool Exists(const CURL& url) override;
139 
140     //! \brief Stat a file.
141     //! \param[in] url URL of file.
142     //! \param[out] buffer The stat info.
143     //! \details Returns 0 on success, non-zero otherwise (see fstat() return values).
144     int  Stat(const CURL& url, struct __stat64* buffer) override;
145 
146     //! \brief Read data from file:
147     //! \param lpBuf Buffer to read data into.
148     //! \param[in] uiBufSize Number of bytes to read.
149     //! \returns Number of bytes read.
150     ssize_t Read(void* lpBuf, size_t uiBufSize) override;
151 
152     //! \brief Write data to file.
153     //! \param[in] lpBuf Data to write.
154     //! \param[in] uiBufSize Number of bytes to write.
155     //! \returns Number of bytes written.
156     ssize_t Write(const void* lpBuf, size_t uiBufSize) override;
157 
158     //! \brief Seek in file.
159     //! \param[in] iFilePosition Position to seek to.
160     //! \param[in] whence Origin for position.
161     //! \returns New file position.
162     int64_t Seek(int64_t iFilePosition, int whence = SEEK_SET) override;
163 
164     //! \brief Truncate a file.
165     //! \param[in] size Size of new file.
166     int Truncate(int64_t size) override;
167 
168     //! \brief Close file.
169     void Close() override;
170 
171     //! \brief Obtain current file position.
172     int64_t GetPosition() override;
173 
174     //! \brief Obtain file size.
175     int64_t GetLength() override;
176 
177     //! \brief Obtain chunksize of file.
178     int GetChunkSize() override;
179 
180     //! \brief Perform I/O controls for file.
181     int IoControl(XFILE::EIoControl request, void* param) override;
182 
183     //! \brief Delete a file.
184     //! \param[in] url URL of file to delete.
185     bool Delete(const CURL& url) override;
186 
187     //! \brief Rename a file.
188     //! \param[in] url URL of file to rename.
189     //! \param[in] url2 New URL of file.
190     bool Rename(const CURL& url, const CURL& url2) override;
191   protected:
192     void* m_context; //!< Opaque add-on specific context for opened file.
193     VFSEntryPtr m_addon; //!< Pointer to wrapped CVFSEntry.
194   };
195 
196   //! \brief Wrapper equpping a CVFSEntry with an IDirectory interface.
197   //! \details Needed as CVFSEntry implements several VFS interfaces
198   //!          with overlapping methods.
199   class CVFSEntryIDirectoryWrapper : public XFILE::IDirectory
200   {
201   public:
202     //! \brief The constructor initializes the reference to the wrapped CVFSEntry.
203     //! \param ptr The CVFSEntry to wrap.
204     explicit CVFSEntryIDirectoryWrapper(VFSEntryPtr ptr);
205 
206     //! \brief Empty destructor.
207     ~CVFSEntryIDirectoryWrapper() override = default;
208 
209     //! \brief Return directory listing.
210     //! \param[in] url URL to file to list.
211     //! \param items List of items in file.
212     //! \return True if listing succeeded, false otherwise.
213     bool GetDirectory(const CURL& url, CFileItemList& items) override;
214 
215     //! \brief Check if directory exists.
216     //! \param[in] url URL to check.
217     bool Exists(const CURL& url) override;
218 
219     //! \brief Delete directory.
220     //! \param[in] url URL to delete.
221     bool Remove(const CURL& url) override;
222 
223     //! \brief Create directory.
224     //! \param[in] url URL to delete.
225     bool Create(const CURL& url) override;
226 
227     //! \brief Static helper for doing a keyboard callback.
228     static bool DoGetKeyboardInput(void* context, const char* heading,
229                                    char** input, bool hidden_input);
230 
231     //! \brief Get keyboard input.
232     bool GetKeyboardInput2(const char* heading, char** input, bool hidden_input);
233 
234     //! \brief Static helper for displaying an error dialog.
235     static void DoSetErrorDialog(void* ctx, const char* heading,
236                                  const char* line1, const char* line2,
237                                  const char* line3);
238 
239     //! \brief Show an error dialog.
240     void SetErrorDialog2(const char* heading, const char* line1,
241                          const char* line2, const char* line3);
242 
243     //! \brief Static helper for requiring authentication.
244     static void DoRequireAuthentication(void* ctx, const char* url);
245 
246     //! \brief Require authentication.
247     void RequireAuthentication2(const CURL& url);
248   protected:
249     VFSEntryPtr m_addon; //!< Pointer to wrapper CVFSEntry.
250   };
251 
252   //! \brief Wrapper equpping a CVFSEntry with an IFileDirectory interface.
253   //! \details Needed as CVFSEntry implements several VFS interfaces
254   //!          with overlapping methods.
255   class CVFSEntryIFileDirectoryWrapper : public XFILE::IFileDirectory,
256                                          public CVFSEntryIDirectoryWrapper
257   {
258   public:
259     //! \brief The constructor initializes the reference to the wrapped CVFSEntry.
260     //! \param ptr The CVFSEntry to wrap.
CVFSEntryIFileDirectoryWrapper(VFSEntryPtr ptr)261     explicit CVFSEntryIFileDirectoryWrapper(VFSEntryPtr ptr)
262       : CVFSEntryIDirectoryWrapper(std::move(ptr))
263     {
264     }
265 
266     //! \brief Empty destructor.
267     ~CVFSEntryIFileDirectoryWrapper() override = default;
268 
269     //! \brief Check if the given file should be treated as a directory.
270     //! \param[in] url URL for file to probe.
ContainsFiles(const CURL & url)271     bool ContainsFiles(const CURL& url) override
272     {
273       return m_addon->ContainsFiles(url, m_items);
274     }
275 
276     //! \brief Return directory listing.
277     //! \param[in] url URL to file to list.
278     //! \param items List of items in file.
279     //! \return True if listing succeeded, false otherwise.
GetDirectory(const CURL & url,CFileItemList & items)280     bool GetDirectory(const CURL& url, CFileItemList& items) override
281     {
282       return CVFSEntryIDirectoryWrapper::GetDirectory(url, items);
283     }
284 
285     //! \brief Check if directory exists.
286     //! \param[in] url URL to check.
Exists(const CURL & url)287     bool Exists(const CURL& url) override
288     {
289       return CVFSEntryIDirectoryWrapper::Exists(url);
290     }
291 
292     //! \brief Delete directory.
293     //! \param[in] url URL to delete.
Remove(const CURL & url)294     bool Remove(const CURL& url) override
295     {
296       return CVFSEntryIDirectoryWrapper::Remove(url);
297     }
298 
299     //! \brief Create directory.
300     //! \param[in] url URL to delete.
Create(const CURL & url)301     bool Create(const CURL& url) override
302     {
303       return CVFSEntryIDirectoryWrapper::Create(url);
304     }
305 
306     CFileItemList m_items; //!< Internal list of items, used for cache purposes.
307   };
308 
309 } /*namespace ADDON*/
310