PageRenderTime 53ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 0ms

/htdocs/core/db/mysqli.class.php

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