Merge branch 'MAINT_3_4_0' into QA_3_4
[phpmyadmin-regexreplace.git] / libraries / blobstreaming.lib.php
blob4efaf34bf145b63b3220e3b1cb2c0238a842770f
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 * @uses PMA_Config::get()
47 * @uses PMA_Config::settings()
48 * @uses PMA_Config::set()
49 * @uses PMA_BS_GetVariables()
50 * @uses PMA_cacheSet()
51 * @uses PMA_cacheGet()
52 * @return boolean
54 function checkBLOBStreamingPlugins()
56 // load PMA configuration
57 $PMA_Config = $GLOBALS['PMA_Config'];
59 // return if unable to load PMA configuration
60 if (empty($PMA_Config)) {
61 return FALSE;
64 // If we don't know that we can skip blobstreaming, we continue
65 // verifications; anyway, in case we won't skip blobstreaming,
66 // we still need to set some variables in non-persistent settings,
67 // which is done via $PMA_Config->set().
69 /** Retrieve current server configuration;
70 * at this point, $PMA_Config->get('Servers') contains the server parameters
71 * as explicitely defined in config.inc.php, so it cannot be used; it's
72 * better to use $GLOBALS['cfg']['Server'] which contains the explicit
73 * parameters merged with the default ones
76 $serverCfg = $GLOBALS['cfg']['Server'];
78 // return if unable to retrieve current server configuration
79 if (! $serverCfg) {
80 return FALSE;
83 // if PHP extension in use is 'mysql', specify element 'PersistentConnections'
84 if ($serverCfg['extension'] == "mysql") {
85 $serverCfg['PersistentConnections'] = $PMA_Config->settings['PersistentConnections'];
88 // if connection type is TCP, unload socket variable
89 if (strtolower($serverCfg['connect_type']) == "tcp") {
90 $serverCfg['socket'] = "";
93 $has_blobstreaming = false;
94 if (PMA_MYSQL_INT_VERSION >= 50109) {
96 // Retrieve MySQL plugins
97 $existing_plugins = PMA_DBI_fetch_result('SHOW PLUGINS');
99 foreach ($existing_plugins as $one_existing_plugin) {
100 // check if required plugins exist
101 if ( strtolower($one_existing_plugin['Library']) == 'libpbms.so'
102 && $one_existing_plugin['Status'] == "ACTIVE") {
103 $has_blobstreaming = true;
104 break;
107 unset($existing_plugins, $one_existing_plugin);
110 // set variable indicating BS plugin existence
111 $PMA_Config->set('BLOBSTREAMING_PLUGINS_EXIST', $has_blobstreaming);
113 if ($has_blobstreaming) {
114 $bs_variables = PMA_BS_GetVariables();
116 // if no BS variables exist, set plugin existence to false and return
117 if (count($bs_variables) <= 0) {
118 $PMA_Config->set('BLOBSTREAMING_PLUGINS_EXIST', FALSE);
119 PMA_cacheSet('skip_blobstreaming', true, true);
120 return FALSE;
121 } // end if (count($bs_variables) <= 0)
123 // Check that the required pbms functions exist:
124 if ((function_exists("pbms_connect") == FALSE) ||
125 (function_exists("pbms_error") == FALSE) ||
126 (function_exists("pbms_close") == FALSE) ||
127 (function_exists("pbms_is_blob_reference") == FALSE) ||
128 (function_exists("pbms_get_info") == FALSE) ||
129 (function_exists("pbms_get_metadata_value") == FALSE) ||
130 (function_exists("pbms_add_metadata") == FALSE) ||
131 (function_exists("pbms_read_stream") == FALSE)) {
133 // We should probably notify the user that they need to install
134 // the pbms client lib and PHP extension to make use of blob streaming.
135 $PMA_Config->set('BLOBSTREAMING_PLUGINS_EXIST', FALSE);
136 PMA_cacheSet('skip_blobstreaming', true, true);
137 return FALSE;
140 if (function_exists("pbms_connection_pool_size")) {
141 if ( isset($PMA_Config->settings['pbms_connection_pool_size'])) {
142 $pool_size = $PMA_Config->settings['pbms_connection_pool_size'];
143 if ($pool_size == "") {
144 $pool_size = 1;
146 } else {
147 $pool_size = 1;
149 pbms_connection_pool_size($pool_size);
152 // get BS server port
153 $BS_PORT = $bs_variables['pbms_port'];
155 // if no BS server port or 'pbms' database exists, set plugin existance to false and return
156 if ((! $BS_PORT) || (! initPBMSDatabase())) {
157 $PMA_Config->set('BLOBSTREAMING_PLUGINS_EXIST', FALSE);
158 PMA_cacheSet('skip_blobstreaming', true, true);
159 return FALSE;
160 } // end if (!$BS_PORT)
162 // Ping PBMS: the database doesn't need to exist for this to work.
163 if (pbms_connect($serverCfg['host'], $BS_PORT, "anydb") == FALSE) {
164 $PMA_Config->set('BLOBSTREAMING_PLUGINS_EXIST', FALSE);
165 PMA_cacheSet('skip_blobstreaming', true, true);
166 return FALSE;
168 pbms_close();
170 if (function_exists("pbms_pconnect")) {
171 $PMA_Config->set('PBMS_PCONNECT_EXISTS', TRUE);
172 } else {
173 $PMA_Config->set('PBMS_PCONNECT_EXISTS', FALSE);
176 // add selected BS, CURL and fileinfo library variables to PMA configuration
177 $PMA_Config->set('BLOBSTREAMING_PORT', $BS_PORT);
178 $PMA_Config->set('BLOBSTREAMING_HOST', $serverCfg['host']);
179 $PMA_Config->set('BLOBSTREAMING_SERVER', $serverCfg['host'] . ':' . $BS_PORT);
180 $PMA_Config->set('PHP_PBMS_EXISTS', FALSE);
181 $PMA_Config->set('FILEINFO_EXISTS', FALSE);
183 // check if PECL's fileinfo library exist
184 $finfo = NULL;
186 if (function_exists("finfo_open")) {
187 $finfo = finfo_open(FILEINFO_MIME);
190 // fileinfo library exists, set necessary variable and close resource
191 if (! empty($finfo)) {
192 $PMA_Config->set('FILEINFO_EXISTS', TRUE);
193 finfo_close($finfo);
194 } // end if (!empty($finfo))
196 } else {
197 PMA_cacheSet('skip_blobstreaming', true, true);
198 return FALSE;
199 } // end if ($has_blobstreaming)
201 return TRUE;
205 * returns a list of BLOBStreaming variables used by MySQL
207 * @access public
208 * @uses PMA_Config::get()
209 * @uses PMA_DBI_query()
210 * @uses PMA_DBI_fetch_assoc()
211 * @return array - list of BLOBStreaming variables
213 function PMA_BS_GetVariables()
215 // load PMA configuration
216 $PMA_Config = $GLOBALS['PMA_Config'];
218 // return if unable to load PMA configuration
219 if (empty($PMA_Config))
220 return NULL;
222 // run query to retrieve BS variables
223 $query = "SHOW VARIABLES LIKE '%pbms%'";
224 $result = PMA_DBI_query($query);
226 $BS_Variables = array();
228 // while there are records to retrieve
229 while ($data = @PMA_DBI_fetch_assoc($result))
230 $BS_Variables[$data['Variable_name']] = $data['Value'];
232 // return BS variables
233 return $BS_Variables;
236 //========================
237 //========================
238 function PMA_BS_ReportPBMSError($msg)
240 $tmp_err = pbms_error();
241 PMA_showMessage(__('PBMS error') . " $msg $tmp_err");
244 //------------
245 function PMA_do_connect($db_name, $quiet)
247 $PMA_Config = $GLOBALS['PMA_Config'];
249 // return if unable to load PMA configuration
250 if (empty($PMA_Config)) {
251 return FALSE;
254 // generate bs reference link
255 $pbms_host = $PMA_Config->get('BLOBSTREAMING_HOST');
256 $pbms_port = $PMA_Config->get('BLOBSTREAMING_PORT');
258 if ($PMA_Config->get('PBMS_PCONNECT_EXISTS')) {
259 // Open a persistent connection.
260 $ok = pbms_pconnect($pbms_host, $pbms_port, $db_name);
261 } else {
262 $ok = pbms_connect($pbms_host, $pbms_port, $db_name);
265 if ($ok == FALSE) {
266 if ($quiet == FALSE) {
267 PMA_BS_ReportPBMSError(__('PBMS connection failed:') . " pbms_connect($pbms_host, $pbms_port, $db_name)");
269 return FALSE;
271 return TRUE;
274 //------------
275 function PMA_do_disconnect()
277 pbms_close();
280 //------------
282 * checks whether the BLOB reference looks valid
285 function PMA_BS_IsPBMSReference($bs_reference, $db_name)
287 if (PMA_cacheGet('skip_blobstreaming', true)) {
288 return FALSE;
291 // You do not really need a connection to the PBMS Daemon
292 // to check if a reference looks valid but unfortunalty the API
293 // requires one at this point so until the API is updated
294 // we need to epen one here. If you use pool connections this
295 // will not be a performance problem.
296 if (PMA_do_connect($db_name, FALSE) == FALSE) {
297 return FALSE;
300 $ok = pbms_is_blob_reference($bs_reference);
301 return $ok ;
304 //------------
305 function PMA_BS_CreateReferenceLink($bs_reference, $db_name)
307 if (PMA_do_connect($db_name, FALSE) == FALSE) {
308 return __('Error');
311 if (pbms_get_info(trim($bs_reference)) == FALSE) {
312 PMA_BS_ReportPBMSError(__('PBMS get BLOB info failed:') . " pbms_get_info($bs_reference)");
313 PMA_do_disconnect();
314 return __('Error');
317 $content_type = pbms_get_metadata_value("Content-Type");
318 if ($content_type == FALSE) {
319 $br = trim($bs_reference);
320 PMA_BS_ReportPBMSError("PMA_BS_CreateReferenceLink('$br', '$db_name'): " . __('get BLOB Content-Type failed'));
323 PMA_do_disconnect();
325 if (! $content_type) {
326 $content_type = "image/jpeg";
329 $bs_url = PMA_BS_getURL($bs_reference);
330 if (empty($bs_url)) {
331 PMA_BS_ReportPBMSError(__('No blob streaming server configured!'));
332 return 'Error';
335 //$output = "<a href=\"#\" onclick=\"requestMIMETypeChange('" . urlencode($db_name) . "', '" . urlencode($GLOBALS['table']) . "', '" . urlencode($bs_reference) . "', '" . urlencode($content_type) . "')\">$content_type</a>";
336 $output = $content_type;
338 // specify custom HTML for various content types
339 switch ($content_type) {
340 // no content specified
341 case NULL:
342 $output = "NULL";
343 break;
344 // image content
345 case 'image/jpeg':
346 case 'image/png':
347 $output .= ' (<a href="' . $bs_url . '" target="new">' . __('View image') . '</a>)';
348 break;
349 // audio content
350 case 'audio/mpeg':
351 $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>)';
352 break;
353 // video content
354 case 'application/x-flash-video':
355 case 'video/mpeg':
356 $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>)';
357 break;
358 // unsupported content. specify download
359 default:
360 $output .= ' (<a href="' . $bs_url . '" target="new">' . __('Download file'). '</a>)';
363 return $output;
366 //------------
367 // In the future there may be server variables to turn on/off PBMS
368 // BLOB streaming on a per table or database basis. So in anticipation of this
369 // PMA_BS_IsTablePBMSEnabled() passes in the table and database name even though
370 // they are not currently needed.
371 function PMA_BS_IsTablePBMSEnabled($db_name, $tbl_name, $tbl_type)
373 if (PMA_cacheGet('skip_blobstreaming', true)) {
374 return FALSE;
377 if ((isset($tbl_type) == FALSE) || (strlen($tbl_type) == 0)) {
378 return FALSE;
381 // load PMA configuration
382 $PMA_Config = $GLOBALS['PMA_Config'];
384 // return if unable to load PMA configuration
385 if (empty($PMA_Config)) {
386 return FALSE;
389 if (! $PMA_Config->get('BLOBSTREAMING_PLUGINS_EXIST')) {
390 return FALSE;
393 // This information should be cached rather than selecting it each time.
394 //$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";
395 $query = "SELECT count(*) FROM pbms.pbms_enabled E where E.name = '" . PMA_sqlAddslashes($tbl_type) . "'";
396 $result = PMA_DBI_query($query);
398 $data = PMA_DBI_fetch_row($result);
399 if ($data[0] == 1) {
400 return TRUE;
403 return FALSE;
406 //------------
407 function PMA_BS_UpLoadFile($db_name, $tbl_name, $file_type, $file_name)
410 if (PMA_cacheGet('skip_blobstreaming', true)) {
411 return FALSE;
414 if (PMA_do_connect($db_name, FALSE) == FALSE) {
415 return FALSE;
418 $fh = fopen($file_name, 'r');
419 if (! $fh) {
420 PMA_do_disconnect();
421 PMA_showMessage(sprintf(__('Could not open file: %s'), $file_name));
422 return FALSE;
425 pbms_add_metadata("Content-Type", $file_type);
427 $pbms_blob_url = pbms_read_stream($fh, filesize($file_name), $tbl_name);
428 if (! $pbms_blob_url) {
429 PMA_BS_ReportPBMSError("pbms_read_stream()");
432 fclose($fh);
433 PMA_do_disconnect();
434 return $pbms_blob_url;
437 //------------
438 function PMA_BS_SetContentType($db_name, $bsTable, $blobReference, $contentType)
440 if (PMA_cacheGet('skip_blobstreaming', true)) {
441 return FALSE;
444 // This is a really ugly way to do this but currently there is nothing better.
445 // In a future version of PBMS the system tables will be redesigned to make this
446 // more efficient.
447 $query = "SELECT Repository_id, Repo_blob_offset FROM pbms_reference WHERE Blob_url='" . PMA_sqlAddslashes($blobReference) . "'";
448 //error_log(" PMA_BS_SetContentType: $query\n", 3, "/tmp/mylog");
449 $result = PMA_DBI_query($query);
450 //error_log(" $query\n", 3, "/tmp/mylog");
452 // if record exists
453 if ($data = PMA_DBI_fetch_assoc($result)) {
454 $where = "WHERE Repository_id=" . $data['Repository_id'] . " AND Repo_blob_offset=" . $data['Repo_blob_offset'] ;
455 $query = "SELECT name from pbms_metadata $where";
456 $result = PMA_DBI_query($query);
458 if (PMA_DBI_num_rows($result) == 0) {
459 $query = "INSERT into pbms_metadata Values( ". $data['Repository_id'] . ", " . $data['Repo_blob_offset'] . ", 'Content_type', '" . PMA_sqlAddslashes($contentType) . "')";
460 } else {
461 $query = "UPDATE pbms_metadata SET name = 'Content_type', Value = '" . PMA_sqlAddslashes($contentType) . "' $where";
463 //error_log("$query\n", 3, "/tmp/mylog");
464 PMA_DBI_query($query);
465 } else {
466 return FALSE;
468 return TRUE;
471 //------------
472 function PMA_BS_IsHiddenTable($table)
474 if ($table === 'pbms_repository' || $table === 'pbms_reference' || $table === 'pbms_metadata'
475 || $table === 'pbms_metadata_header' || $table === 'pbms_dump') {
476 return TRUE;
478 return FALSE;
481 //------------
482 function PMA_BS_getURL($reference)
484 // load PMA configuration
485 $PMA_Config = $GLOBALS['PMA_Config'];
486 if (empty($PMA_Config)) {
487 return FALSE;
490 // retrieve BS server variables from PMA configuration
491 $bs_server = $PMA_Config->get('BLOBSTREAMING_SERVER');
492 if (empty($bs_server)) {
493 return FALSE;
496 $bs_url = PMA_linkURL('http://' . $bs_server . '/' . rtrim($reference));
497 return $bs_url;