You are here

function _filebrowser_load_files in Filebrowser 7.4

Same name and namespace in other branches
  1. 8 filebrowser.common.inc \_filebrowser_load_files()
  2. 6.2 includes/filesystem.inc \_filebrowser_load_files()
  3. 7.2 filebrowser.common.inc \_filebrowser_load_files()
  4. 7.3 filebrowser.common.inc \_filebrowser_load_files()
15 calls to _filebrowser_load_files()
filebrowser_form_create_folder_submit in ./filebrowser.module
create folder submission. @inheritdoc
filebrowser_form_create_folder_validate in ./filebrowser.module
Implements hook_validate() for creating a folder @inheritdoc
filebrowser_form_metadata in ./filebrowser.pages.inc
filebrowser_form_plupload_upload in ./filebrowser.module
upload form using plupload @inheritdoc
filebrowser_form_plupload_upload_submit in ./filebrowser.module
uploads submission. @inheritdoc

... See full list

File

./filebrowser.common.inc, line 263
Misc filebrowser common functions.

Code

function _filebrowser_load_files(&$node, $fid = NULL, $rebuild = FALSE) {
  global $user;

  // if this is an s3 directory create a s3 client and AwsStreamWrapper
  if (is_s3_filesystem($node->folder_path)) {
    $client = awssdk_get_client('s3');
    $client
      ->registerStreamWrapper();
    $is_s3 = true;
  }
  else {
    $is_s3 = false;
  }

  // folder path are node/NID/FID?QUERY
  if (!$fid && (arg(0) == 'node' && is_numeric(arg(2)))) {
    $fid = arg(2);
  }

  // Select current file record according to fid.
  // you are requesting a specific file or sub directory: node/23/47
  if ($fid) {
    $content = _filebrowser_node_content_load($fid);
    if (empty($content['path'])) {
      drupal_goto("node/{$node->nid}");
    }
    $relative_path = $content['path'];
  }
  else {
    $relative_path = '/';
  }
  $is_subdir = $relative_path != '/';

  // If we shouldn't be in a subdirectory, redirect to root_dir.
  if ($is_subdir && !_filebrowser_can_explore_subfolders($node)) {
    drupal_set_message(t('You\'re not allowed to browse sub folders.'), 'error');
    return;
  }

  // More advanced check to make sure no parent directories match our files.
  // blacklist
  if (!empty($relative_path)) {
    $dirs = explode('/', $relative_path);
    foreach ($dirs as $dir) {
      if (!empty($dir)) {
        if (_filebrowser_cant_view_file($node, $dir)) {
          drupal_set_message(t("You're not allowed to view '%dir'.", array(
            '%dir' => $dir,
          )), 'error');
          return;
        }
      }
    }
  }

  // If this folder has already been processed, take it result
  static $cache = array();
  $cid = "{$node->nid}::{$relative_path}";
  if ($rebuild) {
    unset($cache[$cid]);
    unset($node->file_listing);
  }
  if (isset($cache[$cid])) {
    return $node->file_listing = $cache[$cid];
  }

  // Load database folder content
  // first time after node creation $db_content = NULL; there is nothing in the DB
  $db_content = array();
  $query = db_query("SELECT * FROM {node_dir_listing_content} where nid = :nid and root = :root", array(
    ':nid' => $node->nid,
    ':root' => $relative_path,
  ));
  foreach ($query as $data) {
    $db_content[$data->path] = (array) $data;
  }

  //debug($db_content, 'loaded from DB');

  // Build full path
  $fs_root = _filebrowser_encoding_to_fs($node, _filebrowser_get_node_root($node));
  if (!$is_s3) {
    $fs_root = realpath($fs_root);

    // no realpath in case of s3
  }
  if ($fs_root === FALSE) {
    drupal_set_message(t('Configured folder is not readable or is not a directory.'), 'error');
    return;
  }
  if ($is_s3) {
    $fs_root = $fs_root . _filebrowser_encoding_to_fs($node, $relative_path);

    // FIXME: add end slash if not present. This is hackish!
    $fs_root = substr($fs_root, -1, 1) == '/' ? $fs_root : $fs_root . '/';
  }
  else {
    $fs_root = realpath($fs_root . "/" . _filebrowser_encoding_to_fs($node, $relative_path)) . "/";

    // debug($fs_root, 'Line 350 - after realpath + _fb_encoding to fs');
    // echo($fs_root . ' || Line 350 - after realpath + _fb_encoding to fs <br>');
  }

  // Load meta-data
  $file_metadata = array();

  // CLEANUP: var not in use
  // Iterate over files
  $files = array();
  $files_count = 0;
  $total_size = 0;
  $folder_count = 0;
  if (is_dir($fs_root) && ($handler = opendir($fs_root))) {
    while (($fs_filename = readdir($handler)) !== FALSE) {

      //echo 'filename : ' . $fs_filename . "<br>";
      $fs_file_full_path = $fs_root . $fs_filename;

      // Check FS reading rights
      if (!is_readable($fs_file_full_path)) {
        continue;
      }

      // First file filtering
      if ($fs_filename == '.' || $fs_filename == '..') {

        // We are in the root folder, so we don't need an "up" entry
        if ($fs_filename == '..' && !$is_subdir) {

          // file is .. but we are not in a sub directory, so we don't assign it to DB
          continue;
        }
      }
      else {

        // Check subfolder rights
        if (is_dir($fs_file_full_path) && !_filebrowser_can_explore_subfolders($node)) {
          continue;
        }

        // This file is not filtered
        if (is_file($fs_file_full_path) && !_filebrowser_can_view_file($node, $fs_filename)) {
          continue;
        }

        // This file is not allowed
        if (_filebrowser_cant_view_file($node, $fs_filename)) {
          continue;
        }
      }

      // Build file relative path
      $filename = _filebrowser_encoding_from_fs($node, $fs_filename);
      if ($filename == '.') {
        $file_relative_path = $relative_path;
      }
      elseif ($filename == '..') {
        $file_relative_path = _filebrowser_safe_dirname($relative_path);
        $content = (array) db_query("\n            SELECT *\n            FROM {node_dir_listing_content}\n            WHERE nid = :nid and path = :path", array(
          ':nid' => $node->nid,
          ':path' => $file_relative_path,
        ))
          ->fetch();

        //echo ('nid : ' . $node-> nid . ' path: ' . $file_relative_path);
        if ($content) {
          $db_content[$file_relative_path] =& $content;
        }
      }
      else {
        $file_relative_path = $relative_path . ($relative_path != '/' ? '/' : '') . $filename;
      }

      // Build database file record
      if (!isset($db_content[$file_relative_path])) {
        $db_content[$file_relative_path] = array(
          'exists' => TRUE,
          'nid' => $node->nid,
          'root' => $relative_path,
          'path' => $file_relative_path,
        );
      }
      $db_content[$file_relative_path]['exists'] = TRUE;
      $db_content[$file_relative_path]['display-name'] = $filename;
      $files[$filename] = array(
        'nid' => $node->nid,
        'display-name' => $filename,
        'relative-path' => $file_relative_path,
        'full-path' => rtrim($fs_root, '/') . "/" . $fs_filename,
        'status' => MARK_READ,
      );
      $result = module_invoke_all('filebrowser_metadata_get', $files[$filename]);
      if ($result && is_array($result)) {
        $files[$filename] = array_merge($files[$filename], $result);
      }
      if ($files[$filename]['kind'] == 0) {
        $total_size += $files[$filename]['size'];
        $files_count++;
      }
      else {
        if ($fs_filename != '.') {
          $folder_count++;
        }
      }
      if ($user->uid) {
        if ($user->access < $files[$filename]['created']) {
          $files[$filename]['status'] = MARK_NEW;
        }
        elseif ($user->access < $files[$filename]['modified']) {
          $files[$filename]['status'] = MARK_UPDATED;
        }
      }
      if ($fs_filename == '..') {
        $files[$filename]['mime-type'] .= "/parent";
        $files[$filename]['kind'] = 2;
      }
      $file_path = array();
      if ($fs_filename == '..') {
        $parent_folder = dirname($relative_path);
        if ($parent_folder != "/") {
          $file_path['path'] = $parent_folder;
        }

        // echo('fs_filename = ' . $fs_filename . '  |  parent folder = ' . $parent_folder) . '  | file_path[path] = ' .  $file_path['path'] .  "<br>";
      }
      else {
        $file_path['path'] = $relative_path . $fs_filename;
      }
    }

    // Set global folder properties
    $files['.']['size'] = $total_size;
    $files['.']['files_count'] = $files_count;
    $files['.']['folders_count'] = $folder_count;
    $files['.']['relative-path'] = $relative_path;

    // Amazon S3 filesystem does not provide . and .. files. Therefore we will create them manually
    // to maintain same operation as regular FileBrowser FS.
    // FIXME: some properties should be set by function filebrowser_filebrowser_metadata_get()
    if ($is_s3) {
      if ($is_subdir) {

        // Create the .. file data
        $files['..'] = s3_create_subdir($node->nid, $fs_root);

        // Create the . file data
        s3_create_updir($files['.'], $node->nid, $fs_root);

        // Set DB content for Up-directory. In this case the '/' folder
        $db_content['/'] = s3_set_db_content_updir($node->nid);

        //set DB record for current directory (. file)

        // todo: move to s3_fb module
        if (!isset($db_content[$relative_path])) {
          $db_content[$relative_path] = array(
            'exists' => TRUE,
            'nid' => $node->nid,
            'root' => $relative_path,
            'path' => $relative_path,
          );
        }
        $db_content[$relative_path]['exists'] = true;
        $db_content[$relative_path]['display-name'] = '.';
      }
      else {

        // not a sub dir so we only set the . file and / DB data
        if (!isset($db_content['/'])) {
          $db_content['/'] = array(
            'nid' => $node->nid,
            'root' => '/',
            'path' => '/',
          );
        }
        $db_content['/']['exists'] = true;
        $db_content['/']['display-name'] = '.';

        // changes to the File System Array
        $files['.']['nid'] = $node->nid;
        $files['.']['display-name'] = '.';
        $files['.']['full-path'] = $fs_root;

        // evt eindigen met /.
        $files['.']['status'] = MARK_READ;
        $files['.']['kind'] = 1;
        $files['.']['mime-type'] = 'folder';
      }
    }
    closedir($handler);
  }

  // Synchronize what we seen on filesystem with what is stored in database
  // We also build an access URL for each file as it is why we stored this stuff
  // in DB (have a unique ID for each file and path) to get rid of national character
  // mess in URLS.
  $to_delete = array();
  foreach ($db_content as $path => &$record) {

    //debug($record, 'Path');
    if (!isset($record['exists'])) {
      $to_delete[] = $record['fid'];
    }
    else {
      if (!isset($record['fid'])) {
        drupal_write_record('node_dir_listing_content', $record);
      }
      $key = $record['display-name'];
      $files[$key]['fid'] = $record['fid'];
      if ($files[$key]['kind'] != 0) {
        $files[$key]['url'] = _filebrowser_folder_url("node/{$node->nid}" . ($record['path'] != '/' ? "/{$record['fid']}" : ""), array(
          'absolute' => TRUE,
        ));
      }
      else {
        $files[$key]['url'] = url('filebrowser/download/' . $record['fid'], array(
          'absolute' => TRUE,
        ));
      }
    }
  }

  // A quick way to drip obsolete records (FIXME not quite sure there is no limit in the number of
  // items in the list
  if (count($to_delete)) {
    db_query("DELETE FROM {node_dir_listing_content} WHERE fid IN (" . implode(",", $to_delete) . ")");
  }

  // Cache update
  // FIXME : what of two nodes point to the same folder ?
  $cache[$relative_path] =& $files;

  // Add all this data to the node
  $node->file_listing = $files;
}