1 /*
2  * Copyright (C) 2019 Red Hat, Inc.
3  *
4  * Licensed under the GNU Lesser General Public License Version 2.1
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20 
21 #ifndef _LIBDNF_REPO_PRIVATE_HPP
22 #define _LIBDNF_REPO_PRIVATE_HPP
23 
24 #include "Repo.hpp"
25 #include "../dnf-utils.h"
26 #include "../hy-iutil.h"
27 #include "../hy-util-private.hpp"
28 #include "../hy-types.h"
29 
30 #include <utils.hpp>
31 
32 #include <librepo/librepo.h>
33 #include <stdlib.h>
34 #include <sys/stat.h>
35 #include <sys/types.h>
36 #include <unistd.h>
37 
38 #include <gpgme.h>
39 
40 #include <solv/chksum.h>
41 #include <solv/repo.h>
42 #include <solv/util.h>
43 
44 #include <cctype>
45 #include <map>
46 #include <mutex>
47 #include <set>
48 
49 #include <string.h>
50 #include <time.h>
51 
52 #define MD_TYPE_PRIMARY "primary"
53 #define MD_TYPE_FILELISTS "filelists"
54 #define MD_TYPE_PRESTODELTA "prestodelta"
55 #define MD_TYPE_GROUP_GZ "group_gz"
56 #define MD_TYPE_GROUP "group"
57 #define MD_TYPE_UPDATEINFO "updateinfo"
58 #define MD_TYPE_MODULES "modules"
59 /* "other" in this context is not a generic "any other metadata", but real metadata type named "other"
60  * containing changelogs for packages */
61 #define MD_TYPE_OTHER "other"
62 
63 enum _hy_repo_state {
64     _HY_NEW,
65     _HY_LOADED_FETCH,
66     _HY_LOADED_CACHE,
67     _HY_WRITTEN
68 };
69 
70 namespace std {
71 
72 template<>
73 struct default_delete<LrHandle> {
operator ()std::default_delete74     void operator()(LrHandle * ptr) noexcept { lr_handle_free(ptr); }
75 };
76 
77 } // namespace std
78 
79 namespace libdnf {
80 
81 typedef ::Repo LibsolvRepo;
82 
83 class Key {
84 public:
Key(gpgme_key_t key,gpgme_subkey_t subkey)85     Key(gpgme_key_t key, gpgme_subkey_t subkey)
86     {
87         id = subkey->keyid;
88         fingerprint = subkey->fpr;
89         timestamp = subkey->timestamp;
90         userid = key->uids->uid;
91     }
92 
getId() const93     std::string getId() const { return id; }
getUserId() const94     std::string getUserId() const { return userid; }
getFingerprint() const95     std::string getFingerprint() const { return fingerprint; }
getTimestamp() const96     long int getTimestamp() const { return timestamp; }
97 
98     std::vector<char> rawKey;
99     std::string url;
100 
101 private:
102     std::string id;
103     std::string fingerprint;
104     std::string userid;
105     long int timestamp;
106 };
107 
108 class Repo::Impl {
109 public:
110     Impl(Repo & owner, const std::string & id, Type type, std::unique_ptr<ConfigRepo> && conf);
111     ~Impl();
112 
113     bool load();
114     bool loadCache(bool throwExcept, bool ignoreMissing=false);
115     void downloadMetadata(const std::string & destdir);
116     bool isInSync();
117     void fetch(const std::string & destdir, std::unique_ptr<LrHandle> && h);
118     std::string getCachedir() const;
119     std::string getPersistdir() const;
120     int getAge() const;
121     void expire();
122     bool isExpired() const;
123     int getExpiresIn() const;
124     void downloadUrl(const char * url, int fd);
125     void addCountmeFlag(LrHandle *handle);
126     void setHttpHeaders(const char * headers[]);
127     const char * const * getHttpHeaders() const;
128     const std::string & getMetadataPath(const std::string &metadataType) const;
129 
130     std::unique_ptr<LrHandle> lrHandleInitBase();
131     std::unique_ptr<LrHandle> lrHandleInitLocal();
132     std::unique_ptr<LrHandle> lrHandleInitRemote(const char *destdir);
133 
134     void attachLibsolvRepo(LibsolvRepo * libsolvRepo);
135     void detachLibsolvRepo();
136 
137     // Converts configuration string of proxy authorization methods to librepo enum.
138     static LrAuth stringToProxyAuthMethods(const std::string & proxy_auth_method) noexcept;
139 
140     std::string id;
141     Type type;
142     std::unique_ptr<ConfigRepo> conf;
143 
144     char ** mirrors{nullptr};
145     int maxMirrorTries{0}; // try them all
146     // 0 forces expiration on the next call to load(), -1 means undefined value
147     int timestamp;
148     int maxTimestamp{0};
149     bool preserveRemoteTime{false};
150     bool fresh{false};
151     std::string repomdFn;
152     std::set<std::string> additionalMetadata;
153     std::string revision;
154     std::vector<std::string> content_tags;
155     std::vector<std::pair<std::string, std::string>> distro_tags;
156     std::vector<std::pair<std::string, std::string>> metadata_locations;
157     unsigned char checksum[CHKSUM_BYTES];
158     bool useIncludes{false};
159     bool loadMetadataOther;
160     std::map<std::string, std::string> substitutions;
161 
162     std::unique_ptr<RepoCB> callbacks;
163     std::string repoFilePath;
164     LrHandle * getCachedHandle();
165 
166     SyncStrategy syncStrategy;
167     std::map<std::string, std::string> metadataPaths;
168 
169     LibsolvRepo * libsolvRepo{nullptr};
170     bool needs_internalizing{false};
171     int nrefs{1};
172 
173     enum _hy_repo_state state_main{_HY_NEW};
174     enum _hy_repo_state state_filelists{_HY_NEW};
175     enum _hy_repo_state state_presto{_HY_NEW};
176     enum _hy_repo_state state_updateinfo{_HY_NEW};
177     enum _hy_repo_state state_other{_HY_NEW};
178     Id filenames_repodata{0};
179     Id presto_repodata{0};
180     Id updateinfo_repodata{0};
181     Id other_repodata{0};
182     int load_flags{0};
183     /* the following three elements are needed for repo rewriting */
184     int main_nsolvables{0};
185     int main_nrepodata{0};
186     int main_end{0};
187 
188     // Lock attachLibsolvRepo(), detachLibsolvRepo() and hy_repo_free() to ensure atomic behavior
189     // in threaded environment such as PackageKit.
190     std::mutex attachLibsolvMutex;
191 
192 private:
193     Repo * owner;
194     std::unique_ptr<LrResult> lrHandlePerform(LrHandle * handle, const std::string & destDirectory,
195         bool setGPGHomeDir);
196     bool isMetalinkInSync();
197     bool isRepomdInSync();
198     void resetMetadataExpired();
199     std::vector<Key> retrieve(const std::string & url);
200     void importRepoKeys();
201 
202     static int progressCB(void * data, double totalToDownload, double downloaded);
203     static void fastestMirrorCB(void * data, LrFastestMirrorStages stage, void *ptr);
204     static int mirrorFailureCB(void * data, const char * msg, const char * url, const char * metadata);
205 
206     bool expired;
207     std::unique_ptr<LrHandle> handle;
208     std::unique_ptr<char*[], std::function<void(char **)>> httpHeaders{nullptr, [](char ** ptr)
__anon714b6b6f0102(char ** ptr) 209     {
210         for (auto item = ptr; *item; ++item)
211             delete[] *item;
212         delete[] ptr;
213     }};
214     bool endsWith(std::string const &str, std::string const &ending) const;
215     std::string getHash() const;
216 };
217 
218 }
219 
220 #endif
221