82 |
78 |
83 /** |
79 /** |
84 * Amount of queries made |
80 * Amount of queries made |
85 * |
81 * |
86 * @since 1.2.0 |
82 * @since 1.2.0 |
87 * @access private |
|
88 * @var int |
83 * @var int |
89 */ |
84 */ |
90 var $num_queries = 0; |
85 public $num_queries = 0; |
91 |
86 |
92 /** |
87 /** |
93 * Count of rows returned by previous query |
88 * Count of rows returned by previous query |
94 * |
89 * |
95 * @since 0.71 |
90 * @since 0.71 |
96 * @access private |
|
97 * @var int |
91 * @var int |
98 */ |
92 */ |
99 var $num_rows = 0; |
93 public $num_rows = 0; |
100 |
94 |
101 /** |
95 /** |
102 * Count of affected rows by previous query |
96 * Count of affected rows by previous query |
103 * |
97 * |
104 * @since 0.71 |
98 * @since 0.71 |
105 * @access private |
|
106 * @var int |
99 * @var int |
107 */ |
100 */ |
108 var $rows_affected = 0; |
101 var $rows_affected = 0; |
109 |
102 |
110 /** |
103 /** |
111 * The ID generated for an AUTO_INCREMENT column by the previous query (usually INSERT). |
104 * The ID generated for an AUTO_INCREMENT column by the previous query (usually INSERT). |
112 * |
105 * |
113 * @since 0.71 |
106 * @since 0.71 |
114 * @access public |
|
115 * @var int |
107 * @var int |
116 */ |
108 */ |
117 var $insert_id = 0; |
109 public $insert_id = 0; |
118 |
110 |
119 /** |
111 /** |
120 * Last query made |
112 * Last query made |
121 * |
113 * |
122 * @since 0.71 |
114 * @since 0.71 |
123 * @access private |
|
124 * @var array |
115 * @var array |
125 */ |
116 */ |
126 var $last_query; |
117 var $last_query; |
127 |
118 |
128 /** |
119 /** |
129 * Results of the last query made |
120 * Results of the last query made |
130 * |
121 * |
131 * @since 0.71 |
122 * @since 0.71 |
132 * @access private |
|
133 * @var array|null |
123 * @var array|null |
134 */ |
124 */ |
135 var $last_result; |
125 var $last_result; |
136 |
126 |
137 /** |
127 /** |
138 * MySQL result, which is either a resource or boolean. |
128 * MySQL result, which is either a resource or boolean. |
139 * |
129 * |
140 * @since 0.71 |
130 * @since 0.71 |
141 * @access protected |
|
142 * @var mixed |
131 * @var mixed |
143 */ |
132 */ |
144 protected $result; |
133 protected $result; |
145 |
134 |
146 /** |
135 /** |
147 * Cached column info, for sanity checking data before inserting |
136 * Cached column info, for sanity checking data before inserting |
148 * |
137 * |
149 * @since 4.2.0 |
138 * @since 4.2.0 |
150 * @access protected |
|
151 * @var array |
139 * @var array |
152 */ |
140 */ |
153 protected $col_meta = array(); |
141 protected $col_meta = array(); |
154 |
142 |
155 /** |
143 /** |
156 * Calculated character sets on tables |
144 * Calculated character sets on tables |
157 * |
145 * |
158 * @since 4.2.0 |
146 * @since 4.2.0 |
159 * @access protected |
|
160 * @var array |
147 * @var array |
161 */ |
148 */ |
162 protected $table_charset = array(); |
149 protected $table_charset = array(); |
163 |
150 |
164 /** |
151 /** |
165 * Whether text fields in the current query need to be sanity checked. |
152 * Whether text fields in the current query need to be sanity checked. |
166 * |
153 * |
167 * @since 4.2.0 |
154 * @since 4.2.0 |
168 * @access protected |
|
169 * @var bool |
155 * @var bool |
170 */ |
156 */ |
171 protected $check_current_query = true; |
157 protected $check_current_query = true; |
172 |
158 |
173 /** |
159 /** |
174 * Flag to ensure we don't run into recursion problems when checking the collation. |
160 * Flag to ensure we don't run into recursion problems when checking the collation. |
175 * |
161 * |
176 * @since 4.2.0 |
162 * @since 4.2.0 |
177 * @access private |
|
178 * @see wpdb::check_safe_collation() |
163 * @see wpdb::check_safe_collation() |
179 * @var boolean |
164 * @var bool |
180 */ |
165 */ |
181 private $checking_collation = false; |
166 private $checking_collation = false; |
182 |
167 |
183 /** |
168 /** |
184 * Saved info on the table column |
169 * Saved info on the table column |
185 * |
170 * |
186 * @since 0.71 |
171 * @since 0.71 |
187 * @access protected |
|
188 * @var array |
172 * @var array |
189 */ |
173 */ |
190 protected $col_info; |
174 protected $col_info; |
191 |
175 |
192 /** |
176 /** |
193 * Saved queries that were executed |
177 * Saved queries that were executed |
194 * |
178 * |
195 * @since 1.5.0 |
179 * @since 1.5.0 |
196 * @access private |
|
197 * @var array |
180 * @var array |
198 */ |
181 */ |
199 var $queries; |
182 var $queries; |
200 |
183 |
201 /** |
184 /** |
202 * The number of times to retry reconnecting before dying. |
185 * The number of times to retry reconnecting before dying. |
203 * |
186 * |
204 * @since 3.9.0 |
187 * @since 3.9.0 |
205 * @access protected |
|
206 * @see wpdb::check_connection() |
188 * @see wpdb::check_connection() |
207 * @var int |
189 * @var int |
208 */ |
190 */ |
209 protected $reconnect_retries = 5; |
191 protected $reconnect_retries = 5; |
210 |
192 |
214 * You can set this to have multiple WordPress installations |
196 * You can set this to have multiple WordPress installations |
215 * in a single database. The second reason is for possible |
197 * in a single database. The second reason is for possible |
216 * security precautions. |
198 * security precautions. |
217 * |
199 * |
218 * @since 2.5.0 |
200 * @since 2.5.0 |
219 * @access private |
|
220 * @var string |
201 * @var string |
221 */ |
202 */ |
222 var $prefix = ''; |
203 public $prefix = ''; |
223 |
204 |
224 /** |
205 /** |
225 * WordPress base table prefix. |
206 * WordPress base table prefix. |
226 * |
207 * |
227 * @since 3.0.0 |
208 * @since 3.0.0 |
228 * @access public |
|
229 * @var string |
209 * @var string |
230 */ |
210 */ |
231 public $base_prefix; |
211 public $base_prefix; |
232 |
212 |
233 /** |
213 /** |
234 * Whether the database queries are ready to start executing. |
214 * Whether the database queries are ready to start executing. |
235 * |
215 * |
236 * @since 2.3.2 |
216 * @since 2.3.2 |
237 * @access private |
|
238 * @var bool |
217 * @var bool |
239 */ |
218 */ |
240 var $ready = false; |
219 var $ready = false; |
241 |
220 |
242 /** |
221 /** |
243 * Blog ID. |
222 * Blog ID. |
244 * |
223 * |
245 * @since 3.0.0 |
224 * @since 3.0.0 |
246 * @access public |
|
247 * @var int |
225 * @var int |
248 */ |
226 */ |
249 public $blogid = 0; |
227 public $blogid = 0; |
250 |
228 |
251 /** |
229 /** |
252 * Site ID. |
230 * Site ID. |
253 * |
231 * |
254 * @since 3.0.0 |
232 * @since 3.0.0 |
255 * @access public |
|
256 * @var int |
233 * @var int |
257 */ |
234 */ |
258 public $siteid = 0; |
235 public $siteid = 0; |
259 |
236 |
260 /** |
237 /** |
261 * List of WordPress per-blog tables |
238 * List of WordPress per-blog tables |
262 * |
239 * |
263 * @since 2.5.0 |
240 * @since 2.5.0 |
264 * @access private |
|
265 * @see wpdb::tables() |
241 * @see wpdb::tables() |
266 * @var array |
242 * @var array |
267 */ |
243 */ |
268 var $tables = array( 'posts', 'comments', 'links', 'options', 'postmeta', |
244 var $tables = array( 'posts', 'comments', 'links', 'options', 'postmeta', |
269 'terms', 'term_taxonomy', 'term_relationships', 'commentmeta' ); |
245 'terms', 'term_taxonomy', 'term_relationships', 'termmeta', 'commentmeta' ); |
270 |
246 |
271 /** |
247 /** |
272 * List of deprecated WordPress tables |
248 * List of deprecated WordPress tables |
273 * |
249 * |
274 * categories, post2cat, and link2cat were deprecated in 2.3.0, db version 5539 |
250 * categories, post2cat, and link2cat were deprecated in 2.3.0, db version 5539 |
275 * |
251 * |
276 * @since 2.9.0 |
252 * @since 2.9.0 |
277 * @access private |
|
278 * @see wpdb::tables() |
253 * @see wpdb::tables() |
279 * @var array |
254 * @var array |
280 */ |
255 */ |
281 var $old_tables = array( 'categories', 'post2cat', 'link2cat' ); |
256 var $old_tables = array( 'categories', 'post2cat', 'link2cat' ); |
282 |
257 |
283 /** |
258 /** |
284 * List of WordPress global tables |
259 * List of WordPress global tables |
285 * |
260 * |
286 * @since 3.0.0 |
261 * @since 3.0.0 |
287 * @access private |
|
288 * @see wpdb::tables() |
262 * @see wpdb::tables() |
289 * @var array |
263 * @var array |
290 */ |
264 */ |
291 var $global_tables = array( 'users', 'usermeta' ); |
265 var $global_tables = array( 'users', 'usermeta' ); |
292 |
266 |
293 /** |
267 /** |
294 * List of Multisite global tables |
268 * List of Multisite global tables |
295 * |
269 * |
296 * @since 3.0.0 |
270 * @since 3.0.0 |
297 * @access private |
|
298 * @see wpdb::tables() |
271 * @see wpdb::tables() |
299 * @var array |
272 * @var array |
300 */ |
273 */ |
301 var $ms_global_tables = array( 'blogs', 'signups', 'site', 'sitemeta', |
274 var $ms_global_tables = array( 'blogs', 'signups', 'site', 'sitemeta', |
302 'sitecategories', 'registration_log', 'blog_versions' ); |
275 'sitecategories', 'registration_log', 'blog_versions' ); |
303 |
276 |
304 /** |
277 /** |
305 * WordPress Comments table |
278 * WordPress Comments table |
306 * |
279 * |
307 * @since 1.5.0 |
280 * @since 1.5.0 |
308 * @access public |
|
309 * @var string |
281 * @var string |
310 */ |
282 */ |
311 public $comments; |
283 public $comments; |
312 |
284 |
313 /** |
285 /** |
314 * WordPress Comment Metadata table |
286 * WordPress Comment Metadata table |
315 * |
287 * |
316 * @since 2.9.0 |
288 * @since 2.9.0 |
317 * @access public |
|
318 * @var string |
289 * @var string |
319 */ |
290 */ |
320 public $commentmeta; |
291 public $commentmeta; |
321 |
292 |
322 /** |
293 /** |
323 * WordPress Links table |
294 * WordPress Links table |
324 * |
295 * |
325 * @since 1.5.0 |
296 * @since 1.5.0 |
326 * @access public |
|
327 * @var string |
297 * @var string |
328 */ |
298 */ |
329 public $links; |
299 public $links; |
330 |
300 |
331 /** |
301 /** |
332 * WordPress Options table |
302 * WordPress Options table |
333 * |
303 * |
334 * @since 1.5.0 |
304 * @since 1.5.0 |
335 * @access public |
|
336 * @var string |
305 * @var string |
337 */ |
306 */ |
338 public $options; |
307 public $options; |
339 |
308 |
340 /** |
309 /** |
341 * WordPress Post Metadata table |
310 * WordPress Post Metadata table |
342 * |
311 * |
343 * @since 1.5.0 |
312 * @since 1.5.0 |
344 * @access public |
|
345 * @var string |
313 * @var string |
346 */ |
314 */ |
347 public $postmeta; |
315 public $postmeta; |
348 |
316 |
349 /** |
317 /** |
350 * WordPress Posts table |
318 * WordPress Posts table |
351 * |
319 * |
352 * @since 1.5.0 |
320 * @since 1.5.0 |
353 * @access public |
|
354 * @var string |
321 * @var string |
355 */ |
322 */ |
356 public $posts; |
323 public $posts; |
357 |
324 |
358 /** |
325 /** |
359 * WordPress Terms table |
326 * WordPress Terms table |
360 * |
327 * |
361 * @since 2.3.0 |
328 * @since 2.3.0 |
362 * @access public |
|
363 * @var string |
329 * @var string |
364 */ |
330 */ |
365 public $terms; |
331 public $terms; |
366 |
332 |
367 /** |
333 /** |
368 * WordPress Term Relationships table |
334 * WordPress Term Relationships table |
369 * |
335 * |
370 * @since 2.3.0 |
336 * @since 2.3.0 |
371 * @access public |
|
372 * @var string |
337 * @var string |
373 */ |
338 */ |
374 public $term_relationships; |
339 public $term_relationships; |
375 |
340 |
376 /** |
341 /** |
377 * WordPress Term Taxonomy table |
342 * WordPress Term Taxonomy table |
378 * |
343 * |
379 * @since 2.3.0 |
344 * @since 2.3.0 |
380 * @access public |
|
381 * @var string |
345 * @var string |
382 */ |
346 */ |
383 public $term_taxonomy; |
347 public $term_taxonomy; |
384 |
348 |
385 /* |
349 /** |
386 * Global and Multisite tables |
350 * WordPress Term Meta table. |
387 */ |
351 * |
|
352 * @since 4.4.0 |
|
353 * @var string |
|
354 */ |
|
355 public $termmeta; |
|
356 |
|
357 // |
|
358 // Global and Multisite tables |
|
359 // |
388 |
360 |
389 /** |
361 /** |
390 * WordPress User Metadata table |
362 * WordPress User Metadata table |
391 * |
363 * |
392 * @since 2.3.0 |
364 * @since 2.3.0 |
393 * @access public |
|
394 * @var string |
365 * @var string |
395 */ |
366 */ |
396 public $usermeta; |
367 public $usermeta; |
397 |
368 |
398 /** |
369 /** |
399 * WordPress Users table |
370 * WordPress Users table |
400 * |
371 * |
401 * @since 1.5.0 |
372 * @since 1.5.0 |
402 * @access public |
|
403 * @var string |
373 * @var string |
404 */ |
374 */ |
405 public $users; |
375 public $users; |
406 |
376 |
407 /** |
377 /** |
408 * Multisite Blogs table |
378 * Multisite Blogs table |
409 * |
379 * |
410 * @since 3.0.0 |
380 * @since 3.0.0 |
411 * @access public |
|
412 * @var string |
381 * @var string |
413 */ |
382 */ |
414 public $blogs; |
383 public $blogs; |
415 |
384 |
416 /** |
385 /** |
417 * Multisite Blog Versions table |
386 * Multisite Blog Versions table |
418 * |
387 * |
419 * @since 3.0.0 |
388 * @since 3.0.0 |
420 * @access public |
|
421 * @var string |
389 * @var string |
422 */ |
390 */ |
423 public $blog_versions; |
391 public $blog_versions; |
424 |
392 |
425 /** |
393 /** |
426 * Multisite Registration Log table |
394 * Multisite Registration Log table |
427 * |
395 * |
428 * @since 3.0.0 |
396 * @since 3.0.0 |
429 * @access public |
|
430 * @var string |
397 * @var string |
431 */ |
398 */ |
432 public $registration_log; |
399 public $registration_log; |
433 |
400 |
434 /** |
401 /** |
435 * Multisite Signups table |
402 * Multisite Signups table |
436 * |
403 * |
437 * @since 3.0.0 |
404 * @since 3.0.0 |
438 * @access public |
|
439 * @var string |
405 * @var string |
440 */ |
406 */ |
441 public $signups; |
407 public $signups; |
442 |
408 |
443 /** |
409 /** |
444 * Multisite Sites table |
410 * Multisite Sites table |
445 * |
411 * |
446 * @since 3.0.0 |
412 * @since 3.0.0 |
447 * @access public |
|
448 * @var string |
413 * @var string |
449 */ |
414 */ |
450 public $site; |
415 public $site; |
451 |
416 |
452 /** |
417 /** |
453 * Multisite Sitewide Terms table |
418 * Multisite Sitewide Terms table |
454 * |
419 * |
455 * @since 3.0.0 |
420 * @since 3.0.0 |
456 * @access public |
|
457 * @var string |
421 * @var string |
458 */ |
422 */ |
459 public $sitecategories; |
423 public $sitecategories; |
460 |
424 |
461 /** |
425 /** |
462 * Multisite Site Metadata table |
426 * Multisite Site Metadata table |
463 * |
427 * |
464 * @since 3.0.0 |
428 * @since 3.0.0 |
465 * @access public |
|
466 * @var string |
429 * @var string |
467 */ |
430 */ |
468 public $sitemeta; |
431 public $sitemeta; |
469 |
432 |
470 /** |
433 /** |
605 * to the database. |
555 * to the database. |
606 * |
556 * |
607 * @link https://core.trac.wordpress.org/ticket/3354 |
557 * @link https://core.trac.wordpress.org/ticket/3354 |
608 * @since 2.0.8 |
558 * @since 2.0.8 |
609 * |
559 * |
610 * @param string $dbuser MySQL database user |
560 * @global string $wp_version |
|
561 * |
|
562 * @param string $dbuser MySQL database user |
611 * @param string $dbpassword MySQL database password |
563 * @param string $dbpassword MySQL database password |
612 * @param string $dbname MySQL database name |
564 * @param string $dbname MySQL database name |
613 * @param string $dbhost MySQL database host |
565 * @param string $dbhost MySQL database host |
614 */ |
566 */ |
615 public function __construct( $dbuser, $dbpassword, $dbname, $dbhost ) { |
567 public function __construct( $dbuser, $dbpassword, $dbname, $dbhost ) { |
616 register_shutdown_function( array( $this, '__destruct' ) ); |
568 register_shutdown_function( array( $this, '__destruct' ) ); |
617 |
569 |
618 if ( WP_DEBUG && WP_DEBUG_DISPLAY ) |
570 if ( WP_DEBUG && WP_DEBUG_DISPLAY ) |
619 $this->show_errors(); |
571 $this->show_errors(); |
620 |
572 |
621 /* Use ext/mysqli if it exists and: |
573 // Use ext/mysqli if it exists unless WP_USE_EXT_MYSQL is defined as true |
622 * - WP_USE_EXT_MYSQL is defined as false, or |
|
623 * - We are a development version of WordPress, or |
|
624 * - We are running PHP 5.5 or greater, or |
|
625 * - ext/mysql is not loaded. |
|
626 */ |
|
627 if ( function_exists( 'mysqli_connect' ) ) { |
574 if ( function_exists( 'mysqli_connect' ) ) { |
|
575 $this->use_mysqli = true; |
|
576 |
628 if ( defined( 'WP_USE_EXT_MYSQL' ) ) { |
577 if ( defined( 'WP_USE_EXT_MYSQL' ) ) { |
629 $this->use_mysqli = ! WP_USE_EXT_MYSQL; |
578 $this->use_mysqli = ! WP_USE_EXT_MYSQL; |
630 } elseif ( version_compare( phpversion(), '5.5', '>=' ) || ! function_exists( 'mysql_connect' ) ) { |
|
631 $this->use_mysqli = true; |
|
632 } elseif ( false !== strpos( $GLOBALS['wp_version'], '-' ) ) { |
|
633 $this->use_mysqli = true; |
|
634 } |
579 } |
635 } |
580 } |
636 |
581 |
637 $this->dbuser = $dbuser; |
582 $this->dbuser = $dbuser; |
638 $this->dbpassword = $dbpassword; |
583 $this->dbpassword = $dbpassword; |
721 * Set $this->charset and $this->collate |
666 * Set $this->charset and $this->collate |
722 * |
667 * |
723 * @since 3.1.0 |
668 * @since 3.1.0 |
724 */ |
669 */ |
725 public function init_charset() { |
670 public function init_charset() { |
|
671 $charset = ''; |
|
672 $collate = ''; |
|
673 |
726 if ( function_exists('is_multisite') && is_multisite() ) { |
674 if ( function_exists('is_multisite') && is_multisite() ) { |
727 $this->charset = 'utf8'; |
675 $charset = 'utf8'; |
728 if ( defined( 'DB_COLLATE' ) && DB_COLLATE ) { |
676 if ( defined( 'DB_COLLATE' ) && DB_COLLATE ) { |
729 $this->collate = DB_COLLATE; |
677 $collate = DB_COLLATE; |
730 } else { |
678 } else { |
731 $this->collate = 'utf8_general_ci'; |
679 $collate = 'utf8_general_ci'; |
732 } |
680 } |
733 } elseif ( defined( 'DB_COLLATE' ) ) { |
681 } elseif ( defined( 'DB_COLLATE' ) ) { |
734 $this->collate = DB_COLLATE; |
682 $collate = DB_COLLATE; |
735 } |
683 } |
736 |
684 |
737 if ( defined( 'DB_CHARSET' ) ) { |
685 if ( defined( 'DB_CHARSET' ) ) { |
738 $this->charset = DB_CHARSET; |
686 $charset = DB_CHARSET; |
739 } |
687 } |
740 |
688 |
741 if ( ( $this->use_mysqli && ! ( $this->dbh instanceof mysqli ) ) |
689 $charset_collate = $this->determine_charset( $charset, $collate ); |
742 || ( empty( $this->dbh ) || ! ( $this->dbh instanceof mysqli ) ) ) { |
690 |
743 return; |
691 $this->charset = $charset_collate['charset']; |
744 } |
692 $this->collate = $charset_collate['collate']; |
745 |
693 } |
746 if ( 'utf8' === $this->charset && $this->has_cap( 'utf8mb4' ) ) { |
694 |
747 $this->charset = 'utf8mb4'; |
695 /** |
748 } |
696 * Determines the best charset and collation to use given a charset and collation. |
749 |
697 * |
750 if ( 'utf8mb4' === $this->charset && ( ! $this->collate || stripos( $this->collate, 'utf8_' ) === 0 ) ) { |
698 * For example, when able, utf8mb4 should be used instead of utf8. |
751 $this->collate = 'utf8mb4_unicode_ci'; |
699 * |
752 } |
700 * @since 4.6.0 |
|
701 * |
|
702 * @param string $charset The character set to check. |
|
703 * @param string $collate The collation to check. |
|
704 * @return array The most appropriate character set and collation to use. |
|
705 */ |
|
706 public function determine_charset( $charset, $collate ) { |
|
707 if ( ( $this->use_mysqli && ! ( $this->dbh instanceof mysqli ) ) || empty( $this->dbh ) ) { |
|
708 return compact( 'charset', 'collate' ); |
|
709 } |
|
710 |
|
711 if ( 'utf8' === $charset && $this->has_cap( 'utf8mb4' ) ) { |
|
712 $charset = 'utf8mb4'; |
|
713 } |
|
714 |
|
715 if ( 'utf8mb4' === $charset && ! $this->has_cap( 'utf8mb4' ) ) { |
|
716 $charset = 'utf8'; |
|
717 $collate = str_replace( 'utf8mb4_', 'utf8_', $collate ); |
|
718 } |
|
719 |
|
720 if ( 'utf8mb4' === $charset ) { |
|
721 // _general_ is outdated, so we can upgrade it to _unicode_, instead. |
|
722 if ( ! $collate || 'utf8_general_ci' === $collate ) { |
|
723 $collate = 'utf8mb4_unicode_ci'; |
|
724 } else { |
|
725 $collate = str_replace( 'utf8_', 'utf8mb4_', $collate ); |
|
726 } |
|
727 } |
|
728 |
|
729 // _unicode_520_ is a better collation, we should use that when it's available. |
|
730 if ( $this->has_cap( 'utf8mb4_520' ) && 'utf8mb4_unicode_ci' === $collate ) { |
|
731 $collate = 'utf8mb4_unicode_520_ci'; |
|
732 } |
|
733 |
|
734 return compact( 'charset', 'collate' ); |
753 } |
735 } |
754 |
736 |
755 /** |
737 /** |
756 * Sets the connection's character set. |
738 * Sets the connection's character set. |
757 * |
739 * |
765 if ( ! isset( $charset ) ) |
747 if ( ! isset( $charset ) ) |
766 $charset = $this->charset; |
748 $charset = $this->charset; |
767 if ( ! isset( $collate ) ) |
749 if ( ! isset( $collate ) ) |
768 $collate = $this->collate; |
750 $collate = $this->collate; |
769 if ( $this->has_cap( 'collation' ) && ! empty( $charset ) ) { |
751 if ( $this->has_cap( 'collation' ) && ! empty( $charset ) ) { |
|
752 $set_charset_succeeded = true; |
|
753 |
770 if ( $this->use_mysqli ) { |
754 if ( $this->use_mysqli ) { |
771 if ( function_exists( 'mysqli_set_charset' ) && $this->has_cap( 'set_charset' ) ) { |
755 if ( function_exists( 'mysqli_set_charset' ) && $this->has_cap( 'set_charset' ) ) { |
772 mysqli_set_charset( $dbh, $charset ); |
756 $set_charset_succeeded = mysqli_set_charset( $dbh, $charset ); |
773 } else { |
757 } |
|
758 |
|
759 if ( $set_charset_succeeded ) { |
774 $query = $this->prepare( 'SET NAMES %s', $charset ); |
760 $query = $this->prepare( 'SET NAMES %s', $charset ); |
775 if ( ! empty( $collate ) ) |
761 if ( ! empty( $collate ) ) |
776 $query .= $this->prepare( ' COLLATE %s', $collate ); |
762 $query .= $this->prepare( ' COLLATE %s', $collate ); |
777 mysqli_query( $dbh, $query ); |
763 mysqli_query( $dbh, $query ); |
778 } |
764 } |
779 } else { |
765 } else { |
780 if ( function_exists( 'mysql_set_charset' ) && $this->has_cap( 'set_charset' ) ) { |
766 if ( function_exists( 'mysql_set_charset' ) && $this->has_cap( 'set_charset' ) ) { |
781 mysql_set_charset( $charset, $dbh ); |
767 $set_charset_succeeded = mysql_set_charset( $charset, $dbh ); |
782 } else { |
768 } |
|
769 if ( $set_charset_succeeded ) { |
783 $query = $this->prepare( 'SET NAMES %s', $charset ); |
770 $query = $this->prepare( 'SET NAMES %s', $charset ); |
784 if ( ! empty( $collate ) ) |
771 if ( ! empty( $collate ) ) |
785 $query .= $this->prepare( ' COLLATE %s', $collate ); |
772 $query .= $this->prepare( ' COLLATE %s', $collate ); |
786 mysql_query( $query, $dbh ); |
773 mysql_query( $query, $dbh ); |
787 } |
774 } |
1023 * The database name will be changed based on the current database |
1011 * The database name will be changed based on the current database |
1024 * connection. On failure, the execution will bail and display an DB error. |
1012 * connection. On failure, the execution will bail and display an DB error. |
1025 * |
1013 * |
1026 * @since 0.71 |
1014 * @since 0.71 |
1027 * |
1015 * |
1028 * @param string $db MySQL database name |
1016 * @param string $db MySQL database name |
1029 * @param resource $dbh Optional link identifier. |
1017 * @param resource|null $dbh Optional link identifier. |
1030 * @return null Always null. |
|
1031 */ |
1018 */ |
1032 public function select( $db, $dbh = null ) { |
1019 public function select( $db, $dbh = null ) { |
1033 if ( is_null($dbh) ) |
1020 if ( is_null($dbh) ) |
1034 $dbh = $this->dbh; |
1021 $dbh = $this->dbh; |
1035 |
1022 |
1036 if ( $this->use_mysqli ) { |
1023 if ( $this->use_mysqli ) { |
1037 $success = @mysqli_select_db( $dbh, $db ); |
1024 $success = mysqli_select_db( $dbh, $db ); |
1038 } else { |
1025 } else { |
1039 $success = @mysql_select_db( $db, $dbh ); |
1026 $success = mysql_select_db( $db, $dbh ); |
1040 } |
1027 } |
1041 if ( ! $success ) { |
1028 if ( ! $success ) { |
1042 $this->ready = false; |
1029 $this->ready = false; |
1043 if ( ! did_action( 'template_redirect' ) ) { |
1030 if ( ! did_action( 'template_redirect' ) ) { |
1044 wp_load_translations_early(); |
1031 wp_load_translations_early(); |
1045 $this->bail( sprintf( __( '<h1>Can’t select database</h1> |
1032 |
1046 <p>We were able to connect to the database server (which means your username and password is okay) but not able to select the <code>%1$s</code> database.</p> |
1033 $message = '<h1>' . __( 'Can’t select database' ) . "</h1>\n"; |
1047 <ul> |
1034 |
1048 <li>Are you sure it exists?</li> |
1035 $message .= '<p>' . sprintf( |
1049 <li>Does the user <code>%2$s</code> have permission to use the <code>%1$s</code> database?</li> |
1036 /* translators: %s: database name */ |
1050 <li>On some systems the name of your database is prefixed with your username, so it would be like <code>username_%1$s</code>. Could that be the problem?</li> |
1037 __( 'We were able to connect to the database server (which means your username and password is okay) but not able to select the %s database.' ), |
1051 </ul> |
1038 '<code>' . htmlspecialchars( $db, ENT_QUOTES ) . '</code>' |
1052 <p>If you don\'t know how to set up a database you should <strong>contact your host</strong>. If all else fails you may find help at the <a href="https://wordpress.org/support/">WordPress Support Forums</a>.</p>' ), htmlspecialchars( $db, ENT_QUOTES ), htmlspecialchars( $this->dbuser, ENT_QUOTES ) ), 'db_select_fail' ); |
1039 ) . "</p>\n"; |
1053 } |
1040 |
1054 return; |
1041 $message .= "<ul>\n"; |
|
1042 $message .= '<li>' . __( 'Are you sure it exists?' ) . "</li>\n"; |
|
1043 |
|
1044 $message .= '<li>' . sprintf( |
|
1045 /* translators: 1: database user, 2: database name */ |
|
1046 __( 'Does the user %1$s have permission to use the %2$s database?' ), |
|
1047 '<code>' . htmlspecialchars( $this->dbuser, ENT_QUOTES ) . '</code>', |
|
1048 '<code>' . htmlspecialchars( $db, ENT_QUOTES ) . '</code>' |
|
1049 ) . "</li>\n"; |
|
1050 |
|
1051 $message .= '<li>' . sprintf( |
|
1052 /* translators: %s: database name */ |
|
1053 __( 'On some systems the name of your database is prefixed with your username, so it would be like <code>username_%1$s</code>. Could that be the problem?' ), |
|
1054 htmlspecialchars( $db, ENT_QUOTES ) |
|
1055 ). "</li>\n"; |
|
1056 |
|
1057 $message .= "</ul>\n"; |
|
1058 |
|
1059 $message .= '<p>' . sprintf( |
|
1060 /* translators: %s: support forums URL */ |
|
1061 __( 'If you don’t know how to set up a database you should <strong>contact your host</strong>. If all else fails you may find help at the <a href="%s">WordPress Support Forums</a>.' ), |
|
1062 __( 'https://wordpress.org/support/' ) |
|
1063 ) . "</p>\n"; |
|
1064 |
|
1065 $this->bail( $message, 'db_select_fail' ); |
|
1066 } |
1055 } |
1067 } |
1056 } |
1068 } |
1057 |
1069 |
1058 /** |
1070 /** |
1059 * Do not use, deprecated. |
1071 * Do not use, deprecated. |
1060 * |
1072 * |
1061 * Use esc_sql() or wpdb::prepare() instead. |
1073 * Use esc_sql() or wpdb::prepare() instead. |
1062 * |
1074 * |
1063 * @since 2.8.0 |
1075 * @since 2.8.0 |
1064 * @deprecated 3.6.0 |
1076 * @deprecated 3.6.0 Use wpdb::prepare() |
1065 * @see wpdb::prepare |
1077 * @see wpdb::prepare |
1066 * @see esc_sql() |
1078 * @see esc_sql() |
1067 * @access private |
|
1068 * |
1079 * |
1069 * @param string $string |
1080 * @param string $string |
1070 * @return string |
1081 * @return string |
1071 */ |
1082 */ |
1072 function _weak_escape( $string ) { |
1083 function _weak_escape( $string ) { |
1073 if ( func_num_args() === 1 && function_exists( '_deprecated_function' ) ) |
1084 if ( func_num_args() === 1 && function_exists( '_deprecated_function' ) ) |
1074 _deprecated_function( __METHOD__, '3.6', 'wpdb::prepare() or esc_sql()' ); |
1085 _deprecated_function( __METHOD__, '3.6.0', 'wpdb::prepare() or esc_sql()' ); |
1075 return addslashes( $string ); |
1086 return addslashes( $string ); |
1076 } |
1087 } |
1077 |
1088 |
1078 /** |
1089 /** |
1079 * Real escape, using mysqli_real_escape_string() or mysql_real_escape_string() |
1090 * Real escape, using mysqli_real_escape_string() or mysql_real_escape_string() |
1080 * |
1091 * |
1081 * @see mysqli_real_escape_string() |
1092 * @see mysqli_real_escape_string() |
1082 * @see mysql_real_escape_string() |
1093 * @see mysql_real_escape_string() |
1083 * @since 2.8.0 |
1094 * @since 2.8.0 |
1084 * @access private |
|
1085 * |
1095 * |
1086 * @param string $string to escape |
1096 * @param string $string to escape |
1087 * @return string escaped |
1097 * @return string escaped |
1088 */ |
1098 */ |
1089 function _real_escape( $string ) { |
1099 function _real_escape( $string ) { |
1090 if ( $this->dbh ) { |
1100 if ( $this->dbh ) { |
1091 if ( $this->use_mysqli ) { |
1101 if ( $this->use_mysqli ) { |
1092 return mysqli_real_escape_string( $this->dbh, $string ); |
1102 $escaped = mysqli_real_escape_string( $this->dbh, $string ); |
1093 } else { |
1103 } else { |
1094 return mysql_real_escape_string( $string, $this->dbh ); |
1104 $escaped = mysql_real_escape_string( $string, $this->dbh ); |
1095 } |
1105 } |
1096 } |
|
1097 |
|
1098 $class = get_class( $this ); |
|
1099 if ( function_exists( '__' ) ) { |
|
1100 _doing_it_wrong( $class, sprintf( __( '%s must set a database connection for use with escaping.' ), $class ), E_USER_NOTICE ); |
|
1101 } else { |
1106 } else { |
1102 _doing_it_wrong( $class, sprintf( '%s must set a database connection for use with escaping.', $class ), E_USER_NOTICE ); |
1107 $class = get_class( $this ); |
1103 } |
1108 if ( function_exists( '__' ) ) { |
1104 return addslashes( $string ); |
1109 /* translators: %s: database access abstraction class, usually wpdb or a class extending wpdb */ |
|
1110 _doing_it_wrong( $class, sprintf( __( '%s must set a database connection for use with escaping.' ), $class ), '3.6.0' ); |
|
1111 } else { |
|
1112 _doing_it_wrong( $class, sprintf( '%s must set a database connection for use with escaping.', $class ), '3.6.0' ); |
|
1113 } |
|
1114 $escaped = addslashes( $string ); |
|
1115 } |
|
1116 |
|
1117 return $this->add_placeholder_escape( $escaped ); |
1105 } |
1118 } |
1106 |
1119 |
1107 /** |
1120 /** |
1108 * Escape data. Works on arrays. |
1121 * Escape data. Works on arrays. |
1109 * |
1122 * |
1110 * @uses wpdb::_real_escape() |
1123 * @uses wpdb::_real_escape() |
1111 * @since 2.8.0 |
1124 * @since 2.8.0 |
1112 * @access private |
|
1113 * |
1125 * |
1114 * @param string|array $data |
1126 * @param string|array $data |
1115 * @return string|array escaped |
1127 * @return string|array escaped |
1116 */ |
1128 */ |
1117 function _escape( $data ) { |
1129 public function _escape( $data ) { |
1118 if ( is_array( $data ) ) { |
1130 if ( is_array( $data ) ) { |
1119 foreach ( $data as $k => $v ) { |
1131 foreach ( $data as $k => $v ) { |
1120 if ( is_array($v) ) |
1132 if ( is_array( $v ) ) { |
1121 $data[$k] = $this->_escape( $v ); |
1133 $data[$k] = $this->_escape( $v ); |
1122 else |
1134 } else { |
1123 $data[$k] = $this->_real_escape( $v ); |
1135 $data[$k] = $this->_real_escape( $v ); |
|
1136 } |
1124 } |
1137 } |
1125 } else { |
1138 } else { |
1126 $data = $this->_real_escape( $data ); |
1139 $data = $this->_real_escape( $data ); |
1127 } |
1140 } |
1128 |
1141 |
1161 |
1174 |
1162 /** |
1175 /** |
1163 * Escapes content by reference for insertion into the database, for security |
1176 * Escapes content by reference for insertion into the database, for security |
1164 * |
1177 * |
1165 * @uses wpdb::_real_escape() |
1178 * @uses wpdb::_real_escape() |
|
1179 * |
1166 * @since 2.3.0 |
1180 * @since 2.3.0 |
|
1181 * |
1167 * @param string $string to escape |
1182 * @param string $string to escape |
1168 * @return void |
|
1169 */ |
1183 */ |
1170 public function escape_by_ref( &$string ) { |
1184 public function escape_by_ref( &$string ) { |
1171 if ( ! is_float( $string ) ) |
1185 if ( ! is_float( $string ) ) |
1172 $string = $this->_real_escape( $string ); |
1186 $string = $this->_real_escape( $string ); |
1173 } |
1187 } |
1174 |
1188 |
1175 /** |
1189 /** |
1176 * Prepares a SQL query for safe execution. Uses sprintf()-like syntax. |
1190 * Prepares a SQL query for safe execution. Uses sprintf()-like syntax. |
1177 * |
1191 * |
1178 * The following directives can be used in the query format string: |
1192 * The following placeholders can be used in the query string: |
1179 * %d (integer) |
1193 * %d (integer) |
1180 * %f (float) |
1194 * %f (float) |
1181 * %s (string) |
1195 * %s (string) |
1182 * %% (literal percentage sign - no argument needed) |
1196 * |
1183 * |
1197 * All placeholders MUST be left unquoted in the query string. A corresponding argument MUST be passed for each placeholder. |
1184 * All of %d, %f, and %s are to be left unquoted in the query string and they need an argument passed for them. |
1198 * |
1185 * Literals (%) as parts of the query must be properly written as %%. |
1199 * For compatibility with old behavior, numbered or formatted string placeholders (eg, %1$s, %5s) will not have quotes |
1186 * |
1200 * added by this function, so should be passed with appropriate quotes around them for your usage. |
1187 * This function only supports a small subset of the sprintf syntax; it only supports %d (integer), %f (float), and %s (string). |
1201 * |
1188 * Does not support sign, padding, alignment, width or precision specifiers. |
1202 * Literal percentage signs (%) in the query string must be written as %%. Percentage wildcards (for example, |
1189 * Does not support argument numbering/swapping. |
1203 * to use in LIKE syntax) must be passed via a substitution argument containing the complete LIKE string, these |
1190 * |
1204 * cannot be inserted directly in the query string. Also see {@see esc_like()}. |
1191 * May be called like {@link http://php.net/sprintf sprintf()} or like {@link http://php.net/vsprintf vsprintf()}. |
1205 * |
1192 * |
1206 * Arguments may be passed as individual arguments to the method, or as a single array containing all arguments. A combination |
1193 * Both %d and %s should be left unquoted in the query string. |
1207 * of the two is not supported. |
1194 * |
1208 * |
1195 * wpdb::prepare( "SELECT * FROM `table` WHERE `column` = %s AND `field` = %d", 'foo', 1337 ) |
1209 * Examples: |
1196 * wpdb::prepare( "SELECT DATE_FORMAT(`field`, '%%c') FROM `table` WHERE `column` = %s", 'foo' ); |
1210 * $wpdb->prepare( "SELECT * FROM `table` WHERE `column` = %s AND `field` = %d OR `other_field` LIKE %s", array( 'foo', 1337, '%bar' ) ); |
1197 * |
1211 * $wpdb->prepare( "SELECT DATE_FORMAT(`field`, '%%c') FROM `table` WHERE `column` = %s", 'foo' ); |
1198 * @link http://php.net/sprintf Description of syntax. |
1212 * |
|
1213 * @link https://secure.php.net/sprintf Description of syntax. |
1199 * @since 2.3.0 |
1214 * @since 2.3.0 |
1200 * |
1215 * |
1201 * @param string $query Query statement with sprintf()-like placeholders |
1216 * @param string $query Query statement with sprintf()-like placeholders |
1202 * @param array|mixed $args The array of variables to substitute into the query's placeholders if being called like |
1217 * @param array|mixed $args The array of variables to substitute into the query's placeholders if being called with an array of arguments, |
1203 * {@link http://php.net/vsprintf vsprintf()}, or the first variable to substitute into the query's placeholders if |
1218 * or the first variable to substitute into the query's placeholders if being called with individual arguments. |
1204 * being called like {@link http://php.net/sprintf sprintf()}. |
1219 * @param mixed $args,... further variables to substitute into the query's placeholders if being called wih individual arguments. |
1205 * @param mixed $args,... further variables to substitute into the query's placeholders if being called like |
1220 * @return string|void Sanitized query string, if there is a query to prepare. |
1206 * {@link http://php.net/sprintf sprintf()}. |
|
1207 * @return null|false|string Sanitized query string, null if there is no query, false if there is an error and string |
|
1208 * if there was something to prepare |
|
1209 */ |
1221 */ |
1210 public function prepare( $query, $args ) { |
1222 public function prepare( $query, $args ) { |
1211 if ( is_null( $query ) ) |
1223 if ( is_null( $query ) ) { |
1212 return; |
1224 return; |
|
1225 } |
1213 |
1226 |
1214 // This is not meant to be foolproof -- but it will catch obviously incorrect usage. |
1227 // This is not meant to be foolproof -- but it will catch obviously incorrect usage. |
1215 if ( strpos( $query, '%' ) === false ) { |
1228 if ( strpos( $query, '%' ) === false ) { |
1216 _doing_it_wrong( 'wpdb::prepare', sprintf( __( 'The query argument of %s must have a placeholder.' ), 'wpdb::prepare()' ), '3.9' ); |
1229 wp_load_translations_early(); |
|
1230 _doing_it_wrong( 'wpdb::prepare', sprintf( __( 'The query argument of %s must have a placeholder.' ), 'wpdb::prepare()' ), '3.9.0' ); |
1217 } |
1231 } |
1218 |
1232 |
1219 $args = func_get_args(); |
1233 $args = func_get_args(); |
1220 array_shift( $args ); |
1234 array_shift( $args ); |
1221 // If args were passed as an array (as in vsprintf), move them up |
1235 |
1222 if ( isset( $args[0] ) && is_array($args[0]) ) |
1236 // If args were passed as an array (as in vsprintf), move them up. |
|
1237 $passed_as_array = false; |
|
1238 if ( is_array( $args[0] ) && count( $args ) == 1 ) { |
|
1239 $passed_as_array = true; |
1223 $args = $args[0]; |
1240 $args = $args[0]; |
1224 $query = str_replace( "'%s'", '%s', $query ); // in case someone mistakenly already singlequoted it |
1241 } |
1225 $query = str_replace( '"%s"', '%s', $query ); // doublequote unquoting |
1242 |
1226 $query = preg_replace( '|(?<!%)%f|' , '%F', $query ); // Force floats to be locale unaware |
1243 foreach ( $args as $arg ) { |
1227 $query = preg_replace( '|(?<!%)%s|', "'%s'", $query ); // quote the strings, avoiding escaped strings like %%s |
1244 if ( ! is_scalar( $arg ) && ! is_null( $arg ) ) { |
|
1245 wp_load_translations_early(); |
|
1246 _doing_it_wrong( 'wpdb::prepare', sprintf( __( 'Unsupported value type (%s).' ), gettype( $arg ) ), '4.8.2' ); |
|
1247 } |
|
1248 } |
|
1249 |
|
1250 /* |
|
1251 * Specify the formatting allowed in a placeholder. The following are allowed: |
|
1252 * |
|
1253 * - Sign specifier. eg, $+d |
|
1254 * - Numbered placeholders. eg, %1$s |
|
1255 * - Padding specifier, including custom padding characters. eg, %05s, %'#5s |
|
1256 * - Alignment specifier. eg, %05-s |
|
1257 * - Precision specifier. eg, %.2f |
|
1258 */ |
|
1259 $allowed_format = '(?:[1-9][0-9]*[$])?[-+0-9]*(?: |0|\'.)?[-+0-9]*(?:\.[0-9]+)?'; |
|
1260 |
|
1261 /* |
|
1262 * If a %s placeholder already has quotes around it, removing the existing quotes and re-inserting them |
|
1263 * ensures the quotes are consistent. |
|
1264 * |
|
1265 * For backwards compatibility, this is only applied to %s, and not to placeholders like %1$s, which are frequently |
|
1266 * used in the middle of longer strings, or as table name placeholders. |
|
1267 */ |
|
1268 $query = str_replace( "'%s'", '%s', $query ); // Strip any existing single quotes. |
|
1269 $query = str_replace( '"%s"', '%s', $query ); // Strip any existing double quotes. |
|
1270 $query = preg_replace( '/(?<!%)%s/', "'%s'", $query ); // Quote the strings, avoiding escaped strings like %%s. |
|
1271 |
|
1272 $query = preg_replace( "/(?<!%)(%($allowed_format)?f)/" , '%\\2F', $query ); // Force floats to be locale unaware. |
|
1273 |
|
1274 $query = preg_replace( "/%(?:%|$|(?!($allowed_format)?[sdF]))/", '%%\\1', $query ); // Escape any unescaped percents. |
|
1275 |
|
1276 // Count the number of valid placeholders in the query. |
|
1277 $placeholders = preg_match_all( "/(^|[^%]|(%%)+)%($allowed_format)?[sdF]/", $query, $matches ); |
|
1278 |
|
1279 if ( count( $args ) !== $placeholders ) { |
|
1280 if ( 1 === $placeholders && $passed_as_array ) { |
|
1281 // If the passed query only expected one argument, but the wrong number of arguments were sent as an array, bail. |
|
1282 wp_load_translations_early(); |
|
1283 _doing_it_wrong( 'wpdb::prepare', __( 'The query only expected one placeholder, but an array of multiple placeholders was sent.' ), '4.9.0' ); |
|
1284 |
|
1285 return; |
|
1286 } else { |
|
1287 /* |
|
1288 * If we don't have the right number of placeholders, but they were passed as individual arguments, |
|
1289 * or we were expecting multiple arguments in an array, throw a warning. |
|
1290 */ |
|
1291 wp_load_translations_early(); |
|
1292 _doing_it_wrong( 'wpdb::prepare', |
|
1293 /* translators: 1: number of placeholders, 2: number of arguments passed */ |
|
1294 sprintf( __( 'The query does not contain the correct number of placeholders (%1$d) for the number of arguments passed (%2$d).' ), |
|
1295 $placeholders, |
|
1296 count( $args ) ), |
|
1297 '4.8.3' |
|
1298 ); |
|
1299 } |
|
1300 } |
|
1301 |
1228 array_walk( $args, array( $this, 'escape_by_ref' ) ); |
1302 array_walk( $args, array( $this, 'escape_by_ref' ) ); |
1229 return @vsprintf( $query, $args ); |
1303 $query = @vsprintf( $query, $args ); |
|
1304 |
|
1305 return $this->add_placeholder_escape( $query ); |
1230 } |
1306 } |
1231 |
1307 |
1232 /** |
1308 /** |
1233 * First half of escaping for LIKE special characters % and _ before preparing for MySQL. |
1309 * First half of escaping for LIKE special characters % and _ before preparing for MySQL. |
1234 * |
1310 * |
1235 * Use this only before wpdb::prepare() or esc_sql(). Reversing the order is very bad for security. |
1311 * Use this only before wpdb::prepare() or esc_sql(). Reversing the order is very bad for security. |
1236 * |
1312 * |
1237 * Example Prepared Statement: |
1313 * Example Prepared Statement: |
1238 * $wild = '%'; |
1314 * |
1239 * $find = 'only 43% of planets'; |
1315 * $wild = '%'; |
1240 * $like = $wild . $wpdb->esc_like( $find ) . $wild; |
1316 * $find = 'only 43% of planets'; |
1241 * $sql = $wpdb->prepare( "SELECT * FROM $wpdb->posts WHERE post_content LIKE %s", $like ); |
1317 * $like = $wild . $wpdb->esc_like( $find ) . $wild; |
|
1318 * $sql = $wpdb->prepare( "SELECT * FROM $wpdb->posts WHERE post_content LIKE %s", $like ); |
1242 * |
1319 * |
1243 * Example Escape Chain: |
1320 * Example Escape Chain: |
1244 * $sql = esc_sql( $wpdb->esc_like( $input ) ); |
1321 * |
|
1322 * $sql = esc_sql( $wpdb->esc_like( $input ) ); |
1245 * |
1323 * |
1246 * @since 4.0.0 |
1324 * @since 4.0.0 |
1247 * @access public |
|
1248 * |
1325 * |
1249 * @param string $text The raw text to be escaped. The input typed by the user should have no |
1326 * @param string $text The raw text to be escaped. The input typed by the user should have no |
1250 * extra or deleted slashes. |
1327 * extra or deleted slashes. |
1251 * @return string Text in the form of a LIKE phrase. The output is not SQL safe. Call $wpdb::prepare() |
1328 * @return string Text in the form of a LIKE phrase. The output is not SQL safe. Call $wpdb::prepare() |
1252 * or real_escape next. |
1329 * or real_escape next. |
1279 if ( $this->suppress_errors ) |
1356 if ( $this->suppress_errors ) |
1280 return false; |
1357 return false; |
1281 |
1358 |
1282 wp_load_translations_early(); |
1359 wp_load_translations_early(); |
1283 |
1360 |
1284 if ( $caller = $this->get_caller() ) |
1361 if ( $caller = $this->get_caller() ) { |
|
1362 /* translators: 1: Database error message, 2: SQL query, 3: Name of the calling function */ |
1285 $error_str = sprintf( __( 'WordPress database error %1$s for query %2$s made by %3$s' ), $str, $this->last_query, $caller ); |
1363 $error_str = sprintf( __( 'WordPress database error %1$s for query %2$s made by %3$s' ), $str, $this->last_query, $caller ); |
1286 else |
1364 } else { |
|
1365 /* translators: 1: Database error message, 2: SQL query */ |
1287 $error_str = sprintf( __( 'WordPress database error %1$s for query %2$s' ), $str, $this->last_query ); |
1366 $error_str = sprintf( __( 'WordPress database error %1$s for query %2$s' ), $str, $this->last_query ); |
|
1367 } |
1288 |
1368 |
1289 error_log( $error_str ); |
1369 error_log( $error_str ); |
1290 |
1370 |
1291 // Are we showing errors? |
1371 // Are we showing errors? |
1292 if ( ! $this->show_errors ) |
1372 if ( ! $this->show_errors ) |
1293 return false; |
1373 return false; |
1294 |
1374 |
1295 // If there is an error then take note of it |
1375 // If there is an error then take note of it |
1296 if ( is_multisite() ) { |
1376 if ( is_multisite() ) { |
1297 $msg = "WordPress database error: [$str]\n{$this->last_query}\n"; |
1377 $msg = sprintf( |
1298 if ( defined( 'ERRORLOGFILE' ) ) |
1378 "%s [%s]\n%s\n", |
|
1379 __( 'WordPress database error:' ), |
|
1380 $str, |
|
1381 $this->last_query |
|
1382 ); |
|
1383 |
|
1384 if ( defined( 'ERRORLOGFILE' ) ) { |
1299 error_log( $msg, 3, ERRORLOGFILE ); |
1385 error_log( $msg, 3, ERRORLOGFILE ); |
1300 if ( defined( 'DIEONDBERROR' ) ) |
1386 } |
|
1387 if ( defined( 'DIEONDBERROR' ) ) { |
1301 wp_die( $msg ); |
1388 wp_die( $msg ); |
|
1389 } |
1302 } else { |
1390 } else { |
1303 $str = htmlspecialchars( $str, ENT_QUOTES ); |
1391 $str = htmlspecialchars( $str, ENT_QUOTES ); |
1304 $query = htmlspecialchars( $this->last_query, ENT_QUOTES ); |
1392 $query = htmlspecialchars( $this->last_query, ENT_QUOTES ); |
1305 |
1393 |
1306 print "<div id='error'> |
1394 printf( |
1307 <p class='wpdberror'><strong>WordPress database error:</strong> [$str]<br /> |
1395 '<div id="error"><p class="wpdberror"><strong>%s</strong> [%s]<br /><code>%s</code></p></div>', |
1308 <code>$query</code></p> |
1396 __( 'WordPress database error:' ), |
1309 </div>"; |
1397 $str, |
|
1398 $query |
|
1399 ); |
1310 } |
1400 } |
1311 } |
1401 } |
1312 |
1402 |
1313 /** |
1403 /** |
1314 * Enables showing of database errors. |
1404 * Enables showing of database errors. |
1418 $client_flags = defined( 'MYSQL_CLIENT_FLAGS' ) ? MYSQL_CLIENT_FLAGS : 0; |
1506 $client_flags = defined( 'MYSQL_CLIENT_FLAGS' ) ? MYSQL_CLIENT_FLAGS : 0; |
1419 |
1507 |
1420 if ( $this->use_mysqli ) { |
1508 if ( $this->use_mysqli ) { |
1421 $this->dbh = mysqli_init(); |
1509 $this->dbh = mysqli_init(); |
1422 |
1510 |
1423 // mysqli_real_connect doesn't support the host param including a port or socket |
1511 $host = $this->dbhost; |
1424 // like mysql_connect does. This duplicates how mysql_connect detects a port and/or socket file. |
1512 $port = null; |
1425 $port = null; |
1513 $socket = null; |
1426 $socket = null; |
1514 $is_ipv6 = false; |
1427 $host = $this->dbhost; |
1515 |
1428 $port_or_socket = strstr( $host, ':' ); |
1516 if ( $host_data = $this->parse_db_host( $this->dbhost ) ) { |
1429 if ( ! empty( $port_or_socket ) ) { |
1517 list( $host, $port, $socket, $is_ipv6 ) = $host_data; |
1430 $host = substr( $host, 0, strpos( $host, ':' ) ); |
1518 } |
1431 $port_or_socket = substr( $port_or_socket, 1 ); |
1519 |
1432 if ( 0 !== strpos( $port_or_socket, '/' ) ) { |
1520 /* |
1433 $port = intval( $port_or_socket ); |
1521 * If using the `mysqlnd` library, the IPv6 address needs to be |
1434 $maybe_socket = strstr( $port_or_socket, ':' ); |
1522 * enclosed in square brackets, whereas it doesn't while using the |
1435 if ( ! empty( $maybe_socket ) ) { |
1523 * `libmysqlclient` library. |
1436 $socket = substr( $maybe_socket, 1 ); |
1524 * @see https://bugs.php.net/bug.php?id=67563 |
1437 } |
1525 */ |
1438 } else { |
1526 if ( $is_ipv6 && extension_loaded( 'mysqlnd' ) ) { |
1439 $socket = $port_or_socket; |
1527 $host = "[$host]"; |
1440 } |
|
1441 } |
1528 } |
1442 |
1529 |
1443 if ( WP_DEBUG ) { |
1530 if ( WP_DEBUG ) { |
1444 mysqli_real_connect( $this->dbh, $host, $this->dbuser, $this->dbpassword, null, $port, $socket, $client_flags ); |
1531 mysqli_real_connect( $this->dbh, $host, $this->dbuser, $this->dbpassword, null, $port, $socket, $client_flags ); |
1445 } else { |
1532 } else { |
1484 if ( file_exists( WP_CONTENT_DIR . '/db-error.php' ) ) { |
1572 if ( file_exists( WP_CONTENT_DIR . '/db-error.php' ) ) { |
1485 require_once( WP_CONTENT_DIR . '/db-error.php' ); |
1573 require_once( WP_CONTENT_DIR . '/db-error.php' ); |
1486 die(); |
1574 die(); |
1487 } |
1575 } |
1488 |
1576 |
1489 $this->bail( sprintf( __( " |
1577 $message = '<h1>' . __( 'Error establishing a database connection' ) . "</h1>\n"; |
1490 <h1>Error establishing a database connection</h1> |
1578 |
1491 <p>This either means that the username and password information in your <code>wp-config.php</code> file is incorrect or we can't contact the database server at <code>%s</code>. This could mean your host's database server is down.</p> |
1579 $message .= '<p>' . sprintf( |
1492 <ul> |
1580 /* translators: 1: wp-config.php. 2: database host */ |
1493 <li>Are you sure you have the correct username and password?</li> |
1581 __( 'This either means that the username and password information in your %1$s file is incorrect or we can’t contact the database server at %2$s. This could mean your host’s database server is down.' ), |
1494 <li>Are you sure that you have typed the correct hostname?</li> |
1582 '<code>wp-config.php</code>', |
1495 <li>Are you sure that the database server is running?</li> |
1583 '<code>' . htmlspecialchars( $this->dbhost, ENT_QUOTES ) . '</code>' |
1496 </ul> |
1584 ) . "</p>\n"; |
1497 <p>If you're unsure what these terms mean you should probably contact your host. If you still need help you can always visit the <a href='https://wordpress.org/support/'>WordPress Support Forums</a>.</p> |
1585 |
1498 " ), htmlspecialchars( $this->dbhost, ENT_QUOTES ) ), 'db_connect_fail' ); |
1586 $message .= "<ul>\n"; |
|
1587 $message .= '<li>' . __( 'Are you sure you have the correct username and password?' ) . "</li>\n"; |
|
1588 $message .= '<li>' . __( 'Are you sure that you have typed the correct hostname?' ) . "</li>\n"; |
|
1589 $message .= '<li>' . __( 'Are you sure that the database server is running?' ) . "</li>\n"; |
|
1590 $message .= "</ul>\n"; |
|
1591 |
|
1592 $message .= '<p>' . sprintf( |
|
1593 /* translators: %s: support forums URL */ |
|
1594 __( 'If you’re unsure what these terms mean you should probably contact your host. If you still need help you can always visit the <a href="%s">WordPress Support Forums</a>.' ), |
|
1595 __( 'https://wordpress.org/support/' ) |
|
1596 ) . "</p>\n"; |
|
1597 |
|
1598 $this->bail( $message, 'db_connect_fail' ); |
1499 |
1599 |
1500 return false; |
1600 return false; |
1501 } elseif ( $this->dbh ) { |
1601 } elseif ( $this->dbh ) { |
1502 if ( ! $this->has_connected ) { |
1602 if ( ! $this->has_connected ) { |
1503 $this->init_charset(); |
1603 $this->init_charset(); |
1516 |
1616 |
1517 return false; |
1617 return false; |
1518 } |
1618 } |
1519 |
1619 |
1520 /** |
1620 /** |
1521 * Check that the connection to the database is still up. If not, try to reconnect. |
1621 * Parse the DB_HOST setting to interpret it for mysqli_real_connect. |
|
1622 * |
|
1623 * mysqli_real_connect doesn't support the host param including a port or |
|
1624 * socket like mysql_connect does. This duplicates how mysql_connect detects |
|
1625 * a port and/or socket file. |
|
1626 * |
|
1627 * @since 4.9.0 |
|
1628 * |
|
1629 * @param string $host The DB_HOST setting to parse. |
|
1630 * @return array|bool Array containing the host, the port, the socket and whether |
|
1631 * it is an IPv6 address, in that order. If $host couldn't be parsed, |
|
1632 * returns false. |
|
1633 */ |
|
1634 public function parse_db_host( $host ) { |
|
1635 $port = null; |
|
1636 $socket = null; |
|
1637 $is_ipv6 = false; |
|
1638 |
|
1639 // First peel off the socket parameter from the right, if it exists. |
|
1640 $socket_pos = strpos( $host, ':/' ); |
|
1641 if ( $socket_pos !== false ) { |
|
1642 $socket = substr( $host, $socket_pos + 1 ); |
|
1643 $host = substr( $host, 0, $socket_pos ); |
|
1644 } |
|
1645 |
|
1646 // We need to check for an IPv6 address first. |
|
1647 // An IPv6 address will always contain at least two colons. |
|
1648 if ( substr_count( $host, ':' ) > 1 ) { |
|
1649 $pattern = '#^(?:\[)?(?P<host>[0-9a-fA-F:]+)(?:\]:(?P<port>[\d]+))?#'; |
|
1650 $is_ipv6 = true; |
|
1651 } else { |
|
1652 // We seem to be dealing with an IPv4 address. |
|
1653 $pattern = '#^(?P<host>[^:/]*)(?::(?P<port>[\d]+))?#'; |
|
1654 } |
|
1655 |
|
1656 $matches = array(); |
|
1657 $result = preg_match( $pattern, $host, $matches ); |
|
1658 |
|
1659 if ( 1 !== $result ) { |
|
1660 // Couldn't parse the address, bail. |
|
1661 return false; |
|
1662 } |
|
1663 |
|
1664 $host = ''; |
|
1665 foreach ( array( 'host', 'port' ) as $component ) { |
|
1666 if ( ! empty( $matches[ $component ] ) ) { |
|
1667 $$component = $matches[ $component ]; |
|
1668 } |
|
1669 } |
|
1670 |
|
1671 return array( $host, $port, $socket, $is_ipv6 ); |
|
1672 } |
|
1673 |
|
1674 /** |
|
1675 * Checks that the connection to the database is still up. If not, try to reconnect. |
1522 * |
1676 * |
1523 * If this function is unable to reconnect, it will forcibly die, or if after the |
1677 * If this function is unable to reconnect, it will forcibly die, or if after the |
1524 * the template_redirect hook has been fired, return false instead. |
1678 * the {@see 'template_redirect'} hook has been fired, return false instead. |
1525 * |
1679 * |
1526 * If $allow_bail is false, the lack of database connection will need |
1680 * If $allow_bail is false, the lack of database connection will need |
1527 * to be handled manually. |
1681 * to be handled manually. |
1528 * |
1682 * |
1529 * @since 3.9.0 |
1683 * @since 3.9.0 |
1530 * |
1684 * |
1531 * @param bool $allow_bail Optional. Allows the function to bail. Default true. |
1685 * @param bool $allow_bail Optional. Allows the function to bail. Default true. |
1532 * @return bool|null True if the connection is up. |
1686 * @return bool|void True if the connection is up. |
1533 */ |
1687 */ |
1534 public function check_connection( $allow_bail = true ) { |
1688 public function check_connection( $allow_bail = true ) { |
1535 if ( $this->use_mysqli ) { |
1689 if ( $this->use_mysqli ) { |
1536 if ( @mysqli_ping( $this->dbh ) ) { |
1690 if ( ! empty( $this->dbh ) && mysqli_ping( $this->dbh ) ) { |
1537 return true; |
1691 return true; |
1538 } |
1692 } |
1539 } else { |
1693 } else { |
1540 if ( @mysql_ping( $this->dbh ) ) { |
1694 if ( ! empty( $this->dbh ) && mysql_ping( $this->dbh ) ) { |
1541 return true; |
1695 return true; |
1542 } |
1696 } |
1543 } |
1697 } |
1544 |
1698 |
1545 $error_reporting = false; |
1699 $error_reporting = false; |
1724 /** |
1909 /** |
1725 * Internal function to perform the mysql_query() call. |
1910 * Internal function to perform the mysql_query() call. |
1726 * |
1911 * |
1727 * @since 3.9.0 |
1912 * @since 3.9.0 |
1728 * |
1913 * |
1729 * @access private |
|
1730 * @see wpdb::query() |
1914 * @see wpdb::query() |
1731 * |
1915 * |
1732 * @param string $query The query to run. |
1916 * @param string $query The query to run. |
1733 */ |
1917 */ |
1734 private function _do_query( $query ) { |
1918 private function _do_query( $query ) { |
1735 if ( defined( 'SAVEQUERIES' ) && SAVEQUERIES ) { |
1919 if ( defined( 'SAVEQUERIES' ) && SAVEQUERIES ) { |
1736 $this->timer_start(); |
1920 $this->timer_start(); |
1737 } |
1921 } |
1738 |
1922 |
1739 if ( $this->use_mysqli ) { |
1923 if ( ! empty( $this->dbh ) && $this->use_mysqli ) { |
1740 $this->result = @mysqli_query( $this->dbh, $query ); |
1924 $this->result = mysqli_query( $this->dbh, $query ); |
1741 } else { |
1925 } elseif ( ! empty( $this->dbh ) ) { |
1742 $this->result = @mysql_query( $query, $this->dbh ); |
1926 $this->result = mysql_query( $query, $this->dbh ); |
1743 } |
1927 } |
1744 $this->num_queries++; |
1928 $this->num_queries++; |
1745 |
1929 |
1746 if ( defined( 'SAVEQUERIES' ) && SAVEQUERIES ) { |
1930 if ( defined( 'SAVEQUERIES' ) && SAVEQUERIES ) { |
1747 $this->queries[] = array( $query, $this->timer_stop(), $this->get_caller() ); |
1931 $this->queries[] = array( $query, $this->timer_stop(), $this->get_caller() ); |
1748 } |
1932 } |
|
1933 } |
|
1934 |
|
1935 /** |
|
1936 * Generates and returns a placeholder escape string for use in queries returned by ::prepare(). |
|
1937 * |
|
1938 * @since 4.8.3 |
|
1939 * |
|
1940 * @return string String to escape placeholders. |
|
1941 */ |
|
1942 public function placeholder_escape() { |
|
1943 static $placeholder; |
|
1944 |
|
1945 if ( ! $placeholder ) { |
|
1946 // If ext/hash is not present, compat.php's hash_hmac() does not support sha256. |
|
1947 $algo = function_exists( 'hash' ) ? 'sha256' : 'sha1'; |
|
1948 // Old WP installs may not have AUTH_SALT defined. |
|
1949 $salt = defined( 'AUTH_SALT' ) && AUTH_SALT ? AUTH_SALT : (string) rand(); |
|
1950 |
|
1951 $placeholder = '{' . hash_hmac( $algo, uniqid( $salt, true ), $salt ) . '}'; |
|
1952 } |
|
1953 |
|
1954 /* |
|
1955 * Add the filter to remove the placeholder escaper. Uses priority 0, so that anything |
|
1956 * else attached to this filter will recieve the query with the placeholder string removed. |
|
1957 */ |
|
1958 if ( ! has_filter( 'query', array( $this, 'remove_placeholder_escape' ) ) ) { |
|
1959 add_filter( 'query', array( $this, 'remove_placeholder_escape' ), 0 ); |
|
1960 } |
|
1961 |
|
1962 return $placeholder; |
|
1963 } |
|
1964 |
|
1965 /** |
|
1966 * Adds a placeholder escape string, to escape anything that resembles a printf() placeholder. |
|
1967 * |
|
1968 * @since 4.8.3 |
|
1969 * |
|
1970 * @param string $query The query to escape. |
|
1971 * @return string The query with the placeholder escape string inserted where necessary. |
|
1972 */ |
|
1973 public function add_placeholder_escape( $query ) { |
|
1974 /* |
|
1975 * To prevent returning anything that even vaguely resembles a placeholder, |
|
1976 * we clobber every % we can find. |
|
1977 */ |
|
1978 return str_replace( '%', $this->placeholder_escape(), $query ); |
|
1979 } |
|
1980 |
|
1981 /** |
|
1982 * Removes the placeholder escape strings from a query. |
|
1983 * |
|
1984 * @since 4.8.3 |
|
1985 * |
|
1986 * @param string $query The query from which the placeholder will be removed. |
|
1987 * @return string The query with the placeholder removed. |
|
1988 */ |
|
1989 public function remove_placeholder_escape( $query ) { |
|
1990 return str_replace( $this->placeholder_escape(), '%', $query ); |
1749 } |
1991 } |
1750 |
1992 |
1751 /** |
1993 /** |
1752 * Insert a row into a table. |
1994 * Insert a row into a table. |
1753 * |
1995 * |
1793 /** |
2043 /** |
1794 * Helper function for insert and replace. |
2044 * Helper function for insert and replace. |
1795 * |
2045 * |
1796 * Runs an insert or replace query based on $type argument. |
2046 * Runs an insert or replace query based on $type argument. |
1797 * |
2047 * |
1798 * @access private |
|
1799 * @since 3.0.0 |
2048 * @since 3.0.0 |
1800 * @see wpdb::prepare() |
2049 * @see wpdb::prepare() |
1801 * @see wpdb::$field_types |
2050 * @see wpdb::$field_types |
1802 * @see wp_set_wpdb_vars() |
2051 * @see wp_set_wpdb_vars() |
1803 * |
2052 * |
1804 * @param string $table table name |
2053 * @param string $table Table name |
1805 * @param array $data Data to insert (in column => value pairs). Both $data columns and $data values should be "raw" (neither should be SQL escaped). |
2054 * @param array $data Data to insert (in column => value pairs). |
1806 * @param array|string $format Optional. An array of formats to be mapped to each of the value in $data. If string, that format will be used for all of the values in $data. |
2055 * Both $data columns and $data values should be "raw" (neither should be SQL escaped). |
1807 * A format is one of '%d', '%f', '%s' (integer, float, string). If omitted, all values in $data will be treated as strings unless otherwise specified in wpdb::$field_types. |
2056 * Sending a null value will cause the column to be set to NULL - the corresponding format is ignored in this case. |
1808 * @param string $type Optional. What type of operation is this? INSERT or REPLACE. Defaults to INSERT. |
2057 * @param array|string $format Optional. An array of formats to be mapped to each of the value in $data. |
|
2058 * If string, that format will be used for all of the values in $data. |
|
2059 * A format is one of '%d', '%f', '%s' (integer, float, string). |
|
2060 * If omitted, all values in $data will be treated as strings unless otherwise specified in wpdb::$field_types. |
|
2061 * @param string $type Optional. What type of operation is this? INSERT or REPLACE. Defaults to INSERT. |
1809 * @return int|false The number of rows affected, or false on error. |
2062 * @return int|false The number of rows affected, or false on error. |
1810 */ |
2063 */ |
1811 function _insert_replace_helper( $table, $data, $format = null, $type = 'INSERT' ) { |
2064 function _insert_replace_helper( $table, $data, $format = null, $type = 'INSERT' ) { |
1812 $this->insert_id = 0; |
2065 $this->insert_id = 0; |
1813 |
2066 |
1844 * @since 2.5.0 |
2102 * @since 2.5.0 |
1845 * @see wpdb::prepare() |
2103 * @see wpdb::prepare() |
1846 * @see wpdb::$field_types |
2104 * @see wpdb::$field_types |
1847 * @see wp_set_wpdb_vars() |
2105 * @see wp_set_wpdb_vars() |
1848 * |
2106 * |
1849 * @param string $table table name |
2107 * @param string $table Table name |
1850 * @param array $data Data to update (in column => value pairs). Both $data columns and $data values should be "raw" (neither should be SQL escaped). |
2108 * @param array $data Data to update (in column => value pairs). |
1851 * @param array $where A named array of WHERE clauses (in column => value pairs). Multiple clauses will be joined with ANDs. Both $where columns and $where values should be "raw". |
2109 * Both $data columns and $data values should be "raw" (neither should be SQL escaped). |
1852 * @param array|string $format Optional. An array of formats to be mapped to each of the values in $data. If string, that format will be used for all of the values in $data. |
2110 * Sending a null value will cause the column to be set to NULL - the corresponding |
1853 * A format is one of '%d', '%f', '%s' (integer, float, string). If omitted, all values in $data will be treated as strings unless otherwise specified in wpdb::$field_types. |
2111 * format is ignored in this case. |
1854 * @param array|string $where_format Optional. An array of formats to be mapped to each of the values in $where. If string, that format will be used for all of the items in $where. A format is one of '%d', '%f', '%s' (integer, float, string). If omitted, all values in $where will be treated as strings. |
2112 * @param array $where A named array of WHERE clauses (in column => value pairs). |
|
2113 * Multiple clauses will be joined with ANDs. |
|
2114 * Both $where columns and $where values should be "raw". |
|
2115 * Sending a null value will create an IS NULL comparison - the corresponding format will be ignored in this case. |
|
2116 * @param array|string $format Optional. An array of formats to be mapped to each of the values in $data. |
|
2117 * If string, that format will be used for all of the values in $data. |
|
2118 * A format is one of '%d', '%f', '%s' (integer, float, string). |
|
2119 * If omitted, all values in $data will be treated as strings unless otherwise specified in wpdb::$field_types. |
|
2120 * @param array|string $where_format Optional. An array of formats to be mapped to each of the values in $where. |
|
2121 * If string, that format will be used for all of the items in $where. |
|
2122 * A format is one of '%d', '%f', '%s' (integer, float, string). |
|
2123 * If omitted, all values in $where will be treated as strings. |
1855 * @return int|false The number of rows updated, or false on error. |
2124 * @return int|false The number of rows updated, or false on error. |
1856 */ |
2125 */ |
1857 public function update( $table, $data, $where, $format = null, $where_format = null ) { |
2126 public function update( $table, $data, $where, $format = null, $where_format = null ) { |
1858 if ( ! is_array( $data ) || ! is_array( $where ) ) { |
2127 if ( ! is_array( $data ) || ! is_array( $where ) ) { |
1859 return false; |
2128 return false; |
2674 |
2961 |
2675 if ( $db_check_string ) { |
2962 if ( $db_check_string ) { |
2676 $queries = array(); |
2963 $queries = array(); |
2677 foreach ( $data as $col => $value ) { |
2964 foreach ( $data as $col => $value ) { |
2678 if ( ! empty( $value['db'] ) ) { |
2965 if ( ! empty( $value['db'] ) ) { |
2679 if ( ! isset( $queries[ $value['charset'] ] ) ) { |
|
2680 $queries[ $value['charset'] ] = array(); |
|
2681 } |
|
2682 |
|
2683 // We're going to need to truncate by characters or bytes, depending on the length value we have. |
2966 // We're going to need to truncate by characters or bytes, depending on the length value we have. |
2684 if ( 'byte' === $value['length']['type'] ) { |
2967 if ( 'byte' === $value['length']['type'] ) { |
2685 // Split the CONVERT() calls by charset, so we can make sure the connection is right |
2968 // Using binary causes LEFT() to truncate by bytes. |
2686 $queries[ $value['charset'] ][ $col ] = $this->prepare( "CONVERT( LEFT( CONVERT( %s USING binary ), %d ) USING {$value['charset']} )", $value['value'], $value['length']['length'] ); |
2969 $charset = 'binary'; |
2687 } else { |
2970 } else { |
2688 $queries[ $value['charset'] ][ $col ] = $this->prepare( "LEFT( CONVERT( %s USING {$value['charset']} ), %d )", $value['value'], $value['length']['length'] ); |
2971 $charset = $value['charset']; |
|
2972 } |
|
2973 |
|
2974 if ( $this->charset ) { |
|
2975 $connection_charset = $this->charset; |
|
2976 } else { |
|
2977 if ( $this->use_mysqli ) { |
|
2978 $connection_charset = mysqli_character_set_name( $this->dbh ); |
|
2979 } else { |
|
2980 $connection_charset = mysql_client_encoding(); |
|
2981 } |
|
2982 } |
|
2983 |
|
2984 if ( is_array( $value['length'] ) ) { |
|
2985 $length = sprintf( '%.0f', $value['length']['length'] ); |
|
2986 $queries[ $col ] = $this->prepare( "CONVERT( LEFT( CONVERT( %s USING $charset ), $length ) USING $connection_charset )", $value['value'] ); |
|
2987 } else if ( 'binary' !== $charset ) { |
|
2988 // If we don't have a length, there's no need to convert binary - it will always return the same result. |
|
2989 $queries[ $col ] = $this->prepare( "CONVERT( CONVERT( %s USING $charset ) USING $connection_charset )", $value['value'] ); |
2689 } |
2990 } |
2690 |
2991 |
2691 unset( $data[ $col ]['db'] ); |
2992 unset( $data[ $col ]['db'] ); |
2692 } |
2993 } |
2693 } |
2994 } |
2694 |
2995 |
2695 $connection_charset = $this->charset; |
2996 $sql = array(); |
2696 foreach ( $queries as $charset => $query ) { |
2997 foreach ( $queries as $column => $query ) { |
2697 if ( ! $query ) { |
2998 if ( ! $query ) { |
2698 continue; |
2999 continue; |
2699 } |
3000 } |
2700 |
3001 |
2701 // Change the charset to match the string(s) we're converting |
3002 $sql[] = $query . " AS x_$column"; |
2702 if ( $charset !== $connection_charset ) { |
3003 } |
2703 $connection_charset = $charset; |
3004 |
2704 $this->set_charset( $this->dbh, $charset ); |
3005 $this->check_current_query = false; |
2705 } |
3006 $row = $this->get_row( "SELECT " . implode( ', ', $sql ), ARRAY_A ); |
2706 |
3007 if ( ! $row ) { |
2707 $this->check_current_query = false; |
3008 return new WP_Error( 'wpdb_strip_invalid_text_failure' ); |
2708 |
3009 } |
2709 $sql = array(); |
3010 |
2710 foreach ( $query as $column => $column_query ) { |
3011 foreach ( array_keys( $data ) as $column ) { |
2711 $sql[] = $column_query . " AS x_$column"; |
3012 if ( isset( $row["x_$column"] ) ) { |
2712 } |
|
2713 |
|
2714 $row = $this->get_row( "SELECT " . implode( ', ', $sql ), ARRAY_A ); |
|
2715 if ( ! $row ) { |
|
2716 $this->set_charset( $this->dbh, $connection_charset ); |
|
2717 return new WP_Error( 'wpdb_strip_invalid_text_failure' ); |
|
2718 } |
|
2719 |
|
2720 foreach ( array_keys( $query ) as $column ) { |
|
2721 $data[ $column ]['value'] = $row["x_$column"]; |
3013 $data[ $column ]['value'] = $row["x_$column"]; |
2722 } |
3014 } |
2723 } |
3015 } |
2724 |
|
2725 // Don't forget to change the charset back! |
|
2726 if ( $connection_charset !== $this->charset ) { |
|
2727 $this->set_charset( $this->dbh ); |
|
2728 } |
|
2729 } |
3016 } |
2730 |
3017 |
2731 return $data; |
3018 return $data; |
2732 } |
3019 } |
2733 |
3020 |
2734 /** |
3021 /** |
2735 * Strips any invalid characters from the query. |
3022 * Strips any invalid characters from the query. |
2736 * |
3023 * |
2737 * @since 4.2.0 |
3024 * @since 4.2.0 |
2738 * @access protected |
|
2739 * |
3025 * |
2740 * @param string $query Query to convert. |
3026 * @param string $query Query to convert. |
2741 * @return string|WP_Error The converted query, or a WP_Error object if the conversion fails. |
3027 * @return string|WP_Error The converted query, or a WP_Error object if the conversion fails. |
2742 */ |
3028 */ |
2743 protected function strip_invalid_text_from_query( $query ) { |
3029 protected function strip_invalid_text_from_query( $query ) { |
2832 $query = rtrim( $query, ';/-#' ); |
3116 $query = rtrim( $query, ';/-#' ); |
2833 |
3117 |
2834 // Allow (select...) union [...] style queries. Use the first query's table name. |
3118 // Allow (select...) union [...] style queries. Use the first query's table name. |
2835 $query = ltrim( $query, "\r\n\t (" ); |
3119 $query = ltrim( $query, "\r\n\t (" ); |
2836 |
3120 |
2837 /* |
3121 // Strip everything between parentheses except nested selects. |
2838 * Strip everything between parentheses except nested selects and use only 1,000 |
3122 $query = preg_replace( '/\((?!\s*select)[^(]*?\)/is', '()', $query ); |
2839 * chars of the query. |
|
2840 */ |
|
2841 $query = preg_replace( '/\((?!\s*select)[^(]*?\)/is', '()', substr( $query, 0, 1000 ) ); |
|
2842 |
3123 |
2843 // Quickly match most common queries. |
3124 // Quickly match most common queries. |
2844 if ( preg_match( '/^\s*(?:' |
3125 if ( preg_match( '/^\s*(?:' |
2845 . 'SELECT.*?\s+FROM' |
3126 . 'SELECT.*?\s+FROM' |
2846 . '|INSERT(?:\s+LOW_PRIORITY|\s+DELAYED|\s+HIGH_PRIORITY)?(?:\s+IGNORE)?(?:\s+INTO)?' |
3127 . '|INSERT(?:\s+LOW_PRIORITY|\s+DELAYED|\s+HIGH_PRIORITY)?(?:\s+IGNORE)?(?:\s+INTO)?' |
2847 . '|REPLACE(?:\s+LOW_PRIORITY|\s+DELAYED)?(?:\s+INTO)?' |
3128 . '|REPLACE(?:\s+LOW_PRIORITY|\s+DELAYED)?(?:\s+INTO)?' |
2848 . '|UPDATE(?:\s+LOW_PRIORITY)?(?:\s+IGNORE)?' |
3129 . '|UPDATE(?:\s+LOW_PRIORITY)?(?:\s+IGNORE)?' |
2849 . '|DELETE(?:\s+LOW_PRIORITY|\s+QUICK|\s+IGNORE)*(?:\s+FROM)?' |
3130 . '|DELETE(?:\s+LOW_PRIORITY|\s+QUICK|\s+IGNORE)*(?:.+?FROM)?' |
2850 . ')\s+((?:[0-9a-zA-Z$_.`]|[\xC2-\xDF][\x80-\xBF])+)/is', $query, $maybe ) ) { |
3131 . ')\s+((?:[0-9a-zA-Z$_.`-]|[\xC2-\xDF][\x80-\xBF])+)/is', $query, $maybe ) ) { |
2851 return str_replace( '`', '', $maybe[1] ); |
3132 return str_replace( '`', '', $maybe[1] ); |
2852 } |
3133 } |
2853 |
3134 |
2854 // SHOW TABLE STATUS and SHOW TABLES |
3135 // SHOW TABLE STATUS and SHOW TABLES WHERE Name = 'wp_posts' |
2855 if ( preg_match( '/^\s*(?:' |
3136 if ( preg_match( '/^\s*SHOW\s+(?:TABLE\s+STATUS|(?:FULL\s+)?TABLES).+WHERE\s+Name\s*=\s*("|\')((?:[0-9a-zA-Z$_.-]|[\xC2-\xDF][\x80-\xBF])+)\\1/is', $query, $maybe ) ) { |
2856 . 'SHOW\s+TABLE\s+STATUS.+(?:LIKE\s+|WHERE\s+Name\s*=\s*)' |
3137 return $maybe[2]; |
2857 . '|SHOW\s+(?:FULL\s+)?TABLES.+(?:LIKE\s+|WHERE\s+Name\s*=\s*)' |
3138 } |
2858 . ')\W((?:[0-9a-zA-Z$_.`]|[\xC2-\xDF][\x80-\xBF])+)\W/is', $query, $maybe ) ) { |
3139 |
2859 return str_replace( '`', '', $maybe[1] ); |
3140 // SHOW TABLE STATUS LIKE and SHOW TABLES LIKE 'wp\_123\_%' |
|
3141 // This quoted LIKE operand seldom holds a full table name. |
|
3142 // It is usually a pattern for matching a prefix so we just |
|
3143 // strip the trailing % and unescape the _ to get 'wp_123_' |
|
3144 // which drop-ins can use for routing these SQL statements. |
|
3145 if ( preg_match( '/^\s*SHOW\s+(?:TABLE\s+STATUS|(?:FULL\s+)?TABLES)\s+(?:WHERE\s+Name\s+)?LIKE\s*("|\')((?:[\\\\0-9a-zA-Z$_.-]|[\xC2-\xDF][\x80-\xBF])+)%?\\1/is', $query, $maybe ) ) { |
|
3146 return str_replace( '\\_', '_', $maybe[2] ); |
2860 } |
3147 } |
2861 |
3148 |
2862 // Big pattern for the rest of the table-related queries. |
3149 // Big pattern for the rest of the table-related queries. |
2863 if ( preg_match( '/^\s*(?:' |
3150 if ( preg_match( '/^\s*(?:' |
2864 . '(?:EXPLAIN\s+(?:EXTENDED\s+)?)?SELECT.*?\s+FROM' |
3151 . '(?:EXPLAIN\s+(?:EXTENDED\s+)?)?SELECT.*?\s+FROM' |
2884 /** |
3171 /** |
2885 * Load the column metadata from the last query. |
3172 * Load the column metadata from the last query. |
2886 * |
3173 * |
2887 * @since 3.5.0 |
3174 * @since 3.5.0 |
2888 * |
3175 * |
2889 * @access protected |
|
2890 */ |
3176 */ |
2891 protected function load_col_info() { |
3177 protected function load_col_info() { |
2892 if ( $this->col_info ) |
3178 if ( $this->col_info ) |
2893 return; |
3179 return; |
2894 |
3180 |
2895 if ( $this->use_mysqli ) { |
3181 if ( $this->use_mysqli ) { |
2896 for ( $i = 0; $i < @mysqli_num_fields( $this->result ); $i++ ) { |
3182 $num_fields = mysqli_num_fields( $this->result ); |
2897 $this->col_info[ $i ] = @mysqli_fetch_field( $this->result ); |
3183 for ( $i = 0; $i < $num_fields; $i++ ) { |
|
3184 $this->col_info[ $i ] = mysqli_fetch_field( $this->result ); |
2898 } |
3185 } |
2899 } else { |
3186 } else { |
2900 for ( $i = 0; $i < @mysql_num_fields( $this->result ); $i++ ) { |
3187 $num_fields = mysql_num_fields( $this->result ); |
2901 $this->col_info[ $i ] = @mysql_fetch_field( $this->result, $i ); |
3188 for ( $i = 0; $i < $num_fields; $i++ ) { |
|
3189 $this->col_info[ $i ] = mysql_fetch_field( $this->result, $i ); |
2902 } |
3190 } |
2903 } |
3191 } |
2904 } |
3192 } |
2905 |
3193 |
2906 /** |
3194 /** |
2907 * Retrieve column metadata from the last query. |
3195 * Retrieve column metadata from the last query. |
2908 * |
3196 * |
2909 * @since 0.71 |
3197 * @since 0.71 |
2910 * |
3198 * |
2911 * @param string $info_type Optional. Type one of name, table, def, max_length, not_null, primary_key, multiple_key, unique_key, numeric, blob, type, unsigned, zerofill |
3199 * @param string $info_type Optional. Type one of name, table, def, max_length, not_null, primary_key, multiple_key, unique_key, numeric, blob, type, unsigned, zerofill |
2912 * @param int $col_offset Optional. 0: col name. 1: which table the col's in. 2: col's max length. 3: if the col is numeric. 4: col's type |
3200 * @param int $col_offset Optional. 0: col name. 1: which table the col's in. 2: col's max length. 3: if the col is numeric. 4: col's type |
2913 * @return mixed Column Results |
3201 * @return mixed Column Results |
2914 */ |
3202 */ |
2915 public function get_col_info( $info_type = 'name', $col_offset = -1 ) { |
3203 public function get_col_info( $info_type = 'name', $col_offset = -1 ) { |
2916 $this->load_col_info(); |
3204 $this->load_col_info(); |
2917 |
3205 |
2918 if ( $this->col_info ) { |
3206 if ( $this->col_info ) { |
2919 if ( $col_offset == -1 ) { |
3207 if ( $col_offset == -1 ) { |
2920 $i = 0; |
3208 $i = 0; |
2921 $new_array = array(); |
3209 $new_array = array(); |
2922 foreach( (array) $this->col_info as $col ) { |
3210 foreach ( (array) $this->col_info as $col ) { |
2923 $new_array[$i] = $col->{$info_type}; |
3211 $new_array[$i] = $col->{$info_type}; |
2924 $i++; |
3212 $i++; |
2925 } |
3213 } |
2926 return $new_array; |
3214 return $new_array; |
2927 } else { |
3215 } else { |
2958 * |
3246 * |
2959 * Will not die if wpdb::$show_errors is false. |
3247 * Will not die if wpdb::$show_errors is false. |
2960 * |
3248 * |
2961 * @since 1.5.0 |
3249 * @since 1.5.0 |
2962 * |
3250 * |
2963 * @param string $message The Error message |
3251 * @param string $message The Error message |
2964 * @param string $error_code Optional. A Computer readable string to identify the error. |
3252 * @param string $error_code Optional. A Computer readable string to identify the error. |
2965 * @return false|void |
3253 * @return false|void |
2966 */ |
3254 */ |
2967 public function bail( $message, $error_code = '500' ) { |
3255 public function bail( $message, $error_code = '500' ) { |
2968 if ( !$this->show_errors ) { |
3256 if ( !$this->show_errors ) { |
2969 if ( class_exists( 'WP_Error' ) ) |
3257 if ( class_exists( 'WP_Error', false ) ) { |
2970 $this->error = new WP_Error($error_code, $message); |
3258 $this->error = new WP_Error($error_code, $message); |
2971 else |
3259 } else { |
2972 $this->error = $message; |
3260 $this->error = $message; |
|
3261 } |
2973 return false; |
3262 return false; |
2974 } |
3263 } |
2975 wp_die($message); |
3264 wp_die($message); |
2976 } |
3265 } |
2977 |
3266 |
|
3267 |
|
3268 /** |
|
3269 * Closes the current database connection. |
|
3270 * |
|
3271 * @since 4.5.0 |
|
3272 * |
|
3273 * @return bool True if the connection was successfully closed, false if it wasn't, |
|
3274 * or the connection doesn't exist. |
|
3275 */ |
|
3276 public function close() { |
|
3277 if ( ! $this->dbh ) { |
|
3278 return false; |
|
3279 } |
|
3280 |
|
3281 if ( $this->use_mysqli ) { |
|
3282 $closed = mysqli_close( $this->dbh ); |
|
3283 } else { |
|
3284 $closed = mysql_close( $this->dbh ); |
|
3285 } |
|
3286 |
|
3287 if ( $closed ) { |
|
3288 $this->dbh = null; |
|
3289 $this->ready = false; |
|
3290 $this->has_connected = false; |
|
3291 } |
|
3292 |
|
3293 return $closed; |
|
3294 } |
|
3295 |
2978 /** |
3296 /** |
2979 * Whether MySQL database is at least the required minimum version. |
3297 * Whether MySQL database is at least the required minimum version. |
2980 * |
3298 * |
2981 * @since 2.5.0 |
3299 * @since 2.5.0 |
2982 * @uses $wp_version |
3300 * |
2983 * @uses $required_mysql_version |
3301 * @global string $wp_version |
2984 * |
3302 * @global string $required_mysql_version |
2985 * @return WP_Error |
3303 * |
|
3304 * @return WP_Error|void |
2986 */ |
3305 */ |
2987 public function check_database_version() { |
3306 public function check_database_version() { |
2988 global $wp_version, $required_mysql_version; |
3307 global $wp_version, $required_mysql_version; |
2989 // Make sure the server has the required MySQL version |
3308 // Make sure the server has the required MySQL version |
2990 if ( version_compare($this->db_version(), $required_mysql_version, '<') ) |
3309 if ( version_compare($this->db_version(), $required_mysql_version, '<') ) { |
|
3310 /* translators: 1: WordPress version number, 2: Minimum required MySQL version number */ |
2991 return new WP_Error('database_version', sprintf( __( '<strong>ERROR</strong>: WordPress %1$s requires MySQL %2$s or higher' ), $wp_version, $required_mysql_version )); |
3311 return new WP_Error('database_version', sprintf( __( '<strong>ERROR</strong>: WordPress %1$s requires MySQL %2$s or higher' ), $wp_version, $required_mysql_version )); |
|
3312 } |
2992 } |
3313 } |
2993 |
3314 |
2994 /** |
3315 /** |
2995 * Whether the database supports collation. |
3316 * Whether the database supports collation. |
2996 * |
3317 * |
2997 * Called when WordPress is generating the table scheme. |
3318 * Called when WordPress is generating the table scheme. |
2998 * |
3319 * |
|
3320 * Use `wpdb::has_cap( 'collation' )`. |
|
3321 * |
2999 * @since 2.5.0 |
3322 * @since 2.5.0 |
3000 * @deprecated 3.5.0 |
3323 * @deprecated 3.5.0 Use wpdb::has_cap() |
3001 * @deprecated Use wpdb::has_cap( 'collation' ) |
|
3002 * |
3324 * |
3003 * @return bool True if collation is supported, false if version does not |
3325 * @return bool True if collation is supported, false if version does not |
3004 */ |
3326 */ |
3005 public function supports_collation() { |
3327 public function supports_collation() { |
3006 _deprecated_function( __FUNCTION__, '3.5', 'wpdb::has_cap( \'collation\' )' ); |
3328 _deprecated_function( __FUNCTION__, '3.5.0', 'wpdb::has_cap( \'collation\' )' ); |
3007 return $this->has_cap( 'collation' ); |
3329 return $this->has_cap( 'collation' ); |
3008 } |
3330 } |
3009 |
3331 |
3010 /** |
3332 /** |
3011 * The database character collate. |
3333 * The database character collate. |