2013-09-01 08:52:50 +02:00
/*
Copyright ( c ) 2012 , Arvid Norberg
All rights reserved .
Redistribution and use in source and binary forms , with or without
modification , are permitted provided that the following conditions
are met :
* Redistributions of source code must retain the above copyright
notice , this list of conditions and the following disclaimer .
* Redistributions in binary form must reproduce the above copyright
notice , this list of conditions and the following disclaimer in
the documentation and / or other materials provided with the distribution .
* Neither the name of the author nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission .
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS " AS IS "
AND ANY EXPRESS OR IMPLIED WARRANTIES , INCLUDING , BUT NOT LIMITED TO , THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED . IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT , INDIRECT , INCIDENTAL , SPECIAL , EXEMPLARY , OR
CONSEQUENTIAL DAMAGES ( INCLUDING , BUT NOT LIMITED TO , PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES ; LOSS OF USE , DATA , OR PROFITS ; OR BUSINESS
INTERRUPTION ) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY , WHETHER IN
CONTRACT , STRICT LIABILITY , OR TORT ( INCLUDING NEGLIGENCE OR OTHERWISE )
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE , EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE .
*/
# include "test.hpp"
2016-05-26 19:34:13 +02:00
# include "setup_transfer.hpp"
2013-09-01 08:52:50 +02:00
# include "libtorrent/magnet_uri.hpp"
# include "libtorrent/session.hpp"
# include "libtorrent/torrent_handle.hpp"
# include "libtorrent/bencode.hpp"
2015-09-18 06:23:45 +02:00
# include "libtorrent/torrent_info.hpp" // for announce_entry
# include "libtorrent/announce_entry.hpp"
2016-06-04 16:01:43 +02:00
# include "libtorrent/hex.hpp" // to_hex
2013-09-01 08:52:50 +02:00
using namespace libtorrent ;
2014-07-06 21:18:00 +02:00
namespace lt = libtorrent ;
2013-09-01 08:52:50 +02:00
2014-09-21 22:19:37 +02:00
void test_remove_url ( std : : string url )
{
2015-06-05 08:31:52 +02:00
lt : : session s ;
2014-09-21 22:19:37 +02:00
add_torrent_params p ;
2015-06-10 07:22:01 +02:00
p . flags & = ~ add_torrent_params : : flag_paused ;
p . flags & = ~ add_torrent_params : : flag_auto_managed ;
2014-09-21 22:19:37 +02:00
p . url = url ;
p . save_path = " . " ;
torrent_handle h = s . add_torrent ( p ) ;
std : : vector < torrent_handle > handles = s . get_torrents ( ) ;
TEST_EQUAL ( handles . size ( ) , 1 ) ;
TEST_NOTHROW ( s . remove_torrent ( h ) ) ;
handles = s . get_torrents ( ) ;
TEST_EQUAL ( handles . size ( ) , 0 ) ;
}
2015-10-01 07:05:00 +02:00
TORRENT_TEST ( remove_url )
{
test_remove_url ( " magnet:?xt=urn:btih:0123456789abcdef0123456789abcdef01234567 " ) ;
}
2016-05-17 22:49:11 +02:00
# ifndef TORRENT_NO_DEPRECATE
2015-10-01 07:05:00 +02:00
TORRENT_TEST ( remove_url2 )
{
test_remove_url ( " http://non-existent.com/test.torrent " ) ;
}
2016-05-17 22:49:11 +02:00
# endif
2015-10-01 07:05:00 +02:00
2015-05-30 06:31:23 +02:00
TORRENT_TEST ( magnet )
2013-09-01 08:52:50 +02:00
{
session_proxy p1 ;
session_proxy p2 ;
2015-10-01 07:05:00 +02:00
2013-09-01 08:52:50 +02:00
// test session state load/restore
2014-07-06 21:18:00 +02:00
settings_pack pack ;
pack . set_str ( settings_pack : : user_agent , " test " ) ;
pack . set_int ( settings_pack : : tracker_receive_timeout , 1234 ) ;
pack . set_int ( settings_pack : : file_pool_size , 543 ) ;
pack . set_int ( settings_pack : : urlseed_wait_retry , 74 ) ;
pack . set_int ( settings_pack : : initial_picker_threshold , 351 ) ;
pack . set_bool ( settings_pack : : upnp_ignore_nonrouters , true ) ;
pack . set_bool ( settings_pack : : coalesce_writes , true ) ;
pack . set_bool ( settings_pack : : close_redundant_connections , false ) ;
pack . set_int ( settings_pack : : auto_scrape_interval , 235 ) ;
pack . set_int ( settings_pack : : auto_scrape_min_interval , 62 ) ;
2016-06-05 20:07:24 +02:00
std : : unique_ptr < lt : : session > s ( new lt : : session ( pack ) ) ;
2014-07-06 21:18:00 +02:00
TEST_EQUAL ( pack . get_str ( settings_pack : : user_agent ) , " test " ) ;
TEST_EQUAL ( pack . get_int ( settings_pack : : tracker_receive_timeout ) , 1234 ) ;
2013-09-01 08:52:50 +02:00
# ifndef TORRENT_DISABLE_DHT
dht_settings dhts ;
dhts . max_peers_reply = 70 ;
s - > set_dht_settings ( dhts ) ;
# endif
/*
# ifndef TORRENT_DISABLE_DHT
dht_settings dht_sett ;
s - > set_dht_settings ( dht_sett ) ;
# endif
*/
entry session_state ;
s - > save_state ( session_state ) ;
// test magnet link parsing
add_torrent_params p ;
2015-06-10 07:22:01 +02:00
p . flags & = ~ add_torrent_params : : flag_paused ;
p . flags & = ~ add_torrent_params : : flag_auto_managed ;
2013-09-01 08:52:50 +02:00
p . save_path = " . " ;
error_code ec ;
p . url = " magnet:?xt=urn:btih:cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd "
" &tr=http://1 "
" &tr=http://2 "
" &tr=http://3 "
" &dn=foo "
" &dht=127.0.0.1:43 " ;
torrent_handle t = s - > add_torrent ( p , ec ) ;
TEST_CHECK ( ! ec ) ;
2016-05-17 15:24:06 +02:00
if ( ec ) std : : fprintf ( stderr , " %s \n " , ec . message ( ) . c_str ( ) ) ;
2013-09-01 08:52:50 +02:00
std : : vector < announce_entry > trackers = t . trackers ( ) ;
TEST_EQUAL ( trackers . size ( ) , 3 ) ;
std : : set < std : : string > trackers_set ;
for ( std : : vector < announce_entry > : : iterator i = trackers . begin ( )
, end ( trackers . end ( ) ) ; i ! = end ; + + i )
trackers_set . insert ( i - > url ) ;
TEST_CHECK ( trackers_set . count ( " http://1 " ) = = 1 ) ;
TEST_CHECK ( trackers_set . count ( " http://2 " ) = = 1 ) ;
TEST_CHECK ( trackers_set . count ( " http://3 " ) = = 1 ) ;
p . url = " magnet: "
" ?tr=http://1 "
" &tr=http://2 "
" &dn=foo "
" &dht=127.0.0.1:43 "
" &xt=urn:btih:c352cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd " ;
torrent_handle t2 = s - > add_torrent ( p , ec ) ;
TEST_CHECK ( ! ec ) ;
2016-05-17 15:24:06 +02:00
if ( ec ) std : : fprintf ( stderr , " %s \n " , ec . message ( ) . c_str ( ) ) ;
2013-09-01 08:52:50 +02:00
trackers = t2 . trackers ( ) ;
TEST_EQUAL ( trackers . size ( ) , 2 ) ;
p . url = " magnet: "
" ?tr=udp%3A%2F%2Ftracker.openbittorrent.com%3A80 "
" &tr=udp%3A%2F%2Ftracker.publicbt.com%3A80 "
" &tr=udp%3A%2F%2Ftracker.ccc.de%3A80 "
" &xt=urn:btih:a38d02c287893842a32825aa866e00828a318f07 "
" &dn=Ubuntu+11.04+%28Final%29 " ;
torrent_handle t3 = s - > add_torrent ( p , ec ) ;
TEST_CHECK ( ! ec ) ;
2016-05-17 15:24:06 +02:00
if ( ec ) std : : fprintf ( stderr , " %s \n " , ec . message ( ) . c_str ( ) ) ;
2013-09-01 08:52:50 +02:00
trackers = t3 . trackers ( ) ;
TEST_EQUAL ( trackers . size ( ) , 3 ) ;
if ( trackers . size ( ) > 0 )
{
TEST_EQUAL ( trackers [ 0 ] . url , " udp://tracker.openbittorrent.com:80 " ) ;
2016-05-17 15:24:06 +02:00
std : : fprintf ( stderr , " 1: %s \n " , trackers [ 0 ] . url . c_str ( ) ) ;
2013-09-01 08:52:50 +02:00
}
if ( trackers . size ( ) > 1 )
{
TEST_EQUAL ( trackers [ 1 ] . url , " udp://tracker.publicbt.com:80 " ) ;
2016-05-17 15:24:06 +02:00
std : : fprintf ( stderr , " 2: %s \n " , trackers [ 1 ] . url . c_str ( ) ) ;
2013-09-01 08:52:50 +02:00
}
if ( trackers . size ( ) > 2 )
{
TEST_EQUAL ( trackers [ 2 ] . url , " udp://tracker.ccc.de:80 " ) ;
2016-05-17 15:24:06 +02:00
std : : fprintf ( stderr , " 3: %s \n " , trackers [ 2 ] . url . c_str ( ) ) ;
2013-09-01 08:52:50 +02:00
}
2016-07-29 08:36:15 +02:00
sha1_hash const ih = t . info_hash ( ) ;
TEST_EQUAL ( aux : : to_hex ( ih ) , " cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd " ) ;
2013-09-01 08:52:50 +02:00
p1 = s - > abort ( ) ;
2015-10-01 07:05:00 +02:00
s . reset ( new lt : : session ( ) ) ;
2013-09-01 08:52:50 +02:00
std : : vector < char > buf ;
bencode ( std : : back_inserter ( buf ) , session_state ) ;
2015-03-12 06:20:12 +01:00
bdecode_node session_state2 ;
int ret = bdecode ( & buf [ 0 ] , & buf [ 0 ] + buf . size ( ) , session_state2 , ec ) ;
2013-09-01 08:52:50 +02:00
TEST_CHECK ( ret = = 0 ) ;
2016-05-17 15:24:06 +02:00
std : : fprintf ( stderr , " session_state \n %s \n " , print_entry ( session_state2 ) . c_str ( ) ) ;
2013-09-01 08:52:50 +02:00
2015-10-01 07:05:00 +02:00
// make sure settings that haven't been changed from their defaults are not saved
TEST_CHECK ( session_state2 . dict_find ( " settings " )
. dict_find ( " optimistic_disk_retry " ) = = 0 ) ;
s - > load_state ( session_state2 ) ;
2016-05-17 15:24:06 +02:00
# define CMP_SET(x) std::fprintf(stderr, #x ": %d %d\n"\
2015-10-01 07:05:00 +02:00
, s - > get_settings ( ) . get_int ( settings_pack : : x ) \
, pack . get_int ( settings_pack : : x ) ) ; \
TEST_EQUAL ( s - > get_settings ( ) . get_int ( settings_pack : : x ) , pack . get_int ( settings_pack : : x ) )
CMP_SET ( tracker_receive_timeout ) ;
CMP_SET ( file_pool_size ) ;
CMP_SET ( urlseed_wait_retry ) ;
CMP_SET ( initial_picker_threshold ) ;
CMP_SET ( auto_scrape_interval ) ;
CMP_SET ( auto_scrape_min_interval ) ;
p2 = s - > abort ( ) ;
}
TORRENT_TEST ( parse_missing_hash )
{
2013-09-01 08:52:50 +02:00
// parse_magnet_uri
2015-10-01 07:05:00 +02:00
error_code ec ;
add_torrent_params p ;
2013-09-01 08:52:50 +02:00
parse_magnet_uri ( " magnet:?dn=foo&dht=127.0.0.1:43 " , p , ec ) ;
2015-10-01 07:05:00 +02:00
TEST_EQUAL ( ec , error_code ( errors : : missing_info_hash_in_uri ) ) ;
ec . clear ( ) ;
}
TORRENT_TEST ( parse_base32_hash )
{
// parse_magnet_uri
error_code ec ;
add_torrent_params p ;
parse_magnet_uri ( " magnet:?xt=urn:btih:MFRGCYTBMJQWEYLCMFRGCYTBMJQWEYLC " , p , ec ) ;
TEST_CHECK ( ! ec ) ;
TEST_EQUAL ( p . info_hash , sha1_hash ( " abababababababababab " ) ) ;
2013-09-01 08:52:50 +02:00
ec . clear ( ) ;
2015-10-01 07:05:00 +02:00
}
2013-09-01 08:52:50 +02:00
2015-10-01 07:05:00 +02:00
TORRENT_TEST ( parse_web_seeds )
{
2014-04-15 11:31:28 +02:00
// parse_magnet_uri
2015-10-01 07:05:00 +02:00
error_code ec ;
add_torrent_params p ;
2014-04-15 11:31:28 +02:00
parse_magnet_uri ( " magnet:?xt=urn:btih:cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd&ws=http://foo.com/bar&ws=http://bar.com/foo " , p , ec ) ;
TEST_CHECK ( ! ec ) ;
TEST_EQUAL ( p . url_seeds . size ( ) , 2 ) ;
TEST_EQUAL ( p . url_seeds [ 0 ] , " http://foo.com/bar " ) ;
TEST_EQUAL ( p . url_seeds [ 1 ] , " http://bar.com/foo " ) ;
ec . clear ( ) ;
2015-10-01 07:05:00 +02:00
}
2014-04-15 11:31:28 +02:00
2015-10-01 07:05:00 +02:00
TORRENT_TEST ( parse_missing_hash2 )
{
error_code ec ;
add_torrent_params p ;
2013-09-01 08:52:50 +02:00
parse_magnet_uri ( " magnet:?xt=blah&dn=foo&dht=127.0.0.1:43 " , p , ec ) ;
2015-10-01 07:05:00 +02:00
TEST_EQUAL ( ec , error_code ( errors : : missing_info_hash_in_uri ) ) ;
2013-09-01 08:52:50 +02:00
ec . clear ( ) ;
2015-10-01 07:05:00 +02:00
}
TORRENT_TEST ( parse_short_hash )
{
error_code ec ;
add_torrent_params p ;
parse_magnet_uri ( " magnet:?xt=urn:btih:abababab " , p , ec ) ;
TEST_EQUAL ( ec , error_code ( errors : : invalid_info_hash ) ) ;
ec . clear ( ) ;
}
TORRENT_TEST ( parse_long_hash )
{
error_code ec ;
add_torrent_params p ;
parse_magnet_uri ( " magnet:?xt=urn:btih:ababababababababababab " , p , ec ) ;
TEST_EQUAL ( ec , error_code ( errors : : invalid_info_hash ) ) ;
ec . clear ( ) ;
}
TORRENT_TEST ( parse_space_hash )
{
error_code ec ;
add_torrent_params p ;
parse_magnet_uri ( " magnet:?xt=urn:btih: abababababababababab " , p , ec ) ;
TEST_EQUAL ( ec , error_code ( errors : : invalid_info_hash ) ) ;
ec . clear ( ) ;
}
2013-09-01 08:52:50 +02:00
2016-05-26 19:34:13 +02:00
TORRENT_TEST ( parse_peer )
{
error_code ec ;
add_torrent_params p ;
parse_magnet_uri ( " magnet:?xt=urn:btih:cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd&dn=foo&x.pe=127.0.0.1:43&x.pe=<invalid1>&x.pe=<invalid2>:100&x.pe=[::1]:45 " , p , ec ) ;
TEST_CHECK ( ! ec ) ;
# if TORRENT_USE_IPV6
TEST_EQUAL ( p . peers . size ( ) , 2 ) ;
TEST_EQUAL ( p . peers [ 0 ] , ep ( " 127.0.0.1 " , 43 ) ) ;
TEST_EQUAL ( p . peers [ 1 ] , ep ( " ::1 " , 45 ) ) ;
# else
TEST_EQUAL ( p . peers . size ( ) , 1 ) ;
TEST_EQUAL ( p . peers [ 0 ] , ep ( " 127.0.0.1 " , 43 ) ) ;
# endif
ec . clear ( ) ;
}
2013-09-01 08:52:50 +02:00
# ifndef TORRENT_DISABLE_DHT
2015-10-01 07:05:00 +02:00
TORRENT_TEST ( parse_dht_node )
{
error_code ec ;
add_torrent_params p ;
2013-09-01 08:52:50 +02:00
parse_magnet_uri ( " magnet:?xt=urn:btih:cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd&dn=foo&dht=127.0.0.1:43 " , p , ec ) ;
TEST_CHECK ( ! ec ) ;
2016-05-17 15:24:06 +02:00
if ( ec ) std : : fprintf ( stderr , " %s \n " , ec . message ( ) . c_str ( ) ) ;
2013-09-01 08:52:50 +02:00
ec . clear ( ) ;
2015-10-01 07:05:00 +02:00
TEST_EQUAL ( p . dht_nodes . size ( ) , 1 ) ;
TEST_EQUAL ( p . dht_nodes [ 0 ] . first , " 127.0.0.1 " ) ;
TEST_EQUAL ( p . dht_nodes [ 0 ] . second , 43 ) ;
}
2013-09-01 08:52:50 +02:00
# endif
2015-10-01 07:05:00 +02:00
TORRENT_TEST ( make_magnet_uri )
{
// make_magnet_uri
entry info ;
info [ " pieces " ] = " aaaaaaaaaaaaaaaaaaaa " ;
info [ " name " ] = " slightly shorter name, it's kind of sad that people started the trend of incorrectly encoding the regular name field and then adding another one with correct encoding " ;
info [ " name.utf-8 " ] = " this is a long ass name in order to try to make make_magnet_uri overflow and hopefully crash. Although, by the time you read this that particular bug should have been fixed " ;
info [ " piece length " ] = 16 * 1024 ;
info [ " length " ] = 3245 ;
entry torrent ;
torrent [ " info " ] = info ;
entry : : list_type & al1 = torrent [ " announce-list " ] . list ( ) ;
al1 . push_back ( entry : : list_type ( ) ) ;
entry : : list_type & al = al1 . back ( ) . list ( ) ;
al . push_back ( entry ( " http://bigtorrent.org:2710/announce " ) ) ;
al . push_back ( entry ( " http://bt.careland.com.cn:6969/announce " ) ) ;
al . push_back ( entry ( " http://bt.e-burg.org:2710/announce " ) ) ;
al . push_back ( entry ( " http://bttrack.9you.com/announce " ) ) ;
al . push_back ( entry ( " http://coppersurfer.tk:6969/announce " ) ) ;
al . push_back ( entry ( " http://erdgeist.org/arts/software/opentracker/announce " ) ) ;
al . push_back ( entry ( " http://exodus.desync.com/announce " ) ) ;
al . push_back ( entry ( " http://fr33dom.h33t.com:3310/announce " ) ) ;
al . push_back ( entry ( " http://genesis.1337x.org:1337/announce " ) ) ;
al . push_back ( entry ( " http://inferno.demonoid.me:3390/announce " ) ) ;
al . push_back ( entry ( " http://inferno.demonoid.ph:3390/announce " ) ) ;
al . push_back ( entry ( " http://ipv6.tracker.harry.lu/announce " ) ) ;
al . push_back ( entry ( " http://lnxroot.com:6969/announce " ) ) ;
al . push_back ( entry ( " http://nemesis.1337x.org/announce " ) ) ;
al . push_back ( entry ( " http://puto.me:6969/announce " ) ) ;
al . push_back ( entry ( " http://sline.net:2710/announce " ) ) ;
al . push_back ( entry ( " http://tracker.beeimg.com:6969/announce " ) ) ;
al . push_back ( entry ( " http://tracker.ccc.de/announce " ) ) ;
al . push_back ( entry ( " http://tracker.coppersurfer.tk/announce " ) ) ;
al . push_back ( entry ( " http://tracker.coppersurfer.tk:6969/announce " ) ) ;
al . push_back ( entry ( " http://tracker.cpleft.com:2710/announce " ) ) ;
al . push_back ( entry ( " http://tracker.istole.it/announce " ) ) ;
al . push_back ( entry ( " http://tracker.kamyu.net/announce " ) ) ;
al . push_back ( entry ( " http://tracker.novalayer.org:6969/announce " ) ) ;
al . push_back ( entry ( " http://tracker.torrent.to:2710/announce " ) ) ;
al . push_back ( entry ( " http://tracker.torrentbay.to:6969/announce " ) ) ;
al . push_back ( entry ( " udp://tracker.openbittorrent.com:80 " ) ) ;
al . push_back ( entry ( " udp://tracker.publicbt.com:80 " ) ) ;
2013-09-01 08:52:50 +02:00
2015-10-01 07:05:00 +02:00
std : : vector < char > buf ;
bencode ( std : : back_inserter ( buf ) , torrent ) ;
buf . push_back ( ' \0 ' ) ;
2016-05-17 15:24:06 +02:00
std : : printf ( " %s \n " , & buf [ 0 ] ) ;
2015-10-01 07:05:00 +02:00
error_code ec ;
2016-04-25 23:22:09 +02:00
torrent_info ti ( & buf [ 0 ] , int ( buf . size ( ) ) , ec ) ;
2013-09-01 08:52:50 +02:00
2015-10-01 07:05:00 +02:00
TEST_EQUAL ( al . size ( ) , ti . trackers ( ) . size ( ) ) ;
2014-07-06 21:18:00 +02:00
2015-10-01 07:05:00 +02:00
std : : string magnet = make_magnet_uri ( ti ) ;
2016-05-17 15:24:06 +02:00
std : : printf ( " %s len: %d \n " , magnet . c_str ( ) , int ( magnet . size ( ) ) ) ;
2015-10-01 07:05:00 +02:00
}
2014-07-06 21:18:00 +02:00
2015-10-01 07:05:00 +02:00
TORRENT_TEST ( make_magnet_uri2 )
{
2013-09-01 08:52:50 +02:00
// make_magnet_uri
2015-10-01 07:05:00 +02:00
entry info ;
info [ " pieces " ] = " aaaaaaaaaaaaaaaaaaaa " ;
info [ " name " ] = " test " ;
info [ " name.utf-8 " ] = " test " ;
info [ " piece length " ] = 16 * 1024 ;
info [ " length " ] = 3245 ;
entry torrent ;
torrent [ " info " ] = info ;
2013-09-01 08:52:50 +02:00
2015-10-01 07:05:00 +02:00
torrent [ " url-list " ] = " http://foo.com/bar " ;
2013-09-01 08:52:50 +02:00
2015-10-01 07:05:00 +02:00
std : : vector < char > buf ;
bencode ( std : : back_inserter ( buf ) , torrent ) ;
buf . push_back ( ' \0 ' ) ;
2016-05-17 15:24:06 +02:00
std : : printf ( " %s \n " , & buf [ 0 ] ) ;
2015-10-01 07:05:00 +02:00
error_code ec ;
2016-04-25 23:22:09 +02:00
torrent_info ti ( & buf [ 0 ] , int ( buf . size ( ) ) , ec ) ;
2015-10-01 07:05:00 +02:00
std : : string magnet = make_magnet_uri ( ti ) ;
2016-05-17 15:24:06 +02:00
std : : printf ( " %s len: %d \n " , magnet . c_str ( ) , int ( magnet . size ( ) ) ) ;
2015-10-01 07:05:00 +02:00
TEST_CHECK ( magnet . find ( " &ws=http%3a%2f%2ffoo.com%2fbar " ) ! = std : : string : : npos ) ;
2013-09-01 08:52:50 +02:00
}