try {
std::vector<std::string> serials;
std::pair<std::shared_ptr<CRL>, std::string> rev = sign->revoke( x.second, serials );
- } catch( const char* c ) {
- logger::error( "Exception: ", c );
+ } catch( const std::exception &e ) {
+ logger::error( "Exception: ", e.what() );
}
}
}
}
continue;
- } catch( const char* c ) {
- logger::error( "ERROR: ", c );
- } catch( std::string& c ) {
- logger::error( "ERROR: ", c );
+ } catch( std::exception& c ) {
+ logger::error( "ERROR: ", c.what() );
}
try {
jp->failJob( job );
- } catch( const char* c ) {
- logger::error( "ERROR: ", c );
- } catch( std::string& c ) {
- logger::error( "ERROR: ", c );
+ } catch( std::exception& c ) {
+ logger::error( "ERROR: ", c.what() );
}
} else if( job->task == "revoke" ) {
try {
jp->writeBackRevocation( job, timeToString( time ) );
jp->finishJob( job );
- } catch( const char* c ) {
- logger::error( "Exception: ", c );
- } catch( const std::string& c ) {
- logger::error( "Exception: ", c );
+ } catch( const std::exception& c ) {
+ logger::error( "Exception: ", c.what() );
}
} else {
logger::errorf( "Unknown job type (\"%s\")", job->task );
if( !DAEMON || once ) {
return 0;
}
- } catch( const char* c ) {
- logger::error( "Exception: ", c );
- } catch( const std::string& c ) {
- logger::error( "Exception: ", c );
} catch ( std::exception &e ){
logger::errorf ( "std::exception in mainloop: %s", e.what() );
}
dh->handle();
//} catch( const std::exception &ch ) {
//std::cout << "Real exception: " << typeid(ch).name() << ", " << ch.what() << std::endl;
- } catch( const std::string& ch ) {
- logger::error( "Exception: ", ch );
- } catch( char const* ch ) {
- logger::error( "Exception: ", ch );
+ } catch( const std::exception& e ) {
+ logger::error( "Exception: ", e.what() );
}
}
} catch( std::exception& e ) {
logger::fatalf( "Fatal Error: %s!\n", e.what() );
return -1;
-} catch( ... ) {
- logger::fatal( "Fatal Error: Unknown Exception!\n" );
- return -1;
}
if( !config.is_open() ) {
logger::notef( "Where is \"%s\"?", path );
- throw "Config missing";
+ throw std::runtime_error("Config missing");
}
std::string line1;
closedir( dir );
} else {
- throw "Directory with CAConfigs not found";
+ throw std::runtime_error("Directory with CAConfigs not found");
}
profiles.emplace( profileName, prof );
#include <openssl/ssl.h>
#include <log/logger.hpp>
+#include <exception>
CRL::CRL( std::string path ) {
std::shared_ptr<BIO> bio( BIO_new_file( path.c_str(), "r" ), BIO_free );
logger::note("parsing serial");
if( ! BN_hex2bn( &serBN, serial.c_str() ) ) {
- throw "hex2bn malloc fail";
+ throw std::runtime_error("hex2bn malloc fail");
}
std::shared_ptr<BIGNUM> serBNP( serBN, BN_free );
std::shared_ptr<ASN1_INTEGER> ser( BN_to_ASN1_INTEGER( serBN, NULL ), ASN1_INTEGER_free );
if( !ser ) {
- throw "BN Malloc fail";
+ throw std::runtime_error("BN Malloc fail");
}
logger::note("building current time");
std::shared_ptr<ASN1_TIME> tmptm( ASN1_TIME_new(), ASN1_TIME_free );
if( !tmptm ) {
- throw "ASN1-Time Malloc fail";
+ throw std::runtime_error("ASN1-Time Malloc fail");
}
X509_gmtime_adj( tmptm.get(), 0 );
std::shared_ptr<ASN1_TIME> tmptm( ASN1_TIME_new(), ASN1_TIME_free );
if( !tmptm ) {
- throw "ASN1-Time Malloc fail";
+ throw std::runtime_error("ASN1-Time Malloc fail");
}
X509_gmtime_adj( tmptm.get(), 0 );
logger::note("setting issuer");
if( !X509_CRL_set_issuer_name( crl.get(), X509_get_subject_name( ca->ca.get() ) ) ) {
- throw "Setting issuer failed";
+ throw std::runtime_error("Setting issuer failed");
}
logger::note("setting update");
X509_CRL_set_lastUpdate( crl.get(), tmptm.get() );
if( !X509_time_adj_ex( tmptm.get(), 1, 10, NULL ) ) {
- throw "Updating time failed";
+ throw std::runtime_error("Updating time failed");
}
logger::note("setting next update");
EVP_PKEY* pkt = X509_REQ_get_pubkey( req.get() );
if( !pkt ) {
- throw "Error extracting public key";
+ throw std::runtime_error("Error extracting public key");
}
pk = std::shared_ptr<EVP_PKEY>( pkt, EVP_PKEY_free );
X509Req::X509Req( std::string spkac ) {
if( spkac.compare( 0, 6, "SPKAC=" ) != 0 ) {
- throw "Error: not a SPKAC";
+ throw std::runtime_error("Error: not a SPKAC");
}
spkac = spkac.substr( 6 );
NETSCAPE_SPKI* spki_p = NETSCAPE_SPKI_b64_decode( spkac.c_str(), spkac.size() );
if( !spki_p ) {
- throw "Error: decode failed";
+ throw std::runtime_error("Error: decode failed");
}
spki = std::shared_ptr<NETSCAPE_SPKI>( spki_p, NETSCAPE_SPKI_free );
EVP_PKEY* pkt_p = NETSCAPE_SPKI_get_pubkey( spki.get() );
if( !pkt_p ) {
- throw "Error: reading SPKAC Pubkey failed";
+ throw std::runtime_error("Error: reading SPKAC Pubkey failed");
}
pk = std::shared_ptr<EVP_PKEY>( pkt_p, EVP_PKEY_free );
X509_REQ* req = PEM_read_bio_X509_REQ( in.get(), NULL, NULL, NULL );
if( !req ) {
- throw "Error parsing CSR";
+ throw std::runtime_error("Error parsing CSR");
}
return std::shared_ptr<X509Req>( new X509Req( req )); // TODO ask
X509* c = X509_new();
if( !c ) {
- throw "malloc failed";
+ throw std::runtime_error("malloc failed");
}
target = std::shared_ptr<X509>( c, X509_free );
if( !X509_set_version( c, 2 ) ) {
- throw "Setting X509-version to 3 failed";
+ throw std::runtime_error("Setting X509-version to 3 failed");
}
X509_NAME* subjectP = X509_NAME_new();
if( !subjectP ) {
- throw "malloc failure in construct.";
+ throw std::runtime_error("malloc failure in construct.");
}
subject = std::shared_ptr<X509_NAME>( subjectP, X509_NAME_free );
void X509Cert::addRDN( int nid, std::string data ) {
if( ! X509_NAME_add_entry_by_NID( subject.get(), nid, MBSTRING_UTF8, ( unsigned char* )const_cast<char*>( data.data() ), data.size(), -1, 0 ) ) {
- throw "malloc failure in RDN";
+ throw std::runtime_error("malloc failure in RDN");
}
}
void X509Cert::setIssuerNameFrom( std::shared_ptr<X509> caCert ) {
if( !X509_set_issuer_name( target.get(), X509_get_subject_name( caCert.get() ) ) ) {
- throw "Error setting Issuer name";
+ throw std::runtime_error("Error setting Issuer name");
}
}
std::shared_ptr<EVP_PKEY> pktmp = req->getPkey();
if( !X509_set_pubkey( target.get(), pktmp.get() ) ) {
- throw "Setting public key failed.";
+ throw std::runtime_error("Setting public key failed.");
}
}
return ext;
merr:
- throw "memerr";
+ throw std::runtime_error("memerr");
}
void X509Cert::setExtensions( std::shared_ptr<X509> caCert, std::vector<std::shared_ptr<SAN>>& sans, Profile& prof, std::string crlURL, std::string crtURL ) {
GENERAL_NAME* gen = GENERAL_NAME_new();
if( !gen ) {
- throw "Malloc failure.";
+ throw std::runtime_error("Malloc failure.");
}
gen->type = name->type == "DNS" ? GEN_DNS : name->type == "email" ? GEN_EMAIL : 0; // GEN_EMAIL;
|| !( gen->d.ia5 = M_ASN1_IA5STRING_new() )
|| !ASN1_STRING_set( gen->d.ia5, name->content.data(), name->content.size() ) ) {
GENERAL_NAME_free( gen );
- throw "initing iasting5 failed";
+ throw std::runtime_error("initing iasting5 failed");
}
sk_GENERAL_NAME_push( gens.get(), gen );
std::shared_ptr<SignedCertificate> X509Cert::sign( std::shared_ptr<EVP_PKEY> caKey, std::string signAlg ) {
if( !X509_set_subject_name( target.get(), subject.get() ) ) {
- throw "error setting subject";
+ throw std::runtime_error("error setting subject");
}
const EVP_MD* md;
} else if( signAlg == "sha1" ) {
md = EVP_sha1();
} else {
- throw "Unknown md-type";
+ throw std::runtime_error("Unknown md-type");
}
if( !X509_sign( target.get(), caKey.get(), md ) ) {
- throw "Signing failed.";
+ throw std::runtime_error("Signing failed.");
}
//X509_print_fp( stdout, target.get() );
std::shared_ptr<BIO> mem = std::shared_ptr<BIO>( BIO_new( BIO_s_mem() ), BIO_free );
if( !mem ) {
- throw "Failed to allocate memory for the signed certificate.";
+ throw std::runtime_error("Failed to allocate memory for the signed certificate.");
}
PEM_write_bio_X509( mem.get(), target.get() );
std::shared_ptr<BIGNUM> ser( ASN1_INTEGER_to_BN( target->cert_info->serialNumber, NULL ), BN_free );
if( !ser ) {
- throw "Failed to retrieve certificate serial of signed certificate.";
+ throw std::runtime_error("Failed to retrieve certificate serial of signed certificate.");
}
std::shared_ptr<char> serStr(
logger::error( "Invalid Message" );
break;
}
- } catch( const char* msg ) {
- logger::error( msg );
+ } catch( const std::exception& msg ) {
+ logger::error( msg.what() );
return std::shared_ptr<SignedCertificate>();
}
}
int dlen = BIO_write( bios.get(), buf, len );
if( dlen <= 0 ) {
- throw "Memory error.";
+ throw std::runtime_error("Memory error.");
}
len -= dlen;
std::shared_ptr<X509> pem( PEM_read_bio_X509( bios.get(), NULL, 0, NULL ) );
if( !pem ) {
- throw "Pem was not readable";
+ throw std::runtime_error("Pem was not readable");
}
std::shared_ptr<BIGNUM> ser( ASN1_INTEGER_to_BN( pem->cert_info->serialNumber, NULL ), BN_free );
std::string date;
if( static_cast<RecordHeader::SignerResult>( head.command ) != RecordHeader::SignerResult::REVOKED ) {
- throw "Protocol violation";
+ throw std::runtime_error("Protocol violation");
}
const unsigned char* buffer2 = reinterpret_cast<const unsigned char*>( payload.data() );
payload = parseCommandChunked( head, conn );
if( static_cast<RecordHeader::SignerResult>( head.command ) != RecordHeader::SignerResult::FULL_CRL ) {
- throw "Protocol violation";
+ throw std::runtime_error("Protocol violation");
}
std::string name_bak = ca->path + std::string( "/ca.crl.bak" );
#include <sstream>
#include <unordered_map>
+#include <exception>
#include <openssl/ssl.h>
#include <openssl/err.h>
bn = BN_new();
if( !bn || !BN_hex2bn( &bn, "1" )) {
- throw "Initing serial failed";
+ throw std::runtime_error("Initing serial failed");
}
} else {
if( !BN_hex2bn( &bn, res.c_str() ) ) {
- throw "Parsing serial failed.";
+ throw std::runtime_error("Parsing serial failed.");
}
}
data.get()[len + 3] = profile & 0xFF; // profile id
if( !RAND_bytes( data.get() + len + 4, 16 ) || !BN_add_word( serial.get(), 1 ) ) {
- throw "Big number math failed while fetching random data for serial number.";
+ throw std::runtime_error("Big number math failed while fetching random data for serial number.");
}
std::shared_ptr<char> serStr = std::shared_ptr<char>(
if( !ca ) {
logger::error( "ERROR: Signing CA specified in profile could not be loaded." );
- throw "CA-key not found";
+ throw std::runtime_error("CA-key not found");
}
logger::note( "FINE: Key for Signing CA is correctly loaded." );
req = X509Req::parseCSR( cert->csr_content );
} else {
logger::errorf( "ERROR: Unknown type (\"%s\") of certification in request.", cert->csr_type );
- throw "Error, unknown REQ rype " + ( cert->csr_type ); //! \fixme: Pointer instead of string, please use proper exception classes
+ throw std::runtime_error("Error, unknown REQ rype " + cert->csr_type ); //! \fixme: Pointer instead of string, please use proper exception classe)s
}
int i = req->verify();
if( i < 0 ) {
- throw "Request contains a Signature with problems ... ";
+ throw std::runtime_error("Request contains a Signature with problems ... ");
} else if( i == 0 ) {
- throw "Request contains a Signature that does not match ...";
+ throw std::runtime_error("Request contains a Signature that does not match ...");
} else {
logger::note( "FINE: Request contains valid self-signature." );
}
c.addRDN( NID_organizationalUnitName, a->value );
} else {
logger::error( "ERROR: Trying to add illegal RDN/AVA type: ", a->name );
- throw "Unhandled/Illegal AVA type";
+ throw std::runtime_error("Unhandled/Illegal AVA type");
}
}
if( fn.empty() ) {
logger::error( "ERROR: failed to get filename for storage of signed certificate." );
- throw "Storage location could not be determined";
+ throw std::runtime_error("Storage location could not be determined");
}
logger::note( "FINE: Certificate signed successfully." );
} );
if( !SSL_CTX_set_cipher_list( ctx.get(), "HIGH:+CAMELLIA256:!eNull:!aNULL:!ADH:!MD5:-RSA+AES+SHA1:!RC4:!DES:!3DES:!SEED:!EXP:!AES128:!CAMELLIA128" ) ) {
- throw "Cannot set cipher list. Your source is broken.";
+ throw std::runtime_error("Cannot set cipher list. Your source is broken.");
}
SSL_CTX_set_verify( ctx.get(), SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, verify_callback );
SSL_CTX_use_PrivateKey_file( ctx.get(), server ? "keys/signer_server.key" : "keys/signer_client.key", SSL_FILETYPE_PEM );
if( 1 != SSL_CTX_load_verify_locations( ctx.get(), "keys/ca.crt", 0 ) ) {
- throw "Cannot load CA store for certificate validation.";
+ throw std::runtime_error("Cannot load CA store for certificate validation.");
}
if( server ) {
cb.cb.cb_2 = gencb;
if( !DH_generate_parameters_ex( dh_param.get(), 2048, 5, &cb ) ) {
- throw "DH generation failed";
+ throw std::runtime_error("DH generation failed");
}
std::cout << std::endl;
}
if( !SSL_CTX_set_tmp_dh( ctx.get(), dh_param.get() ) ) {
- throw "Cannot set tmp dh.";
+ throw std::runtime_error("Cannot set tmp dh.");
}
}
struct termios attr;
if( tcgetattr( fileno( f.get() ), &attr ) ) {
- throw "failed to get attrs";
+ throw std::runtime_error("failed to get attrs");
}
attr.c_iflag &= ~( IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON );
cfsetospeed( &attr, B115200 );
if( tcsetattr( fileno( f.get() ), TCSANOW, &attr ) ) {
- throw "failed to get attrs";
+ throw std::runtime_error("failed to get attrs");
}
}
logger::notef("openssl formatted me a date: %s", strdate);
if( strdate[strdate.size() - 1] != 'Z' ) {
- throw "Got invalid date?";
+ throw std::runtime_error("Got invalid date?");
}
return strdate.substr( 0, strdate.size() - 1 );
MySQLJobProvider::MySQLJobProvider( const std::string& server, const std::string& user, const std::string& password, const std::string& database ) {
if( !lib_ref || *lib_ref ) {
- throw "MySQL library not initialized!";
+ throw std::runtime_error("MySQL library not initialized!");
}
connect( server, user, password, database );
int err = mysql_real_query( this->conn.get(), query.c_str(), query.size() );
if( err ) {
- throw std::string( "MySQL error: " ) + mysql_error( this->conn.get() );
+ throw std::runtime_error(std::string( "MySQL error: " ) + mysql_error( this->conn.get() ));
}
auto c = conn;
std::string MySQLJobProvider::escape_string( const std::string& target ) {
if( !conn ) {
- throw "Not connected!";
+ throw std::runtime_error("Not connected!");
}
std::string result;
void MySQLJobProvider::finishJob( std::shared_ptr<Job> job ) {
if( !conn ) {
- throw "Not connected!";
+ throw std::runtime_error("Not connected!");
}
std::string q = "UPDATE jobs SET state='done' WHERE id='" + this->escape_string( job->id ) + "' LIMIT 1";
if( query( q ).first ) {
- throw "No database entry found.";
+ throw std::runtime_error("No database entry found.");
}
}
void MySQLJobProvider::failJob( std::shared_ptr<Job> job ) {
if( !conn ) {
- throw "Not connected!";
+ throw std::runtime_error("Not connected!");
}
std::string q = "UPDATE jobs SET warning = warning + 1 WHERE id='" + this->escape_string( job->id ) + "' LIMIT 1";
if( query( q ).first ) {
- throw "No database entry found.";
+ throw std::runtime_error("No database entry found.");
}
}
void MySQLJobProvider::writeBack( std::shared_ptr<Job> job, std::shared_ptr<SignedCertificate> res ) {
if( !conn ) {
- throw "Error while writing back";
+ throw std::runtime_error("Error while writing back");
}
std::string id = "SELECT id FROM cacerts WHERE keyname='" + this->escape_string( res->ca_name ) + "'";
std::tie( err, resu ) = query( id );
if( err ) {
- throw "Error while looking ca cert id";
+ throw std::runtime_error("Error while looking ca cert id");
}
MYSQL_ROW row = mysql_fetch_row( resu.get() );
std::string read_id;
if( !row || !l ) {
- throw "Error while inserting new ca cert not found";
+ throw std::runtime_error("Error while inserting new ca cert not found");
} else {
read_id = std::string( row[0], row[0] + l[0] );
}
// TODO write more thingies back
if( query( q ).first ) {
- throw "Error while writing back";
+ throw std::runtime_error("Error while writing back");
}
}
std::tie( err, resu ) = query( q );
if( err ) {
- throw "Error while looking ca cert id";
+ throw std::runtime_error("Error while looking ca cert id");
}
MYSQL_ROW row = mysql_fetch_row( resu.get() );
unsigned long* l = mysql_fetch_lengths( resu.get() );
if( !row || !l ) {
- throw "Error while inserting new ca cert";
+ throw std::runtime_error("Error while inserting new ca cert");
}
return std::pair<std::string, std::string>( std::string( row[0], row[0] + l[0] ), std::string( row[1], row[1] + l[1] ) );
void MySQLJobProvider::writeBackRevocation( std::shared_ptr<Job> job, std::string date ) {
if( query( "UPDATE certs SET revoked = '" + this->escape_string( date ) + "' WHERE id = '" + this->escape_string( job->target ) + "'" ).first ) {
- throw "Error while writing back revocation";
+ throw std::runtime_error("Error while writing back revocation");
}
}
#include <iostream>
#include <log/logger.hpp>
+#include <exception>
PostgresJobProvider::PostgresJobProvider( const std::string& server, const std::string& user, const std::string& password, const std::string& database ):
c("dbname="+database+" host="+server+" user="+user+" password=" + password + " client_encoding=UTF-8 application_name=cassiopeia-client"){
pqxx::result r = txn.exec(q);
if( r.affected_rows() != 1 ) {
- throw "No database entry found.";
+ throw std::runtime_error("No database entry found.");
}
txn.commit();
}
pqxx::result r = txn.exec(q);
if( r.affected_rows() != 1 ) {
- throw "No database entry found.";
+ throw std::runtime_error("No database entry found.");
}
txn.commit();
}
pqxx::result r = txn.exec(q);
if( r.size() != 1 ) {
- throw "Error, no or multiple certs found";
+ throw std::runtime_error("Error, no or multiple certs found");
}
auto ro = r[0];
std::string read_id;
if( r.size() != 1) {
- throw "Error while inserting new ca cert not found";
+ throw std::runtime_error("Error while inserting new ca cert not found");
} else {
read_id = r[0]["id"].as<std::string>();
}
r = txn.exec( q );
if( r.affected_rows() != 1 ){
- throw "Only one row should be updated.";
+ throw std::runtime_error("Only one row should be updated.");
}
txn.commit();
}
pqxx::result r = txn.exec( q );
if( r.size() != 1) {
- throw "Only one row expected but multiple found.";
+ throw std::runtime_error("Only one row expected but multiple found.");
}
logger::errorf( "executing" );
pqxx::result r = txn.exec( "UPDATE certs SET revoked = " + txn.quote( pgTime( date ) ) + " WHERE id = " + txn.quote( job->target ) );
if( r.affected_rows() != 1 ){
- throw "Only one row should be updated.";
+ throw std::runtime_error("Only one row should be updated.");
}
logger::errorf( "committing" );
txn.commit();
#include "opensslBIO.h"
+#include <log/logger.hpp>
OpensslBIOWrapper::OpensslBIOWrapper( std::shared_ptr<BIO> _b ) : b( _b ), buffer( 2*0xFFFF+20, 0 ), pos(0) {
}
const char* OpensslBIOWrapper::getName() {
return "OpenSSLWrapper";
}
-#include <log/logger.hpp>
std::string OpensslBIOWrapper::readLine(){
int target = 0;
while(1){
- logger::warn("doing data");
+ logger::debug("doing data");
while(target < pos){
if(buffer[target] == '\n'){
target++;
std::string res(buffer.data(), 0, target);
std::copy(buffer.data() + target, buffer.data() + pos, buffer.data() );
pos -= target;
- logger::warn("emit");
+ logger::debug("emit");
return res;
}
target++;
}
std::stringstream ss;
ss << "target: " << target << ", pos:" << pos;
- logger::warn(ss.str());
+ logger::debug(ss.str());
int dlen = read(buffer.data() + pos, buffer.size() - pos);
if ( dlen <= 0 ){
- logger::warn(" error! ");
- throw EOFException();
+ throw eof_exception();
}
std::stringstream ss2;
ss2 << "done: " << dlen;
- logger::warn(ss2.str());
+ logger::debug(ss2.str());
pos += dlen;
}
}
std::string readLine();
};
-class EOFException : public std::exception{
+class eof_exception : public std::exception{
};
std::stringstream ss;
ss << "Expected: " << expectedTotalLength << ", Got: " << input.size();
logger::error( ss.str() );
- throw "Error, invalid length";
+ throw std::length_error("Error, invalid length");
}
if( checksum != -1 || error || dlen < RECORD_HEADER_SIZE ) {
- throw "Error, invalid checksum";
+ throw std::runtime_error("Error, invalid checksum");
}
data.pop_back();
#include <memory>
#include <string>
-
+#include <exception>
#include "bios.h"
#include "io/opensslBIO.h"
void unpackFromString( const std::string& str ) {
if( str.size() != RECORD_HEADER_SIZE ) {
- throw "Invalid string length";
+ throw std::runtime_error("Invalid string length");
}
auto it = str.cbegin();
RecordHeader head;
std::string all = parseCommandChunked( head, io );
execute( static_cast<RecordHeader::SignerCommand>( head.command ), all );
- } catch( const char* msg ) {
- logger::error( "ERROR: ", msg );
+ } catch( const std::exception& msg ) {
+ logger::error( "ERROR: ", msg.what() );
parent->reset();
return;
}
break;
default:
- throw "Unimplemented";
+ throw std::runtime_error("Unimplemented");
}
}
};
}
try {
currentSession->work();
- } catch( EOFException e ){
+ } catch( eof_exception e ){
reset();
}
}
#include "slipBio.h"
#include <unistd.h>
-
+#include <exception>
#include <iostream>
#include "log/logger.hpp"
#endif
if( dlen < 0 ) {
- throw "Error, target write failed";
+ throw std::runtime_error("Error, target write failed");
} else if( dlen == 0 ) {
// sleep
logger::note( "waiting for write ability" );
auto res = std::make_unique<std::ofstream>( tname );
if( ! res->good() ) {
- throw std::string( "Failed to open file for logging: " ) + name;
+ throw std::runtime_error( std::string("Failed to open file for logging: " ) + name );
}
return res;