Create PMA_is_system_schema() function which checks whether current database server...
[phpmyadmin.git] / libraries / blobstreaming.lib.php
blobcdcbb0b5e89f55b4f48d5c9ff77ab6ebde490e71
1 <?php
2 /* vim: set expandtab sw=4 ts=4 sts=4: */
3 /**
4 * @package BLOBStreaming
5 */
7 /**
8 * Initializes PBMS database
10 * @return bool
12 function initPBMSDatabase()
14 $query = "create database IF NOT EXISTS pbms;"; // If no other choice then try this.
16 * The user may not have privileges to create the 'pbms' database
17 * so if it doesn't exist then we perform a select on a pbms system
18 * table in an already existing database which will cause the PBMS
19 * daemon to create the 'pbms' database.
21 $db_array = PMA_DBI_fetch_result('SHOW DATABASES;');
22 if (! empty($db_array)) {
23 $target = "";
24 foreach ($db_array as $current_db) {
25 if ($current_db == 'pbms') {
26 return true;
28 if ($target == "") {
29 if ($current_db != 'pbxt' && !PMA_is_system_schema($current_db, true)) {
30 $target = $current_db;
35 if ($target != "") {
36 $query = "select * from $target.pbms_metadata_header"; // If it exists this table will not contain much
40 $result = PMA_DBI_query($query );
41 if (! $result) {
42 return false;
44 return true;
47 /**
48 * checks whether the necessary plugins for BLOBStreaming exist
50 * @access public
51 * @return boolean
53 function checkBLOBStreamingPlugins()
55 if (PMA_cacheGet('skip_blobstreaming', true) === true) {
56 return false;
59 // load PMA configuration
60 $PMA_Config = $GLOBALS['PMA_Config'];
62 // return if unable to load PMA configuration
63 if (empty($PMA_Config)) {
64 return false;
67 // If we don't know that we can skip blobstreaming, we continue
68 // verifications; anyway, in case we won't skip blobstreaming,
69 // we still need to set some variables in non-persistent settings,
70 // which is done via $PMA_Config->set().
72 /** Retrieve current server configuration;
73 * at this point, $PMA_Config->get('Servers') contains the server parameters
74 * as explicitely defined in config.inc.php, so it cannot be used; it's
75 * better to use $GLOBALS['cfg']['Server'] which contains the explicit
76 * parameters merged with the default ones
79 $serverCfg = $GLOBALS['cfg']['Server'];
81 // return if unable to retrieve current server configuration
82 if (! $serverCfg) {
83 return false;
86 // if PHP extension in use is 'mysql', specify element 'PersistentConnections'
87 if ($serverCfg['extension'] == "mysql") {
88 $serverCfg['PersistentConnections'] = $PMA_Config->settings['PersistentConnections'];
91 // if connection type is TCP, unload socket variable
92 if (strtolower($serverCfg['connect_type']) == "tcp") {
93 $serverCfg['socket'] = "";
96 $has_blobstreaming = PMA_cacheGet('has_blobstreaming', true);
98 if ($has_blobstreaming === null) {
99 if (!PMA_DRIZZLE && PMA_MYSQL_INT_VERSION >= 50109) {
101 // Retrieve MySQL plugins
102 $existing_plugins = PMA_DBI_fetch_result('SHOW PLUGINS');
104 foreach ($existing_plugins as $one_existing_plugin) {
105 // check if required plugins exist
106 if ( strtolower($one_existing_plugin['Library']) == 'libpbms.so'
107 && $one_existing_plugin['Status'] == "ACTIVE") {
108 $has_blobstreaming = true;
109 break;
112 unset($existing_plugins, $one_existing_plugin);
113 } else if (PMA_DRIZZLE) {
114 $has_blobstreaming = (bool)PMA_DBI_fetch_result(
115 "SELECT 1
116 FROM data_dictionary.plugins
117 WHERE module_name = 'PBMS'
118 AND is_active = true
119 LIMIT 1");
121 PMA_cacheSet('has_blobstreaming', $has_blobstreaming, true);
124 // set variable indicating BS plugin existence
125 $PMA_Config->set('BLOBSTREAMING_PLUGINS_EXIST', $has_blobstreaming);
127 if (!$has_blobstreaming) {
128 PMA_cacheSet('skip_blobstreaming', true, true);
129 return false;
132 if ($has_blobstreaming) {
133 $bs_variables = PMA_BS_GetVariables();
135 // if no BS variables exist, set plugin existence to false and return
136 if (count($bs_variables) == 0) {
137 $PMA_Config->set('BLOBSTREAMING_PLUGINS_EXIST', false);
138 PMA_cacheSet('skip_blobstreaming', true, true);
139 PMA_cacheSet('has_blobstreaming', false, true);
140 return false;
141 } // end if (count($bs_variables) <= 0)
143 // Check that the required pbms functions exist:
144 if ((function_exists("pbms_connect") == false) ||
145 (function_exists("pbms_error") == false) ||
146 (function_exists("pbms_close") == false) ||
147 (function_exists("pbms_is_blob_reference") == false) ||
148 (function_exists("pbms_get_info") == false) ||
149 (function_exists("pbms_get_metadata_value") == false) ||
150 (function_exists("pbms_add_metadata") == false) ||
151 (function_exists("pbms_read_stream") == false)) {
153 // We should probably notify the user that they need to install
154 // the pbms client lib and PHP extension to make use of blob streaming.
155 $PMA_Config->set('BLOBSTREAMING_PLUGINS_EXIST', false);
156 PMA_cacheSet('skip_blobstreaming', true, true);
157 PMA_cacheSet('has_blobstreaming', false, true);
158 return false;
161 if (function_exists("pbms_connection_pool_size")) {
162 if ( isset($PMA_Config->settings['pbms_connection_pool_size'])) {
163 $pool_size = $PMA_Config->settings['pbms_connection_pool_size'];
164 if ($pool_size == "") {
165 $pool_size = 1;
167 } else {
168 $pool_size = 1;
170 pbms_connection_pool_size($pool_size);
173 // get BS server port
174 $BS_PORT = $bs_variables['pbms_port'];
176 // if no BS server port or 'pbms' database exists, set plugin existance to false and return
177 if ((! $BS_PORT) || (! initPBMSDatabase())) {
178 $PMA_Config->set('BLOBSTREAMING_PLUGINS_EXIST', false);
179 PMA_cacheSet('skip_blobstreaming', true, true);
180 return false;
181 } // end if (!$BS_PORT)
183 // Ping PBMS: the database doesn't need to exist for this to work.
184 if (pbms_connect($serverCfg['host'], $BS_PORT, "anydb") == false) {
185 $PMA_Config->set('BLOBSTREAMING_PLUGINS_EXIST', false);
186 PMA_cacheSet('skip_blobstreaming', true, true);
187 return false;
189 pbms_close();
191 if (function_exists("pbms_pconnect")) {
192 $PMA_Config->set('PBMS_PCONNECT_EXISTS', true);
193 } else {
194 $PMA_Config->set('PBMS_PCONNECT_EXISTS', false);
197 // add selected BS, CURL and fileinfo library variables to PMA configuration
198 $PMA_Config->set('BLOBSTREAMING_PORT', $BS_PORT);
199 $PMA_Config->set('BLOBSTREAMING_HOST', $serverCfg['host']);
200 $PMA_Config->set('BLOBSTREAMING_SERVER', $serverCfg['host'] . ':' . $BS_PORT);
201 $PMA_Config->set('PHP_PBMS_EXISTS', false);
202 $PMA_Config->set('FILEINFO_EXISTS', false);
204 // check if PECL's fileinfo library exist
205 $finfo = null;
207 if (function_exists("finfo_open")) {
208 $finfo = finfo_open(FILEINFO_MIME);
211 // fileinfo library exists, set necessary variable and close resource
212 if (! empty($finfo)) {
213 $PMA_Config->set('FILEINFO_EXISTS', true);
214 finfo_close($finfo);
215 } // end if (!empty($finfo))
217 } else {
218 PMA_cacheSet('skip_blobstreaming', true, true);
219 return false;
220 } // end if ($has_blobstreaming)
222 return true;
226 * returns a list of BLOBStreaming variables used by MySQL
228 * @access public
229 * @return array - list of BLOBStreaming variables
231 function PMA_BS_GetVariables()
233 // load PMA configuration
234 $PMA_Config = $GLOBALS['PMA_Config'];
236 // return if unable to load PMA configuration
237 if (empty($PMA_Config))
238 return NULL;
240 // run query to retrieve BS variables
241 $query = "SHOW VARIABLES LIKE '%pbms%'";
242 $result = PMA_DBI_query($query);
244 $BS_Variables = array();
246 // while there are records to retrieve
247 while ($data = @PMA_DBI_fetch_assoc($result))
248 $BS_Variables[$data['Variable_name']] = $data['Value'];
250 // return BS variables
251 return $BS_Variables;
255 * Retrieves and shows PBMS error.
257 * @return nothing
259 function PMA_BS_ReportPBMSError($msg)
261 $tmp_err = pbms_error();
262 PMA_showMessage(__('PBMS error') . " $msg $tmp_err");
266 * Tries to connect to PBMS server.
268 * @param string $db_name Database name
269 * @param bool $quiet Whether to report errors
271 * @return bool Connection status.
273 function PMA_do_connect($db_name, $quiet)
275 $PMA_Config = $GLOBALS['PMA_Config'];
277 // return if unable to load PMA configuration
278 if (empty($PMA_Config)) {
279 return false;
282 // generate bs reference link
283 $pbms_host = $PMA_Config->get('BLOBSTREAMING_HOST');
284 $pbms_port = $PMA_Config->get('BLOBSTREAMING_PORT');
286 if ($PMA_Config->get('PBMS_PCONNECT_EXISTS')) {
287 // Open a persistent connection.
288 $ok = pbms_pconnect($pbms_host, $pbms_port, $db_name);
289 } else {
290 $ok = pbms_connect($pbms_host, $pbms_port, $db_name);
293 if ($ok == false) {
294 if ($quiet == false) {
295 PMA_BS_ReportPBMSError(__('PBMS connection failed:') . " pbms_connect($pbms_host, $pbms_port, $db_name)");
297 return false;
299 return true;
303 * Disconnects from PBMS server.
305 * @return nothing
307 function PMA_do_disconnect()
309 pbms_close();
313 * Checks whether the BLOB reference looks valid
315 * @param string $bs_reference BLOB reference
316 * @param string $db_name Database name
318 * @return bool True on success.
320 function PMA_BS_IsPBMSReference($bs_reference, $db_name)
322 if (PMA_cacheGet('skip_blobstreaming', true)) {
323 return false;
326 // You do not really need a connection to the PBMS Daemon
327 // to check if a reference looks valid but unfortunalty the API
328 // requires one at this point so until the API is updated
329 // we need to epen one here. If you use pool connections this
330 // will not be a performance problem.
331 if (PMA_do_connect($db_name, false) == false) {
332 return false;
335 $ok = pbms_is_blob_reference($bs_reference);
336 return $ok ;
339 //------------
340 function PMA_BS_CreateReferenceLink($bs_reference, $db_name)
342 if (PMA_do_connect($db_name, false) == false) {
343 return __('Error');
346 if (pbms_get_info(trim($bs_reference)) == false) {
347 PMA_BS_ReportPBMSError(__('PBMS get BLOB info failed:') . " pbms_get_info($bs_reference)");
348 PMA_do_disconnect();
349 return __('Error');
352 $content_type = pbms_get_metadata_value("Content-Type");
353 if ($content_type == false) {
354 $br = trim($bs_reference);
355 PMA_BS_ReportPBMSError("PMA_BS_CreateReferenceLink('$br', '$db_name'): " . __('PBMS get BLOB Content-Type failed'));
358 PMA_do_disconnect();
360 if (! $content_type) {
361 $content_type = "image/jpeg";
364 $bs_url = PMA_BS_getURL($bs_reference);
365 if (empty($bs_url)) {
366 PMA_BS_ReportPBMSError(__('No blob streaming server configured!'));
367 return 'Error';
370 $output = $content_type;
372 // specify custom HTML for various content types
373 switch ($content_type) {
374 // no content specified
375 case NULL:
376 $output = "NULL";
377 break;
378 // image content
379 case 'image/jpeg':
380 case 'image/png':
381 $output .= ' (<a href="' . $bs_url . '" target="new">' . __('View image') . '</a>)';
382 break;
383 // audio content
384 case 'audio/mpeg':
385 $output .= ' (<a href="#" onclick="popupBSMedia(\'' . PMA_generate_common_url() . '\',\'' . urlencode($bs_reference) . '\', \'' . urlencode($content_type) . '\',' . ($is_custom_type ? 1 : 0) . ', 640, 120)">' . __('Play audio'). '</a>)';
386 break;
387 // video content
388 case 'application/x-flash-video':
389 case 'video/mpeg':
390 $output .= ' (<a href="#" onclick="popupBSMedia(\'' . PMA_generate_common_url() . '\',\'' . urlencode($bs_reference) . '\', \'' . urlencode($content_type) . '\',' . ($is_custom_type ? 1 : 0) . ', 640, 480)">' . __('View video') . '</a>)';
391 break;
392 // unsupported content. specify download
393 default:
394 $output .= ' (<a href="' . $bs_url . '" target="new">' . __('Download file'). '</a>)';
397 return $output;
401 * In the future there may be server variables to turn on/off PBMS
402 * BLOB streaming on a per table or database basis. So in anticipation of this
403 * PMA_BS_IsTablePBMSEnabled() passes in the table and database name even though
404 * they are not currently needed.
406 * @param string $db_name
407 * @param string $tbl_name
408 * @param string $tbl_type
409 * @return bool
411 function PMA_BS_IsTablePBMSEnabled($db_name, $tbl_name, $tbl_type)
413 if (PMA_cacheGet('skip_blobstreaming', true)) {
414 return false;
417 if ((isset($tbl_type) == false) || (strlen($tbl_type) == 0)) {
418 return false;
421 // load PMA configuration
422 $PMA_Config = $GLOBALS['PMA_Config'];
424 // return if unable to load PMA configuration
425 if (empty($PMA_Config)) {
426 return false;
429 if (! $PMA_Config->get('BLOBSTREAMING_PLUGINS_EXIST')) {
430 return false;
433 // This information should be cached rather than selecting it each time.
434 //$query = "SELECT count(*) FROM information_schema.TABLES T, pbms.pbms_enabled E where T.table_schema = ". PMA_backquote($db_name) . " and T.table_name = ". PMA_backquote($tbl_name) . " and T.engine = E.name";
435 $query = "SELECT count(*) FROM pbms.pbms_enabled E where E.name = '" . PMA_sqlAddSlashes($tbl_type) . "'";
436 $result = PMA_DBI_query($query);
438 $data = PMA_DBI_fetch_row($result);
439 if ($data[0] == 1) {
440 return true;
443 return false;
446 //------------
447 function PMA_BS_UpLoadFile($db_name, $tbl_name, $file_type, $file_name)
450 if (PMA_cacheGet('skip_blobstreaming', true)) {
451 return false;
454 if (PMA_do_connect($db_name, false) == false) {
455 return false;
458 $fh = fopen($file_name, 'r');
459 if (! $fh) {
460 PMA_do_disconnect();
461 PMA_showMessage(sprintf(__('Could not open file: %s'), $file_name));
462 return false;
465 pbms_add_metadata("Content-Type", $file_type);
467 $pbms_blob_url = pbms_read_stream($fh, filesize($file_name), $tbl_name);
468 if (! $pbms_blob_url) {
469 PMA_BS_ReportPBMSError("pbms_read_stream()");
472 fclose($fh);
473 PMA_do_disconnect();
474 return $pbms_blob_url;
477 //------------
478 function PMA_BS_SetContentType($db_name, $bsTable, $blobReference, $contentType)
480 if (PMA_cacheGet('skip_blobstreaming', true)) {
481 return false;
484 // This is a really ugly way to do this but currently there is nothing better.
485 // In a future version of PBMS the system tables will be redesigned to make this
486 // more efficient.
487 $query = "SELECT Repository_id, Repo_blob_offset FROM pbms_reference WHERE Blob_url='" . PMA_sqlAddSlashes($blobReference) . "'";
488 //error_log(" PMA_BS_SetContentType: $query\n", 3, "/tmp/mylog");
489 $result = PMA_DBI_query($query);
490 //error_log(" $query\n", 3, "/tmp/mylog");
492 // if record exists
493 if ($data = PMA_DBI_fetch_assoc($result)) {
494 $where = "WHERE Repository_id=" . $data['Repository_id'] . " AND Repo_blob_offset=" . $data['Repo_blob_offset'] ;
495 $query = "SELECT name from pbms_metadata $where";
496 $result = PMA_DBI_query($query);
498 if (PMA_DBI_num_rows($result) == 0) {
499 $query = "INSERT into pbms_metadata Values( ". $data['Repository_id'] . ", " . $data['Repo_blob_offset'] . ", 'Content_type', '" . PMA_sqlAddSlashes($contentType) . "')";
500 } else {
501 $query = "UPDATE pbms_metadata SET name = 'Content_type', Value = '" . PMA_sqlAddSlashes($contentType) . "' $where";
503 //error_log("$query\n", 3, "/tmp/mylog");
504 PMA_DBI_query($query);
505 } else {
506 return false;
508 return true;
511 //------------
512 function PMA_BS_IsHiddenTable($table)
514 if ($table === 'pbms_repository' || $table === 'pbms_reference' || $table === 'pbms_metadata'
515 || $table === 'pbms_metadata_header' || $table === 'pbms_dump') {
516 return true;
518 return false;
521 //------------
522 function PMA_BS_getURL($reference)
524 // load PMA configuration
525 $PMA_Config = $GLOBALS['PMA_Config'];
526 if (empty($PMA_Config)) {
527 return false;
530 // retrieve BS server variables from PMA configuration
531 $bs_server = $PMA_Config->get('BLOBSTREAMING_SERVER');
532 if (empty($bs_server)) {
533 return false;
536 $bs_url = PMA_linkURL('http://' . $bs_server . '/' . rtrim($reference));
537 return $bs_url;