1 /*
2  * Copyright (C) 2012-2014 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 #include "Python.h"
22 #include <vector>
23 #include <string>
24 #include <ctime>
25 #include <datetime.h>
26 
27 #include "dnf-advisory.h"
28 #include "dnf-advisorypkg.h"
29 #include "dnf-advisoryref.h"
30 #include "hy-packageset.h"
31 #include "dnf-reldep.h"
32 #include "dnf-reldep-list.h"
33 #include "hy-iutil.h"
34 #include "hy-util-private.hpp"
35 #include "advisory-py.hpp"
36 #include "advisorypkg-py.hpp"
37 #include "advisoryref-py.hpp"
38 #include "iutil-py.hpp"
39 #include "package-py.hpp"
40 #include "query-py.hpp"
41 #include "reldep-py.hpp"
42 #include "sack-py.hpp"
43 #include "pycomp.hpp"
44 #include "sack/advisorypkg.hpp"
45 #include "sack/changelog.hpp"
46 #include "sack/packageset.hpp"
47 #include "sack/query.hpp"
48 
49 #include "../../libdnf/repo/solvable/Dependency.hpp"
50 #include "libdnf/repo/solvable/DependencyContainer.hpp"
51 
operator =(UniquePtrPyObject && src)52 UniquePtrPyObject & UniquePtrPyObject::operator =(UniquePtrPyObject && src) noexcept
53 {
54     if (this == &src)
55         return *this;
56     Py_XDECREF(pyObj);
57     pyObj = src.pyObj;
58     src.pyObj = NULL;
59     return *this;
60 }
61 
reset(PyObject * pyObj)62 void UniquePtrPyObject::reset(PyObject * pyObj) noexcept
63 {
64     Py_XDECREF(this->pyObj);
65     this->pyObj = pyObj;
66 }
67 
~UniquePtrPyObject()68 UniquePtrPyObject::~UniquePtrPyObject()
69 {
70     Py_XDECREF(pyObj);
71 }
72 
73 PyObject *
advisorylist_to_pylist(const GPtrArray * advisorylist,PyObject * sack)74 advisorylist_to_pylist(const GPtrArray *advisorylist, PyObject *sack)
75 {
76     UniquePtrPyObject list(PyList_New(0));
77     if (!list)
78         return NULL;
79 
80     for (unsigned int i = 0; i < advisorylist->len; ++i) {
81         auto cadvisory =
82             static_cast<DnfAdvisory *>(g_steal_pointer(&g_ptr_array_index(advisorylist, i)));
83         UniquePtrPyObject advisory(advisoryToPyObject(cadvisory, sack));
84 
85         if (!advisory)
86             return NULL;
87 
88         int rc = PyList_Append(list.get(), advisory.get());
89         if (rc == -1)
90             return NULL;
91     }
92 
93     return list.release();
94 }
95 
96 PyObject *
advisoryPkgVectorToPylist(const std::vector<libdnf::AdvisoryPkg> & advisorypkgs)97 advisoryPkgVectorToPylist(const std::vector<libdnf::AdvisoryPkg> & advisorypkgs)
98 {
99     UniquePtrPyObject list(PyList_New(0));
100     if (!list)
101         return NULL;
102 
103     for (auto& advisorypkg : advisorypkgs) {
104         UniquePtrPyObject pyAdvisoryPkg(advisorypkgToPyObject(new libdnf::AdvisoryPkg(advisorypkg)));
105         if (!pyAdvisoryPkg)
106             return NULL;
107         int rc = PyList_Append(list.get(), pyAdvisoryPkg.get());
108         if (rc == -1)
109             return NULL;
110     }
111 
112     return list.release();
113 }
114 
115 PyObject *
advisoryRefVectorToPylist(const std::vector<libdnf::AdvisoryRef> & advisoryRefs,PyObject * sack)116 advisoryRefVectorToPylist(const std::vector<libdnf::AdvisoryRef> & advisoryRefs, PyObject *sack)
117 {
118     UniquePtrPyObject list(PyList_New(0));
119     if (!list)
120         return NULL;
121 
122     for (auto& advisoryRef : advisoryRefs) {
123         UniquePtrPyObject pyAdvisoryRef(advisoryrefToPyObject(new libdnf::AdvisoryRef(advisoryRef), sack));
124         if (!pyAdvisoryRef)
125             return NULL;
126         int rc = PyList_Append(list.get(), pyAdvisoryRef.get());
127         if (rc == -1)
128             return NULL;
129     }
130 
131     return list.release();
132 }
133 
134 PyObject *
changelogslist_to_pylist(const std::vector<libdnf::Changelog> & changelogslist)135 changelogslist_to_pylist(const std::vector<libdnf::Changelog> & changelogslist)
136 {
137     UniquePtrPyObject list(PyList_New(0));
138     if (!list)
139         return NULL;
140     PyDateTime_IMPORT;
141 
142     for (auto & citem: changelogslist) {
143         UniquePtrPyObject d(PyDict_New());
144         if (!d)
145             return NULL;
146         UniquePtrPyObject author(PyUnicode_FromString(citem.getAuthor().c_str()));
147         if (PyDict_SetItemString(d.get(), "author", author.get()) == -1)
148             return NULL;
149         UniquePtrPyObject description(PyUnicode_FromString(citem.getText().c_str()));
150         if (PyDict_SetItemString(d.get(), "text", description.get()) == -1)
151             return NULL;
152         time_t itemts=citem.getTimestamp();
153         struct tm ts;
154         ts = *localtime(&itemts);
155         UniquePtrPyObject timestamp(PyDate_FromDate(ts.tm_year+1900, ts.tm_mon+1, ts.tm_mday));
156         if (PyDict_SetItemString(d.get(), "timestamp", timestamp.get()) == -1)
157             return NULL;
158         if (PyList_Append(list.get(), d.get()) == -1)
159             return NULL;
160     }
161 
162     return list.release();
163 }
164 
165 PyObject *
packagelist_to_pylist(GPtrArray * plist,PyObject * sack)166 packagelist_to_pylist(GPtrArray *plist, PyObject *sack)
167 {
168     UniquePtrPyObject list(PyList_New(0));
169     if (!list)
170         return NULL;
171 
172     for (unsigned int i = 0; i < plist->len; i++) {
173         auto cpkg = static_cast<DnfPackage *>(g_ptr_array_index(plist, i));
174         UniquePtrPyObject package(new_package(sack, dnf_package_get_id(cpkg)));
175         if (!package)
176             return NULL;
177 
178         int rc = PyList_Append(list.get(), package.get());
179         if (rc == -1)
180             return NULL;
181     }
182     return list.release();
183 }
184 
185 PyObject *
packageset_to_pylist(const DnfPackageSet * pset,PyObject * sack)186 packageset_to_pylist(const DnfPackageSet *pset, PyObject *sack)
187 {
188     UniquePtrPyObject list(PyList_New(0));
189     if (!list)
190         return NULL;
191 
192     Id id = -1;
193     while(true) {
194         id = pset->next(id);
195         if (id == -1)
196             break;
197         UniquePtrPyObject package(new_package(sack, id));
198         if (!package)
199             return NULL;
200 
201         int rc = PyList_Append(list.get(), package.get());
202         if (rc == -1)
203             return NULL;
204     }
205 
206     return list.release();
207 }
208 
209 std::unique_ptr<DnfPackageSet>
pyseq_to_packageset(PyObject * obj,DnfSack * sack)210 pyseq_to_packageset(PyObject *obj, DnfSack *sack)
211 {
212     if (queryObject_Check(obj)) {
213         HyQuery target = queryFromPyObject(obj);
214         return std::unique_ptr<DnfPackageSet>(new libdnf::PackageSet(*target->runSet()));
215     }
216 
217     UniquePtrPyObject sequence(PySequence_Fast(obj, "Expected a sequence."));
218     if (!sequence)
219         return NULL;
220     std::unique_ptr<DnfPackageSet> pset(new libdnf::PackageSet(sack));
221 
222     const unsigned count = PySequence_Size(sequence.get());
223     for (unsigned int i = 0; i < count; ++i) {
224         PyObject *item = PySequence_Fast_GET_ITEM(sequence.get(), i);
225         if (item == NULL)
226             return NULL;
227         DnfPackage *pkg = packageFromPyObject(item);
228         if (pkg == NULL)
229             return NULL;
230         pset->set(pkg);
231     }
232 
233     return pset;
234 }
235 
236 std::unique_ptr<libdnf::DependencyContainer>
pyseq_to_reldeplist(PyObject * obj,DnfSack * sack,int cmp_type)237 pyseq_to_reldeplist(PyObject *obj, DnfSack *sack, int cmp_type)
238 {
239     UniquePtrPyObject sequence(PySequence_Fast(obj, "Expected a sequence."));
240     if (!sequence)
241         return NULL;
242     std::unique_ptr<libdnf::DependencyContainer> reldeplist(new libdnf::DependencyContainer(sack));
243 
244     const unsigned count = PySequence_Size(sequence.get());
245     for (unsigned int i = 0; i < count; ++i) {
246         PyObject *item = PySequence_Fast_GET_ITEM(sequence.get(), i);
247         if (item == NULL)
248             return NULL;
249         if (reldepObject_Check(item)) {
250             DnfReldep * reldep = reldepFromPyObject(item);
251             if (reldep == NULL)
252                 return NULL;
253             reldeplist->add(reldep);
254         } else if (cmp_type == HY_GLOB) {
255 
256             PycompString reldep_str(item);
257             if (!reldep_str.getCString())
258                 return NULL;
259 
260             if (!hy_is_glob_pattern(reldep_str.getCString())) {
261                 if (!reldeplist->addReldep(reldep_str.getCString()))
262                     continue;
263             } else {
264                 if (!reldeplist->addReldepWithGlob(reldep_str.getCString()))
265                     continue;
266             }
267 
268         } else {
269             PycompString reldepStr(item);
270             if (!reldepStr.getCString())
271                 return NULL;
272             if (!reldeplist->addReldep(reldepStr.getCString()))
273                 continue;
274         }
275     }
276 
277     return reldeplist;
278 }
279 
280 PyObject *
strlist_to_pylist(const char ** slist)281 strlist_to_pylist(const char **slist)
282 {
283     UniquePtrPyObject list(PyList_New(0));
284     if (!list)
285         return NULL;
286 
287     for (const char **iter = slist; *iter; ++iter) {
288         UniquePtrPyObject str(PyUnicode_DecodeUTF8(*iter, strlen(*iter), "surrogateescape"));
289         if (!str)
290             return NULL;
291         int rc = PyList_Append(list.get(), str.get());
292         if (rc == -1)
293             return NULL;
294     }
295     return list.release();
296 }
297 
298 PyObject *
strCpplist_to_pylist(const std::vector<std::string> & cppList)299 strCpplist_to_pylist(const std::vector<std::string> & cppList)
300 {
301     UniquePtrPyObject list(PyList_New(0));
302     if (!list)
303         return NULL;
304     for (auto & cStr:cppList) {
305         UniquePtrPyObject str(PyUnicode_FromString(cStr.c_str()));
306         if (!str)
307             return NULL;
308         int rc = PyList_Append(list.get(), str.get());
309         if (rc == -1)
310             return NULL;
311     }
312     return list.release();
313 }
314 
315 PyObject *
reldeplist_to_pylist(DnfReldepList * reldeplist,PyObject * sack)316 reldeplist_to_pylist(DnfReldepList *reldeplist, PyObject *sack)
317 {
318     UniquePtrPyObject list(PyList_New(0));
319     if (!list)
320         return NULL;
321 
322     const int count = reldeplist->count();
323     for (int i = 0; i < count; ++i) {
324         UniquePtrPyObject reldep(new_reldep(sack, reldeplist->getId(i)));
325 
326         if (!reldep)
327             return NULL;
328 
329         int rc = PyList_Append(list.get(), reldep.get());
330         if (rc == -1)
331             return NULL;
332     }
333 
334     return list.release();
335 }
336 
337 std::vector<std::string>
pySequenceConverter(PyObject * pySequence)338 pySequenceConverter(PyObject * pySequence)
339 {
340     UniquePtrPyObject seq(PySequence_Fast(pySequence, "Expected a sequence."));
341     if (!seq)
342         throw std::runtime_error("Expected a sequence.");
343     const unsigned count = PySequence_Size(seq.get());
344     std::vector<std::string> output;
345     output.reserve(count);
346     for (unsigned int i = 0; i < count; ++i) {
347         PyObject *item = PySequence_Fast_GET_ITEM(seq.get(), i);
348         if (PyUnicode_Check(item) || PyString_Check(item)) {
349             PycompString pycomStr(item);
350             if (!pycomStr.getCString())
351                 throw std::runtime_error("Invalid value.");
352             output.push_back(pycomStr.getCString());
353         } else {
354             PyErr_SetString(PyExc_TypeError, "Invalid value.");
355             throw std::runtime_error("Invalid value.");
356         }
357     }
358     return output;
359 }
360 
361 PyObject *
problemRulesPyConverter(std::vector<std::vector<std::string>> & allProblems)362 problemRulesPyConverter(std::vector<std::vector<std::string>> & allProblems)
363 {
364     UniquePtrPyObject list_output(PyList_New(0));
365     if (!list_output)
366         return NULL;
367     for (auto & problemList: allProblems) {
368         if (problemList.empty()) {
369             PyErr_SetString(PyExc_ValueError, "Index out of range.");
370             continue;
371         }
372         UniquePtrPyObject list(strCpplist_to_pylist(problemList));
373         int rc = PyList_Append(list_output.get(), list.get());
374         if (rc == -1)
375             return NULL;
376     }
377     return list_output.release();
378 }
379