use 'best' hash for source authentication
[ntk/apt.git] / apt-pkg / deb / debsrcrecords.cc
CommitLineData
11e7af84
AL
1// -*- mode: cpp; mode: fold -*-
2// Description /*{{{*/
c33b707e 3// $Id: debsrcrecords.cc,v 1.6 2004/03/17 05:58:54 mdz Exp $
11e7af84
AL
4/* ######################################################################
5
6 Debian Source Package Records - Parser implementation for Debian style
7 source indexes
8
9 ##################################################################### */
10 /*}}}*/
11// Include Files /*{{{*/
ea542140
DK
12#include <config.h>
13
b2e465d6 14#include <apt-pkg/deblistparser.h>
11e7af84
AL
15#include <apt-pkg/debsrcrecords.h>
16#include <apt-pkg/error.h>
36f610f1 17#include <apt-pkg/strutl.h>
b0e1a43f 18#include <apt-pkg/aptconfiguration.h>
453b82a3
DK
19#include <apt-pkg/srcrecords.h>
20#include <apt-pkg/tagfile.h>
cb6a2b3e 21#include <apt-pkg/hashes.h>
feab34c5 22#include <apt-pkg/gpgv.h>
4ab24e53 23
453b82a3
DK
24#include <ctype.h>
25#include <stdlib.h>
26#include <string.h>
27#include <algorithm>
28#include <string>
29#include <vector>
11e7af84
AL
30 /*}}}*/
31
453b82a3 32using std::max;
8f3ba4e8
DK
33using std::string;
34
11e7af84
AL
35// SrcRecordParser::Binaries - Return the binaries field /*{{{*/
36// ---------------------------------------------------------------------
37/* This member parses the binaries field into a pair of class arrays and
38 returns a list of strings representing all of the components of the
39 binaries field. The returned array need not be freed and will be
b2e465d6
AL
40 reused by the next Binaries function call. This function is commonly
41 used during scanning to find the right package */
11e7af84
AL
42const char **debSrcRecordParser::Binaries()
43{
39fb1e24
DK
44 const char *Start, *End;
45 if (Sect.Find("Binary", Start, End) == false)
46 return NULL;
47 for (; isspace(*Start) != 0; ++Start);
48 if (Start >= End)
49 return NULL;
50
51 StaticBinList.clear();
52 free(Buffer);
53 Buffer = strndup(Start, End - Start);
c33b707e 54
39fb1e24
DK
55 char* bin = Buffer;
56 do {
57 char* binStartNext = strchrnul(bin, ',');
58 char* binEnd = binStartNext - 1;
59 for (; isspace(*binEnd) != 0; --binEnd)
60 binEnd = '\0';
61 StaticBinList.push_back(bin);
62 if (*binStartNext != ',')
63 break;
64 *binStartNext = '\0';
65 for (bin = binStartNext + 1; isspace(*bin) != 0; ++bin);
66 } while (*bin != '\0');
67 StaticBinList.push_back(NULL);
c33b707e 68
e788a834 69 return &StaticBinList[0];
b2e465d6
AL
70}
71 /*}}}*/
72// SrcRecordParser::BuildDepends - Return the Build-Depends information /*{{{*/
73// ---------------------------------------------------------------------
74/* This member parses the build-depends information and returns a list of
75 package/version records representing the build dependency. The returned
76 array need not be freed and will be reused by the next call to this
77 function */
8f3ba4e8 78bool debSrcRecordParser::BuildDepends(std::vector<pkgSrcRecords::Parser::BuildDepRec> &BuildDeps,
41c81fd8 79 bool const &ArchOnly, bool const &StripMultiArch)
b2e465d6
AL
80{
81 unsigned int I;
82 const char *Start, *Stop;
83 BuildDepRec rec;
84 const char *fields[] = {"Build-Depends",
85 "Build-Depends-Indep",
86 "Build-Conflicts",
87 "Build-Conflicts-Indep"};
88
89 BuildDeps.clear();
11e7af84 90
b2e465d6 91 for (I = 0; I < 4; I++)
11e7af84 92 {
45430cbf
AL
93 if (ArchOnly && (I == 1 || I == 3))
94 continue;
95
b2e465d6
AL
96 if (Sect.Find(fields[I], Start, Stop) == false)
97 continue;
11e7af84 98
b2e465d6
AL
99 while (1)
100 {
101 Start = debListParser::ParseDepends(Start, Stop,
565ded7b 102 rec.Package,rec.Version,rec.Op,true,StripMultiArch,true);
b2e465d6
AL
103
104 if (Start == 0)
105 return _error->Error("Problem parsing dependency: %s", fields[I]);
106 rec.Type = I;
107
108 if (rec.Package != "")
109 BuildDeps.push_back(rec);
110
111 if (Start == Stop)
112 break;
113 }
11e7af84
AL
114 }
115
b2e465d6 116 return true;
11e7af84
AL
117}
118 /*}}}*/
36f610f1
AL
119// SrcRecordParser::Files - Return a list of files for this source /*{{{*/
120// ---------------------------------------------------------------------
121/* This parses the list of files and returns it, each file is required to have
122 a complete source package */
8f3ba4e8 123bool debSrcRecordParser::Files(std::vector<pkgSrcRecords::File> &List)
36f610f1
AL
124{
125 List.erase(List.begin(),List.end());
cb6a2b3e 126
1262d358
DK
127 // Stash the / terminated directory prefix
128 string Base = Sect.FindS("Directory");
129 if (Base.empty() == false && Base[Base.length()-1] != '/')
130 Base += '/';
cb6a2b3e 131
1262d358 132 std::vector<std::string> const compExts = APT::Configuration::getCompressorExtensions();
cb6a2b3e 133
1262d358
DK
134 for (char const * const * type = HashString::SupportedHashes(); *type != NULL; ++type)
135 {
136 // derive field from checksum type
137 std::string checksumField("Checksums-");
138 if (strcmp(*type, "MD5Sum") == 0)
139 checksumField = "Files"; // historic name for MD5 checksums
140 else
141 checksumField.append(*type);
142
143 string const Files = Sect.FindS(checksumField.c_str());
144 if (Files.empty() == true)
145 continue;
cb6a2b3e
MV
146
147 // Iterate over the entire list grabbing each triplet
148 const char *C = Files.c_str();
149 while (*C != 0)
1262d358
DK
150 {
151 string hash, size, path;
152
153 // Parse each of the elements
154 if (ParseQuoteWord(C, hash) == false ||
155 ParseQuoteWord(C, size) == false ||
156 ParseQuoteWord(C, path) == false)
157 return _error->Error("Error parsing file record in %s of source package %s", checksumField.c_str(), Package().c_str());
158
159 HashString const hashString(*type, hash);
160 if (Base.empty() == false)
161 path = Base + path;
162
163 // look if we have a record for this file already
164 std::vector<pkgSrcRecords::File>::iterator file = List.begin();
165 for (; file != List.end(); ++file)
166 if (file->Path == path)
167 break;
168
169 // we have it already, store the new hash and be done
170 if (file != List.end())
171 {
172#if __GNUC__ >= 4
173 // set for compatibility only, so warn users not us
174 #pragma GCC diagnostic push
175 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
176#endif
177 if (checksumField == "Files")
178 file->MD5Hash = hash;
179#if __GNUC__ >= 4
180 #pragma GCC diagnostic pop
181#endif
182 // an error here indicates that we have two different hashes for the same file
183 if (file->Hashes.push_back(hashString) == false)
184 return _error->Error("Error parsing checksum in %s of source package %s", checksumField.c_str(), Package().c_str());
185 continue;
186 }
187
188 // we haven't seen this file yet
189 pkgSrcRecords::File F;
190 F.Path = path;
191 F.Size = strtoull(size.c_str(), NULL, 10);
192 F.Hashes.push_back(hashString);
193
194#if __GNUC__ >= 4
195 // set for compatibility only, so warn users not us
196 #pragma GCC diagnostic push
197 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
198#endif
199 if (checksumField == "Files")
200 F.MD5Hash = hash;
201#if __GNUC__ >= 4
202 #pragma GCC diagnostic pop
203#endif
204
205 // Try to guess what sort of file it is we are getting.
206 string::size_type Pos = F.Path.length()-1;
207 while (1)
208 {
209 string::size_type Tmp = F.Path.rfind('.',Pos);
210 if (Tmp == string::npos)
211 break;
212 if (F.Type == "tar") {
213 // source v3 has extension 'debian.tar.*' instead of 'diff.*'
214 if (string(F.Path, Tmp+1, Pos-Tmp) == "debian")
215 F.Type = "diff";
216 break;
217 }
218 F.Type = string(F.Path,Tmp+1,Pos-Tmp);
219
220 if (std::find(compExts.begin(), compExts.end(), std::string(".").append(F.Type)) != compExts.end() ||
221 F.Type == "tar")
222 {
223 Pos = Tmp-1;
224 continue;
225 }
226
227 break;
228 }
229 List.push_back(F);
cb6a2b3e 230 }
36f610f1 231 }
1262d358
DK
232
233 return true;
36f610f1
AL
234}
235 /*}}}*/
7a9f09bd
MV
236// SrcRecordParser::~SrcRecordParser - Destructor /*{{{*/
237// ---------------------------------------------------------------------
238/* */
239debSrcRecordParser::~debSrcRecordParser()
240{
241 delete[] Buffer;
242}
243 /*}}}*/
feab34c5
MV
244
245
a49e7948
MV
246debDscRecordParser::debDscRecordParser(std::string const &DscFile, pkgIndexFile const *Index)
247 : debSrcRecordParser(DscFile, Index)
feab34c5
MV
248{
249 // support clear signed files
250 if (OpenMaybeClearSignedFile(DscFile, Fd) == false)
251 {
252 _error->Error("Failed to open %s", DscFile.c_str());
253 return;
254 }
255
256 // re-init to ensure the updated Fd is used
257 Tags.Init(&Fd);
258 // read the first (and only) record
259 Step();
260
261}