1 /*---------------------------------------------------------------------\
3 | |__ / \ / / . \ . \ |
8 \---------------------------------------------------------------------*/
9 /** \file zypp/repo/RepoFileReader.cc
13 #include <zypp/base/LogTools.h>
14 #include <zypp/base/String.h>
15 #include <zypp/base/Regex.h>
16 #include <zypp/base/InputStream.h>
17 #include <zypp/base/UserRequestException.h>
19 #include <zypp/parser/IniDict.h>
20 #include <zypp/parser/RepoFileReader.h>
24 ///////////////////////////////////////////////////////////////////
27 ///////////////////////////////////////////////////////////////////
30 ///////////////////////////////////////////////////////////////////
33 ///////////////////////////////////////////////////////////////////
34 /// \class RepoFileParser
35 /// \brief Modified \ref IniDict to allow parsing multiple 'baseurl=' entries
36 ///////////////////////////////////////////////////////////////////
37 class RepoFileParser : public IniDict
40 RepoFileParser( const InputStream & is_r )
43 using IniDict::consume; // don't hide overloads we don't redefine here
45 virtual void consume( const std::string & section_r, const std::string & key_r, const std::string & value_r )
47 if ( key_r == "baseurl" )
49 _inMultiline = MultiLine::baseurl;
50 _baseurls[section_r].push_back( Url(value_r) );
52 else if ( key_r == "gpgkey" )
54 _inMultiline = MultiLine::gpgkey;
55 legacyStoreUrl( _gpgkeys[section_r], value_r );
59 _inMultiline = MultiLine::none;
60 IniDict::consume( section_r, key_r, value_r );
64 virtual void garbageLine( const std::string & section_r, const std::string & line_r )
66 switch ( _inMultiline )
68 case MultiLine::baseurl:
69 _baseurls[section_r].push_back( Url(line_r) );
72 case MultiLine::gpgkey:
73 legacyStoreUrl( _gpgkeys[section_r], line_r );
77 IniDict::garbageLine( section_r, line_r ); // throw
82 std::list<Url> & baseurls( const std::string & section_r )
83 { return _baseurls[section_r]; }
85 std::list<Url> & gpgkeys( const std::string & section_r )
86 { return _gpgkeys[section_r]; }
89 void legacyStoreUrl( std::list<Url> & store_r, const std::string & line_r )
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)) );
102 enum class MultiLine { none, baseurl, gpgkey };
103 MultiLine _inMultiline = MultiLine::none;
105 std::map<std::string,std::list<Url>> _baseurls;
106 std::map<std::string,std::list<Url>> _gpgkeys;
110 ///////////////////////////////////////////////////////////////////
113 * \short List of RepoInfo's from a file.
114 * \param file pathname of the file to read.
116 static void repositories_in_stream( const InputStream &is,
117 const RepoFileReader::ProcessRepo &callback,
118 const ProgressData::ReceiverFnc &progress )
120 RepoFileParser dict(is);
121 for_( its, dict.sectionsBegin(), dict.sectionsEnd() )
126 std::string proxyport;
128 for_( it, dict.entriesBegin(*its), dict.entriesEnd(*its) )
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 ; // bsc#1177427 et.al.: type in a .repo file is legacy - ignore it and let RepoManager probe
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" )
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
164 if ( str::regex_match( it->second, what, ex ) )
166 proxy = it->second.substr( 0, it->second.size() - what[0].size() );
167 proxyport = what[0].substr( 1 );
175 ERR << "Unknown attribute in [" << *its << "]: " << it->first << "=" << it->second << " ignored" << endl;
178 for ( auto & url : dict.baseurls( *its ) )
180 if ( ! proxy.empty() && url.getQueryParam( "proxy" ).empty() )
182 url.setQueryParam( "proxy", proxy );
183 url.setQueryParam( "proxyport", proxyport );
185 info.addBaseUrl( url );
188 info.setGpgKeyUrls( std::move(dict.gpgkeys( *its )) );
190 info.setFilepath(is.path());
192 // add it to the list.
194 //if (!progress.tick())
195 // ZYPP_THROW(AbortRequestException());
199 ///////////////////////////////////////////////////////////////////
201 // CLASS NAME : RepoFileReader
203 ///////////////////////////////////////////////////////////////////
205 RepoFileReader::RepoFileReader( const Pathname & repo_file,
206 const ProcessRepo & callback,
207 const ProgressData::ReceiverFnc &progress )
208 : _callback(callback)
210 repositories_in_stream(InputStream(repo_file), _callback, progress);
213 RepoFileReader::RepoFileReader( const InputStream &is,
214 const ProcessRepo & callback,
215 const ProgressData::ReceiverFnc &progress )
216 : _callback(callback)
218 repositories_in_stream(is, _callback, progress);
221 RepoFileReader::~RepoFileReader()
225 std::ostream & operator<<( std::ostream & str, const RepoFileReader & obj )
230 } // namespace parser
231 ///////////////////////////////////////////////////////////////////
233 ///////////////////////////////////////////////////////////////////