Fix is_valid_name() bugs, make it RFC 1035 compliant, update unit test, fix #15
This commit is contained in:
parent
9e820c648b
commit
7c30e44dc9
2 changed files with 105 additions and 62 deletions
|
|
@ -63,58 +63,98 @@ bool is_valid_symbol( const string& symbol )
|
|||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Valid names can contain [a, z], [0, 9], '.', and '-'
|
||||
* They must start with [a, z]
|
||||
* They must end with [a, z] or [0, 9]
|
||||
* '.' must be followed by [a, z]
|
||||
* '-' must be followed by [a, z] or [0, 9]
|
||||
* Names must comply with the following grammar (RFC 1035):
|
||||
* <domain> ::= <subdomain> | " "
|
||||
* <subdomain> ::= <label> | <subdomain> "." <label>
|
||||
* <label> ::= <letter> [ [ <ldh-str> ] <let-dig> ]
|
||||
* <ldh-str> ::= <let-dig-hyp> | <let-dig-hyp> <ldh-str>
|
||||
* <let-dig-hyp> ::= <let-dig> | "-"
|
||||
* <let-dig> ::= <letter> | <digit>
|
||||
*
|
||||
* Which is equivalent to the following:
|
||||
*
|
||||
* <domain> ::= <subdomain> | " "
|
||||
* <subdomain> ::= <label> ("." <label>)*
|
||||
* <label> ::= <letter> [ [ <let-dig-hyp>+ ] <let-dig> ]
|
||||
* <let-dig-hyp> ::= <let-dig> | "-"
|
||||
* <let-dig> ::= <letter> | <digit>
|
||||
*
|
||||
* I.e. a valid name consists of a dot-separated sequence
|
||||
* of one or more labels consisting of the following rules:
|
||||
*
|
||||
* - Each label is three characters or more
|
||||
* - Each label begins with a letter
|
||||
* - Each label ends with a letter or digit
|
||||
* - Each label contains only letters, digits or hyphens
|
||||
*
|
||||
* In addition we require the following:
|
||||
*
|
||||
* - All letters are lowercase
|
||||
* - Length is between (inclusive) GRAPHENE_MIN_ACCOUNT_NAME_LENGTH and GRAPHENE_MAX_ACCOUNT_NAME_LENGTH
|
||||
*/
|
||||
|
||||
bool is_valid_name( const string& name )
|
||||
{
|
||||
if( name.size() < GRAPHENE_MIN_ACCOUNT_NAME_LENGTH )
|
||||
const size_t len = name.size();
|
||||
if( len < GRAPHENE_MIN_ACCOUNT_NAME_LENGTH )
|
||||
return false;
|
||||
|
||||
if( name.size() > GRAPHENE_MAX_ACCOUNT_NAME_LENGTH )
|
||||
if( len > GRAPHENE_MAX_ACCOUNT_NAME_LENGTH )
|
||||
return false;
|
||||
|
||||
if( !isalpha( name.front() ) )
|
||||
return false;
|
||||
|
||||
if( !isalpha( name.back() ) && !isdigit( name.back() ) )
|
||||
return false;
|
||||
|
||||
for( size_t i = 0; i < name.size(); ++i )
|
||||
size_t begin = 0;
|
||||
while( true )
|
||||
{
|
||||
const auto c = name.at( i );
|
||||
|
||||
if( isalpha( c ) && islower( c ) )
|
||||
continue;
|
||||
|
||||
if( isdigit( c ) )
|
||||
continue;
|
||||
|
||||
if( c == '.' )
|
||||
{
|
||||
const auto next = name.at( i + 1 );
|
||||
if( !isalpha( next ) )
|
||||
size_t end = name.find_first_of( '.', begin );
|
||||
if( end == std::string::npos )
|
||||
end = len;
|
||||
if( end - begin < 3 )
|
||||
return false;
|
||||
switch( name[begin] )
|
||||
{
|
||||
case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': case 'h':
|
||||
case 'i': case 'j': case 'k': case 'l': case 'm': case 'n': case 'o': case 'p':
|
||||
case 'q': case 'r': case 's': case 't': case 'u': case 'v': case 'w': case 'x':
|
||||
case 'y': case 'z':
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
switch( name[end-1] )
|
||||
{
|
||||
case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': case 'h':
|
||||
case 'i': case 'j': case 'k': case 'l': case 'm': case 'n': case 'o': case 'p':
|
||||
case 'q': case 'r': case 's': case 't': case 'u': case 'v': case 'w': case 'x':
|
||||
case 'y': case 'z':
|
||||
case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7':
|
||||
case '8': case '9':
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
for( size_t i=begin+1; i<end-1; i++ )
|
||||
{
|
||||
switch( name[i] )
|
||||
{
|
||||
case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': case 'h':
|
||||
case 'i': case 'j': case 'k': case 'l': case 'm': case 'n': case 'o': case 'p':
|
||||
case 'q': case 'r': case 's': case 't': case 'u': case 'v': case 'w': case 'x':
|
||||
case 'y': case 'z':
|
||||
case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7':
|
||||
case '8': case '9':
|
||||
case '-':
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if( c == '-' )
|
||||
{
|
||||
const auto next = name.at( i + 1 );
|
||||
if( !isalpha( next ) && !isdigit( next ) )
|
||||
return false;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if( end == len )
|
||||
break;
|
||||
begin = end+1;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -46,22 +46,22 @@ BOOST_FIXTURE_TEST_SUITE( basic_tests, database_fixture )
|
|||
*/
|
||||
BOOST_AUTO_TEST_CASE( valid_name_test )
|
||||
{
|
||||
BOOST_REQUIRE( is_valid_name( "a" ) );
|
||||
BOOST_REQUIRE( !is_valid_name( "a" ) );
|
||||
BOOST_REQUIRE( !is_valid_name( "A" ) );
|
||||
BOOST_REQUIRE( !is_valid_name( "0" ) );
|
||||
BOOST_REQUIRE( !is_valid_name( "." ) );
|
||||
BOOST_REQUIRE( !is_valid_name( "-" ) );
|
||||
|
||||
BOOST_REQUIRE( is_valid_name( "aa" ) );
|
||||
BOOST_REQUIRE( !is_valid_name( "aa" ) );
|
||||
BOOST_REQUIRE( !is_valid_name( "aA" ) );
|
||||
BOOST_REQUIRE( is_valid_name( "a0" ) );
|
||||
BOOST_REQUIRE( !is_valid_name( "a0" ) );
|
||||
BOOST_REQUIRE( !is_valid_name( "a." ) );
|
||||
BOOST_REQUIRE( !is_valid_name( "a-" ) );
|
||||
|
||||
BOOST_REQUIRE( is_valid_name( "aaa" ) );
|
||||
BOOST_REQUIRE( !is_valid_name( "aAa" ) );
|
||||
BOOST_REQUIRE( is_valid_name( "a0a" ) );
|
||||
BOOST_REQUIRE( is_valid_name( "a.a" ) );
|
||||
BOOST_REQUIRE( !is_valid_name( "a.a" ) );
|
||||
BOOST_REQUIRE( is_valid_name( "a-a" ) );
|
||||
|
||||
BOOST_REQUIRE( is_valid_name( "aa0" ) );
|
||||
|
|
@ -70,31 +70,34 @@ BOOST_AUTO_TEST_CASE( valid_name_test )
|
|||
BOOST_REQUIRE( !is_valid_name( "a.0" ) );
|
||||
BOOST_REQUIRE( is_valid_name( "a-0" ) );
|
||||
|
||||
BOOST_REQUIRE( is_valid_name( "aaa-bbb-1" ) );
|
||||
BOOST_REQUIRE( !is_valid_name( "aaa-bbb.1" ) );
|
||||
BOOST_REQUIRE( is_valid_name( "aaa-bbb-ccc" ) );
|
||||
BOOST_REQUIRE( is_valid_name( "aaa-bbb.ccc" ) );
|
||||
|
||||
BOOST_REQUIRE( !is_valid_name( "aaa,bbb-1" ) );
|
||||
BOOST_REQUIRE( !is_valid_name( "aaa_bbb-1" ) );
|
||||
BOOST_REQUIRE( !is_valid_name( "aaa-BBB-1" ) );
|
||||
BOOST_REQUIRE( !is_valid_name( "aaa,bbb-ccc" ) );
|
||||
BOOST_REQUIRE( !is_valid_name( "aaa_bbb-ccc" ) );
|
||||
BOOST_REQUIRE( !is_valid_name( "aaa-BBB-ccc" ) );
|
||||
|
||||
BOOST_REQUIRE( !is_valid_name( "1aaa-bbb" ) );
|
||||
BOOST_REQUIRE( !is_valid_name( "-aaa-bbb-1" ) );
|
||||
BOOST_REQUIRE( !is_valid_name( ".aaa-bbb-1" ) );
|
||||
BOOST_REQUIRE( !is_valid_name( "/aaa-bbb-1" ) );
|
||||
BOOST_REQUIRE( !is_valid_name( "-aaa-bbb-ccc" ) );
|
||||
BOOST_REQUIRE( !is_valid_name( ".aaa-bbb-ccc" ) );
|
||||
BOOST_REQUIRE( !is_valid_name( "/aaa-bbb-ccc" ) );
|
||||
|
||||
BOOST_REQUIRE( !is_valid_name( "aaa-bbb-1-" ) );
|
||||
BOOST_REQUIRE( !is_valid_name( "aaa-bbb-1." ) );
|
||||
BOOST_REQUIRE( !is_valid_name( "aaa-bbb-1/" ) );
|
||||
BOOST_REQUIRE( !is_valid_name( "aaa-bbb-ccc-" ) );
|
||||
BOOST_REQUIRE( !is_valid_name( "aaa-bbb-ccc." ) );
|
||||
BOOST_REQUIRE( !is_valid_name( "aaa-bbb-ccc.." ) );
|
||||
BOOST_REQUIRE( !is_valid_name( "aaa-bbb-ccc/" ) );
|
||||
|
||||
BOOST_REQUIRE( !is_valid_name( "aaa..bbb-1" ) );
|
||||
BOOST_REQUIRE( is_valid_name( "aaa.bbb-1" ) );
|
||||
BOOST_REQUIRE( !is_valid_name( "aaa.bbb.1" ) );
|
||||
BOOST_REQUIRE( !is_valid_name( "aaa..bbb-ccc" ) );
|
||||
BOOST_REQUIRE( is_valid_name( "aaa.bbb-ccc" ) );
|
||||
BOOST_REQUIRE( is_valid_name( "aaa.bbb.ccc" ) );
|
||||
|
||||
BOOST_REQUIRE( !is_valid_name( "aaa--bbb--1" ) );
|
||||
BOOST_REQUIRE( is_valid_name( "aaa--bbb--ccc" ) );
|
||||
BOOST_REQUIRE( !is_valid_name( "xn--sandmnnchen-p8a.de" ) );
|
||||
BOOST_REQUIRE( is_valid_name( "xn-sandmnnchen-p8a.de" ) );
|
||||
BOOST_REQUIRE( is_valid_name( "xn--sandmnnchen-p8a.dex" ) );
|
||||
BOOST_REQUIRE( !is_valid_name( "xn-sandmnnchen-p8a.de" ) );
|
||||
BOOST_REQUIRE( is_valid_name( "xn-sandmnnchen-p8a.dex" ) );
|
||||
|
||||
BOOST_REQUIRE( is_valid_name( "this-label-has-less-than-64-char.acters-63-to-be-really-precise" ) );
|
||||
BOOST_REQUIRE( is_valid_name( "this-label-has-less-than-64-char.acters-63-to-be-really-precise" ) );
|
||||
BOOST_REQUIRE( !is_valid_name( "this-label-has-more-than-63-char.act.ers-64-to-be-really-precise" ) );
|
||||
BOOST_REQUIRE( !is_valid_name( "none.of.these.labels.has.more.than-63.chars--but.still.not.valid" ) );
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue