@@ -282,226 +282,6 @@ function file_entity_view_mode_label($view_mode, $default = FALSE) {
282282 return isset($labels[$view_mode]) ? $labels[$view_mode] : $default;
283283}
284284
285- /**
286- * @defgroup file_entity_access File access rights
287- * @{
288- * The file access system determines who can do what to which files.
289- *
290- * In determining access rights for a file, file_entity_access() first checks
291- * whether the user has the "bypass file access" permission. Such users have
292- * unrestricted access to all files. user 1 will always pass this check.
293- *
294- * Next, all implementations of hook_file_entity_access() will be called. Each
295- * implementation may explicitly allow, explicitly deny, or ignore the access
296- * request. If at least one module says to deny the request, it will be rejected.
297- * If no modules deny the request and at least one says to allow it, the request
298- * will be permitted.
299- *
300- * There is no access grant system for files.
301- *
302- * In file listings, the process above is followed except that
303- * hook_file_entity_access() is not called on each file for performance reasons
304- * and for proper functioning of the pager system. When adding a filelisting to
305- * your module, be sure to use a dynamic query created by db_select()
306- * and add a tag of "file_entity_access". This will allow modules dealing
307- * with file access to ensure only files to which the user has access
308- * are retrieved, through the use of hook_query_TAG_alter().
309- *
310- * Note: Even a single module returning FILE_ENTITY_ACCESS_DENY from
311- * hook_file_entity_access() will block access to the file. Therefore,
312- * implementers should take care to not deny access unless they really intend to.
313- * Unless a module wishes to actively deny access it should return
314- * FILE_ENTITY_ACCESS_IGNORE (or simply return nothing)
315- * to allow other modules to control access.
316- *
317- * Stream wrappers that are considered private should implement a 'private'
318- * flag equal to TRUE in hook_stream_wrappers().
319- */
320-
321- /**
322- * Implements hook_query_TAG_alter().
323- *
324- * This is the hook_query_alter() for queries tagged with 'file_access'. It adds
325- * file access checks for the user account given by the 'account' meta-data (or
326- * global $user if not provided).
327- */
328- function file_entity_query_file_access_alter(SelectInterface $query) {
329- _file_entity_query_file_entity_access_alter($query, 'file');
330- }
331-
332- /**
333- * Helper for file entity access functions.
334- *
335- * @param $query
336- * The query to add conditions to.
337- * @param $type
338- * Either 'file' or 'entity' depending on what sort of query it is. See
339- * file_entity_query_file_entity_access_alter() and
340- * file_entity_query_entity_field_access_alter() for more.
341- */
342- function _file_entity_query_file_entity_access_alter($query, $type) {
343- $user = \Drupal::currentUser();
344-
345- // Read meta-data from query, if provided.
346- if (!$account = $query->getMetaData('account')) {
347- $account = $user;
348- }
349-
350- // If $account can bypass file access, we don't need to alter the query.
351- if ($account->hasPermission('bypass file access')) {
352- return;
353- }
354-
355- $tables = $query->getTables();
356- $base_table = $query->getMetaData('base_table');
357- // If no base table is specified explicitly, search for one.
358- if (!$base_table) {
359- $fallback = '';
360- foreach ($tables as $alias => $table_info) {
361- if (!($table_info instanceof SelectInterface)) {
362- $table = $table_info['table'];
363- // If the file_managed table is in the query, it wins immediately.
364- if ($table == 'file_managed') {
365- $base_table = $table;
366- break;
367- }
368- // Check whether the table has a foreign key to file_managed.fid. If it
369- // does, do not run this check again as we found a base table and only
370- // file_managed can triumph that.
371- if (!$base_table) {
372- // The schema is cached.
373- $schema = drupal_get_schema($table);
374- if (isset($schema['fields']['fid'])) {
375- if (isset($schema['foreign keys'])) {
376- foreach ($schema['foreign keys'] as $relation) {
377- if ($relation['table'] === 'file_managed' && $relation['columns'] === array('fid' => 'fid')) {
378- $base_table = $table;
379- }
380- }
381- }
382- else {
383- // At least it's a fid. A table with a field called fid is very
384- // very likely to be a file_managed.fid in a file access query.
385- $fallback = $table;
386- }
387- }
388- }
389- }
390- }
391- // If there is nothing else, use the fallback.
392- if (!$base_table) {
393- if ($fallback) {
394- watchdog('security', 'Your file listing query is using @fallback as a base table in a query tagged for file access. This might not be secure and might not even work. Specify foreign keys in your schema to file_managed.fid ', array('@fallback' => $fallback), WATCHDOG_WARNING);
395- $base_table = $fallback;
396- }
397- else {
398- throw new Exception(t('Query tagged for file access but there is no fid. Add foreign keys to file_managed.fid in schema to fix.'));
399- }
400- }
401- }
402-
403- if ($type == 'entity') {
404- // The original query looked something like:
405- // @code
406- // SELECT fid FROM sometable s
407- // WHERE ($file_access_conditions)
408- // @endcode
409- //
410- // Our query will look like:
411- // @code
412- // SELECT entity_type, entity_id
413- // FROM field_data_something s
414- // WHERE (entity_type = 'file' AND $file_access_conditions) OR (entity_type <> 'file')
415- // @endcode
416- //
417- // So instead of directly adding to the query object, we need to collect
418- // all of the file access conditions in a separate db_and() object and
419- // then add it to the query at the end.
420- $file_conditions = db_and();
421- }
422- foreach ($tables as $falias => $tableinfo) {
423- $table = $tableinfo['table'];
424- if (!($table instanceof SelectInterface) && $table == $base_table) {
425- $subquery = db_select('file_managed', 'fm_access')->fields('fm_access', array('fid'));
426- $subquery_conditions = db_or();
427-
428- $wrappers = file_entity_get_public_and_private_stream_wrapper_names();
429- if (!empty($wrappers['public'])) {
430- if ($account->hasPermission('view files')) {
431- foreach (array_keys($wrappers['public']) as $wrapper) {
432- $subquery_conditions->condition('fm_access.uri', $wrapper . '%', 'LIKE');
433- }
434- }
435- elseif ($account->hasPermission('view own files')) {
436- foreach (array_keys($wrappers['public']) as $wrapper) {
437- $subquery_conditions->condition(db_and()
438- ->condition('fm_access.uri', $wrapper . '%', 'LIKE')
439- ->condition('fm_access.uid', $account->id())
440- );
441- }
442- }
443- }
444- if (!empty($wrappers['private'])) {
445- if ($account->hasPermission('view private files')) {
446- foreach (array_keys($wrappers['private']) as $wrapper) {
447- $subquery_conditions->condition('fm_access.uri', $wrapper . '%', 'LIKE');
448- }
449- }
450- elseif ($account->hasPermission('view own private files')) {
451- foreach (array_keys($wrappers['private']) as $wrapper) {
452- $subquery_conditions->condition(db_and()
453- ->condition('fm_access.uri', $wrapper . '%', 'LIKE')
454- ->condition('fm_access.uid', $account->id())
455- );
456- }
457- }
458- }
459-
460- if ($subquery_conditions->count()) {
461- $subquery->condition($subquery_conditions);
462-
463- $field = 'fid';
464- // Now handle entities.
465- if ($type == 'entity') {
466- // Set a common alias for entities.
467- $base_alias = $falias;
468- $field = 'entity_id';
469- }
470- $subquery->where("$falias.$field = fm_access.fid");
471-
472- // For an entity query, attach the subquery to entity conditions.
473- if ($type == 'entity') {
474- $file_conditions->exists($subquery);
475- }
476- // Otherwise attach it to the node query itself.
477- elseif ($table == 'file_managed') {
478- // Fix for https://drupal.org/node/2073085
479- $db_or = db_or();
480- $db_or->exists($subquery);
481- $db_or->isNull($falias . '.' . $field);
482- $query->condition($db_or);
483- }
484- else {
485- $query->exists($subquery);
486- }
487- }
488- }
489- }
490-
491- if ($type == 'entity' && $file_conditions->count()) {
492- // All the file access conditions are only for field values belonging to
493- // files.
494- $file_conditions->condition("$base_alias.entity_type", 'file');
495- $or = db_or();
496- $or->condition($file_conditions);
497- // If the field value belongs to a non-file entity type then this function
498- // does not do anything with it.
499- $or->condition("$base_alias.entity_type", 'file', '<>');
500- // Add the compiled set of rules to the query.
501- $query->condition($or);
502- }
503- }
504-
505285/**
506286 * Implements hook_file_download().
507287 */
@@ -523,10 +303,6 @@ function file_entity_file_download($uri) {
523303 return -1;
524304}
525305
526- /**
527- * @} End of "defgroup file_entity_access".
528- */
529-
530306/**
531307 * @name pathauto_file Pathauto integration for the core file module.
532308 * @{
0 commit comments