7 #include <mysql/errmsg.h>
9 //This static variable exists to handle initializing and finalizing the MySQL driver library
10 std::shared_ptr<int> MySQLJobProvider::lib_ref(
11 //Initializer: Store the return code as a pointer to an integer
12 new int( mysql_library_init( 0, NULL, NULL ) ),
13 //Finalizer: Check the pointer and free resources
16 //The library is not initialized
21 //The library did return an error when initializing
31 MySQLJobProvider::MySQLJobProvider( const std::string& server, const std::string& user, const std::string& password, const std::string& database ) {
32 if( !lib_ref || *lib_ref ) {
33 throw "MySQL library not initialized!";
36 connect( server, user, password, database );
39 MySQLJobProvider::~MySQLJobProvider() {
43 bool MySQLJobProvider::connect( const std::string& server, const std::string& user, const std::string& password, const std::string& database ) {
52 conn = _connect( server, user, password, database );
57 std::shared_ptr<MYSQL> MySQLJobProvider::_connect( const std::string& server, const std::string& user, const std::string& password, const std::string& database ) {
58 MYSQL* tmp( mysql_init( NULL ) );
61 return std::shared_ptr<MYSQL>();
64 tmp = mysql_real_connect( tmp, server.c_str(), user.c_str(), password.c_str(), database.c_str(), 3306, NULL, CLIENT_COMPRESS );
67 return std::shared_ptr<MYSQL>();
71 return std::shared_ptr<MYSQL>(
80 bool MySQLJobProvider::disconnect() {
90 std::pair< int, std::shared_ptr<MYSQL_RES> > MySQLJobProvider::query( const std::string& query ) {
92 return std::make_pair( CR_SERVER_LOST, std::shared_ptr<MYSQL_RES>() );
95 int err = mysql_real_query( this->conn.get(), query.c_str(), query.size() );
98 throw std::string( "MySQL error: " ) + mysql_error( this->conn.get() );
102 std::shared_ptr<MYSQL_RES> res(
103 mysql_store_result( conn.get() ),
104 [c]( MYSQL_RES * r ) {
109 mysql_free_result( r );
112 return std::make_pair( err, res );
115 std::shared_ptr<Job> MySQLJobProvider::fetchJob() {
116 std::string q = "SELECT id, targetId, task, executeFrom, executeTo, warning FROM jobs WHERE state='open' AND warning < 3";
119 std::shared_ptr<MYSQL_RES> res;
121 std::tie( err, res ) = query( q );
124 return std::shared_ptr<Job>();
127 unsigned int num = mysql_num_fields( res.get() );
129 MYSQL_ROW row = mysql_fetch_row( res.get() );
132 return std::shared_ptr<Job>();
135 std::shared_ptr<Job> job( new Job() );
137 unsigned long* l = mysql_fetch_lengths( res.get() );
140 return std::shared_ptr<Job>();
143 job->id = std::string( row[0], row[0] + l[0] );
144 job->target = std::string( row[1], row[1] + l[1] );
145 job->task = std::string( row[2], row[2] + l[2] );
146 job->from = std::string( row[3], row[3] + l[3] );
147 job->to = std::string( row[4], row[4] + l[4] );
148 job->warning = std::string( row[5], row[5] + l[5] );
150 for( unsigned int i = 0; i < num; i++ ) {
151 printf( "[%.*s] ", ( int ) l[i], row[i] ? row[i] : "NULL" );
159 std::string MySQLJobProvider::escape_string( const std::string& target ) {
161 throw "Not connected!";
166 result.resize( target.size() * 2 );
168 long unsigned int len = mysql_real_escape_string( conn.get(), const_cast<char*>( result.data() ), target.c_str(), target.size() );
170 result.resize( len );
175 void MySQLJobProvider::finishJob( std::shared_ptr<Job> job ) {
177 throw "Not connected!";
180 std::string q = "UPDATE jobs SET state='done' WHERE id='" + this->escape_string( job->id ) + "' LIMIT 1";
182 if( query( q ).first ) {
183 throw "No database entry found.";
188 void MySQLJobProvider::failJob( std::shared_ptr<Job> job ) {
190 throw "Not connected!";
193 std::string q = "UPDATE jobs SET warning = warning + 1 WHERE id='" + this->escape_string( job->id ) + "' LIMIT 1";
195 if( query( q ).first ) {
196 throw "No database entry found.";
200 std::shared_ptr<TBSCertificate> MySQLJobProvider::fetchTBSCert( std::shared_ptr<Job> job ) {
201 std::shared_ptr<TBSCertificate> cert = std::shared_ptr<TBSCertificate>( new TBSCertificate() );
202 std::string q = "SELECT md, profile, csr_name, csr_type FROM certs WHERE id='" + this->escape_string( job->target ) + "'";
206 std::shared_ptr<MYSQL_RES> res;
208 std::tie( err, res ) = query( q );
211 return std::shared_ptr<TBSCertificate>();
214 MYSQL_ROW row = mysql_fetch_row( res.get() );
217 return std::shared_ptr<TBSCertificate>();
220 unsigned long* l = mysql_fetch_lengths( res.get() );
223 return std::shared_ptr<TBSCertificate>();
226 cert->md = std::string( row[0], row[0] + l[0] );
227 cert->profile = std::string( row[1], row[1] + l[1] );
228 cert->csr = std::string( row[2], row[2] + l[2] );
229 cert->csr_type = std::string( row[3], row[3] + l[3] );
231 cert->SANs = std::vector<std::shared_ptr<SAN>>();
233 q = "SELECT contents, type FROM subjectAlternativeNames WHERE certId='" + this->escape_string( job->target ) + "'";
234 std::tie( err, res ) = query( q );
237 std::cout << mysql_error( this->conn.get() );
238 return std::shared_ptr<TBSCertificate>();
241 std::cout << "Fetching SANs" << std::endl;
243 while( ( row = mysql_fetch_row( res.get() ) ) ) {
244 unsigned long* l = mysql_fetch_lengths( res.get() );
247 return std::shared_ptr<TBSCertificate>();
250 std::shared_ptr<SAN> nSAN = std::shared_ptr<SAN>( new SAN() );
251 nSAN->content = std::string( row[0], row[0] + l[0] );
252 nSAN->type = std::string( row[1], row[1] + l[1] );
253 cert->SANs.push_back( nSAN );
256 q = "SELECT name, value FROM certAvas WHERE certid='" + this->escape_string( job->target ) + "'";
257 std::tie( err, res ) = query( q );
260 std::cout << mysql_error( this->conn.get() );
261 return std::shared_ptr<TBSCertificate>();
265 while( ( row = mysql_fetch_row( res.get() ) ) ) {
266 unsigned long* l = mysql_fetch_lengths( res.get() );
269 return std::shared_ptr<TBSCertificate>();
272 std::shared_ptr<AVA> nAVA = std::shared_ptr<AVA>( new AVA() );
273 nAVA->name = std::string( row[0], row[0] + l[0] );
274 nAVA->value = std::string( row[1], row[1] + l[1] );
275 cert->AVAs.push_back( nAVA );
281 void MySQLJobProvider::writeBack( std::shared_ptr<Job> job, std::shared_ptr<SignedCertificate> res ) {
283 throw "Error while writing back";
286 std::string q = "UPDATE certs SET crt_name='" + this->escape_string( res->crt_name ) + "', serial='" + this->escape_string( res->serial ) + "', created=NOW() WHERE id='" + this->escape_string( job->target ) + "' LIMIT 1";
288 // TODO write more thingies back
290 if( query( q ).first ) {
291 throw "Error while writing back";