1 /*
2  *  Copyright (C) 2005-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 "XBDateTime.h"
12 #include "addons/AddonVersion.h"
13 #include "addons/addoninfo/AddonType.h"
14 
15 #include <map>
16 #include <memory>
17 #include <string>
18 #include <unordered_map>
19 #include <utility>
20 #include <vector>
21 
22 namespace ADDON
23 {
24 
25 class CAddonBuilder;
26 class CAddonInfo;
27 typedef std::shared_ptr<CAddonInfo> AddonInfoPtr;
28 typedef std::vector<AddonInfoPtr> AddonInfos;
29 
30 enum class AddonDisabledReason
31 {
32   /// @brief Special reason for returning all disabled addons.
33   ///
34   /// Only used as an actual value when an addon is enabled.
35   NONE = 0,
36   USER = 1,
37   INCOMPATIBLE = 2,
38   PERMANENT_FAILURE = 3
39 };
40 
41 enum class AddonOriginType
42 {
43   /// @brief The type of the origin of an addon.
44   ///
45   /// Represents where an addon was installed from.
46   SYSTEM = 0, /// The addon is a system addon
47   REPOSITORY = 1, /// The addon origin is a repository
48   MANUAL = 2 /// The addon origin is a zip file, package or development build
49 };
50 
51 //! @brief Reasons why an addon is not updateable
52 enum class AddonUpdateRule
53 {
54   ANY = 0, //!< used internally, not to be explicitly set
55   USER_DISABLED_AUTO_UPDATE = 1, //!< automatic updates disabled via AddonInfo dialog
56   PIN_OLD_VERSION = 2 //!< user downgraded to an older version
57 };
58 
59 /*!
60  * @brief Add-on state defined within addon.xml to report about the current addon
61  * lifecycle state.
62  *
63  * E.g. the add-on is broken and can no longer be used.
64  *
65  * XML examples:
66  * ~~~~~~~~~~~~~{.xml}
67  * <lifecyclestate type="broken" lang="en_GB">SOME TEXT</lifecyclestate>
68  * ~~~~~~~~~~~~~
69  */
70 enum class AddonLifecycleState
71 {
72   NORMAL = 0, //!< Used if an add-on has no special lifecycle state which is the default state
73   DEPRECATED = 1, //!< the add-on should be marked as deprecated but is still usable
74   BROKEN = 2, //!< the add-on should marked as broken in the repository
75 };
76 
77 struct DependencyInfo
78 {
79   std::string id;
80   AddonVersion versionMin, version;
81   bool optional;
DependencyInfoDependencyInfo82   DependencyInfo(std::string id,
83                  const AddonVersion& versionMin,
84                  const AddonVersion& version,
85                  bool optional)
86     : id(std::move(id)),
87       versionMin(versionMin.empty() ? version : versionMin),
88       version(version),
89       optional(optional)
90   {
91   }
92 
93   bool operator==(const DependencyInfo& rhs) const
94   {
95     return id == rhs.id && versionMin == rhs.versionMin && version == rhs.version &&
96            optional == rhs.optional;
97   }
98 
99   bool operator!=(const DependencyInfo& rhs) const
100   {
101     return !(rhs == *this);
102   }
103 };
104 
105 typedef std::map<std::string, std::string> InfoMap;
106 typedef std::map<std::string, std::string> ArtMap;
107 
108 class CAddonInfoBuilder;
109 
110 class CAddonInfo
111 {
112 public:
113   CAddonInfo() = default;
114   CAddonInfo(std::string id, TYPE type);
115 
SetMainType(TYPE type)116   void SetMainType(TYPE type) { m_mainType = type; }
SetBinary(bool isBinary)117   void SetBinary(bool isBinary) { m_isBinary = isBinary; }
SetLibName(const std::string & libname)118   void SetLibName(const std::string& libname) { m_libname = libname; }
SetPath(const std::string & path)119   void SetPath(const std::string& path) { m_path = path; }
AddExtraInfo(const std::string & idName,const std::string & value)120   void AddExtraInfo(const std::string& idName, const std::string& value) { m_extrainfo[idName] = value; }
SetLastUsed(const CDateTime & dateTime)121   void SetLastUsed(const CDateTime& dateTime) { m_lastUsed = dateTime; }
122 
ID()123   const std::string& ID() const { return m_id; }
124 
125   /**
126    * @brief To get the main type of this addon
127    *
128    * This is the first type defined in addon.xml.
129    *
130    * @return The used main type of addon
131    */
MainType()132   TYPE MainType() const { return m_mainType; }
133 
134   /**
135    * @brief To check addon contains a type
136    *
137    * @param[in] type The to checked type identifier
138    * @param[in] mainOnly to check only in first defined main addon inside addon.xml
139    * @return true in case the wanted type is supported, false if not
140    */
141   bool HasType(TYPE type, bool mainOnly = false) const;
142 
143   /**
144    * @brief To get all available types inside the addon
145    *
146    * To have all `<extension point="..." />` defined in addon.xml inside a list.
147    *
148    * @return List of all supported types
149    */
Types()150   const std::vector<CAddonType>& Types() const { return m_types; }
151 
152   /**
153    * @brief The get for given addon type information and extension data
154    *
155    * @param[in] type The wanted type data
156    * @return addon type class with @ref CAddonExtensions as information
157    *
158    * @note This function return never a "nullptr", in case the wanted type is
159    * not supported, becomes a dummy of @ref CAddonType given.
160    *
161    * ------------------------------------------------------------------------
162    *
163    * **Example:**
164    * ~~~~~~~~~~~~~{.cpp}
165    * // To get <extension ... name="blablabla" /> from addon.xml
166    * std::string name = Type(ADDON_...)->GetValue("@name").asString();
167    * ~~~~~~~~~~~~~
168    *
169    */
170   const CAddonType* Type(TYPE type) const;
171 
172   bool ProvidesSubContent(const TYPE& content, const TYPE& mainType = ADDON_UNKNOWN) const;
173   bool ProvidesSeveralSubContents() const;
174 
Version()175   const AddonVersion& Version() const { return m_version; }
MinVersion()176   const AddonVersion& MinVersion() const { return m_minversion; }
IsBinary()177   bool IsBinary() const { return m_isBinary; }
178   const AddonVersion& DependencyMinVersion(const std::string& dependencyID) const;
179   const AddonVersion& DependencyVersion(const std::string& dependencyID) const;
Name()180   const std::string& Name() const { return m_name; }
License()181   const std::string& License() const { return m_license; }
Summary()182   const std::string& Summary() const { return GetTranslatedText(m_summary); }
Description()183   const std::string& Description() const { return GetTranslatedText(m_description); }
LibName()184   const std::string& LibName() const { return m_libname; }
Author()185   const std::string& Author() const { return m_author; }
Source()186   const std::string& Source() const { return m_source; }
Website()187   const std::string& Website() const { return m_website; }
Forum()188   const std::string& Forum() const { return m_forum; }
EMail()189   const std::string& EMail() const { return m_email; }
Path()190   const std::string& Path() const { return m_path; }
ChangeLog()191   const std::string& ChangeLog() const { return GetTranslatedText(m_changelog); }
Icon()192   const std::string& Icon() const { return m_icon; }
Art()193   const ArtMap& Art() const { return m_art; }
Screenshots()194   const std::vector<std::string>& Screenshots() const { return m_screenshots; }
Disclaimer()195   const std::string& Disclaimer() const { return GetTranslatedText(m_disclaimer); }
GetDependencies()196   const std::vector<DependencyInfo>& GetDependencies() const { return m_dependencies; }
LifecycleState()197   AddonLifecycleState LifecycleState() const { return m_lifecycleState; }
LifecycleStateDescription()198   const std::string& LifecycleStateDescription() const
199   {
200     return GetTranslatedText(m_lifecycleStateDescription);
201   }
Origin()202   const std::string& Origin() const { return m_origin; }
203   const std::string& OriginName() const;
204 
ExtraInfo()205   const InfoMap& ExtraInfo() const { return m_extrainfo; }
206 
207   bool MeetsVersion(const AddonVersion& versionMin, const AddonVersion& version) const;
PackageSize()208   uint64_t PackageSize() const { return m_packageSize; }
InstallDate()209   CDateTime InstallDate() const { return m_installDate; }
LastUpdated()210   CDateTime LastUpdated() const { return m_lastUpdated; }
LastUsed()211   CDateTime LastUsed() const { return m_lastUsed; }
212 
213   /*!
214     * @brief Utilities to translate add-on parts to his requested part.
215     */
216   //@{
217   static std::string TranslateType(TYPE type, bool pretty = false);
218   static std::string TranslateIconType(TYPE type);
219   static TYPE TranslateType(const std::string& string);
220   static TYPE TranslateSubContent(const std::string& content);
221   //@}
222 
223 private:
224   friend class CAddonInfoBuilder;
225 
226   std::string m_id;
227   TYPE m_mainType = ADDON_UNKNOWN;
228   std::vector<CAddonType> m_types;
229 
230   AddonVersion m_version;
231   AddonVersion m_minversion;
232   bool m_isBinary = false;
233   std::string m_name;
234   std::string m_license;
235   std::unordered_map<std::string, std::string> m_summary;
236   std::unordered_map<std::string, std::string> m_description;
237   std::string m_author;
238   std::string m_source;
239   std::string m_website;
240   std::string m_forum;
241   std::string m_email;
242   std::string m_path;
243   std::unordered_map<std::string, std::string> m_changelog;
244   std::string m_icon;
245   ArtMap m_art;
246   std::vector<std::string> m_screenshots;
247   std::unordered_map<std::string, std::string> m_disclaimer;
248   std::vector<DependencyInfo> m_dependencies;
249   AddonLifecycleState m_lifecycleState = AddonLifecycleState::NORMAL;
250   std::unordered_map<std::string, std::string> m_lifecycleStateDescription;
251   CDateTime m_installDate;
252   CDateTime m_lastUpdated;
253   CDateTime m_lastUsed;
254   std::string m_origin;
255   mutable std::unique_ptr<std::string> m_originName; // @todo use std::optional once we use c++17
256   uint64_t m_packageSize = 0;
257   std::string m_libname;
258   InfoMap m_extrainfo;
259   std::vector<std::string> m_platforms;
260 
261   const std::string& GetTranslatedText(const std::unordered_map<std::string, std::string>& locales) const;
262 };
263 
264 } /* namespace ADDON */
265