libzypp 17.38.13
RepoFileReader.cc
Go to the documentation of this file.
1/*---------------------------------------------------------------------\
2| ____ _ __ __ ___ |
3| |__ / \ / / . \ . \ |
4| / / \ V /| _/ _/ |
5| / /__ | | | | | | |
6| /_____||_| |_| |_| |
7| |
8\---------------------------------------------------------------------*/
12#include <iostream>
13#include <zypp/ZYppCallbacks.h>
17#include <utility>
18#include <zypp-core/base/InputStream>
19#include <zypp-core/base/UserRequestException>
20
21#include <zypp-core/parser/IniDict>
23
24using std::endl;
25
27namespace zypp
28{
30 namespace parser
31 {
33 namespace {
34
39 class RepoFileParser : public IniDict
40 {
41 public:
42 RepoFileParser( const InputStream & is_r )
43 { read( is_r ); }
44
45 using IniDict::consume; // don't hide overloads we don't redefine here
46
47 void consume( const std::string & section_r, const std::string & key_r, const std::string & value_r ) override
48 {
49 if ( key_r == "baseurl" )
50 {
51 _inMultiline = MultiLine::baseurl;
52 storeUrl( _baseurls[section_r], value_r );
53 }
54 else if ( key_r == "gpgkey" )
55 {
56 _inMultiline = MultiLine::gpgkey;
57 storeUrl( _gpgkeys[section_r], value_r );
58 }
59 else if ( key_r == "mirrorlist" )
60 {
61 _inMultiline = MultiLine::mirrorlist;
62 storeUrl( _mirrorlist[section_r], value_r );
63 }
64 else if ( key_r == "metalink" )
65 {
66 _inMultiline = MultiLine::metalink;
67 storeUrl( _metalink[section_r], value_r );
68 }
69 else
70 {
71 _inMultiline = MultiLine::none;
72 IniDict::consume( section_r, key_r, value_r );
73 }
74 }
75
76 void garbageLine( const std::string & section_r, const std::string & line_r ) override
77 {
78 switch ( _inMultiline )
79 {
80 case MultiLine::baseurl:
81 storeUrl( _baseurls[section_r], line_r );
82 break;
83
84 case MultiLine::gpgkey:
85 storeUrl( _gpgkeys[section_r], line_r );
86 break;
87
88 case MultiLine::mirrorlist:
89 storeUrl( _mirrorlist[section_r], line_r );
90 break;
91
92 case MultiLine::metalink:
93 storeUrl( _metalink[section_r], line_r );
94 break;
95
96 case MultiLine::none:
97 IniDict::garbageLine( section_r, line_r ); // throw
98 break;
99 }
100 }
101
102 std::list<Url> & baseurls( const std::string & section_r )
103 { return _baseurls[section_r]; }
104
105 std::list<Url> & gpgkeys( const std::string & section_r )
106 { return _gpgkeys[section_r]; }
107
108 std::list<Url> & mirrorlist( const std::string & section_r )
109 { return _mirrorlist[section_r]; }
110
111 std::list<Url> & metalink( const std::string & section_r )
112 { return _metalink[section_r]; }
113
114 private:
115 void storeUrl( std::list<Url> & store_r, const std::string & line_r )
116 {
117 // #285: Fedora/dnf allows WS separated urls (and an optional comma)
118 strv::splitRx( line_r, "[,[:blank:]]*[[:blank:]][,[:blank:]]*", [&store_r]( std::string_view w ) {
119 if ( ! w.empty() )
120 store_r.push_back( Url(std::string(w)) );
121 });
122 }
123
124 enum class MultiLine { none, baseurl, gpgkey, mirrorlist, metalink };
125 MultiLine _inMultiline = MultiLine::none;
126
127 std::map<std::string,std::list<Url>> _baseurls;
128 std::map<std::string,std::list<Url>> _gpgkeys;
129 std::map<std::string,std::list<Url>> _mirrorlist;
130 std::map<std::string,std::list<Url>> _metalink;
131 };
132
133 } //namespace
135
140 static void repositories_in_stream( const InputStream &is,
142 const ProgressData::ReceiverFnc &progress )
143 try {
144 RepoFileParser dict(is);
145 for_( its, dict.sectionsBegin(), dict.sectionsEnd() )
146 {
147 RepoInfo info;
148 info.setAlias(*its);
149 std::string proxy;
150 std::string proxyport;
151
152 for_( it, dict.entriesBegin(*its), dict.entriesEnd(*its) )
153 {
154 //MIL << (*it).first << endl;
155 if (it->first == "name" )
156 info.setName(it-> second);
157 else if ( it->first == "enabled" )
158 info.setEnabled( str::strToTrue( it->second ) );
159 else if ( it->first == "priority" )
160 info.setPriority( str::strtonum<unsigned>( it->second ) );
161 else if ( it->first == "path" ) {
162 Pathname location { it->second };
163 if ( location.relativeDotDot() ) {
164 // Don't accept downloadable data outside repo root
165 JobReport::warning( str::sconcat( *its,": hostile path=",location," => ", location.absolutename() ) );
166 pWAR( "Hostile path=", location, "=>", location.absolutename() );
167 location = location.absolutename();
168 }
169 info.setPath( location );
170 }
171 else if ( it->first == "type" )
172 ; // bsc#1177427 et.al.: type in a .repo file is legacy - ignore it and let RepoManager probe
173 else if ( it->first == "autorefresh" )
174 info.setAutorefresh( str::strToTrue( it->second ) );
175 else if ( it->first == "gpgcheck" )
176 info.setGpgCheck( str::strToTriBool( it->second ) );
177 else if ( it->first == "repo_gpgcheck" )
178 info.setRepoGpgCheck( str::strToTrue( it->second ) );
179 else if ( it->first == "pkg_gpgcheck" )
180 info.setPkgGpgCheck( str::strToTrue( it->second ) );
181 else if ( it->first == "keeppackages" )
182 info.setKeepPackages( str::strToTrue( it->second ) );
183 else if ( it->first == "service" )
184 info.setService( it->second );
185 else if ( it->first == "proxy" )
186 {
187 // Translate it into baseurl queryparams
188 // NOTE: The hack here does not add proxy to mirrorlist urls but the
189 // original code worked without complains, so keep it for now.
190 static const str::regex ex( ":[0-9]+$" ); // portspec
191 str::smatch what;
192 if ( str::regex_match( it->second, what, ex ) )
193 {
194 proxy = it->second.substr( 0, it->second.size() - what[0].size() );
195 proxyport = what[0].substr( 1 );
196 }
197 else
198 {
199 proxy = it->second;
200 }
201 }
202 else
203 {
204 // Extra tags are directly forwarded to the RepoInfo.
205 if ( not info.setExtraValue( it->first, it->second ) ) {
206 WAR << "Unknown attribute in [" << *its << "]: " << it->first << "=" << it->second << " not interpreted; preserved as an extra value" << endl;
207 }
208 }
209 }
210
211 for ( auto & url : dict.baseurls( *its ) )
212 {
213 if ( ! proxy.empty() && url.getQueryParam( "proxy" ).empty() )
214 {
215 url.setQueryParam( "proxy", proxy );
216 url.setQueryParam( "proxyport", proxyport );
217 }
218 info.addBaseUrl( url );
219 }
220
221 if ( ! dict.gpgkeys( *its ).empty() )
222 info.setGpgKeyUrls( std::move(dict.gpgkeys( *its )) );
223
224 if ( ! dict.mirrorlist( *its ).empty() ) // parser tolerates multiple definitions, but 1st one wins
225 info.setMirrorlistUrl( dict.mirrorlist( *its ).front() );
226
227 if ( ! dict.metalink( *its ).empty() ) // parser tolerates multiple definitions, but 1st one wins
228 info.setMetalinkUrl( dict.metalink( *its ).front() );
229
230 info.setFilepath(is.path());
231 MIL << info << endl;
232 // add it to the list.
233 callback(info);
234 //if (!progress.tick())
235 // ZYPP_THROW(AbortRequestException());
236 }
237 }
238 catch ( Exception & ex ) {
239 ex.addHistory( "Parsing .repo file "+is.name() );
240 ZYPP_RETHROW( ex );
241 }
242
244 //
245 // CLASS NAME : RepoFileReader
246 //
248
251 const ProgressData::ReceiverFnc &progress )
252 : _callback(std::move(callback))
253 {
254 repositories_in_stream(InputStream(repo_file), _callback, progress);
255 }
256
259 const ProgressData::ReceiverFnc &progress )
260 : _callback(std::move(callback))
261 {
262 repositories_in_stream(is, _callback, progress);
263 }
264
267
268
269 std::ostream & operator<<( std::ostream & str, const RepoFileReader & obj )
270 {
271 return str;
272 }
273
274 } // namespace parser
276} // namespace zypp
#define for_(IT, BEG, END)
Convenient for-loops using iterator.
Definition Easy.h:27
#define ZYPP_RETHROW(EXCPT)
Drops a logline and rethrows, updating the CodeLocation.
Definition Exception.h:479
#define pWAR
Definition LogTools.h:316
#define MIL
Definition Logger.h:103
#define WAR
Definition Logger.h:104
Base class for Exception.
Definition Exception.h:153
void addHistory(const std::string &msg_r)
Add some message text to the history.
Definition Exception.cc:189
Helper to create and pass std::istream.
Definition inputstream.h:57
const Pathname & path() const
Path to the input file or empty if no file.
function< bool(const ProgressData &)> ReceiverFnc
Most simple version of progress reporting The percentage in most cases.
What is known about a repository.
Definition RepoInfo.h:72
void setPkgGpgCheck(TriBool value_r)
Set the value for pkgGpgCheck (or indeterminate to use the default).
Definition RepoInfo.cc:654
void setGpgKeyUrls(url_set urls)
Set a list of gpgkey URLs defined for this repo.
Definition RepoInfo.cc:755
void setMetalinkUrl(const Url &url)
Set the raw metalink url.
Definition RepoInfo.cc:737
void setMirrorlistUrl(const Url &url)
Set the raw mirrorlist url.
Definition RepoInfo.cc:734
void setKeepPackages(bool keep)
Set if packaqes downloaded from this repository will be kept in local cache.
Definition RepoInfo.cc:819
void setService(const std::string &name)
sets service which added this repository
Definition RepoInfo.cc:822
bool setExtraValue(const std::string &key_r, std::string value_r)
Remember extra value_r for key_r.
Definition RepoInfo.cc:1269
void setGpgCheck(TriBool value_r)
Set the value for gpgCheck (or indeterminate to use the default).
Definition RepoInfo.cc:626
void addBaseUrl(Url url)
Add a base url.
Definition RepoInfo.cc:767
void setPath(const Pathname &path)
set the product path.
Definition RepoInfo.cc:800
void setPriority(unsigned newval_r)
Set repository priority for solver.
Definition RepoInfo.cc:619
void setRepoGpgCheck(TriBool value_r)
Set the value for repoGpgCheck (or indeterminate to use the default).
Definition RepoInfo.cc:644
bool relativeDotDot() const
Test for a relative path referring to ../.
Definition Pathname.h:124
Pathname absolutename() const
Return this path, adding a leading '/' if relative.
Definition Pathname.h:148
Parses a INI file and offers its structure as a dictionary.
Definition inidict.h:42
void consume(const std::string &section) override
Called when a section is found.
Definition inidict.cc:64
virtual void garbageLine(const std::string &section, const std::string &line)
Called whenever a garbage line is found.
Definition iniparser.cc:78
function< bool(const RepoInfo &)> ProcessRepo
Callback definition.
RepoFileReader(const Pathname &repo_file, ProcessRepo callback, const ProgressData::ReceiverFnc &progress=ProgressData::ReceiverFnc())
Constructor.
void setAutorefresh(bool autorefresh)
enable or disable autorefresh
void setFilepath(const Pathname &filename)
set the path to the .repo file
void setAlias(const std::string &alias)
set the repository alias
void setName(const std::string &name)
set the repository name
void setEnabled(bool enabled)
enable or disable the repository
Regular expression.
Definition Regex.h:95
Regular expression match result.
Definition Regex.h:168
unsigned size() const
Definition Regex.cc:106
bool regex_match(const char *s, smatch &matches, const regex &regex) ZYPP_API
Regular expression matching.
Definition Regex.cc:80
Definition ansi.h:855
String related utilities and Regular expression matching.
@ none
Definition Table.h:92
std::map< std::string, std::string > read(const Pathname &_path)
Read sysconfig file path_r and return (key,valye) pairs.
Definition sysconfig.cc:34
Callbacks light.
Definition Callback.h:146
static void repositories_in_stream(const InputStream &is, const RepoFileReader::ProcessRepo &callback, const ProgressData::ReceiverFnc &progress)
List of RepoInfo's from a file.
std::ostream & operator<<(std::ostream &str, const ProductFileData &obj)
relates: ProductFileData Stream output
bool strToTrue(const C_Str &str)
Parsing boolean from string.
Definition String.cc:66
TriBool strToTriBool(const C_Str &str)
Parse str into a bool if it's a legal true or false string; else indeterminate.
Definition String.cc:96
TInt strtonum(const C_Str &str)
Parsing numbers from string.
std::string sconcat(Args &&... args)
Concat words as string.
Definition LogTools.h:276
Url details namespace.
Definition UrlBase.cc:58
Easy-to use interface to the ZYPP dependency resolver.
zypp::Url Url
Definition url.h:15
static bool warning(const std::string &msg_r, const UserData &userData_r=UserData())
send warning text