Merge remote-tracking branch 'origin/master' into drizzle
[phpmyadmin.git] / libraries / blobstreaming.lib.php
blob848a0967e447604cab4efa98f3cf1d607ef44e7a
1 <?php
2 /* vim: set expandtab sw=4 ts=4 sts=4: */
3 /**
4 * @package BLOBStreaming
5 */
7 function initPBMSDatabase()
9 $query = "create database IF NOT EXISTS pbms;"; // If no other choice then try this.
11 * The user may not have privileges to create the 'pbms' database
12 * so if it doesn't exist then we perform a select on a pbms system
13 * table in an already existing database which will cause the PBMS
14 * daemon to create the 'pbms' database.
16 $db_array = PMA_DBI_fetch_result('SHOW DATABASES;');
17 if (! empty($db_array)) {
18 $target = "";
19 foreach ($db_array as $current_db) {
20 if ($current_db == 'pbms') {
21 return true;
23 if ($target == "") {
24 if ($current_db != 'pbxt' && $current_db != 'mysql' && strtolower($current_db) != 'information_schema'
25 && (!PMA_DRIZZLE || strtolower($current_db) != 'data_dictionary')) {
26 $target = $current_db;
31 if ($target != "") {
32 $query = "select * from $target.pbms_metadata_header"; // If it exists this table will not contain much
36 $result = PMA_DBI_query($query );
37 if (! $result) {
38 return false;
40 return true;
43 /**
44 * checks whether the necessary plugins for BLOBStreaming exist
46 * @access public
47 * @return boolean
49 function checkBLOBStreamingPlugins()
51 if (PMA_cacheGet('skip_blobstreaming', true) === true) {
52 return false;
55 // load PMA configuration
56 $PMA_Config = $GLOBALS['PMA_Config'];
58 // return if unable to load PMA configuration
59 if (empty($PMA_Config)) {
60 return false;
63 // If we don't know that we can skip blobstreaming, we continue
64 // verifications; anyway, in case we won't skip blobstreaming,
65 // we still need to set some variables in non-persistent settings,
66 // which is done via $PMA_Config->set().
68 /** Retrieve current server configuration;
69 * at this point, $PMA_Config->get('Servers') contains the server parameters
70 * as explicitely defined in config.inc.php, so it cannot be used; it's
71 * better to use $GLOBALS['cfg']['Server'] which contains the explicit
72 * parameters merged with the default ones
75 $serverCfg = $GLOBALS['cfg']['Server'];
77 // return if unable to retrieve current server configuration
78 if (! $serverCfg) {
79 return false;
82 // if PHP extension in use is 'mysql', specify element 'PersistentConnections'
83 if ($serverCfg['extension'] == "mysql") {
84 $serverCfg['PersistentConnections'] = $PMA_Config->settings['PersistentConnections'];
87 // if connection type is TCP, unload socket variable
88 if (strtolower($serverCfg['connect_type']) == "tcp") {
89 $serverCfg['socket'] = "";
92 $has_blobstreaming = PMA_cacheGet('has_blobstreaming', true);
94 if ($has_blobstreaming === null) {
95 if (!PMA_DRIZZLE && PMA_MYSQL_INT_VERSION >= 50109) {
97 // Retrieve MySQL plugins
98 $existing_plugins = PMA_DBI_fetch_result('SHOW PLUGINS');
100 foreach ($existing_plugins as $one_existing_plugin) {
101 // check if required plugins exist
102 if ( strtolower($one_existing_plugin['Library']) == 'libpbms.so'
103 && $one_existing_plugin['Status'] == "ACTIVE") {
104 $has_blobstreaming = true;
105 break;
108 unset($existing_plugins, $one_existing_plugin);
109 } else if (PMA_DRIZZLE) {
110 $has_blobstreaming = (bool)PMA_DBI_fetch_result(
111 "SELECT 1
112 FROM data_dictionary.plugins
113 WHERE module_name = 'PBMS'
114 AND is_active = true
115 LIMIT 1");
117 PMA_cacheSet('has_blobstreaming', $has_blobstreaming, true);
120 // set variable indicating BS plugin existence
121 $PMA_Config->set('BLOBSTREAMING_PLUGINS_EXIST', $has_blobstreaming);
123 if (!$has_blobstreaming) {
124 PMA_cacheSet('skip_blobstreaming', true, true);
125 return false;
128 if ($has_blobstreaming) {
129 $bs_variables = PMA_BS_GetVariables();
131 // if no BS variables exist, set plugin existence to false and return
132 if (count($bs_variables) == 0) {
133 $PMA_Config->set('BLOBSTREAMING_PLUGINS_EXIST', false);
134 PMA_cacheSet('skip_blobstreaming', true, true);
135 PMA_cacheSet('has_blobstreaming', false, true);
136 return false;
137 } // end if (count($bs_variables) <= 0)
139 // Check that the required pbms functions exist:
140 if ((function_exists("pbms_connect") == false) ||
141 (function_exists("pbms_error") == false) ||
142 (function_exists("pbms_close") == false) ||
143 (function_exists("pbms_is_blob_reference") == false) ||
144 (function_exists("pbms_get_info") == false) ||
145 (function_exists("pbms_get_metadata_value") == false) ||
146 (function_exists("pbms_add_metadata") == false) ||
147 (function_exists("pbms_read_stream") == false)) {
149 // We should probably notify the user that they need to install
150 // the pbms client lib and PHP extension to make use of blob streaming.
151 $PMA_Config->set('BLOBSTREAMING_PLUGINS_EXIST', false);
152 PMA_cacheSet('skip_blobstreaming', true, true);
153 PMA_cacheSet('has_blobstreaming', false, true);
154 return false;
157 if (function_exists("pbms_connection_pool_size")) {
158 if ( isset($PMA_Config->settings['pbms_connection_pool_size'])) {
159 $pool_size = $PMA_Config->settings['pbms_connection_pool_size'];
160 if ($pool_size == "") {
161 $pool_size = 1;
163 } else {
164 $pool_size = 1;
166 pbms_connection_pool_size($pool_size);
169 // get BS server port
170 $BS_PORT = $bs_variables['pbms_port'];
172 // if no BS server port or 'pbms' database exists, set plugin existance to false and return
173 if ((! $BS_PORT) || (! initPBMSDatabase())) {
174 $PMA_Config->set('BLOBSTREAMING_PLUGINS_EXIST', false);
175 PMA_cacheSet('skip_blobstreaming', true, true);
176 return false;
177 } // end if (!$BS_PORT)
179 // Ping PBMS: the database doesn't need to exist for this to work.
180 if (pbms_connect($serverCfg['host'], $BS_PORT, "anydb") == false) {
181 $PMA_Config->set('BLOBSTREAMING_PLUGINS_EXIST', false);
182 PMA_cacheSet('skip_blobstreaming', true, true);
183 return false;
185 pbms_close();
187 if (function_exists("pbms_pconnect")) {
188 $PMA_Config->set('PBMS_PCONNECT_EXISTS', true);
189 } else {
190 $PMA_Config->set('PBMS_PCONNECT_EXISTS', false);
193 // add selected BS, CURL and fileinfo library variables to PMA configuration
194 $PMA_Config->set('BLOBSTREAMING_PORT', $BS_PORT);
195 $PMA_Config->set('BLOBSTREAMING_HOST', $serverCfg['host']);
196 $PMA_Config->set('BLOBSTREAMING_SERVER', $serverCfg['host'] . ':' . $BS_PORT);
197 $PMA_Config->set('PHP_PBMS_EXISTS', false);
198 $PMA_Config->set('FILEINFO_EXISTS', false);
200 // check if PECL's fileinfo library exist
201 $finfo = null;
203 if (function_exists("finfo_open")) {
204 $finfo = finfo_open(FILEINFO_MIME);
207 // fileinfo library exists, set necessary variable and close resource
208 if (! empty($finfo)) {
209 $PMA_Config->set('FILEINFO_EXISTS', true);
210 finfo_close($finfo);
211 } // end if (!empty($finfo))
213 } else {
214 PMA_cacheSet('skip_blobstreaming', true, true);
215 return false;
216 } // end if ($has_blobstreaming)
218 return true;
222 * returns a list of BLOBStreaming variables used by MySQL
224 * @access public
225 * @return array - list of BLOBStreaming variables
227 function PMA_BS_GetVariables()
229 // load PMA configuration
230 $PMA_Config = $GLOBALS['PMA_Config'];
232 // return if unable to load PMA configuration
233 if (empty($PMA_Config))
234 return NULL;
236 // run query to retrieve BS variables
237 $query = "SHOW VARIABLES LIKE '%pbms%'";
238 $result = PMA_DBI_query($query);
240 $BS_Variables = array();
242 // while there are records to retrieve
243 while ($data = @PMA_DBI_fetch_assoc($result))
244 $BS_Variables[$data['Variable_name']] = $data['Value'];
246 // return BS variables
247 return $BS_Variables;
250 //========================
251 //========================
252 function PMA_BS_ReportPBMSError($msg)
254 $tmp_err = pbms_error();
255 PMA_showMessage(__('PBMS error') . " $msg $tmp_err");
258 //------------
259 function PMA_do_connect($db_name, $quiet)
261 $PMA_Config = $GLOBALS['PMA_Config'];
263 // return if unable to load PMA configuration
264 if (empty($PMA_Config)) {
265 return false;
268 // generate bs reference link
269 $pbms_host = $PMA_Config->get('BLOBSTREAMING_HOST');
270 $pbms_port = $PMA_Config->get('BLOBSTREAMING_PORT');
272 if ($PMA_Config->get('PBMS_PCONNECT_EXISTS')) {
273 // Open a persistent connection.
274 $ok = pbms_pconnect($pbms_host, $pbms_port, $db_name);
275 } else {
276 $ok = pbms_connect($pbms_host, $pbms_port, $db_name);
279 if ($ok == false) {
280 if ($quiet == false) {
281 PMA_BS_ReportPBMSError(__('PBMS connection failed:') . " pbms_connect($pbms_host, $pbms_port, $db_name)");
283 return false;
285 return true;
288 //------------
289 function PMA_do_disconnect()
291 pbms_close();
294 //------------
296 * checks whether the BLOB reference looks valid
299 function PMA_BS_IsPBMSReference($bs_reference, $db_name)
301 if (PMA_cacheGet('skip_blobstreaming', true)) {
302 return false;
305 // You do not really need a connection to the PBMS Daemon
306 // to check if a reference looks valid but unfortunalty the API
307 // requires one at this point so until the API is updated
308 // we need to epen one here. If you use pool connections this
309 // will not be a performance problem.
310 if (PMA_do_connect($db_name, false) == false) {
311 return false;
314 $ok = pbms_is_blob_reference($bs_reference);
315 return $ok ;
318 //------------
319 function PMA_BS_CreateReferenceLink($bs_reference, $db_name)
321 if (PMA_do_connect($db_name, false) == false) {
322 return __('Error');
325 if (pbms_get_info(trim($bs_reference)) == false) {
326 PMA_BS_ReportPBMSError(__('PBMS get BLOB info failed:') . " pbms_get_info($bs_reference)");
327 PMA_do_disconnect();
328 return __('Error');
331 $content_type = pbms_get_metadata_value("Content-Type");
332 if ($content_type == false) {
333 $br = trim($bs_reference);
334 PMA_BS_ReportPBMSError("PMA_BS_CreateReferenceLink('$br', '$db_name'): " . __('get BLOB Content-Type failed'));
337 PMA_do_disconnect();
339 if (! $content_type) {
340 $content_type = "image/jpeg";
343 $bs_url = PMA_BS_getURL($bs_reference);
344 if (empty($bs_url)) {
345 PMA_BS_ReportPBMSError(__('No blob streaming server configured!'));
346 return 'Error';
349 $output = $content_type;
351 // specify custom HTML for various content types
352 switch ($content_type) {
353 // no content specified
354 case NULL:
355 $output = "NULL";
356 break;
357 // image content
358 case 'image/jpeg':
359 case 'image/png':
360 $output .= ' (<a href="' . $bs_url . '" target="new">' . __('View image') . '</a>)';
361 break;
362 // audio content
363 case 'audio/mpeg':
364 $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>)';
365 break;
366 // video content
367 case 'application/x-flash-video':
368 case 'video/mpeg':
369 $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>)';
370 break;
371 // unsupported content. specify download
372 default:
373 $output .= ' (<a href="' . $bs_url . '" target="new">' . __('Download file'). '</a>)';
376 return $output;
379 //------------
380 // In the future there may be server variables to turn on/off PBMS
381 // BLOB streaming on a per table or database basis. So in anticipation of this
382 // PMA_BS_IsTablePBMSEnabled() passes in the table and database name even though
383 // they are not currently needed.
384 function PMA_BS_IsTablePBMSEnabled($db_name, $tbl_name, $tbl_type)
386 if (PMA_cacheGet('skip_blobstreaming', true)) {
387 return false;
390 if ((isset($tbl_type) == false) || (strlen($tbl_type) == 0)) {
391 return false;
394 // load PMA configuration
395 $PMA_Config = $GLOBALS['PMA_Config'];
397 // return if unable to load PMA configuration
398 if (empty($PMA_Config)) {
399 return false;
402 if (! $PMA_Config->get('BLOBSTREAMING_PLUGINS_EXIST')) {
403 return false;
406 // This information should be cached rather than selecting it each time.
407 //$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";
408 $query = "SELECT count(*) FROM pbms.pbms_enabled E where E.name = '" . PMA_sqlAddSlashes($tbl_type) . "'";
409 $result = PMA_DBI_query($query);
411 $data = PMA_DBI_fetch_row($result);
412 if ($data[0] == 1) {
413 return true;
416 return false;
419 //------------
420 function PMA_BS_UpLoadFile($db_name, $tbl_name, $file_type, $file_name)
423 if (PMA_cacheGet('skip_blobstreaming', true)) {
424 return false;
427 if (PMA_do_connect($db_name, false) == false) {
428 return false;
431 $fh = fopen($file_name, 'r');
432 if (! $fh) {
433 PMA_do_disconnect();
434 PMA_showMessage(sprintf(__('Could not open file: %s'), $file_name));
435 return false;
438 pbms_add_metadata("Content-Type", $file_type);
440 $pbms_blob_url = pbms_read_stream($fh, filesize($file_name), $tbl_name);
441 if (! $pbms_blob_url) {
442 PMA_BS_ReportPBMSError("pbms_read_stream()");
445 fclose($fh);
446 PMA_do_disconnect();
447 return $pbms_blob_url;
450 //------------
451 function PMA_BS_SetContentType($db_name, $bsTable, $blobReference, $contentType)
453 if (PMA_cacheGet('skip_blobstreaming', true)) {
454 return false;
457 // This is a really ugly way to do this but currently there is nothing better.
458 // In a future version of PBMS the system tables will be redesigned to make this
459 // more efficient.
460 $query = "SELECT Repository_id, Repo_blob_offset FROM pbms_reference WHERE Blob_url='" . PMA_sqlAddSlashes($blobReference) . "'";
461 //error_log(" PMA_BS_SetContentType: $query\n", 3, "/tmp/mylog");
462 $result = PMA_DBI_query($query);
463 //error_log(" $query\n", 3, "/tmp/mylog");
465 // if record exists
466 if ($data = PMA_DBI_fetch_assoc($result)) {
467 $where = "WHERE Repository_id=" . $data['Repository_id'] . " AND Repo_blob_offset=" . $data['Repo_blob_offset'] ;
468 $query = "SELECT name from pbms_metadata $where";
469 $result = PMA_DBI_query($query);
471 if (PMA_DBI_num_rows($result) == 0) {
472 $query = "INSERT into pbms_metadata Values( ". $data['Repository_id'] . ", " . $data['Repo_blob_offset'] . ", 'Content_type', '" . PMA_sqlAddSlashes($contentType) . "')";
473 } else {
474 $query = "UPDATE pbms_metadata SET name = 'Content_type', Value = '" . PMA_sqlAddSlashes($contentType) . "' $where";
476 //error_log("$query\n", 3, "/tmp/mylog");
477 PMA_DBI_query($query);
478 } else {
479 return false;
481 return true;
484 //------------
485 function PMA_BS_IsHiddenTable($table)
487 if ($table === 'pbms_repository' || $table === 'pbms_reference' || $table === 'pbms_metadata'
488 || $table === 'pbms_metadata_header' || $table === 'pbms_dump') {
489 return true;
491 return false;
494 //------------
495 function PMA_BS_getURL($reference)
497 // load PMA configuration
498 $PMA_Config = $GLOBALS['PMA_Config'];
499 if (empty($PMA_Config)) {
500 return false;
503 // retrieve BS server variables from PMA configuration
504 $bs_server = $PMA_Config->get('BLOBSTREAMING_SERVER');
505 if (empty($bs_server)) {
506 return false;
509 $bs_url = PMA_linkURL('http://' . $bs_server . '/' . rtrim($reference));
510 return $bs_url;