monotone

monotone Mtn Source Tree

Root/vocab.cc

1// copyright (C) 2002, 2003 graydon hoare <graydon@pobox.com>
2// all rights reserved.
3// licensed to the public under the terms of the GNU GPL (>= 2)
4// see the file COPYING for details
5
6#include <string>
7#include <iostream>
8#include <boost/filesystem/path.hpp>
9#include <boost/filesystem/exception.hpp>
10#include <boost/version.hpp>
11
12#include "constants.hh"
13#include "file_io.hh"
14#include "sanity.hh"
15#include "vocab.hh"
16
17// verifiers for various types of data
18
19using namespace std;
20
21template <typename T>
22static inline void
23verify(T & val)
24{}
25
26static inline void
27verify(hexenc<id> & val)
28{
29 if (val.ok)
30 return;
31
32 if (val() == "")
33 return;
34
35 N(val().size() == constants::idlen,
36 F("hex encoded ID '%s' size != %d") % val % constants::idlen);
37 string::size_type pos = val().find_first_not_of(constants::legal_id_bytes);
38 N(pos == string::npos,
39 F("bad character '%c' in id name '%s'") % val().at(pos) % val);
40
41 val.ok = true;
42}
43
44static inline void
45verify(ace & val)
46{
47 if (val.ok)
48 return;
49
50 string::size_type pos = val().find_first_not_of(constants::legal_ace_bytes);
51 N(pos == string::npos,
52 F("bad character '%c' in ace string '%s'") % val().at(pos) % val);
53
54 val.ok = true;
55}
56
57
58static inline void
59verify(cert_name & val)
60{
61 if (val.ok)
62 return;
63
64 string::size_type pos = val().find_first_not_of(constants::legal_cert_name_bytes);
65 N(pos == string::npos,
66 F("bad character '%c' in cert name '%s'") % val().at(pos) % val);
67
68 val.ok = true;
69}
70
71static inline void
72verify(rsa_keypair_id & val)
73{
74 if (val.ok)
75 return;
76
77 string::size_type pos = val().find_first_not_of(constants::legal_key_name_bytes);
78 N(pos == string::npos,
79 F("bad character '%c' in key name '%s'") % val().at(pos) % val);
80
81 val.ok = true;
82}
83
84
85static inline void
86verify(local_path & val)
87{
88
89 if (val.ok)
90 return;
91
92 using boost::filesystem::path;
93 boost::filesystem::path p;
94 try
95 {
96 p = mkpath(val());
97#if BOOST_VERSION >= 103100
98 p = p.normalize();
99#endif
100 }
101 catch (std::runtime_error &re)
102 {
103 throw informative_failure(re.what());
104 }
105 catch (fs::filesystem_error &fse)
106 {
107 throw informative_failure(fse.what());
108 }
109
110 N(! (p.has_root_path() || p.has_root_name() || p.has_root_directory()),
111 F("prohibited absolute path '%s'") % val);
112
113 for(path::iterator i = p.begin(); i != p.end(); ++i)
114 {
115 N(!( *i == "" && (! p.empty())),
116 F("empty path component in '%s'") % val);
117
118 N((*i != ".."),
119 F("prohibited path component '%s' in '%s'") % *i % val);
120
121 string::size_type pos = i->find_first_of(constants::illegal_path_bytes);
122 N(pos == string::npos,
123 F("bad character '%d' in path component '%s' of '%s'")
124 % static_cast<int>(i->at(pos)) % *i % val);
125
126 string s = val();
127 for (string::const_iterator j = s.begin(); j != s.end(); ++j)
128 N(*j != '\0',
129 F("null byte in path component '%s' of '%s'") % *i % val);
130
131 }
132
133 val.ok = true;
134}
135
136static inline void
137verify(file_path & val)
138{
139 if (val.ok)
140 return;
141
142 local_path loc(val());
143 verify(loc);
144 N(!book_keeping_file(loc),
145 F("prohibited book-keeping path in '%s'") % val);
146
147 val.ok = true;
148}
149
150
151// instantiation of various vocab functions
152
153#define ATOMIC(ty) \
154 \
155ty::ty(string const & str) : \
156 s(str), ok(false) \
157{ verify(*this); } \
158 \
159ty::ty(ty const & other) : \
160 s(other.s), ok(other.ok) \
161{ verify(*this); } \
162 \
163ty const & ty::operator=(ty const & other) \
164{ s = other.s; ok = other.ok; \
165 verify(*this); return *this; } \
166 \
167ostream & operator<<(ostream & o, \
168 ty const & a) \
169{ return (o << a.s); }
170
171
172
173
174#define ENCODING(enc) \
175 \
176template<typename INNER> \
177enc<INNER>::enc(string const & s) : i(s), ok(false) \
178 { verify(*this); } \
179 \
180template<typename INNER> \
181enc<INNER>::enc(enc<INNER> const & other) \
182 : i(other.i()), ok(other.ok) { verify(*this); } \
183 \
184template<typename INNER> \
185enc<INNER>::enc(INNER const & inner) : \
186 i(inner), ok(false) \
187 { verify(*this); } \
188 \
189template<typename INNER> \
190enc<INNER> const & \
191enc<INNER>::operator=(enc<INNER> const & other) \
192 { i = other.i; ok = other.ok; \
193 verify(*this); return *this;} \
194 \
195template <typename INNER> \
196ostream & operator<<(ostream & o, enc<INNER> const & e) \
197{ return (o << e.i); }
198
199
200#define DECORATE(dec) \
201 \
202template<typename INNER> \
203dec<INNER>::dec(dec<INNER> const & other) \
204 : i(other.i), ok(other.ok) { verify(*this); } \
205 \
206template<typename INNER> \
207dec<INNER>::dec(INNER const & inner) : \
208 i(inner), ok(false) \
209 { verify(*this); } \
210 \
211template<typename INNER> \
212dec<INNER> const & \
213dec<INNER>::operator=(dec<INNER> const & other) \
214 { i = other.i; ok = other.ok; \
215 verify(*this); return *this;} \
216 \
217template <typename INNER> \
218ostream & operator<<(ostream & o, dec<INNER> const & d) \
219{ return (o << d.i); }
220
221
222#define EXTERN
223
224#include "vocab_terms.hh"
225
226#undef EXTERN
227#undef ATOMIC
228#undef DECORATE
229
230template class revision<cert>;
231template class manifest<cert>;
232
233// the rest is unit tests
234
235#ifdef BUILD_UNIT_TESTS
236#include "unit_tests.hh"
237
238static void test_file_path_verification()
239{
240 char const * baddies [] = {"../escape",
241 "foo/../../escape",
242 "/rooted",
243 "foo//nonsense",
244#ifdef _WIN32
245 "c:\\windows\\rooted",
246 "c:/windows/rooted",
247 "c:thing",
248 "//unc/share",
249 "//unc",
250#endif
251 0 };
252
253 for (char const ** c = baddies; *c; ++c)
254 BOOST_CHECK_THROW(file_path p(*c), informative_failure);
255
256 char const * bad = "\t\r\n\v\f\a\b";
257 char badboy[] = "bad";
258 for (char const * c = bad; *c; ++c)
259 {
260 badboy[1] = *c;
261 BOOST_CHECK_THROW(file_path p(badboy), informative_failure);
262 }
263
264 char const * goodies [] = {"unrooted",
265 "unrooted.txt",
266 "fun_with_underscore.png",
267 "fun-with-hyphen.tiff",
268 "unrooted/../unescaping",
269 "unrooted/general/path",
270 "here/..",
271 0 };
272
273 for (char const ** c = goodies; *c; ++c)
274 BOOST_CHECK_NOT_THROW(file_path p(*c), informative_failure);
275}
276
277void add_vocab_tests(test_suite * suite)
278{
279 I(suite);
280 suite->add(BOOST_TEST_CASE(&test_file_path_verification));
281}
282
283#endif // BUILD_UNIT_TESTS

Archive Download this file

Branches

Tags

Quick Links:     www.monotone.ca    -     Downloads    -     Documentation    -     Wiki    -     Code Forge    -     Build Status