Imported Upstream version 15.21.0
[platform/upstream/libzypp.git] / zypp / CheckSum.cc
1 /*---------------------------------------------------------------------\
2 |                          ____ _   __ __ ___                          |
3 |                         |__  / \ / / . \ . \                         |
4 |                           / / \ V /|  _/  _/                         |
5 |                          / /__ | | | | | |                           |
6 |                         /_____||_| |_| |_|                           |
7 |                                                                      |
8 \---------------------------------------------------------------------*/
9 /** \file       zypp/CheckSum.cc
10  *
11 */
12 #include <iostream>
13 #include <sstream>
14
15 #include "zypp/base/Logger.h"
16 #include "zypp/base/Gettext.h"
17 #include "zypp/base/String.h"
18
19 #include "zypp/CheckSum.h"
20 #include "zypp/Digest.h"
21
22 using std::endl;
23
24 ///////////////////////////////////////////////////////////////////
25 namespace zypp
26 { /////////////////////////////////////////////////////////////////
27
28   const std::string & CheckSum::md5Type()
29   { return Digest::md5(); }
30
31   const std::string & CheckSum::shaType()
32   { static std::string _type( "sha" ); return _type; }
33
34   const std::string & CheckSum::sha1Type()
35   { return Digest::sha1(); }
36
37   const std::string & CheckSum::sha224Type()
38   { return Digest::sha224(); }
39
40   const std::string & CheckSum::sha256Type()
41   { return Digest::sha256(); }
42
43   const std::string & CheckSum::sha384Type()
44   { return Digest::sha384(); }
45
46   const std::string & CheckSum::sha512Type()
47   { return Digest::sha512(); }
48
49   CheckSum::CheckSum( const std::string & type, const std::string & checksum )
50   : _type( str::toLower( type ) )
51   , _checksum( checksum )
52   {
53     switch ( checksum.size() )
54     {
55       case 128:
56         if ( _type == sha512Type() )
57           return;
58         if ( _type.empty() || _type == shaType() )
59         {
60           _type = sha512Type();
61           return;
62         }
63         // else: dubious
64         break;
65
66       case 96:
67         if ( _type == sha384Type() )
68           return;
69         if ( _type.empty() || _type == shaType() )
70         {
71           _type = sha384Type();
72           return;
73         }
74         // else: dubious
75         break;
76
77       case 64:
78         if ( _type == sha256Type() )
79           return;
80         if ( _type.empty() || _type == shaType() )
81         {
82           _type = sha256Type();
83           return;
84         }
85         // else: dubious
86         break;
87
88       case 56:
89         if ( _type == sha224Type() )
90           return;
91         if ( _type.empty() || _type == shaType() )
92         {
93           _type = sha224Type();
94           return;
95         }
96         // else: dubious
97         break;
98
99       case 40:
100         if ( _type == sha1Type() )
101           return;
102         if ( _type.empty() || _type == shaType() )
103         {
104           _type = sha1Type();
105           return;
106         }
107         // else: dubious
108         break;
109
110       case 32:
111         if (  _type == md5Type() )
112           return;
113         if ( _type.empty() )
114         {
115           _type = md5Type();
116           return;
117         }
118         // else: dubious
119         break;
120
121       case 0:
122         return; // empty checksum is ok
123         break;
124
125       default:
126         if ( _type.empty() )
127         {
128           WAR << "Can't determine type of " << checksum.size() << " byte checksum '" << _checksum << "'" << endl;
129           return;
130         }
131         // else: dubious
132         break;
133     }
134
135     // dubious: Throw on malformed known types, otherwise log a warning.
136     std::string msg = str::form ( _("Dubious type '%s' for %u byte checksum '%s'"),
137                                   _type.c_str(), checksum.size(), _checksum.c_str() );
138     if (    _type == md5Type()
139          || _type == shaType()
140          || _type == sha1Type()
141          || _type == sha224Type()
142          || _type == sha256Type()
143          || _type == sha384Type()
144          || _type == sha512Type() )
145     {
146       ZYPP_THROW( CheckSumException( msg ) );
147     }
148     else
149     {
150       WAR << msg << endl;
151     }
152   }
153
154   CheckSum::CheckSum( const std::string & type_r, std::istream & input_r )
155   {
156     if ( input_r.good() && ! type_r.empty() )
157       {
158         _type = str::toLower( type_r );
159         _checksum = Digest::digest( _type, input_r );
160         if ( ! input_r.eof() || _checksum.empty() )
161           {
162             _type = _checksum = std::string();
163           }
164       }
165   }
166
167   std::string CheckSum::type() const
168   { return _type; }
169
170   std::string CheckSum::checksum() const
171   { return _checksum; }
172
173   bool CheckSum::empty() const
174   { return (checksum().empty() || type().empty()); }
175
176   std::string CheckSum::asString() const
177   {
178     std::ostringstream str;
179     str << *this;
180     return str.str();
181   }
182
183   std::ostream & operator<<( std::ostream & str, const CheckSum & obj )
184   {
185     if ( obj.checksum().empty() )
186       {
187         return str << std::string("NoCheckSum");
188       }
189
190     return str << ( obj.type().empty() ? std::string("UNKNOWN") : obj.type() ) << '-' << obj.checksum();
191   }
192
193   std::ostream & dumpAsXmlOn( std::ostream & str, const CheckSum & obj )
194   {
195     const std::string & type( obj.type() );
196     const std::string & checksum( obj.checksum() );
197     str << "<checksum";
198     if ( ! type.empty() ) str << " type=\"" << type << "\"";
199     if ( checksum.empty() )
200       str << "/>";
201     else
202       str << ">" << checksum << "</checksum>";
203     return str;
204   }
205
206    /** \relates CheckSum */
207   bool operator==( const CheckSum & lhs, const CheckSum & rhs )
208   { return lhs.checksum() == rhs.checksum() && lhs.type() == rhs.type(); }
209
210   /** \relates CheckSum */
211   bool operator!=( const CheckSum & lhs, const CheckSum & rhs )
212   { return ! ( lhs == rhs ); }
213
214   /////////////////////////////////////////////////////////////////
215 } // namespace zypp
216 ///////////////////////////////////////////////////////////////////