]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/modules/extra/m_sql.cpp
Corrected library paths in $CompileFlags
[user/henk/code/inspircd.git] / src / modules / extra / m_sql.cpp
1 /*       +------------------------------------+
2  *       | Inspire Internet Relay Chat Daemon |
3  *       +------------------------------------+
4  *
5  *  Inspire is copyright (C) 2002-2004 ChatSpike-Dev.
6  *                       E-mail:
7  *                <brain@chatspike.net>
8  *                <Craig@chatspike.net>
9  *     
10  * Written by Craig Edwards, Craig McLure, and others.
11  * This program is free but copyrighted software; see
12  *            the file COPYING for details.
13  *
14  * ---------------------------------------------------
15  */
16
17
18 #include <stdio.h>
19 #include <string>
20 #include <mysql/mysql.h>
21 #include "users.h"
22 #include "channels.h"
23 #include "modules.h"
24
25 /* $ModDesc: m_filter with regexps */
26 /* $CompileFlags: -I/usr/local/include -I/usr/include -L/usr/local/lib/mysql -L/usr/lib/mysql -lmysqlclient */
27
28 /** SQLConnection represents one mysql session.
29  * Each session has its own persistent connection to the database.
30  */
31 class SQLConnection
32 {
33  protected:
34
35         MYSQL connection;
36         MYSQL_RES *res;
37         MYSQL_ROW row;
38         std::string host;
39         std::string user;
40         std::string pass;
41         std::string db;
42         std::map<std::string,std::string> thisrow;
43         bool Enabled;
44         long id;
45
46  public:
47
48         // This constructor creates an SQLConnection object with the given credentials, and creates the underlying
49         // MYSQL struct, but does not connect yet.
50         SQLConnection(std::string thishost, std::string thisuser, std::string thispass, std::string thisdb, long myid)
51         {
52                 this->Enabled = true;
53                 this->host = thishost;
54                 this->user = thisuser;
55                 this->pass = thispass;
56                 this->db = thisdb;
57                 this->id = myid;
58                 mysql_init(&connection);
59         }
60
61         // This method connects to the database using the credentials supplied to the constructor, and returns
62         // true upon success.
63         bool Connect()
64         {
65                 return mysql_real_connect(&connection, host.c_str(), user.c_str(), pass.c_str(), db.c_str(), 0, NULL, 0);
66         }
67
68         // This method issues a query that expects multiple rows of results. Use GetRow() and QueryDone() to retrieve
69         // multiple rows.
70         bool QueryResult(std::string query)
71         {
72                 char escaped_query[query.length()+1];
73                 mysql_real_escape_string(&connection, escaped_query, query.c_str(), query.length());
74                 int r = mysql_query(&connection, escaped_query);
75                 if (!r)
76                 {
77                         res = mysql_use_result(&connection);
78                 }
79                 return (!r);
80         }
81
82         // This method issues a query that just expects a number of 'effected' rows (e.g. UPDATE or DELETE FROM).
83         // the number of effected rows is returned in the return value.
84         unsigned long QueryCount(std::string query)
85         {
86                 char escaped_query[query.length()+1];
87                 mysql_real_escape_string(&connection, escaped_query, query.c_str(), query.length());
88                 int r = mysql_query(&connection, escaped_query);
89                 if (!r)
90                 {
91                         res = mysql_store_result(&connection);
92                         unsigned long rows = mysql_affected_rows(&connection);
93                         mysql_free_result(res);
94                         return rows;
95                 }
96                 return 0;
97         }
98
99         // This method fetches a row, if available from the database. You must issue a query
100         // using QueryResult() first! The row's values are returned as a map of std::string
101         // where each item is keyed by the column name.
102         std::map<std::string,std::string> GetRow()
103         {
104                 thisrow.clear();
105                 if (res)
106                 {
107                         row = mysql_fetch_row(res);
108                         if (row)
109                         {
110                                 unsigned int field_count = 0;
111                                 if(mysql_field_count(&connection) == 0)
112                                         return thisrow;
113                                 MYSQL_FIELD *fields = mysql_fetch_fields(res);
114                                 while (field_count < mysql_field_count(&connection))
115                                 {
116                                         thisrow[std::string(fields[field_count].name)] = std::string(row[field_count]);
117                                         field_count++;
118                                 }
119                                 return thisrow;
120                         }
121                 }
122                 return thisrow;
123         }
124
125         bool QueryDone()
126         {
127                 if (res)
128                 {
129                         mysql_free_result(res);
130                         return true;
131                 }
132                 else return false;
133         }
134
135         std::string GetError()
136         {
137                 return mysql_error(&connection);
138         }
139
140         long GetID()
141         {
142                 return id;
143         }
144
145         std::string GetHost()
146         {
147                 return host;
148         }
149
150         void Enable()
151         {
152                 Enabled = true;
153         }
154
155         void Disable()
156         {
157                 Enabled = false;
158         }
159
160         bool IsEnabled()
161         {
162                 return Enabled;
163         }
164
165         ~SQLConnection()
166         {
167                 mysql_close(&connection);
168         }
169 };
170
171 typedef std::vector<SQLConnection> ConnectionList;
172
173 class ModuleSQL : public Module
174 {
175         Server *Srv;
176         ConfigReader *Conf;
177         ConnectionList Connections;
178  
179  public:
180         void ConnectDatabases()
181         {
182                 for (ConnectionList::iterator i = Connections.begin(); i != Connections.end(); i++)
183                 {
184                         i->Enable();
185                         if (i->Connect())
186                         {
187                                 Srv->Log(DEFAULT,"SQL: Successfully connected database "+i->GetHost());
188                         }
189                         else
190                         {
191                                 Srv->Log(DEFAULT,"SQL: Failed to connect database "+i->GetHost()+": Error: "+i->GetError());
192                                 i->Disable();
193                         }
194                 }
195         }
196
197         void LoadDatabases(ConfigReader* Conf)
198         {
199                 Srv->Log(DEFAULT,"SQL: Loading database settings");
200                 Connections.clear();
201                 for (int j =0; j < Conf->Enumerate("database"); j++)
202                 {
203                         std::string db = Conf->ReadValue("database","name",j);
204                         std::string user = Conf->ReadValue("database","username",j);
205                         std::string pass = Conf->ReadValue("database","password",j);
206                         std::string host = Conf->ReadValue("database","hostname",j);
207                         std::string id = Conf->ReadValue("database","id",j);
208                         if ((db != "") && (host != "") && (user != "") && (id != "") && (pass != ""))
209                         {
210                                 SQLConnection ThisSQL(host,user,pass,db,atoi(id.c_str()));
211                                 Srv->Log(DEFAULT,"Loaded database: "+ThisSQL.GetHost());
212                                 Connections.push_back(ThisSQL);
213                         }
214                 }
215                 ConnectDatabases();
216         }
217
218         ModuleSQL()
219         {
220                 Srv = new Server();
221                 Conf = new ConfigReader();
222                 LoadDatabases(Conf);
223         }
224         
225         virtual ~ModuleSQL()
226         {
227                 Connections.clear();
228                 delete Conf;
229                 delete Srv;
230         }
231         
232         virtual void OnRehash()
233         {
234                 delete Conf;
235                 Conf = new ConfigReader();
236                 LoadDatabases(Conf);
237         }
238         
239         virtual Version GetVersion()
240         {
241                 return Version(1,0,0,0,VF_VENDOR|VF_SERVICEPROVIDER);
242         }
243         
244 };
245
246 // stuff down here is the module-factory stuff. For basic modules you can ignore this.
247
248 class ModuleSQLFactory : public ModuleFactory
249 {
250  public:
251         ModuleSQLFactory()
252         {
253         }
254         
255         ~ModuleSQLFactory()
256         {
257         }
258         
259         virtual Module * CreateModule()
260         {
261                 return new ModuleSQL;
262         }
263         
264 };
265
266
267 extern "C" void * init_module( void )
268 {
269         return new ModuleSQLFactory;
270 }
271