This should be checked in common, not in dbi library
[phpmyadmin.git] / libraries / blobstreaming.lib.php
blob301403c16e8877e20b6859e138f858ba1b7fe373
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') && ($current_db != 'information_schema')) {
25 $target = $current_db;
30 if ($target != "") {
31 $query = "select * from $target.pbms_metadata_header"; // If it exists this table will not contain much
35 $result = PMA_DBI_query($query );
36 if (! $result) {
37 return false;
39 return true;
42 /**
43 * checks whether the necessary plugins for BLOBStreaming exist
45 * @access public
46 * @return boolean
48 function checkBLOBStreamingPlugins()
50 if (PMA_cacheGet('skip_blobstreaming', true) === true) {
51 return false;
54 // load PMA configuration
55 $PMA_Config = $GLOBALS['PMA_Config'];
57 // return if unable to load PMA configuration
58 if (empty($PMA_Config)) {
59 return false;
62 // If we don't know that we can skip blobstreaming, we continue
63 // verifications; anyway, in case we won't skip blobstreaming,
64 // we still need to set some variables in non-persistent settings,
65 // which is done via $PMA_Config->set().
67 /** Retrieve current server configuration;
68 * at this point, $PMA_Config->get('Servers') contains the server parameters
69 * as explicitely defined in config.inc.php, so it cannot be used; it's
70 * better to use $GLOBALS['cfg']['Server'] which contains the explicit
71 * parameters merged with the default ones
74 $serverCfg = $GLOBALS['cfg']['Server'];
76 // return if unable to retrieve current server configuration
77 if (! $serverCfg) {
78 return false;
81 // if PHP extension in use is 'mysql', specify element 'PersistentConnections'
82 if ($serverCfg['extension'] == "mysql") {
83 $serverCfg['PersistentConnections'] = $PMA_Config->settings['PersistentConnections'];
86 // if connection type is TCP, unload socket variable
87 if (strtolower($serverCfg['connect_type']) == "tcp") {
88 $serverCfg['socket'] = "";
91 $has_blobstreaming = false;
92 if (PMA_MYSQL_INT_VERSION >= 50109) {
94 // Retrieve MySQL plugins
95 $existing_plugins = PMA_DBI_fetch_result('SHOW PLUGINS');
97 foreach ($existing_plugins as $one_existing_plugin) {
98 // check if required plugins exist
99 if ( strtolower($one_existing_plugin['Library']) == 'libpbms.so'
100 && $one_existing_plugin['Status'] == "ACTIVE") {
101 $has_blobstreaming = true;
102 break;
105 unset($existing_plugins, $one_existing_plugin);
108 // set variable indicating BS plugin existence
109 $PMA_Config->set('BLOBSTREAMING_PLUGINS_EXIST', $has_blobstreaming);
111 if ($has_blobstreaming) {
112 $bs_variables = PMA_BS_GetVariables();
114 // if no BS variables exist, set plugin existence to false and return
115 if (count($bs_variables) <= 0) {
116 $PMA_Config->set('BLOBSTREAMING_PLUGINS_EXIST', false);
117 PMA_cacheSet('skip_blobstreaming', true, true);
118 return false;
119 } // end if (count($bs_variables) <= 0)
121 // Check that the required pbms functions exist:
122 if ((function_exists("pbms_connect") == false) ||
123 (function_exists("pbms_error") == false) ||
124 (function_exists("pbms_close") == false) ||
125 (function_exists("pbms_is_blob_reference") == false) ||
126 (function_exists("pbms_get_info") == false) ||
127 (function_exists("pbms_get_metadata_value") == false) ||
128 (function_exists("pbms_add_metadata") == false) ||
129 (function_exists("pbms_read_stream") == false)) {
131 // We should probably notify the user that they need to install
132 // the pbms client lib and PHP extension to make use of blob streaming.
133 $PMA_Config->set('BLOBSTREAMING_PLUGINS_EXIST', false);
134 PMA_cacheSet('skip_blobstreaming', true, true);
135 return false;
138 if (function_exists("pbms_connection_pool_size")) {
139 if ( isset($PMA_Config->settings['pbms_connection_pool_size'])) {
140 $pool_size = $PMA_Config->settings['pbms_connection_pool_size'];
141 if ($pool_size == "") {
142 $pool_size = 1;
144 } else {
145 $pool_size = 1;
147 pbms_connection_pool_size($pool_size);
150 // get BS server port
151 $BS_PORT = $bs_variables['pbms_port'];
153 // if no BS server port or 'pbms' database exists, set plugin existance to false and return
154 if ((! $BS_PORT) || (! initPBMSDatabase())) {
155 $PMA_Config->set('BLOBSTREAMING_PLUGINS_EXIST', false);
156 PMA_cacheSet('skip_blobstreaming', true, true);
157 return false;
158 } // end if (!$BS_PORT)
160 // Ping PBMS: the database doesn't need to exist for this to work.
161 if (pbms_connect($serverCfg['host'], $BS_PORT, "anydb") == false) {
162 $PMA_Config->set('BLOBSTREAMING_PLUGINS_EXIST', false);
163 PMA_cacheSet('skip_blobstreaming', true, true);
164 return false;
166 pbms_close();
168 if (function_exists("pbms_pconnect")) {
169 $PMA_Config->set('PBMS_PCONNECT_EXISTS', true);
170 } else {
171 $PMA_Config->set('PBMS_PCONNECT_EXISTS', false);
174 // add selected BS, CURL and fileinfo library variables to PMA configuration
175 $PMA_Config->set('BLOBSTREAMING_PORT', $BS_PORT);
176 $PMA_Config->set('BLOBSTREAMING_HOST', $serverCfg['host']);
177 $PMA_Config->set('BLOBSTREAMING_SERVER', $serverCfg['host'] . ':' . $BS_PORT);
178 $PMA_Config->set('PHP_PBMS_EXISTS', false);
179 $PMA_Config->set('FILEINFO_EXISTS', false);
181 // check if PECL's fileinfo library exist
182 $finfo = null;
184 if (function_exists("finfo_open")) {
185 $finfo = finfo_open(FILEINFO_MIME);
188 // fileinfo library exists, set necessary variable and close resource
189 if (! empty($finfo)) {
190 $PMA_Config->set('FILEINFO_EXISTS', true);
191 finfo_close($finfo);
192 } // end if (!empty($finfo))
194 } else {
195 PMA_cacheSet('skip_blobstreaming', true, true);
196 return false;
197 } // end if ($has_blobstreaming)
199 return true;
203 * returns a list of BLOBStreaming variables used by MySQL
205 * @access public
206 * @return array - list of BLOBStreaming variables
208 function PMA_BS_GetVariables()
210 // load PMA configuration
211 $PMA_Config = $GLOBALS['PMA_Config'];
213 // return if unable to load PMA configuration
214 if (empty($PMA_Config))
215 return NULL;
217 // run query to retrieve BS variables
218 $query = "SHOW VARIABLES LIKE '%pbms%'";
219 $result = PMA_DBI_query($query);
221 $BS_Variables = array();
223 // while there are records to retrieve
224 while ($data = @PMA_DBI_fetch_assoc($result))
225 $BS_Variables[$data['Variable_name']] = $data['Value'];
227 // return BS variables
228 return $BS_Variables;
231 //========================
232 //========================
233 function PMA_BS_ReportPBMSError($msg)
235 $tmp_err = pbms_error();
236 PMA_showMessage(__('PBMS error') . " $msg $tmp_err");
239 //------------
240 function PMA_do_connect($db_name, $quiet)
242 $PMA_Config = $GLOBALS['PMA_Config'];
244 // return if unable to load PMA configuration
245 if (empty($PMA_Config)) {
246 return false;
249 // generate bs reference link
250 $pbms_host = $PMA_Config->get('BLOBSTREAMING_HOST');
251 $pbms_port = $PMA_Config->get('BLOBSTREAMING_PORT');
253 if ($PMA_Config->get('PBMS_PCONNECT_EXISTS')) {
254 // Open a persistent connection.
255 $ok = pbms_pconnect($pbms_host, $pbms_port, $db_name);
256 } else {
257 $ok = pbms_connect($pbms_host, $pbms_port, $db_name);
260 if ($ok == false) {
261 if ($quiet == false) {
262 PMA_BS_ReportPBMSError(__('PBMS connection failed:') . " pbms_connect($pbms_host, $pbms_port, $db_name)");
264 return false;
266 return true;
269 //------------
270 function PMA_do_disconnect()
272 pbms_close();
275 //------------
277 * checks whether the BLOB reference looks valid
280 function PMA_BS_IsPBMSReference($bs_reference, $db_name)
282 if (PMA_cacheGet('skip_blobstreaming', true)) {
283 return false;
286 // You do not really need a connection to the PBMS Daemon
287 // to check if a reference looks valid but unfortunalty the API
288 // requires one at this point so until the API is updated
289 // we need to epen one here. If you use pool connections this
290 // will not be a performance problem.
291 if (PMA_do_connect($db_name, false) == false) {
292 return false;
295 $ok = pbms_is_blob_reference($bs_reference);
296 return $ok ;
299 //------------
300 function PMA_BS_CreateReferenceLink($bs_reference, $db_name)
302 if (PMA_do_connect($db_name, false) == false) {
303 return __('Error');
306 if (pbms_get_info(trim($bs_reference)) == false) {
307 PMA_BS_ReportPBMSError(__('PBMS get BLOB info failed:') . " pbms_get_info($bs_reference)");
308 PMA_do_disconnect();
309 return __('Error');
312 $content_type = pbms_get_metadata_value("Content-Type");
313 if ($content_type == false) {
314 $br = trim($bs_reference);
315 PMA_BS_ReportPBMSError("PMA_BS_CreateReferenceLink('$br', '$db_name'): " . __('get BLOB Content-Type failed'));
318 PMA_do_disconnect();
320 if (! $content_type) {
321 $content_type = "image/jpeg";
324 $bs_url = PMA_BS_getURL($bs_reference);
325 if (empty($bs_url)) {
326 PMA_BS_ReportPBMSError(__('No blob streaming server configured!'));
327 return 'Error';
330 $output = $content_type;
332 // specify custom HTML for various content types
333 switch ($content_type) {
334 // no content specified
335 case NULL:
336 $output = "NULL";
337 break;
338 // image content
339 case 'image/jpeg':
340 case 'image/png':
341 $output .= ' (<a href="' . $bs_url . '" target="new">' . __('View image') . '</a>)';
342 break;
343 // audio content
344 case 'audio/mpeg':
345 $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>)';
346 break;
347 // video content
348 case 'application/x-flash-video':
349 case 'video/mpeg':
350 $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>)';
351 break;
352 // unsupported content. specify download
353 default:
354 $output .= ' (<a href="' . $bs_url . '" target="new">' . __('Download file'). '</a>)';
357 return $output;
360 //------------
361 // In the future there may be server variables to turn on/off PBMS
362 // BLOB streaming on a per table or database basis. So in anticipation of this
363 // PMA_BS_IsTablePBMSEnabled() passes in the table and database name even though
364 // they are not currently needed.
365 function PMA_BS_IsTablePBMSEnabled($db_name, $tbl_name, $tbl_type)
367 if (PMA_cacheGet('skip_blobstreaming', true)) {
368 return false;
371 if ((isset($tbl_type) == false) || (strlen($tbl_type) == 0)) {
372 return false;
375 // load PMA configuration
376 $PMA_Config = $GLOBALS['PMA_Config'];
378 // return if unable to load PMA configuration
379 if (empty($PMA_Config)) {
380 return false;
383 if (! $PMA_Config->get('BLOBSTREAMING_PLUGINS_EXIST')) {
384 return false;
387 // This information should be cached rather than selecting it each time.
388 //$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";
389 $query = "SELECT count(*) FROM pbms.pbms_enabled E where E.name = '" . PMA_sqlAddSlashes($tbl_type) . "'";
390 $result = PMA_DBI_query($query);
392 $data = PMA_DBI_fetch_row($result);
393 if ($data[0] == 1) {
394 return true;
397 return false;
400 //------------
401 function PMA_BS_UpLoadFile($db_name, $tbl_name, $file_type, $file_name)
404 if (PMA_cacheGet('skip_blobstreaming', true)) {
405 return false;
408 if (PMA_do_connect($db_name, false) == false) {
409 return false;
412 $fh = fopen($file_name, 'r');
413 if (! $fh) {
414 PMA_do_disconnect();
415 PMA_showMessage(sprintf(__('Could not open file: %s'), $file_name));
416 return false;
419 pbms_add_metadata("Content-Type", $file_type);
421 $pbms_blob_url = pbms_read_stream($fh, filesize($file_name), $tbl_name);
422 if (! $pbms_blob_url) {
423 PMA_BS_ReportPBMSError("pbms_read_stream()");
426 fclose($fh);
427 PMA_do_disconnect();
428 return $pbms_blob_url;
431 //------------
432 function PMA_BS_SetContentType($db_name, $bsTable, $blobReference, $contentType)
434 if (PMA_cacheGet('skip_blobstreaming', true)) {
435 return false;
438 // This is a really ugly way to do this but currently there is nothing better.
439 // In a future version of PBMS the system tables will be redesigned to make this
440 // more efficient.
441 $query = "SELECT Repository_id, Repo_blob_offset FROM pbms_reference WHERE Blob_url='" . PMA_sqlAddSlashes($blobReference) . "'";
442 //error_log(" PMA_BS_SetContentType: $query\n", 3, "/tmp/mylog");
443 $result = PMA_DBI_query($query);
444 //error_log(" $query\n", 3, "/tmp/mylog");
446 // if record exists
447 if ($data = PMA_DBI_fetch_assoc($result)) {
448 $where = "WHERE Repository_id=" . $data['Repository_id'] . " AND Repo_blob_offset=" . $data['Repo_blob_offset'] ;
449 $query = "SELECT name from pbms_metadata $where";
450 $result = PMA_DBI_query($query);
452 if (PMA_DBI_num_rows($result) == 0) {
453 $query = "INSERT into pbms_metadata Values( ". $data['Repository_id'] . ", " . $data['Repo_blob_offset'] . ", 'Content_type', '" . PMA_sqlAddSlashes($contentType) . "')";
454 } else {
455 $query = "UPDATE pbms_metadata SET name = 'Content_type', Value = '" . PMA_sqlAddSlashes($contentType) . "' $where";
457 //error_log("$query\n", 3, "/tmp/mylog");
458 PMA_DBI_query($query);
459 } else {
460 return false;
462 return true;
465 //------------
466 function PMA_BS_IsHiddenTable($table)
468 if ($table === 'pbms_repository' || $table === 'pbms_reference' || $table === 'pbms_metadata'
469 || $table === 'pbms_metadata_header' || $table === 'pbms_dump') {
470 return true;
472 return false;
475 //------------
476 function PMA_BS_getURL($reference)
478 // load PMA configuration
479 $PMA_Config = $GLOBALS['PMA_Config'];
480 if (empty($PMA_Config)) {
481 return false;
484 // retrieve BS server variables from PMA configuration
485 $bs_server = $PMA_Config->get('BLOBSTREAMING_SERVER');
486 if (empty($bs_server)) {
487 return false;
490 $bs_url = PMA_linkURL('http://' . $bs_server . '/' . rtrim($reference));
491 return $bs_url;