Imported Upstream version 17.14.0
[platform/upstream/libzypp.git] / zypp / parser / susetags / ContentFileReader.cc
1 /*---------------------------------------------------------------------\
2 |                          ____ _   __ __ ___                          |
3 |                         |__  / \ / / . \ . \                         |
4 |                           / / \ V /|  _/  _/                         |
5 |                          / /__ | | | | | |                           |
6 |                         /_____||_| |_| |_|                           |
7 |                                                                      |
8 \---------------------------------------------------------------------*/
9 /** \file       zypp/parser/susetags/ContentFileReader.cc
10  *
11 */
12 #include <iostream>
13 #include <sstream>
14
15 #include "zypp/base/LogTools.h"
16 #include "zypp/base/String.h"
17 #include "zypp/base/IOStream.h"
18 #include "zypp/base/UserRequestException.h"
19 #include "zypp/parser/ParseException.h"
20
21 #include "zypp/parser/susetags/ContentFileReader.h"
22 #include "zypp/parser/susetags/RepoIndex.h"
23
24 using std::endl;
25 #undef  ZYPP_BASE_LOGGER_LOGGROUP
26 #define ZYPP_BASE_LOGGER_LOGGROUP "parser::susetags"
27
28 ///////////////////////////////////////////////////////////////////
29 namespace zypp
30 { /////////////////////////////////////////////////////////////////
31   ///////////////////////////////////////////////////////////////////
32   namespace parser
33   { /////////////////////////////////////////////////////////////////
34     ///////////////////////////////////////////////////////////////////
35     namespace susetags
36     { /////////////////////////////////////////////////////////////////
37
38       ///////////////////////////////////////////////////////////////////
39       //
40       //        CLASS NAME : ContentFileReader::Impl
41       //
42       /** ContentFileReader implementation. */
43       struct ContentFileReader::Impl
44       {
45         public:
46           Impl()
47           {}
48
49           RepoIndex & repoindex()
50           {
51             if ( !_repoindex )
52               _repoindex = new RepoIndex;
53             return *_repoindex;
54           }
55
56           bool hasRepoIndex() const
57           { return _repoindex != nullptr; }
58
59           RepoIndex_Ptr handoutRepoIndex()
60           {
61             RepoIndex_Ptr ret;
62             ret.swap( _repoindex );
63             _repoindex = nullptr;
64             return ret;
65           }
66
67         public:
68           bool setFileCheckSum( std::map<std::string, CheckSum> & map_r, const std::string & value ) const
69           {
70             bool error = false;
71             std::vector<std::string> words;
72             if ( str::split( value, std::back_inserter( words ) ) == 3 )
73             {
74               map_r[words[2]] = CheckSum( words[0], words[1] );
75             }
76             else
77             {
78               error = true;
79             }
80             return error;
81           }
82
83         public:
84           std::string _inputname;
85
86         private:
87           RepoIndex_Ptr      _repoindex;
88       };
89       ///////////////////////////////////////////////////////////////////
90
91       ///////////////////////////////////////////////////////////////////
92       //
93       //        CLASS NAME : ContentFileReader
94       //
95       ///////////////////////////////////////////////////////////////////
96
97       ///////////////////////////////////////////////////////////////////
98       //
99       //        METHOD NAME : ContentFileReader::ContentFileReader
100       //        METHOD TYPE : Ctor
101       //
102       ContentFileReader::ContentFileReader()
103       {}
104
105       ///////////////////////////////////////////////////////////////////
106       //
107       //        METHOD NAME : ContentFileReader::~ContentFileReader
108       //        METHOD TYPE : Dtor
109       //
110       ContentFileReader::~ContentFileReader()
111       {}
112
113       ///////////////////////////////////////////////////////////////////
114       //
115       //        METHOD NAME : ContentFileReader::beginParse
116       //        METHOD TYPE : void
117       //
118       void ContentFileReader::beginParse()
119       {
120         _pimpl.reset( new Impl() );
121         // actually mandatory, but in case they were forgotten...
122         _pimpl->repoindex().descrdir = "suse/setup/descr";
123         _pimpl->repoindex().datadir = "suse";
124       }
125
126       ///////////////////////////////////////////////////////////////////
127       //
128       //        METHOD NAME : ContentFileReader::endParse
129       //        METHOD TYPE : void
130       //
131       void ContentFileReader::endParse()
132       {
133         // consume oldData
134         if ( _pimpl->hasRepoIndex() )
135         {
136           if ( _repoIndexConsumer )
137             _repoIndexConsumer( _pimpl->handoutRepoIndex() );
138         }
139
140         MIL << "[Content]" << endl;
141         _pimpl.reset();
142       }
143
144       ///////////////////////////////////////////////////////////////////
145       //
146       //        METHOD NAME : ContentFileReader::userRequestedAbort
147       //        METHOD TYPE : void
148       //
149       void ContentFileReader::userRequestedAbort( unsigned lineNo_r )
150       {
151         ZYPP_THROW( AbortRequestException( errPrefix( lineNo_r ) ) );
152       }
153
154       ///////////////////////////////////////////////////////////////////
155       //
156       //        METHOD NAME : ContentFileReader::errPrefix
157       //        METHOD TYPE : std::string
158       //
159       std::string ContentFileReader::errPrefix( unsigned lineNo_r,
160                                                 const std::string & msg_r,
161                                                 const std::string & line_r ) const
162       {
163         return str::form( "%s:%u:%s | %s",
164                           _pimpl->_inputname.c_str(),
165                           lineNo_r,
166                           line_r.c_str(),
167                           msg_r.c_str() );
168       }
169
170       ///////////////////////////////////////////////////////////////////
171       //
172       //        METHOD NAME : ContentFileReader::parse
173       //        METHOD TYPE : void
174       //
175       void ContentFileReader::parse( const InputStream & input_r,
176                                      const ProgressData::ReceiverFnc & fnc_r )
177       {
178         MIL << "Start parsing content repoindex" << input_r << endl;
179         if ( ! input_r.stream() )
180         {
181           std::ostringstream s;
182           s << "Can't read bad stream: " << input_r;
183           ZYPP_THROW( ParseException( s.str() ) );
184         }
185         beginParse();
186         _pimpl->_inputname = input_r.name();
187
188         ProgressData ticks( makeProgressData( input_r ) );
189         ticks.sendTo( fnc_r );
190         if ( ! ticks.toMin() )
191           userRequestedAbort( 0 );
192
193         iostr::EachLine line( input_r );
194         for( ; line; line.next() )
195         {
196           // strip 1st word from line to separate tag and value.
197           std::string value( *line );
198           std::string key( str::stripFirstWord( value, /*ltrim_first*/true ) );
199
200           if ( key.empty() || *key.c_str() == '#' ) // empty or comment line
201           {
202             continue;
203           }
204
205           // strip modifier if exists
206           std::string modifier;
207           std::string::size_type pos = key.rfind( '.' );
208           if ( pos != std::string::npos )
209           {
210             modifier = key.substr( pos+1 );
211             key.erase( pos );
212           }
213
214           //
215           // ReppoIndex related data:
216           //
217           else if ( key == "DESCRDIR" )
218           {
219             _pimpl->repoindex().descrdir = value;
220           }
221           else if ( key == "DATADIR" )
222           {
223             _pimpl->repoindex().datadir = value;
224           }
225           else if ( key == "KEY" )
226           {
227             if ( _pimpl->setFileCheckSum( _pimpl->repoindex().signingKeys, value ) )
228             {
229               ZYPP_THROW( ParseException( errPrefix( line.lineNo(), "Expected [KEY algorithm checksum filename]", *line ) ) );
230             }
231           }
232           else if ( key == "META" )
233           {
234             if ( _pimpl->setFileCheckSum( _pimpl->repoindex().metaFileChecksums, value ) )
235             {
236               ZYPP_THROW( ParseException( errPrefix( line.lineNo(), "Expected [algorithm checksum filename]", *line ) ) );
237             }
238           }
239           else if ( key == "HASH" )
240           {
241             if ( _pimpl->setFileCheckSum( _pimpl->repoindex().mediaFileChecksums, value ) )
242             {
243               ZYPP_THROW( ParseException( errPrefix( line.lineNo(), "Expected [algorithm checksum filename]", *line ) ) );
244             }
245           }
246           else
247           {
248             DBG << errPrefix( line.lineNo(), "ignored", *line ) << endl;
249           }
250
251
252           if ( ! ticks.set( input_r.stream().tellg() ) )
253             userRequestedAbort( line.lineNo() );
254         }
255
256         //
257         // post processing
258         //
259         if ( ! ticks.toMax() )
260           userRequestedAbort( line.lineNo() );
261
262         endParse();
263         MIL << "Done parsing " << input_r << endl;
264       }
265
266       /////////////////////////////////////////////////////////////////
267     } // namespace susetags
268     ///////////////////////////////////////////////////////////////////
269     /////////////////////////////////////////////////////////////////
270   } // namespace parser
271   ///////////////////////////////////////////////////////////////////
272   /////////////////////////////////////////////////////////////////
273 } // namespace zypp
274 ///////////////////////////////////////////////////////////////////