ff0309c82c1fdbaeafb82eb9697ee9e023e3c4c0
[platform/upstream/libzypp.git] / zypp / parser / RepoFileReader.cc
1 /*---------------------------------------------------------------------\
2 |                          ____ _   __ __ ___                          |
3 |                         |__  / \ / / . \ . \                         |
4 |                           / / \ V /|  _/  _/                         |
5 |                          / /__ | | | | | |                           |
6 |                         /_____||_| |_| |_|                           |
7 |                                                                      |
8 \---------------------------------------------------------------------*/
9 /** \file       zypp/repo/RepoFileReader.cc
10  *
11 */
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"
17 #include "zypp/base/UserRequestException.h"
18
19 #include "zypp/parser/IniDict.h"
20 #include "zypp/parser/RepoFileReader.h"
21
22 using std::endl;
23
24 ///////////////////////////////////////////////////////////////////
25 namespace zypp
26 {
27   ///////////////////////////////////////////////////////////////////
28   namespace parser
29   {
30     ///////////////////////////////////////////////////////////////////
31     namespace {
32
33       ///////////////////////////////////////////////////////////////////
34       /// \class RepoFileParser
35       /// \brief Modified \ref IniDict to allow parsing multiple 'baseurl=' entries
36       ///////////////////////////////////////////////////////////////////
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             setInBaseurls( true );
50             _baseurls[section_r].push_back( Url(value_r) );
51           }
52           else
53           {
54             setInBaseurls( false );
55             IniDict::consume( section_r, key_r, value_r );
56           }
57         }
58
59         virtual void garbageLine( const std::string & section_r, const std::string & line_r )
60         {
61           if ( _inBaseurls )
62             _baseurls[section_r].push_back( Url(line_r) );
63           else
64             IniDict::garbageLine( section_r, line_r );  // throw
65         }
66
67         std::list<Url> & baseurls( const std::string & section_r )
68         { return _baseurls[section_r]; }
69
70       private:
71         void setInBaseurls( bool yesno_r )
72         { if ( _inBaseurls != yesno_r ) _inBaseurls = yesno_r; }
73
74         DefaultIntegral<bool,false> _inBaseurls;
75         std::map<std::string,std::list<Url>> _baseurls;
76       };
77
78     } //namespace
79     ///////////////////////////////////////////////////////////////////
80
81     /**
82    * \short List of RepoInfo's from a file.
83    * \param file pathname of the file to read.
84    */
85     static void repositories_in_stream( const InputStream &is,
86                                         const RepoFileReader::ProcessRepo &callback,
87                                         const ProgressData::ReceiverFnc &progress )
88     {
89       RepoFileParser dict(is);
90       for_( its, dict.sectionsBegin(), dict.sectionsEnd() )
91       {
92         RepoInfo info;
93         info.setAlias(*its);
94         std::string proxy;
95         std::string proxyport;
96
97         for_( it, dict.entriesBegin(*its), dict.entriesEnd(*its) )
98         {
99           //MIL << (*it).first << endl;
100           if (it->first == "name" )
101             info.setName(it-> second);
102           else if ( it->first == "enabled" )
103             info.setEnabled( str::strToTrue( it->second ) );
104           else if ( it->first == "priority" )
105             info.setPriority( str::strtonum<unsigned>( it->second ) );
106           else if ( it->first == "path" )
107             info.setPath( Pathname(it->second) );
108           else if ( it->first == "type" )
109             info.setType(repo::RepoType(it->second));
110           else if ( it->first == "autorefresh" )
111             info.setAutorefresh( str::strToTrue( it->second ) );
112           else if ( it->first == "mirrorlist" && !it->second.empty())
113             info.setMirrorListUrl(Url(it->second));
114           else if ( it->first == "metalink" && !it->second.empty())
115             info.setMetalinkUrl(Url(it->second));
116           else if ( it->first == "gpgkey" && !it->second.empty())
117           {
118             std::vector<std::string> keys;
119             str::split( it->second, std::back_inserter(keys) );
120             if ( ! keys.empty() )
121               info.setGpgKeyUrl( Url(*keys.begin()) );
122           }
123           else if ( it->first == "gpgcheck" )
124             info.setGpgCheck( str::strToTriBool( it->second ) );
125           else if ( it->first == "repo_gpgcheck" )
126             info.setRepoGpgCheck( str::strToTrue( it->second ) );
127           else if ( it->first == "pkg_gpgcheck" )
128             info.setPkgGpgCheck( str::strToTrue( it->second ) );
129           else if ( it->first == "keeppackages" )
130             info.setKeepPackages( str::strToTrue( it->second ) );
131           else if ( it->first == "service" )
132             info.setService( it->second );
133           else if ( it->first == "proxy" )
134           {
135             // Translate it into baseurl queryparams
136             // NOTE: The hack here does not add proxy to mirrorlist urls but the
137             //       original code worked without complains, so keep it for now.
138             static const str::regex ex( ":[0-9]+$" );   // portspec
139             str::smatch what;
140             if ( str::regex_match( it->second, what, ex ) )
141             {
142               proxy = it->second.substr( 0, it->second.size() - what[0].size() );
143               proxyport = what[0].substr( 1 );
144             }
145             else
146             {
147               proxy = it->second;
148             }
149           }
150           else
151             ERR << "Unknown attribute in [" << *its << "]: " << it->first << "=" << it->second << " ignored" << endl;
152         }
153
154         for ( auto & url : dict.baseurls( *its ) )
155         {
156           if ( ! proxy.empty() && url.getQueryParam( "proxy" ).empty() )
157           {
158             url.setQueryParam( "proxy", proxy );
159             url.setQueryParam( "proxyport", proxyport );
160           }
161           info.addBaseUrl( url );
162         }
163
164         info.setFilepath(is.path());
165         MIL << info << endl;
166         // add it to the list.
167         callback(info);
168         //if (!progress.tick())
169         //  ZYPP_THROW(AbortRequestException());
170       }
171     }
172
173     ///////////////////////////////////////////////////////////////////
174     //
175     //  CLASS NAME : RepoFileReader
176     //
177     ///////////////////////////////////////////////////////////////////
178
179     RepoFileReader::RepoFileReader( const Pathname & repo_file,
180                                     const ProcessRepo & callback,
181                                     const ProgressData::ReceiverFnc &progress )
182       : _callback(callback)
183     {
184       repositories_in_stream(InputStream(repo_file), _callback, progress);
185     }
186
187     RepoFileReader::RepoFileReader( const InputStream &is,
188                                     const ProcessRepo & callback,
189                                     const ProgressData::ReceiverFnc &progress )
190       : _callback(callback)
191     {
192       repositories_in_stream(is, _callback, progress);
193     }
194
195     RepoFileReader::~RepoFileReader()
196     {}
197
198
199     std::ostream & operator<<( std::ostream & str, const RepoFileReader & obj )
200     {
201       return str;
202     }
203
204   } // namespace parser
205   ///////////////////////////////////////////////////////////////////
206 } // namespace zypp
207 ///////////////////////////////////////////////////////////////////