diff options
Diffstat (limited to 'src/modules/UserBackendMysql/UserBackendMysql.cpp')
-rw-r--r-- | src/modules/UserBackendMysql/UserBackendMysql.cpp | 233 |
1 files changed, 233 insertions, 0 deletions
diff --git a/src/modules/UserBackendMysql/UserBackendMysql.cpp b/src/modules/UserBackendMysql/UserBackendMysql.cpp new file mode 100644 index 0000000..af25f5b --- /dev/null +++ b/src/modules/UserBackendMysql/UserBackendMysql.cpp @@ -0,0 +1,233 @@ +/* + * UserBackendMysql.cpp + * + * Copyright (C) 2008 Matthias Schiffer <matthias@gamezock.de> + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <config.h> + +#include "UserBackendMysql.h" +#include <Common/ActionManager.h> +#include <Common/ConfigEntry.h> +#include <Common/ConfigManager.h> +#include <Common/Logger.h> + +#include <sstream> + +#include <boost/bind.hpp> +#include <boost/regex.hpp> + +#define init UserBackendMysql_LTX_init +#define deinit UserBackendMysql_LTX_deinit + + +namespace Mad { +namespace Modules { + +UserBackendMysql *UserBackendMysql::backend; + +bool UserBackendMysql::handleConfigEntry(const Common::ConfigEntry &entry, bool handled) { + if(handled) + return false; + + if(entry[0].getKey().matches("UserBackendMysql")) { + if(entry[1].getKey().matches("Host")) { + if(entry[2].empty()) + host = entry[1][0]; + } + else if(entry[1].getKey().matches("Username")) { + if(entry[2].empty()) + username = entry[1][0]; + } + else if(entry[1].getKey().matches("Password")) { + if(entry[2].empty()) + passwd = entry[1][0]; + } + else if(entry[1].getKey().matches("Database")) { + if(entry[2].empty()) + db = entry[1][0]; + } + else if(entry[1].getKey().matches("Port")) { + if(entry[2].empty()) { + char *endptr; + long val; + + val = strtol(entry[1][0].c_str(), &endptr, 10); + + if(endptr != 0 || val < 0 || val > 65535) + Common::Logger::log(Common::Logger::WARNING, "UserBackendMysql: Invalid port"); + else + port = val; + } + } + else if(entry[1].getKey().matches("UnixSocket")) { + if(entry[2].empty()) + unixSocket = entry[1][0]; + } + else if(entry[1].getKey().matches("Queries")) { + if(entry[2].getKey().matches("ListUsers")) { + if(entry[3].empty()) + queryListUsers = entry[2][0]; + } + else if(entry[2].getKey().matches("ListGroups")) { + if(entry[3].empty()) + queryListGroups = entry[2][0]; + } + else if(entry[2].getKey().matches("ListUserGroups")) { + if(entry[3].empty()) + queryListUserGroups = entry[2][0]; + } + else if(entry[2].getKey().matches("ListGroupUsers")) { + if(entry[3].empty()) + queryListGroupUsers = entry[2][0]; + } + else if(entry[2].getKey().matches("UserById")) { + if(entry[3].empty()) + queryUserById = entry[2][0]; + } + else if(entry[2].getKey().matches("UserByName")) { + if(entry[3].empty()) + queryUserByName = entry[2][0]; + } + else if(entry[2].getKey().matches("GroupById")) { + if(entry[3].empty()) + queryGroupById = entry[2][0]; + } + else if(entry[2].getKey().matches("GroupByName")) { + if(entry[3].empty()) + queryGroupByName = entry[2][0]; + } + else if(!entry[2].empty()) + return false; + } + else if(!entry[1].empty()) + return false; + + return true; + } + + return false; +} + +void UserBackendMysql::configFinished() { + if(db.empty()) { + Common::Logger::log(Common::Logger::ERROR, "UserBackendMysql: No database name given"); + return; + } + + mysql = mysql_init(0); + mysql_real_connect(mysql, host.c_str(), username.c_str(), passwd.c_str(), db.c_str(), port, unixSocket.empty() ? 0 : unixSocket.c_str(), 0); + + Server::UserManager::get()->registerBackend(backend); +} + + +bool UserBackendMysql::getUserList(const boost::function1<void, const std::map<unsigned long, Common::UserInfo>& > &callback) { + mysql_ping(mysql); + + mysql_real_query(mysql, queryListUsers.c_str(), queryListUsers.length()); + MYSQL_RES *result = mysql_use_result(mysql); + + if(mysql_num_fields(result) < 4) + return true; // TODO Error + + std::map<unsigned long, Common::UserInfo> users; + + while(MYSQL_ROW row = mysql_fetch_row(result)) { + Common::UserInfo user(strtoul(row[0], 0, 10), row[2]); + + user.setGid(strtoul(row[1], 0, 10)); + user.setFullName(row[3]); + + users.insert(std::make_pair(user.getUid(), user)); + } + + Common::ActionManager::get()->add(boost::bind(callback, users)); + + return true; +} + +bool UserBackendMysql::getUserInfo(unsigned long uid, const boost::function1<void, const Common::UserInfo&> &callback) { + mysql_ping(mysql); + + std::string query = queryUserById; + + std::ostringstream tmp; + tmp << '"'; + tmp << uid; + tmp << '"'; + + query = boost::regex_replace(query, boost::regex("\\{ID\\}"), tmp.str(), boost::match_default); + + mysql_real_query(mysql, query.c_str(), query.length()); + MYSQL_RES *result = mysql_use_result(mysql); + + if(mysql_num_fields(result) < 4) + return true; // TODO Error + + MYSQL_ROW row = mysql_fetch_row(result); + + if(row) { + Common::UserInfo user(strtoul(row[0], 0, 10), row[2]); + + user.setGid(strtoul(row[1], 0, 10)); + user.setFullName(row[3]); + + Common::ActionManager::get()->add(boost::bind(callback, user)); + + while((row = mysql_fetch_row(result)) != 0) {} + } + else { + Common::ActionManager::get()->add(boost::bind(callback, Common::UserInfo())); + } + + return true; +} + + +void UserBackendMysql::registerBackend() { + if(backend) + return; + + backend = new UserBackendMysql(); + Common::ConfigManager::get()->registerConfigurable(backend); +} + +void UserBackendMysql::unregisterBackend() { + if(!backend) + return; + + Common::ConfigManager::get()->unregisterConfigurable(backend); + Server::UserManager::get()->unregisterBackend(backend); + + delete backend; + backend = 0; +} + +} +} + +extern "C" { + +void init() { + Mad::Modules::UserBackendMysql::registerBackend(); +} + +void deinit() { + Mad::Modules::UserBackendMysql::unregisterBackend(); +} + +} |