PageRenderTime 54ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/htdocs/core/db/mysql.class.php

https://github.com/asterix14/dolibarr
PHP | 1229 lines | 707 code | 126 blank | 396 comment | 122 complexity | b51b3123192e49e79870d6f0b52a5e82 MD5 | raw file
Possible License(s): LGPL-2.0
  1. <?php
  2. /* Copyright (C) 2001 Fabien Seisen <seisen@linuxfr.org>
  3. * Copyright (C) 2002-2007 Rodolphe Quiedeville <rodolphe@quiedeville.org>
  4. * Copyright (C) 2004-2008 Laurent Destailleur <eldy@users.sourceforge.net>
  5. * Copyright (C) 2006 Andre Cianfarani <acianfa@free.fr>
  6. * Copyright (C) 2005-2009 Regis Houssin <regis@dolibarr.fr>
  7. *
  8. * This program is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation; either version 2 of the License, or
  11. * (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  20. */
  21. /**
  22. * \file htdocs/core/db/mysql.class.php
  23. * \brief Class file to manage Dolibarr database access for a Mysql database
  24. */
  25. /**
  26. * \class DoliDBMysql
  27. * \brief Class to manage Dolibarr database access for a Mysql database
  28. */
  29. class DoliDBMysql
  30. {
  31. //! Database handler
  32. var $db;
  33. //! Database type
  34. var $type='mysql';
  35. //! Database label
  36. var $label='MySQL';
  37. //! Charset used to force charset when creating database
  38. var $forcecharset='utf8'; // latin1, utf8
  39. //! Collate used to force collate when creating database
  40. var $forcecollate='utf8_general_ci'; // latin1_swedish_ci, utf8_general_ci
  41. //! Version min database
  42. var $versionmin=array(3,1,0);
  43. //! Resultset of last request
  44. var $results;
  45. //! 1 if connected, 0 else
  46. var $connected;
  47. //! 1 if database selected, 0 else
  48. var $database_selected;
  49. //! Database name selected
  50. var $database_name;
  51. //! Nom user base
  52. var $database_user;
  53. //! 1 si une transaction est en cours, 0 sinon
  54. var $transaction_opened;
  55. //! Last executed request
  56. var $lastquery;
  57. //! Last failed executed request
  58. var $lastqueryerror;
  59. //! Message erreur mysql
  60. var $lasterror;
  61. //! Message erreur mysql
  62. var $lasterrno;
  63. var $ok;
  64. var $error;
  65. /**
  66. * Constructor.
  67. * This create an opened connexion to a database server and eventually to a database
  68. *
  69. * @param string $type Type of database (mysql, pgsql...)
  70. * @param string $host Address of database server
  71. * @param string $user Nom de l'utilisateur autorise
  72. * @param string $pass Mot de passe
  73. * @param string $name Nom de la database
  74. * @param int $port Port of database server
  75. * @return int 1 if OK, 0 if not
  76. */
  77. function DoliDBMysql($type, $host, $user, $pass, $name='', $port=0)
  78. {
  79. global $conf,$langs;
  80. if (! empty($conf->db->character_set)) $this->forcecharset=$conf->db->character_set;
  81. if (! empty($conf->db->dolibarr_main_db_collation)) $this->forcecollate=$conf->db->dolibarr_main_db_collation;
  82. $this->database_user=$user;
  83. $this->transaction_opened=0;
  84. //print "Name DB: $host,$user,$pass,$name<br>";
  85. if (! function_exists("mysql_connect"))
  86. {
  87. $this->connected = 0;
  88. $this->ok = 0;
  89. $this->error="Mysql PHP functions for using MySql driver are not available in this version of PHP. Try to use another driver.";
  90. dol_syslog("DoliDB::DoliDB : Mysql PHP functions for using Mysql driver are not available in this version of PHP. Try to use another driver.",LOG_ERR);
  91. return $this->ok;
  92. }
  93. if (! $host)
  94. {
  95. $this->connected = 0;
  96. $this->ok = 0;
  97. $this->error=$langs->trans("ErrorWrongHostParameter");
  98. dol_syslog("DoliDB::DoliDB : Erreur Connect, wrong host parameters",LOG_ERR);
  99. return $this->ok;
  100. }
  101. // Essai connexion serveur
  102. $this->db = $this->connect($host, $user, $pass, $name, $port);
  103. if ($this->db)
  104. {
  105. $this->connected = 1;
  106. $this->ok = 1;
  107. }
  108. else
  109. {
  110. // host, login ou password incorrect
  111. $this->connected = 0;
  112. $this->ok = 0;
  113. $this->error=mysql_error();
  114. dol_syslog("DoliDB::DoliDB : Erreur Connect mysql_error=".$this->error,LOG_ERR);
  115. }
  116. // Si connexion serveur ok et si connexion base demandee, on essaie connexion base
  117. if ($this->connected && $name)
  118. {
  119. if ($this->select_db($name))
  120. {
  121. $this->database_selected = 1;
  122. $this->database_name = $name;
  123. $this->ok = 1;
  124. // If client connected with different charset than Dolibarr HTML output
  125. $clientmustbe='';
  126. if (preg_match('/UTF-8/i',$conf->file->character_set_client)) $clientmustbe='utf8';
  127. if (preg_match('/ISO-8859-1/i',$conf->file->character_set_client)) $clientmustbe='latin1';
  128. if (mysql_client_encoding($this->db) != $clientmustbe)
  129. {
  130. $this->query("SET NAMES '".$clientmustbe."'", $this->db);
  131. //$this->query("SET CHARACTER SET ". $this->forcecharset);
  132. }
  133. }
  134. else
  135. {
  136. $this->database_selected = 0;
  137. $this->database_name = '';
  138. $this->ok = 0;
  139. $this->error=$this->error();
  140. dol_syslog("DoliDB::DoliDB : Erreur Select_db ".$this->error,LOG_ERR);
  141. }
  142. }
  143. else
  144. {
  145. // Pas de selection de base demandee, ok ou ko
  146. $this->database_selected = 0;
  147. if ($this->connected)
  148. {
  149. // If client connected with different charset than Dolibarr HTML output
  150. $clientmustbe='';
  151. if (preg_match('/UTF-8/i',$conf->file->character_set_client)) $clientmustbe='utf8';
  152. if (preg_match('/ISO-8859-1/i',$conf->file->character_set_client)) $clientmustbe='latin1';
  153. if (mysql_client_encoding($this->db) != $clientmustbe)
  154. {
  155. $this->query("SET NAMES '".$clientmustbe."'", $this->db);
  156. //$this->query("SET CHARACTER SET ". $this->forcecharset);
  157. }
  158. }
  159. }
  160. return $this->ok;
  161. }
  162. /**
  163. * Convert a SQL request in Mysql syntax to native syntax
  164. *
  165. * @param string $line SQL request line to convert
  166. * @param string $type Type of SQL order ('ddl' for insert, update, select, delete or 'dml' for create, alter...)
  167. * @return string SQL request line converted
  168. */
  169. function convertSQLFromMysql($line,$type='ddl')
  170. {
  171. return $line;
  172. }
  173. /**
  174. * Select a database
  175. *
  176. * @param string $database Name of database
  177. * @return boolean true if OK, false if KO
  178. */
  179. function select_db($database)
  180. {
  181. dol_syslog("DoliDB::select_db database=".$database, LOG_DEBUG);
  182. return mysql_select_db($database, $this->db);
  183. }
  184. /**
  185. * Connexion to server
  186. *
  187. * @param string $host database server host
  188. * @param string $login login
  189. * @param string $passwd password
  190. * @param string $name name of database (not used for mysql, used for pgsql)
  191. * @param string $port Port of database server
  192. * @return resource Database access handler
  193. * @see close
  194. */
  195. function connect($host, $login, $passwd, $name, $port=0)
  196. {
  197. dol_syslog("DoliDB::connect host=$host, port=$port, login=$login, passwd=--hidden--, name=$name",LOG_DEBUG);
  198. $newhost=$host;
  199. // With mysql, port must be in hostname
  200. if ($port) $newhost.=':'.$port;
  201. $this->db = @mysql_connect($newhost, $login, $passwd);
  202. //print "Resultat fonction connect: ".$this->db;
  203. return $this->db;
  204. }
  205. /**
  206. * Return label of manager
  207. *
  208. * @return string Label
  209. */
  210. function getLabel()
  211. {
  212. return $this->label;
  213. }
  214. /**
  215. * Return version of database server
  216. *
  217. * @return string Version string
  218. */
  219. function getVersion()
  220. {
  221. return mysql_get_server_info($this->db);
  222. }
  223. /**
  224. * Return version of database server into an array
  225. *
  226. * @return array Version array
  227. */
  228. function getVersionArray()
  229. {
  230. return explode('.',$this->getVersion());
  231. }
  232. /**
  233. * Close database connexion
  234. *
  235. * @return boolean True if disconnect successfull, false otherwise
  236. * @see connect
  237. */
  238. function close()
  239. {
  240. if ($this->db)
  241. {
  242. //dol_syslog("DoliDB::disconnect",LOG_DEBUG);
  243. $this->connected=0;
  244. return mysql_close($this->db);
  245. }
  246. return false;
  247. }
  248. /**
  249. * Start transaction
  250. *
  251. * @return int 1 if transaction successfuly opened or already opened, 0 if error
  252. */
  253. function begin()
  254. {
  255. if (! $this->transaction_opened)
  256. {
  257. $ret=$this->query("BEGIN");
  258. if ($ret)
  259. {
  260. $this->transaction_opened++;
  261. dol_syslog("BEGIN Transaction",LOG_DEBUG);
  262. }
  263. return $ret;
  264. }
  265. else
  266. {
  267. $this->transaction_opened++;
  268. return 1;
  269. }
  270. }
  271. /**
  272. * Validate a database transaction
  273. *
  274. * @param $log Add more log to default log line
  275. * @return int 1 if validation is OK or transaction level no started, 0 if ERROR
  276. */
  277. function commit($log='')
  278. {
  279. if ($this->transaction_opened<=1)
  280. {
  281. $ret=$this->query("COMMIT");
  282. if ($ret)
  283. {
  284. $this->transaction_opened=0;
  285. dol_syslog("COMMIT Transaction".($log?' '.$log:''),LOG_DEBUG);
  286. }
  287. return $ret;
  288. }
  289. else
  290. {
  291. $this->transaction_opened--;
  292. return 1;
  293. }
  294. }
  295. /**
  296. * Annulation d'une transaction et retour aux anciennes valeurs
  297. *
  298. * @param $log Add more log to default log line
  299. * @return int 1 si annulation ok ou transaction non ouverte, 0 en cas d'erreur
  300. */
  301. function rollback($log='')
  302. {
  303. if ($this->transaction_opened<=1)
  304. {
  305. $ret=$this->query("ROLLBACK");
  306. $this->transaction_opened=0;
  307. dol_syslog("ROLLBACK Transaction".($log?' '.$log:''),LOG_DEBUG);
  308. return $ret;
  309. }
  310. else
  311. {
  312. $this->transaction_opened--;
  313. return 1;
  314. }
  315. }
  316. /**
  317. * Execute a SQL request and return the resultset
  318. *
  319. * @param query SQL query string
  320. * @param usesavepoint 0=Default mode, 1=Run a savepoint before and a rollbock to savepoint if error (this allow to have some request with errors inside global transactions).
  321. * Note that with Mysql, this parameter is not used as Myssql can already commit a transaction even if one request is in error, without using savepoints.
  322. * @param type Type of SQL order ('ddl' for insert, update, select, delete or 'dml' for create, alter...)
  323. * @return resource Resultset of answer
  324. */
  325. function query($query,$usesavepoint=0,$type='auto')
  326. {
  327. $query = trim($query);
  328. if (! $this->database_name)
  329. {
  330. // Ordre SQL ne necessitant pas de connexion a une base (exemple: CREATE DATABASE)
  331. $ret = mysql_query($query, $this->db);
  332. }
  333. else
  334. {
  335. mysql_select_db($this->database_name);
  336. $ret = mysql_query($query, $this->db);
  337. }
  338. if (! preg_match("/^COMMIT/i",$query) && ! preg_match("/^ROLLBACK/i",$query))
  339. {
  340. // Si requete utilisateur, on la sauvegarde ainsi que son resultset
  341. if (! $ret)
  342. {
  343. $this->lastqueryerror = $query;
  344. $this->lasterror = $this->error();
  345. $this->lasterrno = $this->errno();
  346. dol_syslog("Mysql.lib::query SQL error: ".$query." ".$this->lasterrno, LOG_WARNING);
  347. }
  348. $this->lastquery=$query;
  349. $this->results = $ret;
  350. }
  351. return $ret;
  352. }
  353. /**
  354. * Renvoie la ligne courante (comme un objet) pour le curseur resultset
  355. *
  356. * @param resultset Curseur de la requete voulue
  357. * @return object Object result line or false if KO or end of cursor
  358. */
  359. function fetch_object($resultset)
  360. {
  361. // If resultset not provided, we take the last used by connexion
  362. if (! is_resource($resultset)) { $resultset=$this->results; }
  363. return mysql_fetch_object($resultset);
  364. }
  365. /**
  366. * Renvoie les donnees dans un tableau
  367. *
  368. * @param resultset Curseur de la requete voulue
  369. * @return array
  370. */
  371. function fetch_array($resultset)
  372. {
  373. // If resultset not provided, we take the last used by connexion
  374. if (! is_resource($resultset)) { $resultset=$this->results; }
  375. return mysql_fetch_array($resultset);
  376. }
  377. /**
  378. * Renvoie les donnees comme un tableau
  379. *
  380. * @param resultset Curseur de la requete voulue
  381. * @return array
  382. */
  383. function fetch_row($resultset)
  384. {
  385. // If resultset not provided, we take the last used by connexion
  386. if (! is_resource($resultset)) { $resultset=$this->results; }
  387. return @mysql_fetch_row($resultset);
  388. }
  389. /**
  390. * Renvoie le nombre de lignes dans le resultat d'une requete SELECT
  391. *
  392. * @see affected_rows
  393. * @param resultset Curseur de la requete voulue
  394. * @return int Nombre de lignes
  395. */
  396. function num_rows($resultset)
  397. {
  398. // If resultset not provided, we take the last used by connexion
  399. if (! is_resource($resultset)) { $resultset=$this->results; }
  400. return mysql_num_rows($resultset);
  401. }
  402. /**
  403. * Renvoie le nombre de lignes dans le resultat d'une requete INSERT, DELETE ou UPDATE
  404. *
  405. * @see num_rows
  406. * @param resultset Curseur de la requete voulue
  407. * @return int Nombre de lignes
  408. */
  409. function affected_rows($resultset)
  410. {
  411. // If resultset not provided, we take the last used by connexion
  412. if (! is_resource($resultset)) { $resultset=$this->results; }
  413. // mysql necessite un link de base pour cette fonction contrairement
  414. // a pqsql qui prend un resultset
  415. return mysql_affected_rows($this->db);
  416. }
  417. /**
  418. * Libere le dernier resultset utilise sur cette connexion.
  419. *
  420. * @param resultset Curseur de la requete voulue
  421. */
  422. function free($resultset=0)
  423. {
  424. // If resultset not provided, we take the last used by connexion
  425. if (! is_resource($resultset)) { $resultset=$this->results; }
  426. // Si resultset en est un, on libere la memoire
  427. if (is_resource($resultset)) mysql_free_result($resultset);
  428. }
  429. /**
  430. * Defini les limites de la requete
  431. *
  432. * @param limit nombre maximum de lignes retournees
  433. * @param offset numero de la ligne a partir de laquelle recuperer les ligne
  434. * @return string chaine exprimant la syntax sql de la limite
  435. */
  436. function plimit($limit=0,$offset=0)
  437. {
  438. global $conf;
  439. if (! $limit) $limit=$conf->liste_limit;
  440. if ($offset > 0) return " LIMIT $offset,$limit ";
  441. else return " LIMIT $limit ";
  442. }
  443. /**
  444. * Define sort criteria of request
  445. *
  446. * @param sortfield List of sort fields
  447. * @param sortorder Sort order
  448. * @return string String to provide syntax of a sort sql string
  449. * TODO Mutualized this into a mother class
  450. */
  451. function order($sortfield=0,$sortorder=0)
  452. {
  453. if ($sortfield)
  454. {
  455. $return='';
  456. $fields=explode(',',$sortfield);
  457. foreach($fields as $val)
  458. {
  459. if (! $return) $return.=' ORDER BY ';
  460. else $return.=',';
  461. $return.=preg_replace('/[^0-9a-z_\.]/i','',$val);
  462. if ($sortorder) $return.=' '.preg_replace('/[^0-9a-z]/i','',$sortorder);
  463. }
  464. return $return;
  465. }
  466. else
  467. {
  468. return '';
  469. }
  470. }
  471. /**
  472. * Escape a string to insert data
  473. *
  474. * @param stringtoencode String to escape
  475. * @return string String escaped
  476. */
  477. function escape($stringtoencode)
  478. {
  479. return addslashes($stringtoencode);
  480. }
  481. /**
  482. * Convert (by PHP) a GM Timestamp date into a string date with PHP server TZ to insert into a date field.
  483. * Function to use to build INSERT, UPDATE or WHERE predica
  484. *
  485. * @param param Date TMS to convert
  486. * @return string Date in a string YYYYMMDDHHMMSS
  487. */
  488. function idate($param)
  489. {
  490. return adodb_strftime("%Y%m%d%H%M%S",$param);
  491. }
  492. /**
  493. * Convert (by PHP) a PHP server TZ string date into a GM Timestamps date
  494. * 19700101020000 -> 3600 with TZ+1
  495. *
  496. * @param string Date in a string (YYYYMMDDHHMMSS, YYYYMMDD, YYYY-MM-DD HH:MM:SS)
  497. * @return date Date TMS
  498. */
  499. function jdate($string)
  500. {
  501. $string=preg_replace('/([^0-9])/i','',$string);
  502. $tmp=$string.'000000';
  503. $date=dol_mktime(substr($tmp,8,2),substr($tmp,10,2),substr($tmp,12,2),substr($tmp,4,2),substr($tmp,6,2),substr($tmp,0,4));
  504. return $date;
  505. }
  506. /**
  507. * Formate a SQL IF
  508. *
  509. * @param test chaine test
  510. * @param resok resultat si test egal
  511. * @param resko resultat si test non egal
  512. * @return string chaine formate SQL
  513. */
  514. function ifsql($test,$resok,$resko)
  515. {
  516. return 'IF('.$test.','.$resok.','.$resko.')';
  517. }
  518. /**
  519. * \brief Renvoie la derniere requete soumise par la methode query()
  520. * \return lastquery
  521. */
  522. function lastquery()
  523. {
  524. return $this->lastquery;
  525. }
  526. /**
  527. * \brief Renvoie la derniere requete en erreur
  528. * \return string lastqueryerror
  529. */
  530. function lastqueryerror()
  531. {
  532. return $this->lastqueryerror;
  533. }
  534. /**
  535. * \brief Renvoie le libelle derniere erreur
  536. * \return string lasterror
  537. */
  538. function lasterror()
  539. {
  540. return $this->lasterror;
  541. }
  542. /**
  543. * \brief Renvoie le code derniere erreur
  544. * \return string lasterrno
  545. */
  546. function lasterrno()
  547. {
  548. return $this->lasterrno;
  549. }
  550. /**
  551. * \brief Renvoie le code erreur generique de l'operation precedente.
  552. * \return error_num (Exemples: DB_ERROR_TABLE_ALREADY_EXISTS, DB_ERROR_RECORD_ALREADY_EXISTS...)
  553. */
  554. function errno()
  555. {
  556. if (! $this->connected) {
  557. // Si il y a eu echec de connexion, $this->db n'est pas valide.
  558. return 'DB_ERROR_FAILED_TO_CONNECT';
  559. }
  560. else {
  561. // Constants to convert a MySql error code to a generic Dolibarr error code
  562. $errorcode_map = array(
  563. 1004 => 'DB_ERROR_CANNOT_CREATE',
  564. 1005 => 'DB_ERROR_CANNOT_CREATE',
  565. 1006 => 'DB_ERROR_CANNOT_CREATE',
  566. 1007 => 'DB_ERROR_ALREADY_EXISTS',
  567. 1008 => 'DB_ERROR_CANNOT_DROP',
  568. 1025 => 'DB_ERROR_NO_FOREIGN_KEY_TO_DROP',
  569. 1044 => 'DB_ERROR_ACCESSDENIED',
  570. 1046 => 'DB_ERROR_NODBSELECTED',
  571. 1048 => 'DB_ERROR_CONSTRAINT',
  572. 1050 => 'DB_ERROR_TABLE_ALREADY_EXISTS',
  573. 1051 => 'DB_ERROR_NOSUCHTABLE',
  574. 1054 => 'DB_ERROR_NOSUCHFIELD',
  575. 1060 => 'DB_ERROR_COLUMN_ALREADY_EXISTS',
  576. 1061 => 'DB_ERROR_KEY_NAME_ALREADY_EXISTS',
  577. 1062 => 'DB_ERROR_RECORD_ALREADY_EXISTS',
  578. 1064 => 'DB_ERROR_SYNTAX',
  579. 1068 => 'DB_ERROR_PRIMARY_KEY_ALREADY_EXISTS',
  580. 1075 => 'DB_ERROR_CANT_DROP_PRIMARY_KEY',
  581. 1091 => 'DB_ERROR_NOSUCHFIELD',
  582. 1100 => 'DB_ERROR_NOT_LOCKED',
  583. 1136 => 'DB_ERROR_VALUE_COUNT_ON_ROW',
  584. 1146 => 'DB_ERROR_NOSUCHTABLE',
  585. 1216 => 'DB_ERROR_NO_PARENT',
  586. 1217 => 'DB_ERROR_CHILD_EXISTS',
  587. 1451 => 'DB_ERROR_CHILD_EXISTS'
  588. );
  589. if (isset($errorcode_map[mysql_errno($this->db)]))
  590. {
  591. return $errorcode_map[mysql_errno($this->db)];
  592. }
  593. $errno=mysql_errno($this->db);
  594. return ($errno?'DB_ERROR_'.$errno:'0');
  595. }
  596. }
  597. /**
  598. \brief Renvoie le texte de l'erreur mysql de l'operation precedente.
  599. \return error_text
  600. */
  601. function error()
  602. {
  603. if (! $this->connected) {
  604. // Si il y a eu echec de connexion, $this->db n'est pas valide pour mysql_error.
  605. return 'Not connected. Check setup parameters in conf/conf.php file and your mysql client and server versions';
  606. }
  607. else {
  608. return mysql_error($this->db);
  609. }
  610. }
  611. /**
  612. \brief Recupere l'id genere par le dernier INSERT.
  613. \param tab Nom de la table concernee par l'insert. Ne sert pas sous MySql mais requis pour compatibilite avec Postgresql
  614. \return int id
  615. */
  616. function last_insert_id($tab)
  617. {
  618. return mysql_insert_id($this->db);
  619. }
  620. // Next functions are not required. Only minor features use them.
  621. //---------------------------------------------------------------
  622. /**
  623. * Encrypt sensitive data in database
  624. * Warning: This function includes the escape, so it must use direct value
  625. * @param fieldorvalue Field name or value to encrypt
  626. * @param withQuotes Return string with quotes
  627. * @return return XXX(field) or XXX('value') or field or 'value'
  628. */
  629. function encrypt($fieldorvalue, $withQuotes=0)
  630. {
  631. global $conf;
  632. // Type of encryption (2: AES (recommended), 1: DES , 0: no encryption)
  633. $cryptType = ($conf->db->dolibarr_main_db_encryption?$conf->db->dolibarr_main_db_encryption:0);
  634. //Encryption key
  635. $cryptKey = (!empty($conf->db->dolibarr_main_db_cryptkey)?$conf->db->dolibarr_main_db_cryptkey:'');
  636. $return = ($withQuotes?"'":"").$this->escape($fieldorvalue).($withQuotes?"'":"");
  637. if ($cryptType && !empty($cryptKey))
  638. {
  639. if ($cryptType == 2)
  640. {
  641. $return = 'AES_ENCRYPT('.$return.',\''.$cryptKey.'\')';
  642. }
  643. else if ($cryptType == 1)
  644. {
  645. $return = 'DES_ENCRYPT('.$return.',\''.$cryptKey.'\')';
  646. }
  647. }
  648. return $return;
  649. }
  650. /**
  651. * \brief Decrypt sensitive data in database
  652. * \param value Value to decrypt
  653. * \return return Decrypted value if used
  654. */
  655. function decrypt($value)
  656. {
  657. global $conf;
  658. // Type of encryption (2: AES (recommended), 1: DES , 0: no encryption)
  659. $cryptType = ($conf->db->dolibarr_main_db_encryption?$conf->db->dolibarr_main_db_encryption:0);
  660. //Encryption key
  661. $cryptKey = (!empty($conf->db->dolibarr_main_db_cryptkey)?$conf->db->dolibarr_main_db_cryptkey:'');
  662. $return = $value;
  663. if ($cryptType && !empty($cryptKey))
  664. {
  665. if ($cryptType == 2)
  666. {
  667. $return = 'AES_DECRYPT('.$value.',\''.$cryptKey.'\')';
  668. }
  669. else if ($cryptType == 1)
  670. {
  671. $return = 'DES_DECRYPT('.$value.',\''.$cryptKey.'\')';
  672. }
  673. }
  674. return $return;
  675. }
  676. /**
  677. * \brief Renvoie l'id de la connexion
  678. * \return string Id connexion
  679. */
  680. function DDLGetConnectId()
  681. {
  682. $resql=$this->query('SELECT CONNECTION_ID()');
  683. $row=$this->fetch_row($resql);
  684. return $row[0];
  685. }
  686. /**
  687. * \brief Create a new database
  688. * \param database Database name to create
  689. * \param charset Charset used to store data
  690. * \param collation Charset used to sort data
  691. * \param owner Username of database owner
  692. * \return resource resource defined if OK, null if KO
  693. * \remarks Do not use function xxx_create_db (xxx=mysql, ...) as they are deprecated
  694. * We force to create database with charset this->forcecharset and collate this->forcecollate
  695. */
  696. function DDLCreateDb($database,$charset='',$collation='',$owner='')
  697. {
  698. if (empty($charset)) $charset=$this->forcecharset;
  699. if (empty($collation)) $collation=$this->collation;
  700. // ALTER DATABASE dolibarr_db DEFAULT CHARACTER SET latin DEFAULT COLLATE latin1_swedish_ci
  701. $sql = 'CREATE DATABASE '.$database;
  702. $sql.= ' DEFAULT CHARACTER SET '.$charset.' DEFAULT COLLATE '.$collation;
  703. dol_syslog($sql,LOG_DEBUG);
  704. $ret=$this->query($sql);
  705. if (! $ret)
  706. {
  707. // We try again for compatibility with Mysql < 4.1.1
  708. $sql = 'CREATE DATABASE '.$database;
  709. $ret=$this->query($sql);
  710. dol_syslog($sql,LOG_DEBUG);
  711. }
  712. return $ret;
  713. }
  714. /**
  715. * \brief List tables into a database.
  716. * \param database Name of database
  717. * \param table Filter on some tables
  718. * \return array Array list of tables
  719. */
  720. function DDLListTables($database, $table='')
  721. {
  722. $listtables=array();
  723. $like = '';
  724. if ($table) $like = "LIKE '".$table."'";
  725. $sql="SHOW TABLES FROM ".$database." ".$like.";";
  726. //print $sql;
  727. $result = $this->query($sql);
  728. while($row = $this->fetch_row($result))
  729. {
  730. $listtables[] = $row[0];
  731. }
  732. return $listtables;
  733. }
  734. /**
  735. * \brief Liste les informations des champs d'une table.
  736. * \param table Nom de la table
  737. * \return array Tableau des informations des champs de la table
  738. */
  739. function DDLInfoTable($table)
  740. {
  741. $infotables=array();
  742. $sql="SHOW FULL COLUMNS FROM ".$table.";";
  743. dol_syslog($sql,LOG_DEBUG);
  744. $result = $this->query($sql);
  745. while($row = $this->fetch_row($result))
  746. {
  747. $infotables[] = $row;
  748. }
  749. return $infotables;
  750. }
  751. /**
  752. * Create a table into database
  753. *
  754. * @param string $table Nom de la table
  755. * @param array $fields Tableau associatif [nom champ][tableau des descriptions]
  756. * @param string $primary_key Nom du champ qui sera la clef primaire
  757. * @param string $type Type de la table
  758. * @param array $unique_keys Tableau associatifs Nom de champs qui seront clef unique => valeur
  759. * @param array $fulltext_keys Tableau des Nom de champs qui seront indexes en fulltext
  760. * @param string $keys Tableau des champs cles noms => valeur
  761. * @return int <0 if KO, >=0 if OK
  762. */
  763. function DDLCreateTable($table,$fields,$primary_key,$type,$unique_keys="",$fulltext_keys="",$keys="")
  764. {
  765. // cles recherchees dans le tableau des descriptions (fields) : type,value,attribute,null,default,extra
  766. // ex. : $fields['rowid'] = array('type'=>'int','value'=>'11','null'=>'not null','extra'=> 'auto_increment');
  767. $sql = "create table ".$table."(";
  768. $i=0;
  769. foreach($fields as $field_name => $field_desc)
  770. {
  771. $sqlfields[$i] = $field_name." ";
  772. $sqlfields[$i] .= $field_desc['type'];
  773. if( preg_match("/^[^\s]/i",$field_desc['value']))
  774. $sqlfields[$i] .= "(".$field_desc['value'].")";
  775. else if( preg_match("/^[^\s]/i",$field_desc['attribute']))
  776. $sqlfields[$i] .= " ".$field_desc['attribute'];
  777. else if( preg_match("/^[^\s]/i",$field_desc['default']))
  778. {
  779. if(preg_match("/null/i",$field_desc['default']))
  780. $sqlfields[$i] .= " default ".$field_desc['default'];
  781. else
  782. $sqlfields[$i] .= " default '".$field_desc['default']."'";
  783. }
  784. else if( preg_match("/^[^\s]/i",$field_desc['null']))
  785. $sqlfields[$i] .= " ".$field_desc['null'];
  786. else if( preg_match("/^[^\s]/i",$field_desc['extra']))
  787. $sqlfields[$i] .= " ".$field_desc['extra'];
  788. $i++;
  789. }
  790. if($primary_key != "")
  791. $pk = "primary key(".$primary_key.")";
  792. if($unique_keys != "")
  793. {
  794. $i = 0;
  795. foreach($unique_keys as $key => $value)
  796. {
  797. $sqluq[$i] = "UNIQUE KEY '".$key."' ('".$value."')";
  798. $i++;
  799. }
  800. }
  801. if($keys != "")
  802. {
  803. $i = 0;
  804. foreach($keys as $key => $value)
  805. {
  806. $sqlk[$i] = "KEY ".$key." (".$value.")";
  807. $i++;
  808. }
  809. }
  810. $sql .= implode(',',$sqlfields);
  811. if($primary_key != "")
  812. $sql .= ",".$pk;
  813. if($unique_keys != "")
  814. $sql .= ",".implode(',',$sqluq);
  815. if($keys != "")
  816. $sql .= ",".implode(',',$sqlk);
  817. $sql .=") type=".$type;
  818. dol_syslog($sql,LOG_DEBUG);
  819. if(! $this -> query($sql))
  820. return -1;
  821. else
  822. return 1;
  823. }
  824. /**
  825. * Return a pointer on fields describing table
  826. * @param table Nom de la table
  827. * @param field Optionnel : Nom du champ si l'on veut la desc d'un champ
  828. * @return resource
  829. */
  830. function DDLDescTable($table,$field="")
  831. {
  832. $sql="DESC ".$table." ".$field;
  833. dol_syslog(get_class($this)."::DDLDescTable ".$sql,LOG_DEBUG);
  834. $this->results = $this->query($sql);
  835. return $this->results;
  836. }
  837. /**
  838. * Insert a new field in table
  839. * @param table Table name
  840. * @param field_name Name of field
  841. * @param field_desc Array with properties describing new field
  842. * @param field_position Optionnal ie.: "after fielddummy"
  843. * @return int <0 if KO, >0 if OK
  844. */
  845. function DDLAddField($table,$field_name,$field_desc,$field_position="")
  846. {
  847. // cles recherchees dans le tableau des descriptions (field_desc) : type,value,attribute,null,default,extra
  848. // ex. : $field_desc = array('type'=>'int','value'=>'11','null'=>'not null','extra'=> 'auto_increment');
  849. $sql= "ALTER TABLE ".$table." ADD ".$field_name." ";
  850. $sql.= $field_desc['type'];
  851. if(preg_match("/^[^\s]/i",$field_desc['value']))
  852. if (! in_array($field_desc['type'],array('date','datetime')))
  853. {
  854. $sql.= "(".$field_desc['value'].")";
  855. }
  856. if(preg_match("/^[^\s]/i",$field_desc['attribute']))
  857. $sql.= " ".$field_desc['attribute'];
  858. if(preg_match("/^[^\s]/i",$field_desc['null']))
  859. $sql.= " ".$field_desc['null'];
  860. if(preg_match("/^[^\s]/i",$field_desc['default']))
  861. {
  862. if(preg_match("/null/i",$field_desc['default']))
  863. $sql.= " default ".$field_desc['default'];
  864. else
  865. $sql.= " default '".$field_desc['default']."'";
  866. }
  867. if(preg_match("/^[^\s]/i",$field_desc['extra']))
  868. $sql.= " ".$field_desc['extra'];
  869. $sql.= " ".$field_position;
  870. dol_syslog(get_class($this)."::DDLAddField ".$sql,LOG_DEBUG);
  871. if(! $this->query($sql))
  872. {
  873. return -1;
  874. }
  875. else
  876. {
  877. return 1;
  878. }
  879. }
  880. /**
  881. * Update format of a field into a table
  882. * @param table Name of table
  883. * @param field_name Name of field to modify
  884. * @param field_desc Array with description of field format
  885. * @return int <0 if KO, >0 if OK
  886. */
  887. function DDLUpdateField($table,$field_name,$field_desc)
  888. {
  889. $sql = "ALTER TABLE ".$table;
  890. $sql .= " MODIFY COLUMN ".$field_name." ".$field_desc['type'];
  891. if ($field_desc['type'] == 'int' || $field_desc['type'] == 'varchar') $sql.="(".$field_desc['value'].")";
  892. dol_syslog(get_class($this)."::DDLUpdateField ".$sql,LOG_DEBUG);
  893. if (! $this->query($sql))
  894. return -1;
  895. else
  896. return 1;
  897. }
  898. /**
  899. * Drop a field in table
  900. * @param table Nom de la table
  901. * @param field_name Nom du champ a inserer
  902. * @return int <0 si KO, >0 si OK
  903. */
  904. function DDLDropField($table,$field_name)
  905. {
  906. $sql= "ALTER TABLE ".$table." DROP COLUMN `".$field_name."`";
  907. dol_syslog(get_class($this)."::DDLDropField ".$sql,LOG_DEBUG);
  908. if (! $this->query($sql))
  909. {
  910. $this->error=$this->lasterror();
  911. return -1;
  912. }
  913. else return 1;
  914. }
  915. /**
  916. * \brief Create a user and privileges to connect to database (even if database does not exists yet)
  917. * \param dolibarr_main_db_host Ip server
  918. * \param dolibarr_main_db_user Username to create
  919. * \param dolibarr_main_db_pass Password
  920. * \param dolibarr_main_db_name Database name where user must be granted
  921. * \return int <0 if KO, >=0 if OK
  922. */
  923. function DDLCreateUser($dolibarr_main_db_host,$dolibarr_main_db_user,$dolibarr_main_db_pass,$dolibarr_main_db_name)
  924. {
  925. $sql = "INSERT INTO user ";
  926. $sql.= "(Host,User,password,Select_priv,Insert_priv,Update_priv,Delete_priv,Create_priv,Drop_priv,Index_Priv,Alter_priv,Lock_tables_priv)";
  927. $sql.= " VALUES ('".addslashes($dolibarr_main_db_host)."','".addslashes($dolibarr_main_db_user)."',password('".addslashes($dolibarr_main_db_pass)."')";
  928. $sql.= ",'Y','Y','Y','Y','Y','Y','Y','Y','Y')";
  929. dol_syslog("mysql.lib::DDLCreateUser", LOG_DEBUG); // No sql to avoid password in log
  930. $resql=$this->query($sql);
  931. if (! $resql)
  932. {
  933. dol_syslog("mysqli.lib::DDLCreateUser sql=".$sql, LOG_ERR);
  934. return -1;
  935. }
  936. $sql = "INSERT INTO db ";
  937. $sql.= "(Host,Db,User,Select_priv,Insert_priv,Update_priv,Delete_priv,Create_priv,Drop_priv,Index_Priv,Alter_priv,Lock_tables_priv)";
  938. $sql.= " VALUES ('".addslashes($dolibarr_main_db_host)."','".addslashes($dolibarr_main_db_name)."','".addslashes($dolibarr_main_db_user)."'";
  939. $sql.= ",'Y','Y','Y','Y','Y','Y','Y','Y','Y')";
  940. dol_syslog("mysql.lib::DDLCreateUser sql=".$sql,LOG_DEBUG);
  941. $resql=$this->query($sql);
  942. if (! $resql)
  943. {
  944. dol_syslog("mysqli.lib::DDLCreateUser sql=".$sql, LOG_ERR);
  945. return -1;
  946. }
  947. $sql="FLUSH Privileges";
  948. dol_syslog("mysql.lib::DDLCreateUser sql=".$sql,LOG_DEBUG);
  949. $resql=$this->query($sql);
  950. if (! $resql)
  951. {
  952. dol_syslog("mysqli.lib::DDLCreateUser sql=".$sql, LOG_ERR);
  953. return -1;
  954. }
  955. return 1;
  956. }
  957. /**
  958. * \brief Return charset used to store data in database
  959. * \return string Charset
  960. */
  961. function getDefaultCharacterSetDatabase()
  962. {
  963. $resql=$this->query('SHOW VARIABLES LIKE \'character_set_database\'');
  964. if (!$resql)
  965. {
  966. // version Mysql < 4.1.1
  967. return $this->forcecharset;
  968. }
  969. $liste=$this->fetch_array($resql);
  970. return $liste['Value'];
  971. }
  972. /**
  973. * \brief Return list of available charset that can be used to store data in database
  974. * \return array List of Charset
  975. */
  976. function getListOfCharacterSet()
  977. {
  978. $resql=$this->query('SHOW CHARSET');
  979. $liste = array();
  980. if ($resql)
  981. {
  982. $i = 0;
  983. while ($obj = $this->fetch_object($resql) )
  984. {
  985. $liste[$i]['charset'] = $obj->Charset;
  986. $liste[$i]['description'] = $obj->Description;
  987. $i++;
  988. }
  989. $this->free($resql);
  990. } else {
  991. // version Mysql < 4.1.1
  992. return null;
  993. }
  994. return $liste;
  995. }
  996. /**
  997. * \brief Return collation used in database
  998. * \return string Collation value
  999. */
  1000. function getDefaultCollationDatabase()
  1001. {
  1002. $resql=$this->query('SHOW VARIABLES LIKE \'collation_database\'');
  1003. if (!$resql)
  1004. {
  1005. // version Mysql < 4.1.1
  1006. return $this->forcecollate;
  1007. }
  1008. $liste=$this->fetch_array($resql);
  1009. return $liste['Value'];
  1010. }
  1011. /**
  1012. * \brief Return list of available collation that can be used for database
  1013. * \return array Liste of Collation
  1014. */
  1015. function getListOfCollation()
  1016. {
  1017. $resql=$this->query('SHOW COLLATION');
  1018. $liste = array();
  1019. if ($resql)
  1020. {
  1021. $i = 0;
  1022. while ($obj = $this->fetch_object($resql) )
  1023. {
  1024. $liste[$i]['collation'] = $obj->Collation;
  1025. $i++;
  1026. }
  1027. $this->free($resql);
  1028. } else {
  1029. // version Mysql < 4.1.1
  1030. return null;
  1031. }
  1032. return $liste;
  1033. }
  1034. /**
  1035. * Return full path of dump program
  1036. * @return string Full path of dump program
  1037. */
  1038. function getPathOfDump()
  1039. {
  1040. $fullpathofdump='/pathtomysqldump/mysqldump';
  1041. $resql=$this->query('SHOW VARIABLES LIKE \'basedir\'');
  1042. if ($resql)
  1043. {
  1044. $liste=$this->fetch_array($resql);
  1045. $basedir=$liste['Value'];
  1046. $fullpathofdump=$basedir.(preg_match('/\/$/',$basedir)?'':'/').'bin/mysqldump';
  1047. }
  1048. return $fullpathofdump;
  1049. }
  1050. /**
  1051. * \brief Return full path of restore program
  1052. * \return string Full path of restore program
  1053. */
  1054. function getPathOfRestore()
  1055. {
  1056. $fullpathofimport='/pathtomysql/mysql';
  1057. $resql=$this->query('SHOW VARIABLES LIKE \'basedir\'');
  1058. if ($resql)
  1059. {
  1060. $liste=$this->fetch_array($resql);
  1061. $basedir=$liste['Value'];
  1062. $fullpathofimport=$basedir.(preg_match('/\/$/',$basedir)?'':'/').'bin/mysql';
  1063. }
  1064. return $fullpathofimport;
  1065. }
  1066. /**
  1067. * \brief Return value of server parameters
  1068. * \param filter Filter list on a particular value
  1069. * \return string Value for parameter
  1070. */
  1071. function getServerParametersValues($filter='')
  1072. {
  1073. $result=array();
  1074. $sql='SHOW VARIABLES';
  1075. if ($filter) $sql.=" LIKE '".addslashes($key)."'";
  1076. $resql=$this->query($sql);
  1077. if ($resql)
  1078. {
  1079. $obj=$this->fetch_object($resql);
  1080. $result[$obj->Variable_name]=$obj->Value;
  1081. }
  1082. return $result;
  1083. }
  1084. /**
  1085. * \brief Return value of server status
  1086. * \param filter Filter list on a particular value
  1087. * \return string Value for parameter
  1088. */
  1089. function getServerStatusValues($key,$filter='')
  1090. {
  1091. $result=array();
  1092. $sql='SHOW STATUS';
  1093. if ($filter) $sql.=" LIKE '".addslashes($key)."'";
  1094. $resql=$this->query($sql);
  1095. if ($resql)
  1096. {
  1097. $obj=$this->fetch_object($resql);
  1098. $result[$obj->Variable_name]=$obj->Value;
  1099. }
  1100. return $result;
  1101. }
  1102. }
  1103. ?>