source: alternc/trunk/bureau/class/m_mysql.php @ 1527

Revision 1527, 15.4 KB checked in by benjamin, 9 years ago (diff)

erreur ->

Line 
1<?php
2/*
3 $Id: m_mysql.php,v 1.35 2005/12/18 09:51:32 benjamin Exp $
4 ----------------------------------------------------------------------
5 AlternC - Web Hosting System
6 Copyright (C) 2002 by the AlternC Development Team.
7 http://alternc.org/
8 ----------------------------------------------------------------------
9 Based on:
10 Valentin Lacambre's web hosting softwares: http://altern.org/
11 ----------------------------------------------------------------------
12 LICENSE
13
14 This program is free software; you can redistribute it and/or
15 modify it under the terms of the GNU General Public License (GPL)
16 as published by the Free Software Foundation; either version 2
17 of the License, or (at your option) any later version.
18
19 This program is distributed in the hope that it will be useful,
20 but WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22 GNU General Public License for more details.
23
24 To read the license please visit http://www.gnu.org/copyleft/gpl.html
25 ----------------------------------------------------------------------
26 Original Author of file: Benjamin Sonntag
27 Purpose of file: Manage mysql database for users.
28 ----------------------------------------------------------------------
29*/
30/**
31 * MySQL user database management for AlternC.
32 * This class manage user's databases in MySQL, and user's MySQL accounts.
33 *
34 * @copyright    AlternC-Team 2002-2005 http://alternc.org/
35 */
36class m_mysql {
37
38  var $server;
39  var $client;
40
41  /*---------------------------------------------------------------------------*/
42  /** Constructor
43  * m_mysql([$mid]) Constructeur de la classe m_mysql, initialise le membre concerne
44  */
45  function m_mysql() {
46      $this->server = $GLOBALS['L_MYSQL_HOST'];
47      $this->client = $GLOBALS['L_MYSQL_CLIENT'];
48  }
49
50  /* ----------------------------------------------------------------- */
51  /** Hook called by m_quota to obtain the quota managed by this class.
52   * Quota name
53   */
54  function alternc_quota_names() {
55    return "mysql";
56  }
57
58  /*---------------------------------------------------------------------------*/
59  /** Get the list of the database for the current user.
60   * @return array returns an associative array as follow : <br>
61   *  "db" => database name "bck" => backup mode for this db
62   *  "dir" => Backup folder.
63   *  "size" => Size of the database (in bytes)
64   *  Returns FALSE if the user has no database.
65   */
66  function get_dblist() {
67    global $db,$err,$bro,$cuid;
68    $err->log("mysql","get_dblist");
69    $db->query("SELECT login,pass,db, bck_mode, bck_dir FROM db WHERE uid='$cuid';");
70    if (!$db->num_rows()) {
71      $err->raise("mysql",11);
72      return false;
73    }
74    $c=array();
75    while ($db->next_record()) {
76      list($dbu,$dbn)=split_mysql_database_name($db->f("db"));
77      $c[]=array("db"=>$db->f("db"), "name"=>$dbn,"bck"=>$db->f("bck_mode"), "dir"=>$db->f("bck_dir"), "login"=>$db->f("login"), "pass"=>$db->f("pass"));
78    }
79   
80    /* find the size of each database */
81    foreach ($c as $key => $val) {
82      $c[$key]['size'] = $this->get_db_size($c[$key]['db']);
83    }
84    return $c;
85  }
86
87  /*---------------------------------------------------------------------------*/
88  /** Returns the details of a user's database.
89   * $dbn is the name of the database (after the _) or nothing for the database "$user"
90   * @return array returns an associative array as follow :
91   *  "db" => Name of the database
92   *  "bck" => Current bckup mode
93   *  "dir" => Backup directory
94   *  "size" => Size of the database (in bytes)
95   *  "pass" => Password of the user
96   *  "history" => Number of backup we keep
97   *  "gzip" => Does we compress the dumps ?
98   *  Returns FALSE if the user has no database of if the database does not exist.
99   */
100  function get_mysql_details($dbn) {
101    global $db,$err,$bro,$mem,$cuid;
102    $root="/var/alternc/html/".substr($mem->user["login"],0,1)."/".$mem->user["login"];
103    $root=realpath($root);
104    $err->log("mysql","get_mysql_details");
105    $dbname=$mem->user["login"].($dbn?"_":"").$dbn;
106    $size=$this->get_db_size($dbname);
107    $db->query("SELECT login,pass,db, bck_mode, bck_gzip, bck_dir, bck_history FROM db WHERE uid='$cuid' AND db='$dbname';");
108    if (!$db->num_rows()) {
109      $err->raise("mysql",4);
110      return array("enabled"=>false);
111    }
112    $c=array();
113    $db->next_record();
114    list($dbu,$dbn)=split_mysql_database_name($db->f("db"));
115    return array("enabled"=>true,"login"=>$db->f("login"),"db"=>$db->f("db"), "name"=>$dbn,"bck"=>$db->f("bck_mode"), "dir"=>substr($db->f("bck_dir"),strlen($root)), "size"=>$size, "pass"=>$db->f("pass"), "history"=>$db->f("bck_history"), "gzip"=>$db->f("bck_gzip"));
116  }
117
118  /*---------------------------------------------------------------------------*/
119  /** Create a new database for the current user.
120   * @param $dbn string Database name ($user_$dbn is the mysql db name)
121   * @return TRUE if the database $user_$db has been successfully created, or FALSE if
122   * an error occured, such as over quota user.
123   */
124  function add_db($dbn) {
125    global $db,$err,$quota,$mem,$cuid;
126    $err->log("mysql","add_db",$dbn);
127    if (!$quota->cancreate("mysql")) {
128      $err->raise("mysql",1);
129      return false;
130    }
131    if (!ereg("^[0-9a-z]*$",$dbn)) {
132      $err->raise("mysql",2);
133      return false;
134    }
135    $dbname=$mem->user["login"].($dbn?"_":"").$dbn;
136    if (strlen($dbname) > 64) {
137      $err->raise("mysql",12);
138      return false;
139    }
140    $db->query("SELECT * FROM db WHERE db='$dbname';");
141    if ($db->num_rows()) {
142      $err->raise("mysql",3);
143      return false;
144    }
145    // find the login/pass for this user :
146    $db->query("SELECT login,pass FROM db WHERE uid='$cuid' LIMIT 0,1;");
147    if (!$db->num_rows()) {
148      $lo=$mem->user["login"];
149      $pa="";
150    } else {
151      $db->next_record();
152      $lo=addslashes($db->f("login"));
153      $pa=addslashes($db->f("pass"));
154    }
155    // Ok, database does not exist, quota is ok and dbname is compliant. Let's proceed
156    $db->query("INSERT INTO db (uid,login,pass,db,bck_mode) VALUES ('$cuid','$lo','$pa','$dbname',0);");
157    // give everything but GRANT on db.*
158    // we assume there's already a user
159    $db->query("GRANT ALL PRIVILEGES ON `".$dbname."`.* TO '".$lo."'@'$this->client'");
160    $db->query("CREATE DATABASE $dbname;");
161    return true;
162  }
163
164  /*---------------------------------------------------------------------------*/
165  /** Delete a database for the current user.
166   * @param $dbn string Name of the database to delete. The db name is $user_$dbn
167   * @return TRUE if the database $user_$db has been successfully deleted, or FALSE if
168   *  an error occured, such as db does not exist.
169   */
170  function del_db($dbn) {
171    global $db,$err,$mem,$cuid;
172    $err->log("mysql","del_db",$dbn);
173    if (!ereg("^[0-9a-z]*$",$dbn)) {
174      $err->raise("mysql",2);
175      return false;
176    }
177    $dbname=$mem->user["login"].($dbn?"_":"").$dbn;
178    $db->query("SELECT login FROM db WHERE db='$dbname';");
179    if (!$db->num_rows()) {
180      $err->raise("mysql",4);
181      return false;
182    }
183    $db->next_record();
184    $login=$db->f("login");
185
186    // Ok, database exists and dbname is compliant. Let's proceed
187    $db->query("DELETE FROM db WHERE uid='$cuid' AND db='$dbname';");
188    $db->query("DROP DATABASE $dbname;");
189    $db->query("SELECT COUNT(*) AS cnt FROM db WHERE uid='$cuid';");
190    $db->next_record();
191    $db->query("REVOKE ALL PRIVILEGES ON `".$dbname."`.* FROM '".$login."'@'$this->client'");
192    if ($db->f("cnt")==0) {
193      $db->query("DELETE FROM mysql.user WHERE User='".$login."';");
194      $db->query("FLUSH PRIVILEGES;");
195    }
196    return true;
197  }
198 
199  /*---------------------------------------------------------------------------*/
200  /** Set the backup parameters for the database $db
201   * @param $db string database name
202   * @param $bck_mode integer Backup mode (0 = none 1 = daily 2 = weekly)
203   * @param $bck_history integer How many backup should we keep ?
204   * @param $bck_gzip boolean shall we compress the backup ?
205   * @param $bck_dir string Directory relative to the user account where the backup will be stored
206   * @return boolean true if the backup parameters has been successfully changed, false if not.
207   */
208  function put_mysql_backup($dbn,$bck_mode,$bck_history,$bck_gzip,$bck_dir) {
209    global $db,$err,$mem,$bro,$cuid;
210    $err->log("mysql","put_mysql_backup");
211    if (!ereg("^[0-9a-z]*$",$dbn)) {
212      $err->raise("mysql",2);
213      return false;
214    }
215    $dbname=$mem->user["login"].($dbn?"_":"").$dbn;
216    $db->query("SELECT * FROM db WHERE uid='$cuid' AND db='$dbname';");
217    if (!$db->num_rows()) {
218      $err->raise("mysql",4);
219      return false;
220    }
221    $db->next_record();
222    $bck_mode=intval($bck_mode);
223    $bck_history=intval($bck_history);
224    if ($bck_gzip)
225      $bck_gzip="1";
226    else
227      $bck_gzip="0";
228    if (!$bck_mode)
229      $bck_mode="0";
230    if (!$bck_history) {
231      $err->raise("mysql",5);
232      return false;
233    }
234    if (($bck_dir=$bro->convertabsolute($bck_dir,0))===false) { // return a full path or FALSE
235      $err->raise("mysql",6);
236      return false;
237    }
238    $db->query("UPDATE db SET bck_mode='$bck_mode', bck_history='$bck_history', bck_gzip='$bck_gzip', bck_dir='$bck_dir' WHERE uid='$cuid' AND db='$dbname';");
239    return true;
240  }
241
242  /*---------------------------------------------------------------------------*/
243  /** Change the password of the user in MySQL
244   * @param $password string new password (cleartext)
245   * @return boolean TRUE if the password has been successfully changed, FALSE else.
246   */
247  function put_mysql_details($password) {
248    global $db,$err,$mem,$cuid;
249    $err->log("mysql","put_mysql_details");
250    $db->query("SELECT * FROM db WHERE uid='$cuid';");
251    if (!$db->num_rows()) {
252      $err->raise("mysql",7);
253      return false;
254    }
255    $db->next_record();
256    $login=$db->f("login");
257
258    if (strlen($password)>16 || strlen($password)<4 ) {
259      $err->raise("mysql",8);
260      return false;
261    }
262    // Update all the "pass" fields for this user :
263    $db->query("UPDATE db SET pass='$password' WHERE uid='$cuid';");
264    $db->query("SET PASSWORD FOR '$login'@'$this->client' = PASSWORD('$password')");
265    return true;
266  }
267
268  /* ----------------------------------------------------------------- */
269  /** Create a new mysql account for this user
270   * @param string cleartext password for the new account
271   * It also create the first database.
272   */
273  function new_mysql($password) {
274    global $db,$err,$mem,$cuid;
275    $err->log("mysql","new_mysql");
276    if (strlen($password)>16 || strlen($password)<4 ) {
277      $err->raise("mysql",8);
278      return false;
279    }
280    $db->query("SELECT * FROM db WHERE uid='$cuid';");
281    if ($db->num_rows()) {
282      $err->raise("mysql",10);
283      return false;
284    }
285    $login=$mem->user["login"];
286    $dbname=$mem->user["login"];
287    // OK, creation now...
288    $db->query("INSERT INTO db (uid,login,pass,db) VALUES ('$cuid','".$login."','$password','".$dbname."');");
289    // give everything but GRANT on $user.*
290    $db->query("GRANT ALL PRIVILEGES ON `".$dbname."`.* TO '".$login."'@'$this->client' IDENTIFIED BY '".$password."'");
291    $db->query("CREATE DATABASE ".$dbname.";");
292    return true;
293  }
294
295
296  /* ----------------------------------------------------------------- */
297  /** Restore a sql backup script on a user's database.
298   */
299  function restore($file,$stdout,$id) {
300    global $err,$bro,$mem,$L_MYSQL_HOST;
301    if (!$r=$this->get_mysql_details($id)) {
302      return false;
303    }
304    if (!($fi=$bro->convertabsolute($file,0))) {
305      $err->raise("mysql",9);
306      return false;
307    }
308    if (substr($fi,-3)==".gz") {
309      $exe="/bin/gzip -d -c <".escapeshellarg($fi)." | /usr/bin/mysql -h".escapeshellarg($L_MYSQL_HOST)." -u".escapeshellarg($r["login"])." -p".escapeshellarg($r["pass"])." ".escapeshellarg($r["db"]);
310    } elseif (substr($fi,-4)==".bz2") {
311      $exe="/bin/bunzip2 -d -c <".escapeshellarg($fi)." | /usr/bin/mysql -h".escapeshellarg($L_MYSQL_HOST)." -u".escapeshellarg($r["login"])." -p".escapeshellarg($r["pass"])." ".escapeshellarg($r["db"]);
312    } else {
313 {
314      $exe="/usr/bin/mysql -h".escapeshellarg($L_MYSQL_HOST)." -u".escapeshellarg($r["login"])." -p".escapeshellarg($r["pass"])." ".escapeshellarg($r["db"])." <".escapeshellarg($fi);
315    }
316    $exe .= " 2>&1";
317   
318    echo "<code><pre>" ;
319    if ($stdout) {
320      passthru($exe,$ret);
321    } else {
322      exec ($exe,$ret);
323    }
324    echo "</pre></code>" ;
325    if ($ret != 0) {
326      return false ;
327    } else {
328      return true ;
329    }
330  }
331 
332  /* ----------------------------------------------------------------- */
333  /** Get size of a database
334   * @param $dbname name of the database
335   * @return integer database size
336   * @access private
337   */
338 function get_db_size($dbname) {
339   global $db,$err;
340
341   $db->query("SHOW TABLE STATUS FROM `$dbname`;");
342   $size = 0;
343   while ($db->next_record()) {
344     $size += $db->f('Data_length') + $db->f('Index_length')
345              + $db->f('Data_free');
346   }
347   return $size;
348 }
349 
350  /* ----------------------------------------------------------------- */
351  /** Hook function called by the quota class to compute user used quota
352   * Returns the used quota for the $name service for the current user.
353   * @param $name string name of the quota
354   * @return integer the number of service used or false if an error occured
355   * @access private
356   */
357  function alternc_get_quota($name) {
358    global $err,$db,$cuid;
359    if ($name=="mysql") {
360      $err->log("mysql","alternc_get_quota");
361      $c=$this->get_dblist();
362      if (is_array($c)) {
363        return count($c);
364      } else {
365        return 0;
366      }
367    } else return false;
368  }
369
370
371  /* ----------------------------------------------------------------- */
372  /** Hook function called when a user is deleted.
373   * AlternC's standard function that delete a member
374   */
375  function alternc_del_member() {
376    global $db,$err,$cuid;
377    $err->log("mysql","alternc_del_member");
378    $c=$this->get_dblist();
379    if (is_array($c)) {
380      for($i=0;$i<count($c);$i++) {
381        $this->del_db($c[$i]["name"]);
382      }
383    }
384    return true;
385  }
386
387
388  /* ----------------------------------------------------------------- */
389  /**
390   * Exporte toutes les informations mysql du compte.
391   * @access private
392   * EXPERIMENTAL 'sid' function ;)
393   */
394  function alternc_export($tmpdir) {
395    global $db,$err,$cuid;
396    $err->log("mysql","export");
397    $db->query("SELECT login, pass, db, bck_mode, bck_dir, bck_history, bck_gzip FROM db WHERE uid='$cuid';");
398    if ($db->next_record()) {
399      $str="<mysql>\n";
400      $str.="  <login>".xml_entities($db->Record["login"])."</login>";
401      $str.="  <pass>".xml_entities($db->Record["pass"])."</pass>";
402      do {
403        // Do the dump :
404        $filename=$tmpdir."/mysql.".$db->Record["db"].".sql.gz";
405        exec("/usr/bin/mysqldump --add-drop-table --allow-keywords -Q -f -q -a -e -u".escapeshellarg($db->Record["login"])." -p".escapeshellarg($db->Record["pass"])." ".escapeshellarg($db->Record["db"])." |/bin/gzip >".escapeshellarg($filename));
406        $str.="  <db>\n";
407        $str.="    <name>".xml_entities($db->Record["db"])."</name>\n";
408        if ($s["bck_mode"]!=0) {
409          $str.="    <backup>\n";
410          $str.="      <mode>".xml_entities($db->Record["bck_mode"])."</mode>\n";
411          $str.="      <dir>".xml_entities($db->Record["bck_dir"])."</dir>\n";
412          $str.="      <history>".xml_entities($db->Record["bck_history"])."</history>\n";
413          $str.="      <gzip>".xml_entities($db->Record["bck_gzip"])."</gzip>\n";
414          $str.="    </backup>\n";
415        }
416        $str.="  </db>\n";
417      } while ($db->next_record());
418      $str.="</mysql>\n";
419    }
420    return $str;
421  }
422
423
424} /* Class m_mysql */
425
426?>
Note: See TracBrowser for help on using the repository browser.