<?php
// $Id: imce.module,v 1.7.2.6 2007/05/15 14:46:03 ufku Exp $

/**
 * Implementation of hook_help().
 */
function imce_help($section) {
  switch ($section) {
    case 'admin/modules#description':
      return t('Provides an image browser for tinyMCE.');
  }
}

/**
 * Implementation of hook_footer().
 */
function imce_footer() {//set imce if tinymce is in action 
  if (strpos(drupal_set_html_head(), 'tinyMCE.init') && user_access('view files')) {
    return '<script type="text/javascript"> imceBrowserURL = "'.url('imce/browse').'"; </script>
<script type="text/javascript" src="'. base_path() .drupal_get_path('module', 'imce').'/imce_set.js' .'"></script>';
  }
}

/**
 * Implementation of hook_perm().
 */
function imce_perm() {
  return array('view files', 'upload files', 'delete files', 'limitless upload');
}

/**
 * Implementation of hook_menu().
 */
function imce_menu($may_cache) {
  global $user;
  $items = array();
  if ($may_cache) {
    $items[] = array(
      'path' => 'imce/browse',
      'title' => 'imce settings',
      'access' => user_access('view files'),
      'callback' => 'imce_browse',
      'type' => MENU_CALLBACK);
  }
  elseif (arg(0)=='imce' && arg(1)!='browse' && $_REQUEST['token']==md5('imce'.session_id())) {
    if (arg(1)=='delete' && user_access('delete files') && ($delpath = file_check_location($_GET['delpath'], imce_get_directory()))) {
      imce_delete_file($delpath);
    }
    elseif (arg(1)=='upload' && user_access('upload files') && $_FILES['thefile']) {
      imce_copy_uploaded($_FILES['thefile'], imce_get_directory());
    }
    drupal_goto('imce/browse');
  }
  return $items;
}

/**
 * Image Browser.
 */
function imce_browse() {
  
  //get working directory.
  if (!($dir = imce_get_directory())) {
    print t('Directory error!');
    exit();
  }

  $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'));
  $delete = user_access('delete files');
  $basepath = base_path();
  $private = (variable_get('file_downloads', '')==FILE_DOWNLOADS_PRIVATE);
  $token = md5('imce'.session_id());
  //file list
  $files = imce_scan_directory($dir);
  foreach ($files['list'] as $path=>$file) {
    $url = $private ? url('system/files/').trim(substr($path, strlen(file_directory_path())), '\\/') : $basepath. $path;
    $rows[] = array(
      'data' => array(
        array('data' => $file['f'], 'class' => 'filename'),
        array('data' => format_size($file['s']), 'class' => 'size'),
        array('data' => $file['w'].'x'.$file['h'], 'class' => 'dimensions'),
        array('data' => date('Y-m-d', $file['d']), 'class' => 'date', 'timestamp' => $file['d'], 'title' => date('H:i:s', $file['d'])),
        array('data' => ($delete ? l(t('delete'), 'imce/delete', array('onclick' => 'return confirm(\''.t('Delete?').'\')'), 'delpath='.$path.'&token='. $token).' - ' : ''). '<a href="javascript: imceFinitor(\''.$url.'\', '.$file['w'].', '.$file['h'].')">'. t('add').'</a>', 'class' => 'operations'),
      ),
      'ipath' => $url,
      'iw' => $file['w'],
      'ih' => $file['h']
    );
  }
  if (!isset($rows)) {
    $rows = array(array(array('data'=>'<div class="messages">'.t('Directory is empty.').'</div>', 'colspan'=>5,)));
  }
  $_SESSION['imcetotal'] = $files['size'];

//upload form
  $upload_form = user_access('upload files') ? ('<form action="'.url('imce/upload').'" method="post" id="uploadform" enctype="multipart/form-data">
  <input type="file" name="thefile" id="thefile" size="40">
  <input type="hidden" name="token" value="'. $token .'">
  <input type="submit" name="submit" value="'.t('Upload File').'">'.
  (variable_get('imce_resizing', 0) ? (user_access('limitless upload') ? '<input type="checkbox" checked="checked" name="resize">'.t('Scale if necessary') : '<input type="hidden" value="1" name="resize">' ) : '').'
  </form>
  <div class="limits"><strong>'. t('Limits').'</strong>: '.t('File size').' = '. variable_get('imce_max_size', 100).' KB, '.t('Dimensions').' = '. variable_get('imce_max_width', 500). 'x'. variable_get('imce_max_height', 500).', '.t('Quota').' = <strong>'. format_size($_SESSION['imcetotal']).'</strong>/'. variable_get('imce_quota', 500).' KB</div><div class="nolimit">'. (user_access('limitless upload') ? t('No limits for you!') : '').'</div>') : '';

  $imce_path = $basepath. drupal_get_path('module', 'imce');
  $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 Browser').'</title>
  <script type="text/javascript" src="'. $basepath .'misc/drupal.js"></script>
  <script type="text/javascript" src="'. $imce_path .'/imce_browse.js"></script>'.
  (variable_get('imce_sorting', 0) ? '<script type="text/javascript" src="'. $imce_path .'/imce_sort.js"></script>' : '').
  theme('stylesheet_import', $imce_path.'/imce.css').'
</head>
<body>
<div id="headerdiv">'.
theme('table', $header, array(), array('id'=>'headertable')).'
</div>
<div id="bodydiv">'.
theme('table', array(), $rows, array('id'=>'bodytable')).'
</div>
<div id="imagepreview">'.theme('status_messages').'</div>'.
$upload_form.'
<input type="hidden" value="'.t('This is not an image! Continue?').'" id="confirm-msg" />
<input type="hidden" value="'.($_SESSION['imcelatest'] ? ($private ? url('system/files/').trim(substr($_SESSION['imcelatest'], strlen(file_directory_path())), '\\/') : $basepath.$_SESSION['imcelatest']) : '').'" id="latest-file" />
</body>
</html>';
  unset($_SESSION['imcelatest']);
  print $output;
  exit();
}

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

  //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_');
  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'])>48 ? substr($file['name'], -48) : $file['name']; //max filename lenght is 48
  if (!($dot = strrpos($file['name'], '.'))) {
    drupal_set_message(t('Invalid filename.'), 'error');
    return false;
  }
  
  $extension = strtolower(substr($file['name'], $dot));
  $nolimit = user_access('limitless upload');
  
  //check image dimensions and type.
  if (in_array($extension, array('.gif', '.jpg', '.jpeg', '.png')) && ($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;
    }
    $maxw = variable_get('imce_max_width', 500);
    $maxh = variable_get('imce_max_height', 500);
    if ($info[0]>$maxw || $info[1]>$maxh) {
      if (variable_get('imce_resizing', 0) && $_POST['resize']) {
        if(!image_scale($file['tmp_name'], $file['tmp_name'], $maxw, $maxh)) {
          drupal_set_message(t('Error scaling image.'), 'error');
          return false;
        }
        clearstatcache();
        $file['size'] = filesize($file['tmp_name']);//new size
        drupal_set_message(t('Image was scaled to allowed dimensions.'));
      }
      else if (!$nolimit) {
        drupal_set_message(t('Image dimensions exceed the limit.'), 'error');
        return false;
      }
    }
  }
  // file is not an image. check if the extension is allowed
  elseif (($extensions = variable_get('imce_allowed_extensions', ''))) {
    if (!in_array($extension, explode(',', str_replace(' ', '', $extensions)))) {
      drupal_set_message(t('Invalid file extension. Allowed extensions are .jpg, .gif, .png, %ext', array('%ext' => $extensions)), 'error');
      return false;
    }
  }
  else {
    drupal_set_message(t('Only images with .jpg, .gif, and .png extensions are allowed.'), 'error');
    return false;
  }

  //check quota, filesize.
  if ($file['size'] > variable_get('imce_max_size', 100)*1024 && !$nolimit) {
    drupal_set_message(t('File size exceeds upload limit.'), 'error');
    return false;
  }
  $newtotal = $file['size'] + $_SESSION['imcetotal'];
  if ($newtotal > variable_get('imce_quota', 500)*1024 && !$nolimit) {
    drupal_set_message(t('You have not enough free space.'), 'error');
    return false;
  }

  //copy file
  $cleared = preg_replace("/[^\w\-\_]/", '_', substr($file['name'], 0, $dot)).$extension;//clear unwanted characters in filename.
  $newpath = file_create_filename($cleared, $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.'));
  return true;
}

/**
 * delete a file
 */
function imce_delete_file($file) {
  if (@unlink($file)) {
    drupal_set_message(t('File deleted successfully.'));
    return true;
  }
  drupal_set_message(t('Error deleting file.'), 'error');
  return false;
}

/**
 * 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;
  }
  $files = array();
  $totalsize = 0;
  while(($file = @readdir($handle)) !== false) {
    if ($file == '.' || $file == '..' || $file == 'CVS' || $file == '.svn') continue;
    $path = $dir.'/'.$file;
    $size = filesize($path);
    $ext = strtolower(substr($file, strrpos($file, '.')));
    $img = in_array($ext, array('.gif', '.jpg', '.jpeg', '.png')) ? @getimagesize($path) : NULL;
    $date = filemtime($path);
    $files[$path] = array('f'=>$file, 's'=>$size, 'w'=>(int)$img[0], 'h'=>(int)$img[1], 'd'=>$date);
    $totalsize += $size;
  }
  return array('list'=>$files, 'size'=>$totalsize);
}

/**
 * return working image directory.
 */
function imce_get_directory() {
  global $user;
  if ($shared = variable_get('imce_shared_folder', '')) {//use shared folder if it is declared
    $dir = file_directory_path().'/'.$shared;
  }
  else {//use personal folders by default.
    $dir = file_directory_path().'/'.variable_get('imce_personal_prefix', 'u').$user->uid;
  }
  return file_check_directory($dir, true) ? $dir : false;
}

/**
 * Implementation of hook_settings().
 */
function imce_settings() {
  $form['imce_max_width'] = array( 
    '#type' => 'textfield',
    '#size' => 4,
    '#default_value' => variable_get('imce_max_width', 500),
    '#prefix' => '<div class="form-item"><label>'.t('Image dimensions').':</label><div class="container-inline">'.t('Width').' X '.t('Height').': ',
    '#suffix' => ' X ',
  );
  $form['imce_max_height'] = array( 
    '#type' => 'textfield',
    '#size' => 4,
    '#default_value' => variable_get('imce_max_height', 500),
    '#suffix' => 'px</div><div class="description">'.t('Define the maximum dimensions for an image to be uploaded.').'</div></div>',
  );
  $form['imce_resizing'] = array(
    '#type' => 'checkbox',
    '#title' => t('Enable resizing'),
    '#default_value' => variable_get('imce_resizing', 0),
    '#description' => t('Check this if you want big images to be resized to allowed dimensions. Note that, image resizing increases script execution time.'),
  );
  $form['imce_max_size'] = array( 
    '#type' => 'textfield', 
    '#title' => t('File size'),
    '#default_value' => variable_get('imce_max_size', 100),
    '#description' => t('Define the maximum file size(KB) for an image to be uploaded.'),
  );
  $form['imce_quota'] = array( 
    '#type' => 'textfield', 
    '#title' => t('Upload quota'), 
    '#default_value' => variable_get('imce_quota', 500),
    '#description' => t('Define the total upload quota(KB) per user.'),
  );
  $form['imce_personal_prefix'] = array( 
    '#type' => 'textfield', 
    '#title' => t('Prefix for personal folder names'), 
    '#default_value' => variable_get('imce_personal_prefix', 'u'),
    '#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['imce_shared_folder'] = array( 
    '#type' => 'textfield',
    '#title' => t('Use a shared folder'),
    '#default_value' => variable_get('imce_shared_folder', ''),
    '#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['imce_allowed_extensions'] = array(
    '#type' => 'textfield',
    '#title' => t('Non-image file support'),
    '#default_value' => variable_get('imce_allowed_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['imce_sorting'] = array(
    '#type' => 'checkbox',
    '#title' => t('Enable sorting'),
    '#default_value' => variable_get('imce_sorting', 0),
    '#description' => t('Check this to enable sorting of files according to their filename, filesize, file modification date, and image dimensions. Sorting is javascript-based, thus there is no need for page refresh and sorting speed depends on the client computer.'),
  );
  return $form;
} 

/**
 * Implementation of hook_file_download().
 */
function imce_file_download($file) {
  $imcefile = FALSE;
  if ($shared = variable_get('imce_shared_folder', '')) {
    if ($shared == '/' || strpos($file, $shared) === 0) {
      $imcefile = TRUE;
    }
  }
  else {
    if (preg_match("/^".str_replace(array('/', '-'), array('\/', '\-'), variable_get('imce_personal_prefix', 'u'))."[0-9]+\//", $file)) {
      $imcefile = TRUE;
    }
  }
  if ($imcefile && ($path = file_create_path($file))) {
    $ctype = ($info = @getimagesize($path)) ? $info['mime'] : (function_exists('mime_content_type') ? mime_content_type($path) : 'application/x-download');
    return array('Content-type: '. $ctype);
  }
}
