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

Archive Download this file

Branches

Tags

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