Follow gpgcheck tag in .repo file and do no check if disabled.
[platform/upstream/libzypp.git] / zypp / repo / susetags / Downloader.cc
1
2 #include <iostream>
3 #include <fstream>
4
5 #include "zypp/base/Logger.h"
6 #include "zypp/base/String.h"
7 #include "zypp/OnMediaLocation.h"
8 #include "zypp/MediaSetAccess.h"
9 #include "zypp/Fetcher.h"
10 #include "zypp/Locale.h"
11 #include "zypp/ZConfig.h"
12 #include "zypp/repo/MediaInfoDownloader.h"
13 #include "zypp/repo/susetags/Downloader.h"
14 #include "zypp/parser/ParseException.h"
15 #include "zypp/parser/susetags/RepoIndex.h"
16 #include "zypp/base/UserRequestException.h"
17
18 using namespace std;
19 using namespace zypp::parser;
20 using namespace zypp::parser::susetags;
21
22 namespace zypp
23 {
24 namespace repo
25 {
26 namespace susetags
27 {
28
29 Downloader::Downloader(const RepoInfo &info )
30     : _info(info)
31 {
32
33 }
34
35 Downloader::Downloader(const Pathname &path )
36 {
37     RepoInfo info;
38     info.setPath(path);
39     _info = info;
40 }
41
42 RepoStatus Downloader::status( MediaSetAccess &media )
43 {
44     Pathname content = media.provideFile( _info.path() + "/content");
45     Pathname mediafile = media.provideFile( _info.path() + "/media.1/media" );
46
47   return RepoStatus(content) && RepoStatus(mediafile);
48 }
49
50 void Downloader::download( MediaSetAccess &media,
51                            const Pathname &dest_dir,
52                            const ProgressData::ReceiverFnc & progress )
53 {
54   downloadMediaInfo( dest_dir, media );
55
56   SignatureFileChecker sigchecker(_info.name());
57
58   Pathname sig = _info.path() + "/content.asc";
59   if ( media.doesFileExist(sig) )
60   {
61     this->enqueue( OnMediaLocation( sig, 1 ) );
62     this->start( dest_dir, media );
63     this->reset();
64
65     sigchecker = SignatureFileChecker( dest_dir + sig, _info.name() );
66   }
67
68   Pathname key = _info.path() + "/content.key";
69   if ( media.doesFileExist(key) )
70   {
71     this->enqueue( OnMediaLocation( key, 1 ) );
72     this->start( dest_dir, media );
73     this->reset();
74     sigchecker.addPublicKey(dest_dir + key);
75   }
76
77   if ( ! _info.gpgCheck() )
78   {
79     WAR << "Signature checking disabled in config of repository " << _info.alias() << endl;
80   }
81   this->enqueue( OnMediaLocation( _info.path() + "/content", 1 ),
82                  _info.gpgCheck() ? FileChecker(sigchecker) : FileChecker(NullFileChecker()) );
83   this->start( dest_dir, media );
84   this->reset();
85
86   Pathname descr_dir;
87
88   // Content file first to get the repoindex
89   {
90       Pathname inputfile( dest_dir +  _info.path() + "/content" );
91     ContentFileReader content;
92     content.setRepoIndexConsumer( bind( &Downloader::consumeIndex, this, _1 ) );
93     content.parse( inputfile );
94   }
95   if ( ! _repoindex )
96   {
97     ZYPP_THROW( ParseException( (dest_dir+_info.path()).asString() + ": " + "No repository index in content file." ) );
98   }
99   MIL << "RepoIndex: " << _repoindex << endl;
100   if ( _repoindex->metaFileChecksums.empty() )
101   {
102     ZYPP_THROW( ParseException( (dest_dir+_info.path()).asString() + ": " + "No metadata checksums in content file." ) );
103   }
104   if ( _repoindex->signingKeys.empty() )
105   {
106     WAR << "No signing keys defined." << endl;
107   }
108
109   // Prepare parsing
110   descr_dir = _repoindex->descrdir; // path below reporoot
111   //_datadir  = _repoIndex->datadir;  // path below reporoot
112
113
114   for ( RepoIndex::FileChecksumMap::const_iterator it = _repoindex->metaFileChecksums.begin();
115         it != _repoindex->metaFileChecksums.end();
116         ++it )
117   {
118     // omit unwanted translations
119     if ( str::hasPrefix( it->first, "packages" ) )
120     {
121       std::string rest( str::stripPrefix( it->first, "packages" ) );
122       if ( ! (   rest.empty()
123               || rest == ".DU"
124               || rest == ".en"
125               || rest == ".gz"
126               || rest == ".DU.gz"
127               || rest == ".en.gz" ) )
128       {
129         // Not 100% correct as we take each fallback of textLocale
130         Locale toParse( ZConfig::instance().textLocale() );
131         while ( toParse != Locale::noCode )
132         {
133           if ( rest == ("."+toParse.code()) || (rest == ("."+toParse.code()+".gz")) )
134             break;
135           toParse = toParse.fallback();
136         }
137         if ( toParse == Locale::noCode )
138         {
139           // discard
140           continue;
141         }
142       }
143     }
144     else if ( it->first == "patterns.pat"
145               || it->first == "patterns.pat.gz" )
146     {
147       // take all patterns in one go
148     }
149     else if ( str::endsWith( it->first, ".pat" )
150               || str::endsWith( it->first, ".pat.gz" ) )
151     {
152
153       // *** see also zypp/parser/susetags/RepoParser.cc ***
154
155       // omit unwanted patterns, see https://bugzilla.novell.com/show_bug.cgi?id=298716
156       // expect "<name>.<arch>.pat[.gz]", <name> might contain additional dots
157       // split at dots, take .pat or .pat.gz into account
158
159       std::vector<std::string> patparts;
160       unsigned archpos = 2;
161       // expect "<name>.<arch>.pat[.gz]", <name> might contain additional dots
162       unsigned count = str::split( it->first, std::back_inserter(patparts), "." );
163       if ( patparts[count-1] == "gz" )
164           archpos++;
165
166       if ( count > archpos )
167       {
168         try                             // might by an invalid architecture
169         {
170           Arch patarch( patparts[count-archpos] );
171           if ( !patarch.compatibleWith( ZConfig::instance().systemArchitecture() ) )
172           {
173             // discard, if not compatible
174             MIL << "Discarding pattern " << it->first << endl;
175             continue;
176           }
177         }
178         catch ( const Exception & excpt )
179         {
180           WAR << "Pattern file name does not contain recognizable architecture: " << it->first << endl;
181           // keep .pat file if it doesn't contain an recognizable arch
182         }
183       }
184     }
185     MIL << "adding job " << it->first << endl;
186     OnMediaLocation location( _info.path() + descr_dir + it->first, 1 );
187     location.setChecksum( it->second );
188     this->enqueueDigested(location);
189   }
190
191   for ( RepoIndex::FileChecksumMap::const_iterator it = _repoindex->signingKeys.begin();
192         it != _repoindex->signingKeys.end();
193         ++it )
194   {
195     OnMediaLocation location( _info.path() + it->first, 1 );
196     location.setChecksum( it->second );
197     this->enqueueDigested(location);
198   }
199
200   this->start( dest_dir, media );
201 }
202
203 void Downloader::consumeIndex( const RepoIndex_Ptr & data_r )
204 {
205   MIL << "Consuming repo index" << endl;
206   _repoindex = data_r;
207 }
208
209 }// ns susetags
210 }// ns source
211 } // ns zypp