diff options
Diffstat (limited to 'src/modules')
-rw-r--r-- | src/modules/UserBackendMysql/UserBackendMysql.cpp | 111 | ||||
-rw-r--r-- | src/modules/UserBackendMysql/UserBackendMysql.h | 51 |
2 files changed, 130 insertions, 32 deletions
diff --git a/src/modules/UserBackendMysql/UserBackendMysql.cpp b/src/modules/UserBackendMysql/UserBackendMysql.cpp index 82258e8..0619409 100644 --- a/src/modules/UserBackendMysql/UserBackendMysql.cpp +++ b/src/modules/UserBackendMysql/UserBackendMysql.cpp @@ -30,6 +30,8 @@ #include <boost/regex.hpp> #include <boost/thread/locks.hpp> +#include <mysql/mysqld_error.h> + namespace Mad { namespace Modules { namespace UserBackendMysql { @@ -110,6 +112,10 @@ bool UserBackendMysql::handleConfigEntry(const Core::ConfigEntry &entry, bool ha if(entry[3].empty()) queryUserGroupTable = entry[2][0]; } + else if(entry[2].getKey().matches("AddUser")) { + if(entry[3].empty()) + queryAddUser = entry[2][0]; + } else if(!entry[2].empty()) return false; } @@ -150,16 +156,16 @@ boost::shared_ptr<const std::map<unsigned long, Common::UserInfo> > UserBackendM throw Core::Exception(Core::Exception::NOT_AVAILABLE); mysql_real_query(mysql, queryListUsers.c_str(), queryListUsers.length()); - MYSQL_RES *result = mysql_store_result(mysql); + Result result(mysql); lock.unlock(); - if(!result || mysql_num_fields(result) < 4) + if(!result || result.getErrno() || result.getFieldNumber() < 4) throw Core::Exception(Core::Exception::NOT_AVAILABLE); boost::shared_ptr<std::map<unsigned long, Common::UserInfo> > users(new std::map<unsigned long, Common::UserInfo>()); - while(MYSQL_ROW row = mysql_fetch_row(result)) { + while(MYSQL_ROW row = result.getNextRow()) { Common::UserInfo user(strtoul(row[0], 0, 10), row[2]); user.setGid(strtoul(row[1], 0, 10)); @@ -196,14 +202,14 @@ boost::shared_ptr<const Common::UserInfo> UserBackendMysql::getUserInfo(unsigned query = boost::regex_replace(query, boost::regex("\\{UID\\}"), tmp.str(), boost::match_default); mysql_real_query(mysql, query.c_str(), query.length()); - MYSQL_RES *result = mysql_store_result(mysql); + Result result(mysql); lock.unlock(); - if(!result || mysql_num_fields(result) < 4) + if(!result || result.getErrno() || result.getFieldNumber() < 4) throw Core::Exception(Core::Exception::NOT_AVAILABLE); - MYSQL_ROW row = mysql_fetch_row(result); + MYSQL_ROW row = result.getNextRow(); if(row) { boost::shared_ptr<Common::UserInfo> user(new Common::UserInfo(strtoul(row[0], 0, 10), row[2])); @@ -211,8 +217,6 @@ boost::shared_ptr<const Common::UserInfo> UserBackendMysql::getUserInfo(unsigned user->setGid(strtoul(row[1], 0, 10)); user->setFullName(row[3]); - while((row = mysql_fetch_row(result)) != 0) {} - return user; } @@ -241,14 +245,14 @@ boost::shared_ptr<const Common::UserInfo> UserBackendMysql::getUserInfoByName(co std::string query = boost::regex_replace(queryUserByName, boost::regex("\\{USER\\}"), "\""+std::string(escapedName.get())+"\"", boost::match_default); mysql_real_query(mysql, query.c_str(), query.length()); - MYSQL_RES *result = mysql_store_result(mysql); + Result result(mysql); lock.unlock(); - if(!result || mysql_num_fields(result) < 4) + if(!result || result.getErrno() || result.getFieldNumber() < 4) throw Core::Exception(Core::Exception::NOT_AVAILABLE); - MYSQL_ROW row = mysql_fetch_row(result); + MYSQL_ROW row = result.getNextRow(); if(row) { boost::shared_ptr<Common::UserInfo> user(new Common::UserInfo(strtoul(row[0], 0, 10), row[2])); @@ -256,8 +260,6 @@ boost::shared_ptr<const Common::UserInfo> UserBackendMysql::getUserInfoByName(co user->setGid(strtoul(row[1], 0, 10)); user->setFullName(row[3]); - while((row = mysql_fetch_row(result)) != 0) {} - return user; } @@ -287,16 +289,16 @@ boost::shared_ptr<const std::set<unsigned long> > UserBackendMysql::getUserGroup std::string query = boost::regex_replace(queryListUserGroups, boost::regex("\\{UID\\}"), tmp.str(), boost::match_default); mysql_real_query(mysql, query.c_str(), query.length()); - MYSQL_RES *result = mysql_store_result(mysql); + Result result(mysql); lock.unlock(); - if(!result || mysql_num_fields(result) < 1) + if(!result || result.getErrno() || result.getFieldNumber() < 1) throw Core::Exception(Core::Exception::NOT_AVAILABLE); boost::shared_ptr<std::set<unsigned long> > groups(new std::set<unsigned long>); - while(MYSQL_ROW row = mysql_fetch_row(result)) + while(MYSQL_ROW row = result.getNextRow()) groups->insert(strtoul(row[0], 0, 10)); return groups; @@ -319,16 +321,16 @@ boost::shared_ptr<const std::map<unsigned long, Common::GroupInfo> > UserBackend throw Core::Exception(Core::Exception::NOT_AVAILABLE); mysql_real_query(mysql, queryListGroups.c_str(), queryListGroups.length()); - MYSQL_RES *result = mysql_store_result(mysql); + Result result(mysql); lock.unlock(); - if(!result || mysql_num_fields(result) < 2) + if(!result || result.getErrno() || result.getFieldNumber() < 2) throw Core::Exception(Core::Exception::NOT_AVAILABLE); boost::shared_ptr<std::map<unsigned long, Common::GroupInfo> > groups(new std::map<unsigned long, Common::GroupInfo>()); - while(MYSQL_ROW row = mysql_fetch_row(result)) { + while(MYSQL_ROW row = result.getNextRow()) { Common::GroupInfo group(strtoul(row[0], 0, 10), row[1]); groups->insert(std::make_pair(group.getGid(), group)); @@ -362,14 +364,14 @@ boost::shared_ptr<const Common::GroupInfo> UserBackendMysql::getGroupInfo(unsign query = boost::regex_replace(query, boost::regex("\\{GID\\}"), tmp.str(), boost::match_default); mysql_real_query(mysql, query.c_str(), query.length()); - MYSQL_RES *result = mysql_store_result(mysql); + Result result(mysql); lock.unlock(); - if(!result || mysql_num_fields(result) < 2) + if(!result || result.getErrno() || result.getFieldNumber() < 2) throw Core::Exception(Core::Exception::NOT_AVAILABLE); - MYSQL_ROW row = mysql_fetch_row(result); + MYSQL_ROW row = result.getNextRow(); if(row) return boost::shared_ptr<Common::GroupInfo>(new Common::GroupInfo(strtoul(row[0], 0, 10), row[1])); @@ -399,14 +401,14 @@ boost::shared_ptr<const Common::GroupInfo> UserBackendMysql::getGroupInfoByName( std::string query = boost::regex_replace(queryGroupByName, boost::regex("\\{GROUP\\}"), "\""+std::string(escapedName.get())+"\"", boost::match_default); mysql_real_query(mysql, query.c_str(), query.length()); - MYSQL_RES *result = mysql_store_result(mysql); + Result result(mysql); lock.unlock(); - if(!result || mysql_num_fields(result) < 2) + if(!result || result.getErrno() || result.getFieldNumber() < 2) throw Core::Exception(Core::Exception::NOT_AVAILABLE); - MYSQL_ROW row = mysql_fetch_row(result); + MYSQL_ROW row = result.getNextRow(); if(row) return boost::shared_ptr<Common::GroupInfo>(new Common::GroupInfo(strtoul(row[0], 0, 10), row[1])); @@ -437,16 +439,16 @@ boost::shared_ptr<const std::set<unsigned long> > UserBackendMysql::getGroupUser std::string query = boost::regex_replace(queryListGroupUsers, boost::regex("\\{GID\\}"), tmp.str(), boost::match_default); mysql_real_query(mysql, query.c_str(), query.length()); - MYSQL_RES *result = mysql_store_result(mysql); + Result result(mysql); lock.unlock(); - if(!result || mysql_num_fields(result) < 1) + if(!result || result.getErrno() || result.getFieldNumber() < 1) throw Core::Exception(Core::Exception::NOT_AVAILABLE); boost::shared_ptr<std::set<unsigned long> > users(new std::set<unsigned long>); - while(MYSQL_ROW row = mysql_fetch_row(result)) + while(MYSQL_ROW row = result.getNextRow()) users->insert(strtoul(row[0], 0, 10)); return users; @@ -468,21 +470,68 @@ boost::shared_ptr<const std::multimap<unsigned long, unsigned long> > UserBacken throw Core::Exception(Core::Exception::NOT_AVAILABLE); mysql_real_query(mysql, queryUserGroupTable.c_str(), queryUserGroupTable.length()); - MYSQL_RES *result = mysql_store_result(mysql); + Result result(mysql); lock.unlock(); - if(!result || mysql_num_fields(result) < 2) + if(!result || result.getErrno() || result.getFieldNumber() < 2) throw Core::Exception(Core::Exception::NOT_AVAILABLE); boost::shared_ptr<std::multimap<unsigned long, unsigned long> > usergroups(new std::multimap<unsigned long, unsigned long>); - while(MYSQL_ROW row = mysql_fetch_row(result)) + while(MYSQL_ROW row = result.getNextRow()) usergroups->insert(std::make_pair(strtoul(row[0], 0, 10), strtoul(row[1], 0, 10))); return usergroups; } +void UserBackendMysql::addUser(const Common::UserInfo &userInfo) throw(Core::Exception) { + application->getThreadManager()->detach(); + + boost::lock_guard<boost::mutex> lock(mutex); + + if(!mysql || mysql_ping(mysql)) + throw Core::Exception(Core::Exception::NOT_AVAILABLE); + + std::ostringstream tmp; + tmp << '"'; + tmp << userInfo.getUid(); + tmp << '"'; + + std::string query = boost::regex_replace(queryAddUser, boost::regex("\\{UID\\}"), tmp.str(), boost::match_default); + + tmp.str(std::string()); + tmp << '"'; + tmp << userInfo.getGid(); + tmp << '"'; + + query = boost::regex_replace(query, boost::regex("\\{GID\\}"), tmp.str(), boost::match_default); + + const std::string &username = userInfo.getUsername(); + boost::scoped_array<char> escapedUsername(new char[username.length()*2+1]); + mysql_real_escape_string(mysql, escapedUsername.get(), username.c_str(), username.length()); + + query = boost::regex_replace(query, boost::regex("\\{USER\\}"), "\"" + std::string(escapedUsername.get()) + "\"", boost::match_default); + + const std::string &fullName = userInfo.getFullName(); + boost::scoped_array<char> escapedFullName(new char[fullName.length()*2+1]); + mysql_real_escape_string(mysql, escapedFullName.get(), fullName.c_str(), fullName.length()); + + query = boost::regex_replace(query, boost::regex("\\{FULL_NAME\\}"), "\"" + std::string(escapedFullName.get()) + "\"", boost::match_default); + + mysql_real_query(mysql, query.c_str(), query.length()); + Result result(mysql); + + if(result.getErrno()) { + if(result.getErrno() == ER_DUP_ENTRY) + throw Core::Exception(Core::Exception::DUPLICATE_ENTRY); + else + throw Core::Exception(Core::Exception::NOT_AVAILABLE); + } + + lastUpdate = boost::posix_time::microsec_clock::universal_time(); +} + } } } diff --git a/src/modules/UserBackendMysql/UserBackendMysql.h b/src/modules/UserBackendMysql/UserBackendMysql.h index 52a134a..25c3837 100644 --- a/src/modules/UserBackendMysql/UserBackendMysql.h +++ b/src/modules/UserBackendMysql/UserBackendMysql.h @@ -34,8 +34,54 @@ namespace Mad { namespace Modules { namespace UserBackendMysql { -class UserBackendMysql : public Common::UserBackend, private Core::Configurable { +class UserBackendMysql : public Common::UserBackend, private Core::Configurable, private boost::noncopyable { private: + class Result : private boost::noncopyable { + private: + MYSQL_RES *result; + + unsigned int mysqlErrno; + const char *error; + + public: + Result(MYSQL *mysql) { + result = mysql_store_result(mysql); + + mysqlErrno = mysql_errno(mysql); + error = mysql_error(mysql); + } + + ~Result() { + if(result) { + mysql_free_result(result); + } + } + + operator bool() const { + return result; + } + + unsigned int getErrno() const { + return mysqlErrno; + } + + const char* getError() const { + return error; + } + + unsigned int getFieldNumber() const { + return mysql_num_fields(result); + } + + my_ulonglong getRowNumber() const { + return mysql_num_rows(result); + } + + MYSQL_ROW getNextRow() { + return mysql_fetch_row(result); + } + }; + Common::Application *application; std::string host, username, passwd, db, unixSocket; @@ -46,6 +92,7 @@ class UserBackendMysql : public Common::UserBackend, private Core::Configurable std::string queryUserById, queryUserByName; std::string queryGroupById, queryGroupByName; std::string queryUserGroupTable; + std::string queryAddUser; MYSQL *mysql; @@ -69,6 +116,8 @@ class UserBackendMysql : public Common::UserBackend, private Core::Configurable virtual boost::shared_ptr<const std::multimap<unsigned long, unsigned long> > getFullUserGroupList(boost::posix_time::ptime *timestamp) throw(Core::Exception); + virtual void addUser(const Common::UserInfo &userInfo) throw(Core::Exception); + public: UserBackendMysql(Common::Application *application0) : application(application0), port(0), mysql(0), lastUpdate(boost::posix_time::microsec_clock::universal_time()) { application->getConfigManager()->registerConfigurable(this); |