Opps, did forget the fetch :(
[ctracker.git] / libs / lib_connect.php
1 <?php
2 /**
3  * Database connection library
4  *
5  * @author              Roland Haeder <webmaster@ship-simu.org>
6  * @version             3.0.0
7  * @copyright   Copyright (c) 2009 - 2011 Cracker Tracker Team
8  * @license             GNU GPL 3.0 or any newer version
9  * @link                http://www.ship-simu.org
10  *
11  * This program is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation, either version 3 of the License, or
14  * (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program. If not, see <http://www.gnu.org/licenses/>.
23  */
24
25 // Function to aquire a database link
26 function aquireCrackerTrackerDatabaseLink () {
27         // Is the link up?
28         if ((!isCrackerTrackerDatabaseLinkUp()) && (!empty($GLOBALS['ctracker_host'])) && (!empty($GLOBALS['ctracker_dbname'])) && (!empty($GLOBALS['ctracker_user']))) {
29                 // Then connect to the database
30                 $GLOBALS['ctracker_link'] = mysql_connect($GLOBALS['ctracker_host'], $GLOBALS['ctracker_user'], $GLOBALS['ctracker_password']) or crackerTrackerDatabaseError(__FUNCTION__, __LINE__);
31
32                 // Select the database
33                 if (!mysql_select_db($GLOBALS['ctracker_dbname'], $GLOBALS['ctracker_link'])) {
34                         // Attempt has failed
35                         crackerTrackerDatabaseError(__FUNCTION__, __LINE__);
36                 } elseif (isCrackerTrackerTableCreated('ctracker_config')) {
37                         // Load the config
38                         crackerTrackerLoadConfig();
39                 }
40         } else {
41                 // Init fake config
42                 crackerTrackerInitFakeConfig();
43         }
44 }
45
46 // Inits a fake configurtation
47 function crackerTrackerInitFakeConfig () {
48         // Set the array
49         $GLOBALS['ctracker_config'] = array(
50                 'ctracker_alert_user' => 'Y',
51         );
52 }
53
54 // Checks if the link is up
55 function isCrackerTrackerDatabaseLinkUp () {
56         return ((isset($GLOBALS['ctracker_link'])) && (is_resource($GLOBALS['ctracker_link'])));
57 }
58
59 // Database error detected
60 function crackerTrackerDatabaseError ($F, $L) {
61         // Should we debug?
62         if (isCrackerTrackerDebug()) {
63                 // Output error
64                 print 'Function    : ' . $F . '<br />';
65                 print 'Line        : ' . $L . '<br />';
66                 print 'MySQL error : ' . mysql_error() . '<br />';
67                 print 'Last SQL    : '. $GLOBALS['ctracker_last_sql'] . '<br />';
68         } // END - if
69
70         // Currently only die here
71         crackerTrackerDie();
72 }
73
74 // Closes a maybe open database link
75 function crackerTrackerCloseDatabaseLink () {
76         // Is the link up?
77         if (isCrackerTrackerDatabaseLinkUp()) {
78                 // Did it work?
79                 if (!mysql_close($GLOBALS['ctracker_link'])) {
80                         // Remove all data from global space
81                         unsetCtrackerData();
82
83                         // Attempt has failed
84                         crackerTrackerDatabaseError(__FUNCTION__, __LINE__);
85                 } // END - if
86         } // END - if
87
88         // Remove all data from global space
89         unsetCtrackerData();
90 }
91
92 // Inserts given array, if IP/check_worm combination was not found
93 function crackerTrackerInsertArray ($table, $rowData) {
94         // Is there a link up?
95         if (!isCrackerTrackerDatabaseLinkUp()) {
96                 // Abort silently here
97                 return FALSE;
98         } // END - if
99
100         // Is it found?
101         if (!isCrackerTrackerEntryFound($rowData)) {
102                 // Prepare SQL
103                 $SQL = 'INSERT INTO `' . $table . '` (`' . implode('`,`', array_keys($rowData)) . '`) VALUES(' . implode_secure($rowData) . ')';
104
105                 // Reset insert id
106                 $GLOBALS['ctracker_last_insert_id'] = FALSE;
107
108                 // Run it
109                 runCrackerTrackerSql($SQL, __FUNCTION__, __LINE__);
110
111                 // Remember the last insert id
112                 $GLOBALS['ctracker_last_insert_id'] = mysql_insert_id($GLOBALS['ctracker_link']) or crackerTrackerDatabaseError(__FUNCTION__, __LINE__);
113         } else {
114                 // Only update the entry
115                 updateCrackerTrackerEntry($rowData);
116         }
117 }
118
119 // Updates a given entry by just counting it up
120 function updateCrackerTrackerEntry ($rowData) {
121         // Construct the SELECT query
122         $SQL = 'UPDATE `ctracker_data` SET `count`=`count`+1 WHERE (`remote_addr`="' . crackerTrackerEscapeString($rowData['remote_addr']) . '" OR `proxy_addr`="' . crackerTrackerEscapeString($rowData['proxy_addr']) . '") AND `check_worm` = "' . crackerTrackerEscapeString($rowData['check_worm']) . '" LIMIT 1';
123
124         // Run the SQL and check if we have one line
125         runCrackerTrackerSql($SQL, __FUNCTION__, __LINE__);
126 }
127
128 // Checks if an entry with IP/check_worm/domain combination is there
129 function isCrackerTrackerEntryFound ($rowData) {
130         // Construct the SELECT query
131         $SQL = 'SELECT `id` FROM `ctracker_data` WHERE (`remote_addr`="' . crackerTrackerEscapeString($rowData['remote_addr']) . '" OR `proxy_addr`="' . crackerTrackerEscapeString($rowData['proxy_addr']) . '") AND `check_worm` = "' . crackerTrackerEscapeString($rowData['check_worm']) . '" AND `server_name`="' . crackerTrackerEscapeString($rowData['server_name']) . '" LIMIT 1';
132
133         // Run the SQL and check if we have one line
134         return ((isCrackerTrackerDatabaseLinkUp()) && (mysql_num_rows(runCrackerTrackerSql($SQL, __FUNCTION__, __LINE__)) == 1));
135 }
136
137 // Escapes the string
138 function crackerTrackerEscapeString ($string) {
139         // Is the link up?
140         if (!isCrackerTrackerDatabaseLinkUp()) {
141                 // Then we cant use mysql_real_escape_string!
142                 $string = addslashes($string);
143         } elseif (function_exists('mysql_real_escape_string')) {
144                 // Use mysql_real_escape_string()
145                 $string = mysql_real_escape_string($string, $GLOBALS['ctracker_link']);
146         } elseif (function_exists('mysql_escape_string')) {
147                 // Use deprecated function
148                 $string = mysql_escape_string($string, $GLOBALS['ctracker_link']);
149         } else {
150                 // Use fall-back (bad!)
151                 $string = addslashes($string);
152         }
153
154         // Return the secured string
155         return $string;
156 } // END - if
157
158 // Runs an SQL query and checks for errors
159 function runCrackerTrackerSql ($SQL, $F, $L) {
160         // Is the link up?
161         if (!isCrackerTrackerDatabaseLinkUp()) {
162                 // Abort here
163                 crackerTrackerDie();
164         } // END - if
165
166         // Remember last SQL
167         $GLOBALS['ctracker_last_sql'] = $SQL;
168
169         // Run the query
170         $GLOBALS['ctracker_last_result'] = mysql_query($SQL, $GLOBALS['ctracker_link']) or crackerTrackerDatabaseError(__FUNCTION__, __LINE__);
171
172         // And return it
173         return $GLOBALS['ctracker_last_result'];
174 }
175
176 // Checks wether a table was found
177 function isCrackerTrackerTableCreated ($table) {
178         // Default is not found
179         $found = FALSE;
180
181         // Run the query
182         $result = runCrackerTrackerSql('SHOW TABLES', __FUNCTION__, __LINE__);
183
184         // Is our table there?
185         while (list($tab) = mysql_fetch_row($result)) {
186                 // Is the table there?
187                 if ($tab == $table) {
188                         // Okay, found. So abort
189                         $found = TRUE;
190                         break;
191                 } // END - if
192         } // END - if
193
194         // Free result
195         mysql_free_result($result) or crackerTrackerDatabaseError(__FUNCTION__, __LINE__);
196
197         // Return result
198         return $found;
199 }
200
201 // Creates the given table with columns
202 function crackerTrackerCreateTable ($table, array $columns, array $keys) {
203         // Begin the SQL
204         $SQL = 'CREATE TABLE IF NOT EXISTS `' . $table . '` (';
205
206         // Add table name as first column
207         $SQL .= '`' . $table . '` BIGINT ( 20 ) UNSIGNED NOT NULL AUTO_INCREMENT, ';
208
209         // Add all columns
210         foreach ($columns as $column=>$type) {
211                 // Add this entry
212                 $SQL .= '`' . $column . '` ' . $type . ', ';
213         } // END - foreach
214
215         // Add table name as primary key
216         $SQL .= 'PRIMARY KEY (`' . $table . '`), ';
217
218         // Add keys
219         foreach ($keys as $key=>$type) {
220                 // Add this entry
221                 $SQL .= '' . $type . ' (`' . $key . '`), ';
222         } // END - foreach
223
224         // Finish SQL
225         $SQL = substr($SQL, 0, -2) . ') TYPE=InnoDB';
226
227         // And run it
228         runCrackerTrackerSql($SQL);
229 }
230
231 // Inits a table by inserting 
232 function crackerTrackerInitTable ($table) {
233         // Prepare SQL and run it
234         runCrackerTrackerSql('INSERT INTO `' . $table . '` (`' . $table . '`) VALUES (NULL)');
235 }
236
237 // Updates the database scheme automatically
238 function crackerTrackerUpdateDatabaseScheme () {
239         // Is a link there?
240         if (!isCrackerTrackerDatabaseLinkUp()) {
241                 // Abort here silently
242                 return;
243         } // END - if
244
245         // Is the main config table there?
246         if (!isCrackerTrackerTableCreated('ctracker_config')) {
247                 // Then do it for us
248                 crackerTrackerCreateTable('ctracker_config', array(
249                         'ctracker_db_version' => 'BIGINT ( 20 ) UNSIGNED NOT NULL DEFAULT 0',
250                         'ctracker_min_sleep'  => 'SMALLINT ( 5 ) UNSIGNED NOT NULL DEFAULT 10',
251                         'ctracker_max_sleep'  => 'SMALLINT ( 5 ) UNSIGNED NOT NULL DEFAULT 30',
252                         'ctracker_alert_user' => "ENUM('Y','N') NOT NULL DEFAULT 'Y'",
253                         'ctracker_language'   => "CHAR ( 2) NOT NULL DEFAULT 'en'"
254                 ), array());
255
256                 // Init that table
257                 crackerTrackerInitTable('ctracker_config');
258         } // END - if
259
260         // Init update array here
261         crackerTrackerInitUpdates();
262
263         // Run any SQL updates recursively
264         while (isset($GLOBALS['ctracker_updates'][getCrackerTrackerConfig('ctracker_db_version')])) {
265                 // Run that updates
266                 runCrackerTrackerUpdates(getCrackerTrackerConfig('ctracker_db_version'));
267
268                 // Update config
269                 runCrackerTrackerSql('UPDATE `ctracker_config` SET `ctracker_db_version`=`ctracker_db_version`+1 WHERE `ctracker_config`=1 LIMIT 1', __FUNCTION__, __LINE__);
270
271                 // And count it up in the config array
272                 $GLOBALS['ctracker_config']['ctracker_db_version']++;
273         } // END - if
274 }
275
276 // Load the configuration
277 function crackerTrackerLoadConfig () {
278         // Construct SQL command and run it
279         $result = runCrackerTrackerSql('SELECT * FROM `ctracker_config` WHERE `ctracker_config`=1 LIMIT 1', __FUNCTION__, __LINE__);
280
281         // And get it
282         $GLOBALS['ctracker_config'] = mysql_fetch_array($result);
283
284         // Free result
285         mysql_free_result($result) or crackerTrackerDatabaseError(__FUNCTION__, __LINE__);
286 }
287
288 // Getter for config
289 function getCrackerTrackerConfig ($entry) {
290         // Is the config entry there?
291         if (!isset($GLOBALS['ctracker_config'][$entry])) {
292                 // Then better die here, else we may have an endless loop
293                 if (isCrackerTrackerDebug()) {
294                         // Nicer message in debug mode
295                         die('Configuration entry ' . $entry . ' missing!');
296                 } else {
297                         // die() on production systems
298                         die();
299                 }
300         } // END - if
301
302         // Return it
303         return $GLOBALS['ctracker_config'][$entry];
304 }
305
306 // Did the current IP already generated blocked attempts?
307 function isCrackerTrackerIpSuspicious () {
308         // Skip this silently if we have not config
309         if (!isCrackerTrackerDatabaseLinkUp()) {
310                 // Skip this step silently, all is not suspicious
311                 return FALSE;
312         } // END - if
313
314         // Check if an entry is there
315         $result = runCrackerTrackerSql("SELECT COUNT(`id`) AS `cnt` FROM `ctracker_data` USE INDEX (`remote_proxy_last`) WHERE `remote_addr`='" . determineCrackerTrackerRealRemoteAddress() . "' OR `proxy_addr`='" . getenv('REMOTE_ADDR') . "' LIMIT 1", __FUNCTION__, __LINE__);
316
317         // Get row count
318         list($rows) = mysql_fetch_row($result);
319
320         // Is there one entry?
321         $found = ($rows > 0);
322
323         // And again?
324         if ($found === TRUE) {
325                 // Yes, one is found, then load it
326                 $result = runCrackerTrackerSql("SELECT SQL_SMALL_RESULT * FROM `ctracker_data` USE INDEX (`remote_proxy_last`) WHERE `remote_addr`='" . determineCrackerTrackerRealRemoteAddress() . "' OR `proxy_addr`='" . getenv('REMOTE_ADDR') . "' ORDER BY `last_attempt` DESC LIMIT 1", __FUNCTION__, __LINE__);
327
328                 // Cache the entry
329                 $GLOBALS['ctracker_last_suspicious_entry'] = mysql_fetch_array($result);
330         } // END - if
331
332         // Free result
333         mysql_free_result($result) or crackerTrackerDatabaseError(__FUNCTION__, __LINE__);
334
335         // Return the result
336         return $found;
337 }
338
339 // Does the current IP have a ticket?
340 function ifCrackerTrackerIpHasTicket () {
341         // We only give one ticket per IP!
342         $result = runCrackerTrackerSql("SELECT * FROM `ctracker_ticket` WHERE `ctracker_ticket_remote_addr`='" . determineCrackerTrackerRealRemoteAddress() . "' OR `ctracker_ticket_proxy_addr`='" . getenv('REMOTE_ADDR') . "' LIMIT 1", __FUNCTION__, __LINE__);
343
344         // Do we have a ticket?
345         $found = (mysql_num_rows($result) == 1);
346
347         // And again?
348         if ($found === TRUE) {
349                 // Cache the ticket data
350                 $GLOBALS['ctracker_last_ticket'] = mysql_fetch_array($result);
351         } // END - if
352
353         // Free result
354         mysql_free_result($result) or crackerTrackerDatabaseError(__FUNCTION__, __LINE__);
355
356         // Return the result
357         return $found;
358 }
359
360 // Adds a ticket based on given (mostly $_POST) data
361 function addCrackerTrackerTicket (array $data) {
362         // Prepare the array
363         $GLOBALS['ctracker_last_ticket'] = array(
364                 'ctracker_ticket_remote_addr' => determineCrackerTrackerRealRemoteAddress(),
365                 'ctracker_ticket_proxy_addr'  => getenv('REMOTE_ADDR'),
366                 'ctracker_ticket_user_agent'  => crackerTrackerUserAgent(),
367                 'ctracker_ticket_name'        => crackerTrackerSecureString($data['name']),
368                 'ctracker_ticket_email'       => crackerTrackerSecureString($data['email']),
369                 'ctracker_ticket_comment'     => crackerTrackerSecureString($data['comment'])
370         );
371
372         // Insert it
373         crackerTrackerInsertArray('ctracker_ticket', $GLOBALS['ctracker_last_ticket']);
374
375         // Is there an entry?
376         if ((isset($GLOBALS['ctracker_last_insert_id'])) && ($GLOBALS['ctracker_last_insert_id'] > 0)) {
377                 // All fine, so prepare the link between ticket<->data
378                 $data = array(
379                         'ctracker_ticket_id' => $GLOBALS['ctracker_last_insert_id'],
380                         'ctracker_data_id'   => $GLOBALS['ctracker_last_suspicious_entry']['id']
381                 );
382
383                 // And insert it as well
384                 crackerTrackerInsertArray('ctracker_ticket_data', $data);
385
386                 // Add ticket id again
387                 $GLOBALS['ctracker_ticket'] = $data['ctracker_ticket_id'];
388
389                 // Merge all data for emails
390                 $GLOBALS['ctracker_last_ticket'] = array_merge($GLOBALS['ctracker_last_ticket'], $data);
391
392                 // Is this also there?
393                 if ((isset($GLOBALS['ctracker_last_insert_id'])) && ($GLOBALS['ctracker_last_insert_id'] > 0)) {
394                         // All fine, so display "thank you page"
395                         crackerTrackerLoadTemplate('add_ticket_thanks');
396                 } else {
397                         // Did not insert
398                         crackerTrackerDie();
399                 }
400         } else {
401                 // Did not insert
402                 crackerTrackerDie();
403         }
404 }
405
406 // [EOF]
407 ?>