libzypp  17.14.0
RepoFileReader.cc
Go to the documentation of this file.
1 /*---------------------------------------------------------------------\
2 | ____ _ __ __ ___ |
3 | |__ / \ / / . \ . \ |
4 | / / \ V /| _/ _/ |
5 | / /__ | | | | | | |
6 | /_____||_| |_| |_| |
7 | |
8 \---------------------------------------------------------------------*/
12 #include <iostream>
13 #include "zypp/base/LogTools.h"
14 #include "zypp/base/String.h"
15 #include "zypp/base/Regex.h"
16 #include "zypp/base/InputStream.h"
18 
19 #include "zypp/parser/IniDict.h"
21 
22 using std::endl;
23 
25 namespace zypp
26 {
28  namespace parser
29  {
31  namespace {
32 
37  class RepoFileParser : public IniDict
38  {
39  public:
40  RepoFileParser( const InputStream & is_r )
41  { read( is_r ); }
42 
43  using IniDict::consume; // don't hide overloads we don't redefine here
44 
45  virtual void consume( const std::string & section_r, const std::string & key_r, const std::string & value_r )
46  {
47  if ( key_r == "baseurl" )
48  {
49  _inMultiline = MultiLine::baseurl;
50  _baseurls[section_r].push_back( Url(value_r) );
51  }
52  else if ( key_r == "gpgkey" )
53  {
54  _inMultiline = MultiLine::gpgkey;
55  legacyStoreUrl( _gpgkeys[section_r], value_r );
56  }
57  else
58  {
59  _inMultiline = MultiLine::none;
60  IniDict::consume( section_r, key_r, value_r );
61  }
62  }
63 
64  virtual void garbageLine( const std::string & section_r, const std::string & line_r )
65  {
66  switch ( _inMultiline )
67  {
68  case MultiLine::baseurl:
69  _baseurls[section_r].push_back( Url(line_r) );
70  break;
71 
72  case MultiLine::gpgkey:
73  legacyStoreUrl( _gpgkeys[section_r], line_r );
74  break;
75 
76  case MultiLine::none:
77  IniDict::garbageLine( section_r, line_r ); // throw
78  break;
79  }
80  }
81 
82  std::list<Url> & baseurls( const std::string & section_r )
83  { return _baseurls[section_r]; }
84 
85  std::list<Url> & gpgkeys( const std::string & section_r )
86  { return _gpgkeys[section_r]; }
87 
88  private:
89  void legacyStoreUrl( std::list<Url> & store_r, const std::string & line_r )
90  {
91  // Legacy:
92  // commit 4ef65a442038caf7a1e310bc719e329b34dbdb67
93  // - split the gpgkey line and take the first one as url to avoid
94  // crash when creating an url from the line, as Fedora hat the
95  // *BRILLIANT* idea of using more than one url per line.
96  std::vector<std::string> keys;
97  str::split( line_r, std::back_inserter(keys) );
98  for ( auto && str : keys )
99  store_r.push_back( Url(std::move(str)) );
100  }
101 
102  enum class MultiLine { none, baseurl, gpgkey };
103  MultiLine _inMultiline = MultiLine::none;
104 
105  std::map<std::string,std::list<Url>> _baseurls;
106  std::map<std::string,std::list<Url>> _gpgkeys;
107  };
108 
109  } //namespace
111 
116  static void repositories_in_stream( const InputStream &is,
117  const RepoFileReader::ProcessRepo &callback,
118  const ProgressData::ReceiverFnc &progress )
119  {
120  RepoFileParser dict(is);
121  for_( its, dict.sectionsBegin(), dict.sectionsEnd() )
122  {
123  RepoInfo info;
124  info.setAlias(*its);
125  std::string proxy;
126  std::string proxyport;
127 
128  for_( it, dict.entriesBegin(*its), dict.entriesEnd(*its) )
129  {
130  //MIL << (*it).first << endl;
131  if (it->first == "name" )
132  info.setName(it-> second);
133  else if ( it->first == "enabled" )
134  info.setEnabled( str::strToTrue( it->second ) );
135  else if ( it->first == "priority" )
136  info.setPriority( str::strtonum<unsigned>( it->second ) );
137  else if ( it->first == "path" )
138  info.setPath( Pathname(it->second) );
139  else if ( it->first == "type" )
140  info.setType(repo::RepoType(it->second));
141  else if ( it->first == "autorefresh" )
142  info.setAutorefresh( str::strToTrue( it->second ) );
143  else if ( it->first == "mirrorlist" && !it->second.empty())
144  info.setMirrorListUrl(Url(it->second));
145  else if ( it->first == "metalink" && !it->second.empty())
146  info.setMetalinkUrl(Url(it->second));
147  else if ( it->first == "gpgcheck" )
148  info.setGpgCheck( str::strToTriBool( it->second ) );
149  else if ( it->first == "repo_gpgcheck" )
150  info.setRepoGpgCheck( str::strToTrue( it->second ) );
151  else if ( it->first == "pkg_gpgcheck" )
152  info.setPkgGpgCheck( str::strToTrue( it->second ) );
153  else if ( it->first == "keeppackages" )
154  info.setKeepPackages( str::strToTrue( it->second ) );
155  else if ( it->first == "service" )
156  info.setService( it->second );
157  else if ( it->first == "proxy" )
158  {
159  // Translate it into baseurl queryparams
160  // NOTE: The hack here does not add proxy to mirrorlist urls but the
161  // original code worked without complains, so keep it for now.
162  static const str::regex ex( ":[0-9]+$" ); // portspec
163  str::smatch what;
164  if ( str::regex_match( it->second, what, ex ) )
165  {
166  proxy = it->second.substr( 0, it->second.size() - what[0].size() );
167  proxyport = what[0].substr( 1 );
168  }
169  else
170  {
171  proxy = it->second;
172  }
173  }
174  else
175  ERR << "Unknown attribute in [" << *its << "]: " << it->first << "=" << it->second << " ignored" << endl;
176  }
177 
178  for ( auto & url : dict.baseurls( *its ) )
179  {
180  if ( ! proxy.empty() && url.getQueryParam( "proxy" ).empty() )
181  {
182  url.setQueryParam( "proxy", proxy );
183  url.setQueryParam( "proxyport", proxyport );
184  }
185  info.addBaseUrl( url );
186  }
187 
188  info.setGpgKeyUrls( std::move(dict.gpgkeys( *its )) );
189 
190  info.setFilepath(is.path());
191  MIL << info << endl;
192  // add it to the list.
193  callback(info);
194  //if (!progress.tick())
195  // ZYPP_THROW(AbortRequestException());
196  }
197  }
198 
200  //
201  // CLASS NAME : RepoFileReader
202  //
204 
205  RepoFileReader::RepoFileReader( const Pathname & repo_file,
206  const ProcessRepo & callback,
207  const ProgressData::ReceiverFnc &progress )
208  : _callback(callback)
209  {
210  repositories_in_stream(InputStream(repo_file), _callback, progress);
211  }
212 
214  const ProcessRepo & callback,
215  const ProgressData::ReceiverFnc &progress )
216  : _callback(callback)
217  {
218  repositories_in_stream(is, _callback, progress);
219  }
220 
222  {}
223 
224 
225  std::ostream & operator<<( std::ostream & str, const RepoFileReader & obj )
226  {
227  return str;
228  }
229 
230  } // namespace parser
232 } // namespace zypp