Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
Sebastian Schrader
Kea
Commits
f773f9ac
Commit
f773f9ac
authored
Aug 01, 2011
by
Jelte Jansen
Browse files
[trac1160] move getToken and numToToken to util
parent
25b02eea
Changes
5
Hide whitespace changes
Inline
Side-by-side
src/lib/dns/rdata/any_255/tsig_250.cc
View file @
f773f9ac
...
...
@@ -19,6 +19,7 @@
#include <boost/lexical_cast.hpp>
#include <util/buffer.h>
#include <util/strutil.h>
#include <util/encode/base64.h>
#include <dns/messagerenderer.h>
...
...
@@ -30,6 +31,7 @@ using namespace std;
using
namespace
boost
;
using
namespace
isc
::
util
;
using
namespace
isc
::
util
::
encode
;
using
namespace
isc
::
util
::
str
;
// BEGIN_ISC_NAMESPACE
// BEGIN_RDATA_NAMESPACE
...
...
@@ -65,45 +67,6 @@ struct TSIG::TSIGImpl {
const
vector
<
uint8_t
>
other_data_
;
};
namespace
{
string
getToken
(
istringstream
&
iss
,
const
string
&
full_input
)
{
string
token
;
iss
>>
token
;
if
(
iss
.
bad
()
||
iss
.
fail
())
{
isc_throw
(
InvalidRdataText
,
"Invalid TSIG text: parse error "
<<
full_input
);
}
return
(
token
);
}
// This helper function converts a string token to an *unsigned* integer.
// NumType is a *signed* integral type (e.g. int32_t) that is sufficiently
// wide to store resulting integers.
// BitSize is the maximum number of bits that the resulting integer can take.
// This function first checks whether the given token can be converted to
// an integer of NumType type. It then confirms the conversion result is
// within the valid range, i.e., [0, 2^NumType - 1]. The second check is
// necessary because lexical_cast<T> where T is an unsigned integer type
// doesn't correctly reject negative numbers when compiled with SunStudio.
template
<
typename
NumType
,
int
BitSize
>
NumType
tokenToNum
(
const
string
&
num_token
)
{
NumType
num
;
try
{
num
=
lexical_cast
<
NumType
>
(
num_token
);
}
catch
(
const
boost
::
bad_lexical_cast
&
ex
)
{
isc_throw
(
InvalidRdataText
,
"Invalid TSIG numeric parameter: "
<<
num_token
);
}
if
(
num
<
0
||
num
>=
(
static_cast
<
NumType
>
(
1
)
<<
BitSize
))
{
isc_throw
(
InvalidRdataText
,
"Numeric TSIG parameter out of range: "
<<
num
);
}
return
(
num
);
}
}
/// \brief Constructor from string.
///
/// \c tsig_str must be formatted as follows:
...
...
@@ -148,47 +111,52 @@ tokenToNum(const string& num_token) {
TSIG
::
TSIG
(
const
std
::
string
&
tsig_str
)
:
impl_
(
NULL
)
{
istringstream
iss
(
tsig_str
);
const
Name
algorithm
(
getToken
(
iss
,
tsig_str
));
const
int64_t
time_signed
=
tokenToNum
<
int64_t
,
48
>
(
getToken
(
iss
,
tsig_str
));
const
int32_t
fudge
=
tokenToNum
<
int32_t
,
16
>
(
getToken
(
iss
,
tsig_str
));
const
int32_t
macsize
=
tokenToNum
<
int32_t
,
16
>
(
getToken
(
iss
,
tsig_str
));
const
string
mac_txt
=
(
macsize
>
0
)
?
getToken
(
iss
,
tsig_str
)
:
""
;
vector
<
uint8_t
>
mac
;
decodeBase64
(
mac_txt
,
mac
);
if
(
mac
.
size
()
!=
macsize
)
{
isc_throw
(
InvalidRdataText
,
"TSIG MAC size and data are inconsistent"
);
}
const
int32_t
orig_id
=
tokenToNum
<
int32_t
,
16
>
(
getToken
(
iss
,
tsig_str
));
const
string
error_txt
=
getToken
(
iss
,
tsig_str
);
int32_t
error
=
0
;
// XXX: In the initial implementation we hardcode the mnemonics.
// We'll soon generalize this.
if
(
error_txt
==
"BADSIG"
)
{
error
=
16
;
}
else
if
(
error_txt
==
"BADKEY"
)
{
error
=
17
;
}
else
if
(
error_txt
==
"BADTIME"
)
{
error
=
18
;
}
else
{
error
=
tokenToNum
<
int32_t
,
16
>
(
error_txt
);
}
const
int32_t
otherlen
=
tokenToNum
<
int32_t
,
16
>
(
getToken
(
iss
,
tsig_str
));
const
string
otherdata_txt
=
(
otherlen
>
0
)
?
getToken
(
iss
,
tsig_str
)
:
""
;
vector
<
uint8_t
>
other_data
;
decodeBase64
(
otherdata_txt
,
other_data
);
if
(
!
iss
.
eof
())
{
isc_throw
(
InvalidRdataText
,
"Unexpected input for TSIG RDATA: "
<<
tsig_str
);
try
{
const
Name
algorithm
(
getToken
(
iss
));
const
int64_t
time_signed
=
tokenToNum
<
int64_t
,
48
>
(
getToken
(
iss
));
const
int32_t
fudge
=
tokenToNum
<
int32_t
,
16
>
(
getToken
(
iss
));
const
int32_t
macsize
=
tokenToNum
<
int32_t
,
16
>
(
getToken
(
iss
));
const
string
mac_txt
=
(
macsize
>
0
)
?
getToken
(
iss
)
:
""
;
vector
<
uint8_t
>
mac
;
decodeBase64
(
mac_txt
,
mac
);
if
(
mac
.
size
()
!=
macsize
)
{
isc_throw
(
InvalidRdataText
,
"TSIG MAC size and data are inconsistent"
);
}
const
int32_t
orig_id
=
tokenToNum
<
int32_t
,
16
>
(
getToken
(
iss
));
const
string
error_txt
=
getToken
(
iss
);
int32_t
error
=
0
;
// XXX: In the initial implementation we hardcode the mnemonics.
// We'll soon generalize this.
if
(
error_txt
==
"BADSIG"
)
{
error
=
16
;
}
else
if
(
error_txt
==
"BADKEY"
)
{
error
=
17
;
}
else
if
(
error_txt
==
"BADTIME"
)
{
error
=
18
;
}
else
{
error
=
tokenToNum
<
int32_t
,
16
>
(
error_txt
);
}
const
int32_t
otherlen
=
tokenToNum
<
int32_t
,
16
>
(
getToken
(
iss
));
const
string
otherdata_txt
=
(
otherlen
>
0
)
?
getToken
(
iss
)
:
""
;
vector
<
uint8_t
>
other_data
;
decodeBase64
(
otherdata_txt
,
other_data
);
if
(
!
iss
.
eof
())
{
isc_throw
(
InvalidRdataText
,
"Unexpected input for TSIG RDATA: "
<<
tsig_str
);
}
impl_
=
new
TSIGImpl
(
algorithm
,
time_signed
,
fudge
,
mac
,
orig_id
,
error
,
other_data
);
}
catch
(
StringTokenError
ste
)
{
isc_throw
(
InvalidRdataText
,
"Invalid TSIG text: "
<<
ste
.
what
()
<<
": "
<<
tsig_str
);
}
impl_
=
new
TSIGImpl
(
algorithm
,
time_signed
,
fudge
,
mac
,
orig_id
,
error
,
other_data
);
}
/// \brief Constructor from wire-format data.
...
...
src/lib/dns/rdata/in_1/srv_33.cc
View file @
f773f9ac
...
...
@@ -18,6 +18,7 @@
#include <boost/lexical_cast.hpp>
#include <util/buffer.h>
#include <util/strutil.h>
#include <dns/messagerenderer.h>
#include <dns/name.h>
...
...
@@ -44,39 +45,6 @@ struct SRVImpl {
Name
target_
;
};
namespace
{
string
getToken
(
istringstream
&
iss
,
const
string
&
full_input
)
{
string
token
;
iss
>>
token
;
if
(
iss
.
bad
()
||
iss
.
fail
())
{
isc_throw
(
InvalidRdataText
,
"Invalid SRV text: parse error "
<<
full_input
);
}
return
(
token
);
}
// This helper function converts a string token to an *unsigned* integer.
// NumType is a *signed* integral type (e.g. int32_t) that is sufficiently
// wide to store resulting integers.
template
<
typename
NumType
,
int
BitSize
>
NumType
tokenToNum
(
const
string
&
num_token
)
{
NumType
num
;
try
{
num
=
lexical_cast
<
NumType
>
(
num_token
);
}
catch
(
const
boost
::
bad_lexical_cast
&
ex
)
{
isc_throw
(
InvalidRdataText
,
"Invalid SRV numeric parameter: "
<<
num_token
);
}
if
(
num
<
0
||
num
>=
(
static_cast
<
NumType
>
(
1
)
<<
BitSize
))
{
isc_throw
(
InvalidRdataText
,
"Numeric SRV parameter out of range: "
<<
num
);
}
return
(
num
);
}
}
/// \brief Constructor from string.
///
/// \c srv_str must be formatted as follows:
...
...
@@ -103,17 +71,22 @@ SRV::SRV(const string& srv_str) :
{
istringstream
iss
(
srv_str
);
const
int32_t
priority
=
tokenToNum
<
int32_t
,
16
>
(
getToken
(
iss
,
srv_str
));
const
int32_t
weight
=
tokenToNum
<
int32_t
,
16
>
(
getToken
(
iss
,
srv_str
));
const
int32_t
port
=
tokenToNum
<
int32_t
,
16
>
(
getToken
(
iss
,
srv_str
));
const
Name
targetname
(
getToken
(
iss
,
srv_str
));
if
(
!
iss
.
eof
())
{
isc_throw
(
InvalidRdataText
,
"Unexpected input for SRV RDATA: "
<<
srv_str
);
try
{
const
int32_t
priority
=
str
::
tokenToNum
<
int32_t
,
16
>
(
str
::
getToken
(
iss
));
const
int32_t
weight
=
str
::
tokenToNum
<
int32_t
,
16
>
(
str
::
getToken
(
iss
));
const
int32_t
port
=
str
::
tokenToNum
<
int32_t
,
16
>
(
str
::
getToken
(
iss
));
const
Name
targetname
(
str
::
getToken
(
iss
));
if
(
!
iss
.
eof
())
{
isc_throw
(
InvalidRdataText
,
"Unexpected input for SRV RDATA: "
<<
srv_str
);
}
impl_
=
new
SRVImpl
(
priority
,
weight
,
port
,
targetname
);
}
catch
(
str
::
StringTokenError
ste
)
{
isc_throw
(
InvalidRdataText
,
"Invalid SRV text: "
<<
ste
.
what
()
<<
": "
<<
srv_str
);
}
impl_
=
new
SRVImpl
(
priority
,
weight
,
port
,
targetname
);
}
/// \brief Constructor from wire-format data.
...
...
src/lib/util/strutil.cc
View file @
f773f9ac
...
...
@@ -132,6 +132,17 @@ format(const std::string& format, const std::vector<std::string>& args) {
return
(
result
);
}
std
::
string
getToken
(
std
::
istringstream
&
iss
)
{
string
token
;
iss
>>
token
;
if
(
iss
.
bad
()
||
iss
.
fail
())
{
isc_throw
(
StringTokenError
,
"could not read token from string"
);
}
return
(
token
);
}
}
// namespace str
}
// namespace util
}
// namespace isc
src/lib/util/strutil.h
View file @
f773f9ac
...
...
@@ -18,7 +18,10 @@
#include <algorithm>
#include <cctype>
#include <string>
#include <sstream>
#include <vector>
#include <exceptions/exceptions.h>
#include <boost/lexical_cast.hpp>
namespace
isc
{
namespace
util
{
...
...
@@ -26,6 +29,16 @@ namespace str {
/// \brief A Set of C++ Utilities for Manipulating Strings
///
/// \brief A standard string util exception that is thrown if getToken or
/// numToToken are called with bad input data
///
class
StringTokenError
:
public
Exception
{
public:
StringTokenError
(
const
char
*
file
,
size_t
line
,
const
char
*
what
)
:
isc
::
Exception
(
file
,
line
,
what
)
{}
};
/// \brief Normalize Backslash
///
/// Only relevant to Windows, this replaces all "\" in a string with "/" and
...
...
@@ -140,6 +153,55 @@ std::string format(const std::string& format,
const
std
::
vector
<
std
::
string
>&
args
);
/// \brief Returns one token from the given stringstream
///
/// Using the >> operator, with basic error checking
///
/// \exception StringTokenError if the token cannot be read from the stream
///
/// \param iss stringstream to read one token from
///
/// \return the first token read from the stringstream
std
::
string
getToken
(
std
::
istringstream
&
iss
);
/// \brief Converts a string token to an *unsigned* integer.
///
/// The value is converted using a lexical cast, with error and bounds
/// checking.
///
/// NumType is a *signed* integral type (e.g. int32_t) that is sufficiently
/// wide to store resulting integers.
///
/// BitSize is the maximum number of bits that the resulting integer can take.
/// This function first checks whether the given token can be converted to
/// an integer of NumType type. It then confirms the conversion result is
/// within the valid range, i.e., [0, 2^NumType - 1]. The second check is
/// necessary because lexical_cast<T> where T is an unsigned integer type
/// doesn't correctly reject negative numbers when compiled with SunStudio.
///
/// \exception StringTokenError if the value is out of range, or if it
/// could not be converted
///
/// \param num_token the string token to convert
///
/// \return the converted value, of type NumType
template
<
typename
NumType
,
int
BitSize
>
NumType
tokenToNum
(
const
std
::
string
&
num_token
)
{
NumType
num
;
try
{
num
=
boost
::
lexical_cast
<
NumType
>
(
num_token
);
}
catch
(
const
boost
::
bad_lexical_cast
&
ex
)
{
isc_throw
(
StringTokenError
,
"Invalid SRV numeric parameter: "
<<
num_token
);
}
if
(
num
<
0
||
num
>=
(
static_cast
<
NumType
>
(
1
)
<<
BitSize
))
{
isc_throw
(
StringTokenError
,
"Numeric SRV parameter out of range: "
<<
num
);
}
return
(
num
);
}
}
// namespace str
}
// namespace util
}
// namespace isc
...
...
src/lib/util/tests/strutil_unittest.cc
View file @
f773f9ac
...
...
@@ -12,6 +12,8 @@
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
#include <stdint.h>
#include <string>
#include <gtest/gtest.h>
...
...
@@ -213,3 +215,63 @@ TEST_F(StringUtilTest, Formatting) {
string
format9
=
"%s %s"
;
EXPECT_EQ
(
format9
,
isc
::
util
::
str
::
format
(
format9
,
args
));
}
TEST_F
(
StringUtilTest
,
getToken
)
{
string
s
(
"a b c"
);
istringstream
ss
(
s
);
EXPECT_EQ
(
"a"
,
isc
::
util
::
str
::
getToken
(
ss
));
EXPECT_EQ
(
"b"
,
isc
::
util
::
str
::
getToken
(
ss
));
EXPECT_EQ
(
"c"
,
isc
::
util
::
str
::
getToken
(
ss
));
EXPECT_THROW
(
isc
::
util
::
str
::
getToken
(
ss
),
isc
::
util
::
str
::
StringTokenError
);
}
int32_t
tokenToNumCall_32_16
(
const
string
&
token
)
{
return
isc
::
util
::
str
::
tokenToNum
<
int32_t
,
16
>
(
token
);
}
int16_t
tokenToNumCall_16_8
(
const
string
&
token
)
{
return
isc
::
util
::
str
::
tokenToNum
<
int16_t
,
8
>
(
token
);
}
TEST_F
(
StringUtilTest
,
tokenToNum
)
{
uint32_t
num32
=
tokenToNumCall_32_16
(
"0"
);
EXPECT_EQ
(
0
,
num32
);
num32
=
tokenToNumCall_32_16
(
"123"
);
EXPECT_EQ
(
123
,
num32
);
num32
=
tokenToNumCall_32_16
(
"65535"
);
EXPECT_EQ
(
65535
,
num32
);
EXPECT_THROW
(
tokenToNumCall_32_16
(
""
),
isc
::
util
::
str
::
StringTokenError
);
EXPECT_THROW
(
tokenToNumCall_32_16
(
"a"
),
isc
::
util
::
str
::
StringTokenError
);
EXPECT_THROW
(
tokenToNumCall_32_16
(
"-1"
),
isc
::
util
::
str
::
StringTokenError
);
EXPECT_THROW
(
tokenToNumCall_32_16
(
"65536"
),
isc
::
util
::
str
::
StringTokenError
);
EXPECT_THROW
(
tokenToNumCall_32_16
(
"1234567890"
),
isc
::
util
::
str
::
StringTokenError
);
EXPECT_THROW
(
tokenToNumCall_32_16
(
"-1234567890"
),
isc
::
util
::
str
::
StringTokenError
);
uint16_t
num16
=
tokenToNumCall_16_8
(
"123"
);
EXPECT_EQ
(
123
,
num16
);
num16
=
tokenToNumCall_16_8
(
"0"
);
EXPECT_EQ
(
0
,
num16
);
num16
=
tokenToNumCall_16_8
(
"255"
);
EXPECT_EQ
(
255
,
num16
);
EXPECT_THROW
(
tokenToNumCall_16_8
(
""
),
isc
::
util
::
str
::
StringTokenError
);
EXPECT_THROW
(
tokenToNumCall_16_8
(
"a"
),
isc
::
util
::
str
::
StringTokenError
);
EXPECT_THROW
(
tokenToNumCall_16_8
(
"-1"
),
isc
::
util
::
str
::
StringTokenError
);
EXPECT_THROW
(
tokenToNumCall_16_8
(
"256"
),
isc
::
util
::
str
::
StringTokenError
);
EXPECT_THROW
(
tokenToNumCall_16_8
(
"1234567890"
),
isc
::
util
::
str
::
StringTokenError
);
EXPECT_THROW
(
tokenToNumCall_16_8
(
"-1234567890"
),
isc
::
util
::
str
::
StringTokenError
);
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment