You are here

imce.module in IMCE 5

Same filename and directory in other branches
  1. 8.2 imce.module
  2. 8 imce.module
  3. 6.2 imce.module
  4. 6 imce.module
  5. 7 imce.module

File

imce.module
View source
<?php

/**
 * Implementation of hook_footer().
 */
function imce_footer() {
  if (user_access('access imce')) {
    $header = drupal_get_js();

    //set imce if tinymce is in action
    if (!imce_integrate('tinymce', 'check') && module_exists('tinymce') && variable_get('imce_settings_tinymce', 1) && strpos($header, 'tiny_mce')) {
      $output .= '<script type="text/javascript" src="' . base_path() . drupal_get_path('module', 'imce') . '/imce_set_tinymce.js' . '"></script>';
    }

    //set imce if fckeditor is in action
    if (!imce_integrate('fck', 'check') && module_exists('fckeditor') && variable_get('imce_settings_fck', 0) && strpos($header, 'fckeditor.js')) {
      $output .= '<script type="text/javascript" src="' . base_path() . drupal_get_path('module', 'imce') . '/imce_set_fck.js' . '"></script>';
    }
    if ($output) {
      return '<script type="text/javascript"> var imceBrowserURL = "' . url('imce/browse') . '"; </script>' . $output;
    }
  }
}

/**
 * Implementation of hook_perm().
 */
function imce_perm() {
  return array(
    'access imce',
    'administer imce',
  );
}

/**
 * Implementation of hook_menu().
 */
function imce_menu($may_cache) {
  global $user;
  $GLOBALS['imce_ext'] = array(
    '.gif',
    '.jpg',
    '.jpeg',
    '.png',
  );
  $items = array();
  if ($may_cache) {
    $items[] = array(
      'path' => 'imce/browse',
      'title' => 'IMCE browse',
      'access' => user_access('access imce'),
      'callback' => 'imce_browse',
      'type' => MENU_CALLBACK,
    );
    $items[] = array(
      'path' => 'admin/settings/imce',
      'title' => t('IMCE settings'),
      'description' => t('Control how your image/file browser works.'),
      'access' => user_access('administer imce'),
      'callback' => 'imce_form_admin',
    );
    $items[] = array(
      'path' => 'admin/settings/imce/settings',
      'title' => t('Settings'),
      'type' => MENU_DEFAULT_LOCAL_TASK,
    );
    $items[] = array(
      'path' => 'admin/settings/imce/subfolder',
      'title' => t('Sub-folder tool'),
      'access' => user_access('administer imce'),
      'callback' => 'imce_form_subfolder',
      'type' => MENU_LOCAL_TASK,
      'weight' => 1,
    );
  }
  elseif (arg(0) == 'user' && ($uid = arg(1)) && is_numeric($uid)) {
    if ($user->uid == $uid) {
      $access = user_access('access imce');
      $acc = $user;
    }
    elseif (user_access('administer imce') && $uid != 1 && ($acc = user_load(array(
      'uid' => $uid,
    )))) {
      $access = array_intersect(user_roles(0, 'access imce'), $acc->roles);
    }
    if ($access) {
      $items[] = array(
        'path' => 'user/' . $uid . '/imce',
        'title' => t('Personal files'),
        'access' => TRUE,
        'callback' => 'imce_user_page',
        'callback arguments' => array(
          $acc,
        ),
        'type' => MENU_LOCAL_TASK,
        'weight' => 10,
      );
    }
  }
  elseif (arg(0) == 'imce' && arg(1) != 'browse' && user_access('access imce')) {
    if (drupal_valid_token($_REQUEST['token'], 'imce')) {
      $set = (object) imce_settings_user();
      if (arg(1) == 'delete' && $set->delete && ($filename = basename(arg(2)))) {
        imce_delete_file($set, $filename);
      }
      elseif (arg(1) == 'upload' && $set->upload && $_FILES['thefile']) {
        imce_copy_uploaded($set, $_FILES['thefile']);
      }
      elseif (arg(1) == 'resize' && $set->resize && ($filename = basename($_POST['img_name']))) {
        imce_resize_image($set, $filename, $_POST['img_w'], $_POST['img_h'], $_POST['img_copy']);
      }
      elseif (arg(1) == 'dir' && $set->subnav && isset($_POST['dirname'])) {
        $target = $set->dir . '/' . $_POST['dirname'];
        if (is_dir($target) && ($real = file_check_location($target, $set->root))) {
          $_SESSION['imcedir'] = imce_relative_path($real, file_directory_path());
        }
      }
    }
    elseif (arg(1) == 'login' && user_access('administer imce') && is_numeric($uid = arg(2)) && $uid != 1 && $user->uid != $uid && ($acc = user_load(array(
      'uid' => $uid,
    ))) && array_intersect(user_roles(0, 'access imce'), $acc->roles)) {
      $_SESSION['imceuser'] = array(
        'uid' => $acc->uid,
        'roles' => $acc->roles,
        'name' => $acc->name ? $acc->name : t('Anonymous'),
        'ownperm' => arg(3) == 'own',
      );
      unset($_SESSION['imcedir']);
    }
    elseif (arg(1) == 'logout' && user_access('administer imce')) {
      unset($_SESSION['imceuser'], $_SESSION['imcedir']);
    }
    drupal_goto('imce/browse');
  }
  return $items;
}

/**
 * Image Browser.
 */
function imce_browse() {
  $set = (object) imce_settings_user();
  $private = variable_get('file_downloads', '') == FILE_DOWNLOADS_PRIVATE;
  $syspath = file_directory_path();
  $basepath = base_path();
  $imcepath = $basepath . drupal_get_path('module', 'imce');
  $header = array(
    array(
      'data' => t('filename'),
      'class' => 'filename',
    ),
    array(
      'data' => t('size'),
      'class' => 'size',
    ),
    array(
      'data' => t('dimensions'),
      'class' => 'dimensions',
    ),
    array(
      'data' => t('date'),
      'class' => 'date',
    ),
    array(
      'data' => t('operations'),
      'class' => 'operations',
    ),
  );
  $token = drupal_get_token('imce');

  //file list
  $directory = imce_scan_directory($set->dir);

  //prevent quota theft by multiple sessions.
  if ($_SESSION['imcelatest'] && $directory['size'] > $set->quota * 1024 && !$set->nolimit) {
    $directory['size'] -= filesize($_SESSION['imcelatest']);
    @unlink($_SESSION['imcelatest']);
    unset($directory['files'][$_SESSION['imcelatest']], $_SESSION['imcelatest']);
    drupal_set_message(t('File was deleted due to quota exceed!'), 'error');
  }
  foreach ($directory['files'] as $path => $file) {
    $rows[] = array(
      array(
        'data' => $file['f'],
        'class' => 'filename',
      ),
      array(
        'data' => format_size($file['s']),
        'class' => 'size',
        'id' => 's-' . $file['s'],
      ),
      array(
        'data' => $file['w'] . 'x' . $file['h'],
        'class' => 'dimensions',
      ),
      array(
        'data' => date('Y-m-d', $file['d']),
        'class' => 'date',
        'id' => 'd-' . $file['d'],
        'title' => date('H:i:s', $file['d']),
      ),
      array(
        'data' => $set->delete ? l(t('delete'), 'imce/delete/' . $file['f'], NULL, 'token=' . $token) : '',
        'class' => 'operations',
      ),
    );
  }
  if (!isset($rows)) {
    $rows = array(
      array(
        '<div class="messages">' . t('Directory is empty.') . '</div>',
      ),
    );
  }
  $_SESSION['imcetotal'] = $directory['size'];

  //folder list
  if ($set->subnav) {
    foreach ($directory['folders'] as $folder) {
      $foptions .= '<option value="' . $folder . '">/' . $folder . '</option>';
    }
    $subdir = $set->root != $set->dir;
    if ($foptions || $subdir) {
      $foptions = ' <form action="' . url('imce/dir') . '" name="dirform" id="dirform" method="post"><select name="dirname" id="dirname">' . ($subdir ? '<option value="..">' . t('Up') . '</option>' : '') . '<option value="/" selected="selected">/</option>' . $foptions . '</select><input type="submit" name="op" id="dirop" value="' . t('Go') . '" /><input type="hidden" name="token" value="' . $token . '" /></form>';
    }
  }

  //upload form
  if ($set->upload) {
    $uploadform = '<form action="' . url('imce/upload') . '" method="post" id="uploadform" enctype="multipart/form-data">
  <input type="file" name="thefile" id="thefile" size="30" />
  <input type="hidden" name="token" value="' . $token . '" />
  <input type="submit" name="submit" value="' . t('Upload File') . '" />' . ($set->nolimit ? '<input type="checkbox" checked="checked" name="scale" />' . t('Scale if necessary') : ($set->scale ? '<input type="hidden" value="1" name="scale" />' : '')) . ($set->twidth && $set->theight ? '<input type="checkbox" name="thumb" />' . t('Create thumbnail') . ' (' . $set->twidth . 'x' . $set->theight . ')' : '') . '
</form>
<div class="limits">' . ($set->nolimit ? t('Dimensions for scaling') . ' = <strong>' . $set->width . 'x' . $set->height . '</strong>, ' . t('Quota') . ' = <strong>' . format_size($_SESSION['imcetotal']) . '</strong>/' . t('Unlimited') : '<strong>' . t('Limits') . '</strong>: ' . t('File size') . ' = <strong>' . $set->filesize . ' KB</strong>, ' . t('Dimensions') . ' = <strong>' . $set->width . 'x' . $set->height . '</strong>, ' . t('Quota') . ' = <strong>' . format_size($_SESSION['imcetotal']) . '</strong>/' . $set->quota . ' KB') . '</div>';
  }

  //resize form
  if ($set->resize) {
    $resizeform = '<form action="' . url('imce/resize') . '" method="post" id="resizeform">
  <input type="submit" name="submit" value="' . t('Resize image') . '" />
  <input type="hidden" name="token" value="' . $token . '" />
  <span id="resize-file-span">' . t('filename') . ':<input type="text" name="img_name" id="img_name" size="12" />
  ' . t('dimensions') . ':</span><input type="text" name="img_w" id="img_w" size="2" />x<input type="text" name="img_h" id="img_h" size="2" />
  <input type="checkbox" name="img_copy" />' . t('Create a copy') . '
</form>';
  }
  $output = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  <title>' . t('Image/File Browser') . '</title>
  <script type="text/javascript">
    var imceVar = [];
    imceVar["fileUrl"] = "' . imce_relative_url($set->dir) . '";
    imceVar["latestFile"] = "' . ($_SESSION['imcelatest'] ? imce_relative_url($_SESSION['imcelatest']) : '') . '";
    imceVar["confirmDel"] = "' . ($set->delete ? t('Are you sure want to delete this file?') : '') . '";
    imceVar["viewText"] = "' . t('view') . '";
    imceVar["addText"] = "' . t('add') . '";' . ($set->extras ? '
    imceVar["filterText"] = ["' . t('Display') . '", "' . t('all') . '", "' . t('images') . '", "' . t('non-images') . '"];' : '') . '
  </script>
  <script type="text/javascript" src="' . $basepath . 'misc/jquery.js"></script>
  <script type="text/javascript" src="' . $imcepath . '/imce_browse.js"></script>' . ($set->extras ? '<script type="text/javascript" src="' . $imcepath . '/imce_extras.js"></script>' : '') . '
  <style type="text/css" media="all">@import "' . $imcepath . '/imce.css";</style>
</head>
<body>
<div id="headerdiv">' . theme('table', $header, array(), array(
    'id' => 'headertable',
  )) . '
</div>
<div id="bodydiv" title="' . ($set->extras ? t('Keyboard shortcuts') . ': ' . t('UP(previous), DOWN(next), DELETE, INSERT(add)') : '') . '">' . theme('table', array(), $rows, array(
    'id' => 'bodytable',
  )) . '
</div>
<div id="resize-bar"><div id="resize-bar-in">^</div></div>
<div id="relative-div">
  <div id="info-div">' . t('Directory') . ': ' . ($private && $set->uid != 1 ? imce_relative_path($set->dir, $syspath) : $set->dir) . ($foptions ? $foptions : '') . ($_SESSION['imceuser'] ? '<div>' . t('User') . ': ' . $_SESSION['imceuser']['name'] . ' - ' . l(t('logout'), 'imce/logout') . '</div>' : '') . '
  </div>
</div>
<div id="imagepreview">' . theme('status_messages') . '</div>
<div class="forms">' . $uploadform . $resizeform . '
</div>
</body>
</html>';
  unset($_SESSION['imcelatest']);
  print $output;
  exit;
}

/**
 * copy uploaded file to the specified directory.
 */
function imce_copy_uploaded($set, $file) {

  //is the file real
  if (!is_uploaded_file($file['tmp_name']) || !isset($_SESSION['imcetotal'])) {
    drupal_set_message(t('No files were uploaded.'), 'error');
    return FALSE;
  }

  //move uploaded file to drupal's temp directory
  $temp = tempnam(file_directory_temp(), 'tmp_');
  register_shutdown_function('file_delete', realpath($temp));
  if (!move_uploaded_file($file['tmp_name'], $temp)) {
    drupal_set_message(t('File upload error. Could not move uploaded file.'));
    return FALSE;
  }
  $file['tmp_name'] = $temp;

  //dont like too long filenames and files without an extension.
  $file['name'] = trim(basename($file['name']), '.');
  $file['name'] = strlen($file['name']) > 128 ? substr($file['name'], -128) : $file['name'];

  //max filename lenght is 128
  if (!($dot = strrpos($file['name'], '.'))) {
    drupal_set_message(t('Invalid filename.'), 'error');
    return FALSE;
  }
  $extension = strtolower(substr($file['name'], $dot));

  //check image type and dimensions.
  if (in_array($extension, $GLOBALS['imce_ext']) && ($info = @getimagesize($file['tmp_name']))) {
    if (!in_array($info[2], array(
      1,
      2,
      3,
    ))) {

      // 1=gif, 2=jpg, 3=png. real file types
      drupal_set_message(t('Only images with .jpg, .gif, and .png extensions are allowed.'), 'error');
      return FALSE;
    }
    if ($info[0] > $set->width || $info[1] > $set->height) {
      if (($set->scale || $set->nolimit) && $_POST['scale']) {
        if (!image_scale($file['tmp_name'], $file['tmp_name'], $set->width, $set->height)) {
          drupal_set_message(t('Error scaling image.'), 'error');
          return FALSE;
        }
        clearstatcache();
        $file['size'] = filesize($file['tmp_name']);

        //new size
        $info = @getimagesize($file['tmp_name']);
        drupal_set_message(t('Image was scaled to allowed dimensions.'));
      }
      else {
        if (!$set->nolimit) {
          drupal_set_message(t('Image dimensions exceed the limit.'), 'error');
          return FALSE;
        }
      }
    }
  }
  else {
    if ($set->extensions) {
      if (!in_array($extension, explode(',', str_replace(' ', '', $set->extensions)))) {
        drupal_set_message(t('Invalid file extension. Allowed extensions are .jpg, .gif, .png, !ext', array(
          '!ext' => $set->extensions,
        )), 'error');
        return FALSE;
      }
    }
    else {
      if ($set->uid != 1) {

        //no limitation for user1 regarding non-image files.
        drupal_set_message(t('Only images with .jpg, .gif, and .png extensions are allowed.'), 'error');
        return FALSE;
      }
    }
  }

  //check quota, filesize.
  if ($file['size'] > $set->filesize * 1024 && !$set->nolimit) {
    drupal_set_message(t('File size exceeds upload limit.'), 'error');
    return FALSE;
  }
  $newtotal = $file['size'] + $_SESSION['imcetotal'];
  if ($newtotal > $set->quota * 1024 && !$set->nolimit) {
    drupal_set_message(t('You dont have enough free space.'), 'error');
    return FALSE;
  }

  //clear filename and copy file
  $cleared = preg_replace("/[^\\w\\-\\_]/", '_', substr($file['name'], 0, $dot)) . $extension;
  $newpath = file_create_filename($cleared, $set->dir);
  if (!@copy($file['tmp_name'], $newpath)) {
    drupal_set_message(t('Error copying the file.'), 'error');
    return FALSE;
  }

  //success
  @chmod($newpath, 0664);
  $_SESSION['imcetotal'] = $newtotal;
  $_SESSION['imcelatest'] = $newpath;
  drupal_set_message(t('Upload successful.'));

  //thumbnails
  if ($_POST['thumb'] && $info && $set->twidth && $set->theight && ($set->twidth < $info[0] || $set->theight < $info[1])) {
    $aspect = $info[1] / $info[0];
    if ($aspect < $set->theight / $set->twidth) {
      $w = (int) min($set->twidth, $info[0]);
      $h = (int) round($w * $aspect);
    }
    else {
      $h = (int) min($set->theight, $info[1]);
      $w = (int) round($h / $aspect);
    }
    if (imce_resize_image($set, basename($newpath), $w, $h, TRUE)) {
      drupal_set_message(t('Thumbnail created.'));
    }
    else {
      drupal_set_message(t('Thumbnail can not be created.'), 'error');
    }
  }
  return TRUE;
}

/**
 * delete a file
 */
function imce_delete_file($set, $filename) {
  if (file_delete($set->dir . '/' . $filename)) {
    drupal_set_message(t('File deleted successfully.'));
    return TRUE;
  }
  drupal_set_message(t('Error deleting file.'), 'error');
  return FALSE;
}

/**
 * Resize file:$file in directory:$dir to dimensions $w x $h
 */
function imce_resize_image($set, $filename, $w, $h, $copy = FALSE) {

  //check if file exists
  $path = $set->dir . '/' . $filename;
  if (!is_file($path)) {
    drupal_set_message(t('File does not exist.'), 'error');
    return FALSE;
  }
  $_SESSION['imcelatest'] = $path;

  // check resize dimensions and file type
  if (!($dot = strrpos($filename, '.')) || !in_array(strtolower(substr($filename, $dot)), $GLOBALS['imce_ext'])) {
    drupal_set_message(t('File type is not supported.'), 'error');
    return FALSE;
  }
  if (!($w > 0 && $h > 0) || ($w > $set->width || $h > $set->height) && !$set->nolimit) {
    drupal_set_message(t('Image dimensions exceed the limit.'), 'error');
    return FALSE;
  }

  //resize image to a temp file
  $temp = tempnam(file_directory_temp(), 'tmp_');
  register_shutdown_function('file_delete', realpath($temp));
  if (!image_resize($path, $temp, $w, $h)) {
    drupal_set_message(t('Error resizing image.'), 'error');
    return FALSE;
  }

  //check quota
  $newtotal = $_SESSION['imcetotal'] + ($copy ? @filesize($temp) : @filesize($temp) - @filesize($path));
  if ($newtotal > $set->quota * 1024 && !$set->nolimit) {
    drupal_set_message(t('You dont have enough free space.'), 'error');
    return FALSE;
  }

  //copy file
  $newpath = $copy ? file_create_filename($filename, $set->dir) : $path;
  if (!@copy($temp, $newpath)) {
    drupal_set_message(t('Error copying the file.'), 'error');
    return FALSE;
  }

  //success
  @chmod($newpath, 0664);
  $_SESSION['imcetotal'] = $newtotal;
  $_SESSION['imcelatest'] = $newpath;
  drupal_set_message(t('Resizing successful.'));
  return TRUE;
}

/**
 * scan directory and return file list and total size of dir.
 */
function imce_scan_directory($dir) {
  if (!is_dir($dir) || !is_readable($dir) || !($handle = @opendir($dir))) {
    drupal_set_message(t('Error opening directory'), 'error');
    return FALSE;
  }
  $directory = array(
    'size' => 0,
    'files' => array(),
    'folders' => array(),
  );
  while (($file = readdir($handle)) !== FALSE) {
    if ($file == '.' || $file == '..' || $file == 'CVS' || $file == '.svn' || $file == '.htaccess') {
      continue;
    }
    if (is_dir($dir . '/' . $file)) {
      $directory['folders'][] = $file;
      continue;
    }
    $path = $dir . '/' . $file;
    $size = filesize($path);
    $ext = strtolower(substr($file, strrpos($file, '.')));
    $img = in_array($ext, $GLOBALS['imce_ext']) ? @getimagesize($path) : array(
      0,
      0,
    );
    $date = filemtime($path);
    $directory['files'][$path] = array(
      'f' => $file,
      's' => $size,
      'w' => (int) $img[0],
      'h' => (int) $img[1],
      'd' => $date,
    );
    $directory['size'] += $size;
  }
  closedir($handle);
  return $directory;
}

/**
 * return working image directory.
 */
function imce_get_directory($set) {
  if ($set['shared']) {

    //use shared folder if it is declared
    $dir = file_directory_path() . ($set['shared'] == '/' ? '' : '/' . $set['shared']);
  }
  else {

    //use personal folders by default.
    $dir = file_directory_path() . '/' . $set['prefix'] . $set['uid'];
  }
  if (file_check_directory($dir, TRUE)) {
    if ($set['subnav'] && $set['subdirs']) {
      foreach (explode(',', $set['subdirs']) as $sub) {
        $sub = $dir . '/' . trim($sub, '\\/ ');
        file_check_directory($sub, TRUE);
      }
    }
    return $dir;
  }
  exit(t('Directory error!') . ' - ' . $dir . theme('status_messages'));

  //without a working directory imce is useless. so, terminate.
}

/**
 * get role settings
 */
function imce_settings_role($rid) {
  $settings = variable_get('imce_settings_roles', array());
  return is_array($settings[$rid]) ? $settings[$rid] : imce_settings_default();
}

/**
 * get current user's settings
 */
function imce_settings_user() {
  global $user;
  if ($user->uid == 1) {
    $set = imce_settings_user1();
  }
  else {
    $settings = variable_get('imce_settings_roles', array());
    foreach (imce_sorted_roles() as $rid => $name) {
      if (isset($user->roles[$rid]) && is_array($settings[$rid])) {
        $set = $settings[$rid];
        break;
      }
    }
  }
  $set = $set ? $set : imce_settings_default();
  $set['uid'] = $user->uid;
  $set['root'] = imce_get_directory($set);
  if ($_SESSION['imceuser']) {
    $settings = variable_get('imce_settings_roles', array());
    foreach (imce_sorted_roles() as $rid => $name) {
      if (isset($_SESSION['imceuser']['roles'][$rid]) && is_array($settings[$rid])) {
        $userset = $settings[$rid];
        break;
      }
    }
    $userset = $userset ? $userset : imce_settings_default();
    $userset['uid'] = $_SESSION['imceuser']['uid'];
    if ($_SESSION['imceuser']['ownperm']) {
      $set = $userset;
    }
    $set['root'] = imce_get_directory($userset);
  }
  $set['dir'] = $set['subnav'] && $_SESSION['imcedir'] && file_check_location(file_directory_path() . '/' . $_SESSION['imcedir'], $set['root']) ? file_directory_path() . '/' . $_SESSION['imcedir'] : $set['root'];
  return $set;
}

/**
 * get user #1 settings
 */
function imce_settings_user1() {
  return array_merge(imce_settings_default(), variable_get('imce_settings_user1', array()), array(
    'resize' => 1,
    'scale' => 1,
    'delete' => 1,
    'upload' => 1,
    'nolimit' => 1,
    'subnav' => 1,
  ));
}

/**
 * return default settings.
 */
function imce_settings_default() {
  return array(
    'width' => 500,
    'height' => 500,
    'scale' => 0,
    'twidth' => '',
    'theight' => '',
    'resize' => 0,
    'filesize' => 100,
    'quota' => 500,
    'prefix' => 'u',
    'shared' => '',
    'extensions' => '',
    'extras' => 0,
    'delete' => 1,
    'upload' => 1,
    'nolimit' => 0,
    'subnav' => 0,
    'subdirs' => '',
  );
}

/**
 * sort roles according to precedence settings. previously sorted roles are followed by latest added roles.
 */
function imce_sorted_roles() {
  static $order;
  if (isset($order)) {
    return $order;
  }
  $order = array();
  $roles = user_roles(0, 'access imce');
  foreach (variable_get('imce_settings_rank', array()) as $rid) {
    if (isset($roles[$rid])) {
      $order[$rid] = $roles[$rid];
      unset($roles[$rid]);
    }
  }
  krsort($roles);

  //sort the remaining unsorted roles by id, descending.
  $order += $roles;
  return $order;
}

/**
 * Return settings form for a role or user1.
 */
function imce_form_template($rid) {
  if ($rid == 'user1') {
    $set = (object) imce_settings_user1();
    $form['width'] = array(
      '#type' => 'textfield',
      '#size' => 4,
      '#default_value' => $set->width,
      '#prefix' => '<div class="form-item"><label>' . t('Dimensions for scaling') . ':</label><div class="container-inline">' . t('Width') . ' X ' . t('Height') . ': ',
      '#suffix' => ' X ',
    );
    $form['height'] = array(
      '#type' => 'textfield',
      '#size' => 4,
      '#default_value' => $set->height,
      '#suffix' => 'px</div><div class="description">' . t('These dimensions will be used while scaling down newly uploaded big images.') . '</div></div>',
    );
    $form['twidth'] = array(
      '#type' => 'textfield',
      '#size' => 4,
      '#default_value' => $set->twidth,
      '#prefix' => '<div class="form-item"><label>' . t('Thumbnail dimensions') . ':</label><div class="container-inline">' . t('Width') . ' X ' . t('Height') . ': ',
      '#suffix' => ' X ',
    );
    $form['theight'] = array(
      '#type' => 'textfield',
      '#size' => 4,
      '#default_value' => $set->theight,
      '#suffix' => 'px</div><div class="description">' . t('You can enable automatic thumbnail creation from newly uploaded images. To disable leave the fields blank.') . '</div></div>',
    );
    $form['shared'] = array(
      '#type' => 'textfield',
      '#title' => t('Your upload directory'),
      '#default_value' => $set->shared ? $set->shared : 'u1',
      '#description' => t('This directory must be relative to <strong>!filepath</strong> directory. So if you want to use <strong>!filepath/foldername</strong>, just enter <strong>foldername</strong> here. You may also enter <strong>/</strong> to use the file system root. If you leave it blank, u1 will be used.', array(
        '!filepath' => file_directory_path(),
      )),
    );
    $form['extras'] = array(
      '#type' => 'checkbox',
      '#title' => '<strong>' . t('Enable extras') . '</strong>',
      '#default_value' => $set->extras,
      '#description' => t('This javascript package includes browsing enhancements like file sorting, keyboard shortcuts, file filtering, etc.'),
    );
    return $form;
  }
  $set = (object) imce_settings_role($rid);
  $form['delete'] = array(
    '#type' => 'checkbox',
    '#title' => t('delete files'),
    '#default_value' => $set->delete,
    '#prefix' => '<div class="form-item"><label>' . t('Permissions') . ':</label><div class="container-inline">',
    '#suffix' => ', ',
  );
  $form['upload'] = array(
    '#type' => 'checkbox',
    '#title' => t('upload files'),
    '#default_value' => $set->upload,
    '#suffix' => ', ',
  );
  $form['nolimit'] = array(
    '#type' => 'checkbox',
    '#title' => t('limitless upload'),
    '#default_value' => $set->nolimit,
    '#suffix' => '</div><div class="description">' . t('Enable/disable access for file upload and deletion in user directories. Limitless upload disables controlling filesize, image dimensions and quota.') . '</div></div>',
  );
  $form['width'] = array(
    '#type' => 'textfield',
    '#size' => 4,
    '#default_value' => $set->width,
    '#prefix' => '<div class="form-item"><label>' . t('Image dimensions') . ':</label><div class="container-inline">' . t('Width') . ' X ' . t('Height') . ': ',
    '#suffix' => ' X ',
  );
  $form['height'] = array(
    '#type' => 'textfield',
    '#size' => 4,
    '#default_value' => $set->height,
    '#suffix' => 'px</div><div class="description">' . t('Define the maximum dimensions for an image to be uploaded.') . '</div></div>',
  );
  $form['scale'] = array(
    '#type' => 'checkbox',
    '#title' => '<strong>' . t('Enable scaling of newly uploaded images.') . '</strong>',
    '#default_value' => $set->scale,
    '#description' => t('If a newly uploaded image has dimensions exceeding the limit, it will be scaled down instead of giving an error.'),
  );
  $form['twidth'] = array(
    '#type' => 'textfield',
    '#size' => 4,
    '#default_value' => $set->twidth,
    '#prefix' => '<div class="form-item"><label>' . t('Thumbnail dimensions') . ':</label><div class="container-inline">' . t('Width') . ' X ' . t('Height') . ': ',
    '#suffix' => ' X ',
  );
  $form['theight'] = array(
    '#type' => 'textfield',
    '#size' => 4,
    '#default_value' => $set->theight,
    '#suffix' => 'px</div><div class="description">' . t('You can enable automatic thumbnail creation from newly uploaded images. To disable leave the fields blank.') . '</div></div>',
  );
  $form['resize'] = array(
    '#type' => 'checkbox',
    '#title' => '<strong>' . t('Enable custom resizing.') . '</strong>',
    '#default_value' => $set->resize,
    '#description' => t('Users will be able to resize their images to any size up to allowed dimensions.'),
  );
  $form['filesize'] = array(
    '#type' => 'textfield',
    '#title' => t('File size'),
    '#default_value' => $set->filesize,
    '#description' => t('Define the maximum file size(KB) for an image to be uploaded.'),
  );
  $form['quota'] = array(
    '#type' => 'textfield',
    '#title' => t('Upload quota'),
    '#default_value' => $set->quota,
    '#description' => t('Define the total upload quota(KB) per user.'),
  );
  $form['prefix'] = array(
    '#type' => 'textfield',
    '#title' => t('Prefix for personal folder names'),
    '#default_value' => $set->prefix,
    '#description' => t('Define the prefix that user IDs will be appended in order to create personal folders. Ex: entering "u" will result in folder names like u1, u14 etc. If you leave it blank, user IDs will be used as folder names.'),
  );
  $form['shared'] = array(
    '#type' => 'textfield',
    '#title' => t('Use a shared folder'),
    '#default_value' => $set->shared,
    '#description' => t('If you want all your users to <strong>use a common folder instead of personal folders</strong>, here you can define that folder name (ex. images). Notice that shared upload means shared quota. If you are happy with personal folders leave this field blank.'),
  );
  $form['subnav'] = array(
    '#type' => 'checkbox',
    '#title' => '<strong>' . t('Enable sub-folder navigation.') . '</strong>',
    '#default_value' => $set->subnav,
    '#description' => t('This option allows users to manage multiple folders under their main folder. Only the users who have at least one sub-folder can use this feature.'),
  );
  $form['subdirs'] = array(
    '#type' => 'textfield',
    '#title' => t('Default sub-folder names'),
    '#default_value' => $set->subdirs,
    '#description' => t('Enter comma separated sub-folder names that will be created automatically, if the sub-folder navigation is enabled. Each user of this role will have these folders in their main folder by default. Additional folders can be created using !subfoldertool. You should note that total user quota increases with every new sub-folder because the quotation is per folder basis.', array(
      '!subfoldertool' => l(t('Sub-folder tool'), 'admin/settings/imce/subfolder'),
    )),
  );
  $form['extensions'] = array(
    '#type' => 'textfield',
    '#title' => t('Non-image file support'),
    '#default_value' => $set->extensions,
    '#description' => t('Although IMCE is mainly designed to browse images, it supports uploading and browsing of any file type. If you like to use this feature, define your <strong>allowed non-image file extensions</strong> here with a comma between them. Ex .doc, .pdf, .zip.  Note that, image upload limits also apply for these files. For a pure image browser leave this field blank.'),
  );
  $form['extras'] = array(
    '#type' => 'checkbox',
    '#title' => '<strong>' . t('Enable extras') . '</strong>',
    '#default_value' => $set->extras,
    '#description' => t('This javascript package includes browsing enhancements like file sorting, keyboard shortcuts, file filtering, etc.'),
  );
  return $form;
}

/**
 * return the form for admin/settings/imce
 */
function imce_form_admin_form() {
  $roles = imce_sorted_roles();
  $form['#tree'] = TRUE;
  $form['common'] = array(
    '#type' => 'fieldset',
    '#collapsible' => TRUE,
    '#title' => t('Common settings'),
  );
  $form['common']['tinymce'] = module_exists('tinymce') ? array(
    '#type' => 'checkbox',
    //tinymce support
    '#title' => '<strong>' . t('Enable tinyMCE support') . '</strong>',
    '#default_value' => variable_get('imce_settings_tinymce', 1),
    '#description' => t('Make IMCE the default image/file browser for tinyMCE.'),
  ) : NULL;
  $form['common']['fck'] = module_exists('fckeditor') ? array(
    '#type' => 'checkbox',
    //fck support
    '#title' => '<strong>' . t('Enable FCKEditor support') . '</strong>',
    '#default_value' => variable_get('imce_settings_fck', 0),
    '#description' => t('Replace the built-in file browser of FCKeditor with IMCE.'),
  ) : NULL;
  if (variable_get('file_downloads', '') == FILE_DOWNLOADS_PRIVATE) {
    $form['common']['disable_private'] = array(
      '#type' => 'checkbox',
      '#title' => t('Disable serving of private files'),
      '#default_value' => variable_get('imce_settings_disable_private', 0),
      '#description' => t('By default IMCE serves all files under private files directory without applying any access restrictions. This allows anonymous access to any file(/system/files/filename) unless there is a module restricting access to the files. Here you can disable this default behavior.'),
    );
  }
  $form['common']['textarea'] = array(
    '#type' => 'textfield',
    //plain textarea support
    '#title' => t('Enable inline image/file insertion into plain textareas'),
    '#default_value' => variable_get('imce_settings_textarea', ''),
    '#maxlength' => 255,
    '#description' => t('This feature allows you to add your images or files as <strong>html code into any plain textarea</strong>. This is useful especially when you dont use a wysiwyg editor such as tinyMCE or FCKeditor. Enter <strong>comma separated textarea IDs</strong> if you want to enable this feature. Otherwise, leave it blank. Hint: ID of Body fields in most node types is edit-body.'),
  );
  if (count($roles) > 1) {

    //role precedence settings appear if there is more than 1 role.
    $rids = $rtext = array();
    foreach ($roles as $rid => $name) {
      $rids[] = $rid;
      $rtext[] = '<strong>' . $rid . '-)</strong>' . $name;
    }
    $form['common']['rank'] = array(
      '#type' => 'textfield',
      '#title' => t('Role precedence'),
      '#default_value' => implode('>', $rids),
      '#description' => t('A user having <strong>multiple roles</strong> gets the permissions of the highest one. Sort role IDs according to their <strong>precedence from higher to lower</strong> by putting > in between. Here is the id-name pairs of roles having access to IMCE:') . '<div>' . implode(', ', $rtext) . '</div>',
    );
  }
  if ($GLOBALS['user']->uid == 1) {

    //user #1 settings.
    $form['user1'] = array(
      '#type' => 'fieldset',
      '#collapsible' => TRUE,
      '#title' => t('Settings for user #1'),
    ) + imce_form_template('user1');
  }
  foreach ($roles as $rid => $name) {

    //role settings
    $form['roles'][$rid] = array(
      '#type' => 'fieldset',
      '#collapsible' => TRUE,
      '#collapsed' => TRUE,
      '#title' => t('Settings for the role: !role', array(
        '!role' => $name,
      )),
    ) + imce_form_template($rid);
  }
  $form['submit'] = array(
    '#type' => 'submit',
    '#value' => t('Save'),
  );
  return $form;
}

/**
 * return the form for admin/settings/imce
 */
function imce_form_admin() {
  return drupal_get_form('imce_form_admin_form');
}

/**
 * Save settings. (Forms API -> formID_submit)
 */
function imce_form_admin_form_submit($form_id, $edit) {
  if (isset($edit['common']['tinymce'])) {
    variable_set('imce_settings_tinymce', $edit['common']['tinymce']);
  }
  if (isset($edit['common']['fck'])) {
    variable_set('imce_settings_fck', $edit['common']['fck']);
  }
  if (isset($edit['common']['textarea'])) {
    variable_set('imce_settings_textarea', $edit['common']['textarea']);
  }
  if (isset($edit['common']['disable_private'])) {
    variable_set('imce_settings_disable_private', $edit['common']['disable_private']);
  }
  if (isset($edit['common']['rank'])) {
    variable_set('imce_settings_rank', explode('>', str_replace(' ', '', $edit['common']['rank'])));
  }
  if (isset($edit['user1'])) {
    variable_set('imce_settings_user1', $edit['user1']);
  }
  if (isset($edit['roles'])) {
    variable_set('imce_settings_roles', $edit['roles']);
  }
  drupal_set_message(t('The changes have been saved.'));
}

/**
 * Implementation of hook_file_download(). support for private downloads.
 */
function imce_file_download($file) {
  $serve = variable_get('file_downloads', '') == FILE_DOWNLOADS_PRIVATE && !variable_get('imce_settings_disable_private', 0) && ($path = file_create_path($file)) && file_exists($path);
  if (!$serve) {
    return;
  }
  $roles = variable_get('imce_settings_roles', array());
  $roles += array(
    'user1' => variable_get('imce_settings_user1', array()),
  );
  $roles += array(
    'default' => imce_settings_default(),
  );
  $imcefile = FALSE;
  foreach ($roles as $rid => $set) {
    if ($set['shared']) {
      if ($set['shared'] == '/' || strpos($file, $set['shared'] . '/') === 0) {
        $imcefile = TRUE;
        break;
      }
    }
    else {
      if (preg_match("/^" . str_replace(array(
        '/',
        '-',
      ), array(
        '\\/',
        '\\-',
      ), $set['prefix']) . "[0-9]+\\//", $file)) {
        $imcefile = TRUE;
        break;
      }
    }
  }
  if ($imcefile) {
    $ctype = ($info = @getimagesize($path)) ? $info['mime'] : (function_exists('mime_content_type') ? mime_content_type($path) : 'application/x-download');
    return array(
      'Content-type: ' . $ctype,
    );
  }
}

/**
 * Implementation of hook_elements().
 */
function imce_elements() {
  $type = array();
  if (($ids = str_replace(' ', '', variable_get('imce_settings_textarea', ''))) && user_access('access imce')) {
    $type['textarea'] = array(
      '#process' => array(
        'imce_process_textarea' => array(
          explode(',', $ids),
        ),
      ),
    );
  }
  return $type;
}

/**
 * Inline image/link insertion to textareas.
 */
function imce_process_textarea($element, $edit = NULL, $ids = array()) {
  if (in_array($element['#id'], $ids)) {
    drupal_add_js(drupal_get_path('module', 'imce') . '/imce_set_inline.js');
    $element['#description'] .= '<div style="display:none">' . t('Insert !image or !link.', array(
      '!image' => l(t('image'), 'imce/browse', array(
        'name' => $element['#id'] . '-IMCE-image',
        'class' => 'imce-insert-inline',
      )),
      '!link' => l(t('link'), 'imce/browse', array(
        'name' => $element['#id'] . '-IMCE-link',
        'class' => 'imce-insert-inline',
      )),
    )) . '</div>';
  }
  return $element;
}

/**
 * IMCE user/x/imce page.
 */
function imce_user_page($acc) {
  if ($GLOBALS['user']->uid == $acc->uid) {

    //user
    $output = '<iframe id="imce-frame" height="500px" width="99%" name="imce-frame" src="' . url('imce/browse') . '" scrolling="no"></iframe>';
  }
  else {

    //admin
    $output = '<p class="imce-login">' . t('Browse this user\'s files using !yours or !his', array(
      '!yours' => l(t('your privileges'), 'imce/login/' . $acc->uid, array(
        'target' => 'imce-frame',
      )),
      '!his' => l(t('his/her privileges'), 'imce/login/' . $acc->uid . '/own', array(
        'target' => 'imce-frame',
      )),
    )) . '</p><br /><iframe id="imce-frame" height="500px" width="99%" name="imce-frame" src="about:blank" scrolling="no"></iframe>';
  }
  drupal_set_title($acc->name);
  return $output;
}

/* 
 * Convert absolute paths to relative paths. return new path relative to the root.
 */
function imce_relative_path($path, $root = NULL) {
  $abs = str_replace('\\', '/', realpath($path));
  $root = str_replace('\\', '/', $root ? realpath($root) : dirname(realpath($_SERVER['SCRIPT_FILENAME'])));
  return strpos($abs, $root) === 0 ? trim(substr($abs, strlen($root)), '/') : substr($abs, ($pos = strpos($abs, '/')) ? $pos : 0);
}

/* 
 * convert file path to relative url.
 */
function imce_relative_url($path = '') {
  if (variable_get('file_downloads', '') == FILE_DOWNLOADS_PRIVATE) {
    $file = trim(substr($path, strlen(file_directory_path())), '\\/');
    return url('system/files') . (strlen($file) ? '/' . $file : '');
  }
  return base_path() . $path;
}

/**
 * return sub folder creation form
 */
function imce_form_subfolder_form() {
  $form['help'] = array(
    '#value' => t('<p>Here you can create sub-folders for your users. Multiple folder creation is possible at a time with the <strong>*</strong> character. For example, specifying <strong>user*/foo</strong> will create <strong>foo</strong> named folders under each folder starting with <strong>user</strong>. */foo*/bar will create bar named folders under folders starting with foo in each folder of file system path.</p>'),
  );
  $form['path'] = array(
    '#type' => 'textfield',
    '#default_value' => $_POST['edit']['path'],
    '#maxlength' => 255,
    '#prefix' => '<div class="form-item"><label>' . t('Folder path') . ':</label><div class="container-inline">' . file_directory_path() . '/',
    '#suffix' => '</div></div>',
  );
  $form['submit'] = array(
    '#type' => 'submit',
    '#value' => t('Create'),
  );
  return $form;
}

/**
 * get sbfolder creation form
 */
function imce_form_subfolder() {
  return drupal_get_form('imce_form_subfolder_form');
}

/**
 * subfolder form submit. (Forms API -> formID_submit)
 */
function imce_form_subfolder_form_submit($form_id, $edit) {
  imce_create_subfolders($edit['path'], file_directory_path());
  return FALSE;
}

/**
 * create folder(s) under root according to path.
 */
function imce_create_subfolders($path, $root) {
  $args = explode('/', str_replace('\\', '/', $path));
  $dirs = array(
    $root,
  );
  for ($i = 0; strlen($arg = $args[$i]); $i++) {
    if (strpos($arg, '*') === FALSE) {

      //no asterisks. create the folder(s)
      for ($j = 0; isset($dirs[$j]); $j++) {
        $dirs[$j] .= '/' . $arg;
        if (!file_check_location($dirs[$j], $root) || !file_check_directory($dirs[$j], TRUE)) {
          drupal_set_message(t('Specified path must be under file sytem path.'), 'error');
          return FALSE;
        }
      }
    }
    else {

      //get matching subfolders.
      $newdirs = array();
      $expr = str_replace('*', '.*', $arg);
      foreach ($dirs as $dir) {
        $newdirs = array_merge($newdirs, imce_get_subfolders($dir, $expr));
      }
      if (empty($newdirs)) {
        drupal_set_message(t('No matching sub-folders found.'), 'error');
        return FALSE;
      }
      $dirs = $newdirs;
    }
  }
  return TRUE;
}

/**
 * scan directory and return folders matching expression.
 */
function imce_get_subfolders($dir, $expr = '') {
  $folders = array();
  if ($handle = @opendir($dir)) {
    while (($file = readdir($handle)) !== FALSE) {
      if ($file != '.' && $file != '..' && is_dir($dir . '/' . $file) && preg_match('/^' . $expr . '$/', $file)) {
        $folders[] = $dir . '/' . $file;
      }
    }
    closedir($handle);
  }
  return $folders;
}

/**
 * integrate with editors.
 */
function imce_integrate($e, $check = NULL) {
  static $state = array();
  if ($check) {
    return $state[$e];
  }
  if (!$state[$e]) {
    drupal_add_js(drupal_get_path('module', 'imce') . '/imce_set_' . $e . '.js');
    drupal_add_js('var imceBrowserURL = "' . url('imce/browse') . '";', 'inline');
    $state[$e] = TRUE;
  }
}

Functions

Namesort descending Description
imce_browse Image Browser.
imce_copy_uploaded copy uploaded file to the specified directory.
imce_create_subfolders create folder(s) under root according to path.
imce_delete_file delete a file
imce_elements Implementation of hook_elements().
imce_file_download Implementation of hook_file_download(). support for private downloads.
imce_footer Implementation of hook_footer().
imce_form_admin return the form for admin/settings/imce
imce_form_admin_form return the form for admin/settings/imce
imce_form_admin_form_submit Save settings. (Forms API -> formID_submit)
imce_form_subfolder get sbfolder creation form
imce_form_subfolder_form return sub folder creation form
imce_form_subfolder_form_submit subfolder form submit. (Forms API -> formID_submit)
imce_form_template Return settings form for a role or user1.
imce_get_directory return working image directory.
imce_get_subfolders scan directory and return folders matching expression.
imce_integrate integrate with editors.
imce_menu Implementation of hook_menu().
imce_perm Implementation of hook_perm().
imce_process_textarea Inline image/link insertion to textareas.
imce_relative_path
imce_relative_url
imce_resize_image Resize file:$file in directory:$dir to dimensions $w x $h
imce_scan_directory scan directory and return file list and total size of dir.
imce_settings_default return default settings.
imce_settings_role get role settings
imce_settings_user get current user's settings
imce_settings_user1 get user #1 settings
imce_sorted_roles sort roles according to precedence settings. previously sorted roles are followed by latest added roles.
imce_user_page IMCE user/x/imce page.