[ Index ]

PHP Cross Reference of Drupal 6 (gatewave)

title

Body

[close]

/sites/all/modules/filefield_sources/sources/ -> remote.inc (source)

   1  <?php
   2  // $Id: remote.inc,v 1.9 2010/08/09 04:11:50 quicksketch Exp $
   3  
   4  /**
   5   * @file
   6   * A FileField extension to allow referencing of existing files.
   7   *
   8   * The "hooks" in this file are not true hooks, they're called individually
   9   * from the main filefield_sources.module in the corresponding hook by the
  10   * same name. Any of these hooks could be broken out into a separate module.
  11   */
  12  
  13  define('FILEFIELD_SOURCE_REMOTE_HINT_TEXT', 'http://example.com/files/file.png');
  14  
  15  /**
  16   * Implementation of hook_filefield_source_info().
  17   */
  18  function filefield_source_remote_info() {
  19    $source = array();
  20    $source['remote'] = array(
  21      'name' => t('Remote URL textfield'),
  22      'label' => t('Remote URL'),
  23      'description' => t('Download a file from a remote server.'),
  24      'process' => 'filefield_source_remote_process',
  25      'value' => 'filefield_source_remote_value',
  26    );
  27    return $source;
  28  }
  29  
  30  /**
  31   * Implementation of hook_menu().
  32   */
  33  function filefield_source_remote_menu() {
  34    $items = array();
  35  
  36    $items['filefield/remote/progress/%/%/%'] = array(
  37      'page callback' => 'filefield_source_remote_progress',
  38      'page arguments' => array(3, 4, 5),
  39      'access arguments' => array('access content'),
  40      'file' => 'sources/remote.inc',
  41      'type' => MENU_CALLBACK,
  42    );
  43    return $items;
  44  }
  45  
  46  /**
  47   * Implementation of hook_theme().
  48   */
  49  function filefield_source_remote_theme() {
  50    return array(
  51      'filefield_source_remote_element' => array(
  52        'arguments' => array('element' => NULL),
  53        'file' => 'sources/remote.inc',
  54      ),
  55   );
  56  }
  57  
  58  /**
  59   * Implementation of hook_filefield_source_settings().
  60   */
  61  function filefield_source_remote_settings($op, $field) {
  62    $return = array();
  63  
  64    // Add settings to the FileField widget form.
  65  
  66    return $return;
  67  
  68  }
  69  
  70  /**
  71   * A #process callback to extend the filefield_widget element type.
  72   */
  73  function filefield_source_remote_process($element, $edit, &$form_state, $form) {
  74  
  75    $element['filefield_remote'] = array(
  76      '#theme' => 'filefield_source_remote_element',
  77      '#weight' => 100.5,
  78      '#access' => empty($element['fid']['#value']),
  79      '#filefield_sources_hint_text' => FILEFIELD_SOURCE_REMOTE_HINT_TEXT,
  80    );
  81  
  82    $element['filefield_remote']['url'] = array(
  83      '#type' => 'textfield',
  84      '#description' => filefield_sources_element_validation_help($element),
  85      '#maxlength' => NULL,
  86    );
  87  
  88    $element['filefield_remote']['transfer'] = array(
  89      '#type' => 'submit',
  90      '#value' => t('Transfer'),
  91      '#submit' => array('node_form_submit_build_node'),
  92      '#ahah' => array(
  93         'path' => 'filefield/ahah/'. $element['#type_name'] .'/'. $element['#field_name'] .'/'. $element['#delta'],
  94         'wrapper' => $element['#id'] .'-ahah-wrapper',
  95         'method' => 'replace',
  96         'effect' => 'fade',
  97         'progress' => array(
  98           'type' => 'bar',
  99           'path' => 'filefield/remote/progress/' . $element['#type_name'] .'/'. $element['#field_name'] .'/'. $element['#delta'],
 100           'message' => t('Starting transfer...'),
 101         )
 102      ),
 103    );
 104  
 105    return $element;
 106  }
 107  
 108  /**
 109   * A #filefield_value_callback function.
 110   */
 111  function filefield_source_remote_value($element, &$item) {
 112    if (isset($item['filefield_remote']['url']) && strlen($item['filefield_remote']['url']) > 0 && valid_url($item['filefield_remote']['url']) && $item['filefield_remote']['url'] != FILEFIELD_SOURCE_REMOTE_HINT_TEXT) {
 113      $field = content_fields($element['#field_name'], $element['#type_name']);
 114      $url = $item['filefield_remote']['url'];
 115  
 116      // Check the headers to make sure it exists and is within the allowed size.
 117      $ch = curl_init();
 118      curl_setopt($ch, CURLOPT_URL, $url);
 119      curl_setopt($ch, CURLOPT_HEADER, TRUE);
 120      curl_setopt($ch, CURLOPT_NOBODY, TRUE);
 121      curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
 122      // Causes a warning if PHP safe mode is on.
 123      @curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE);
 124      curl_exec($ch);
 125      $info = curl_getinfo($ch);
 126      curl_close($ch);
 127  
 128      if ($info['http_code'] != 200) {
 129        switch ($info['http_code']) {
 130          case 403:
 131            form_error($element, t('The remote file could not be transfered because access to the file was denied.'));
 132            break;
 133          case 404:
 134            form_error($element, t('The remote file could not be transfered because it was not found.'));
 135            break;
 136          default:
 137            form_error($element, t('The remote file could not be transfered due to an HTTP error (@code).', array('@code' => $info['http_code'])));
 138        }
 139        return;
 140      }
 141  
 142      // Update the $url variable to reflect any redirects.
 143      $url = $info['url'];
 144      $url_info = parse_url($url);
 145      $pathinfo = pathinfo($url_info['path']);
 146      $filename = rawurldecode(basename($url_info['path']));
 147      $filename = filefield_sources_clean_filename($filename);
 148      $filepath = file_create_filename($filename, file_directory_temp());
 149  
 150      if (empty($pathinfo['extension'])) {
 151        form_error($element, t('The remote URL must be a file and have an extension.'));
 152        return;
 153      }
 154  
 155      // Perform basic extension check on the file before trying to transfer.
 156      $extensions = $field['widget']['file_extensions'];
 157      $regex = '/\.('. ereg_replace(' +', '|', preg_quote($extensions)) .')$/i';
 158      if (!empty($extensions) && !preg_match($regex, $filename)) {
 159        form_error($element, t('Only files with the following extensions are allowed: %files-allowed.', array('%files-allowed' => $extensions)));
 160        return;
 161      }
 162  
 163      // Check file size based off of header information.
 164      if (!empty($element['#upload_validators']['filefield_validate_size'][0])) {
 165        $max_size = $element['#upload_validators']['filefield_validate_size'][0];
 166        $file_size = $info['download_content_length'];
 167        if ($file_size > $max_size) {
 168          form_error($element, t('The remote file is %filesize exceeding the maximum file size of %maxsize.', array('%filesize' => format_size($file_size), '%maxsize' => format_size($max_size))));
 169          return;
 170        }
 171      }
 172  
 173      // Set progress bar information.
 174      $options = array(
 175        'key' => $element['#type_name'] . '_' . $element['#field_name'] . '_' . $element['#delta'],
 176        'filepath' => $filepath,
 177      );
 178      filefield_source_remote_set_transfer_options($options);
 179  
 180      // Then make the actual request to download the file.
 181      $ch = curl_init();
 182      curl_setopt($ch, CURLOPT_URL, $url);
 183      curl_setopt($ch, CURLOPT_HEADER, FALSE);
 184      curl_setopt($ch, CURLOPT_WRITEFUNCTION, 'filefield_source_remote_curl_write');
 185      // Causes a warning if PHP safe mode is on.
 186      @curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE);
 187      if (curl_exec($ch) && $file = field_file_save_file($filepath, $element['#upload_validators'], filefield_widget_file_path($field))) {
 188        $item = array_merge($item, $file);
 189      }
 190      curl_close($ch);
 191  
 192      // Delete the temporary file.
 193      @unlink($filepath);
 194    }
 195  }
 196  
 197  /**
 198   * Menu callback; progress.js callback to return upload progress.
 199   */
 200  function filefield_source_remote_progress($type_name, $field_name, $delta) {
 201    $key = $type_name . '_' . $field_name . '_' . $delta;
 202    $progress = array(
 203      'message' => t('Starting transfer...'),
 204      'percentage' => -1,
 205    );
 206  
 207    if ($cache = cache_get('filefield_transfer:'. session_id() . ':' . $key)) {
 208      $current = $cache->data['current'];
 209      $total = $cache->data['total'];
 210      $progress['message'] = t('Transfering... (@current of @total)', array('@current' => format_size($current), '@total' => format_size($total)));
 211      $progress['percentage'] = round(100 * $current / $total);
 212    }
 213  
 214    drupal_json($progress);
 215  }
 216  
 217  /**
 218   * cURL write function to save the file to disk. Also updates progress bar.
 219   */
 220  function filefield_source_remote_curl_write(&$ch, $data) {
 221    $progress_update = 0;
 222    $options = filefield_source_remote_get_transfer_options();
 223  
 224    // Get the current progress and update the progress value.
 225    // Only update every 64KB to reduce cache_set calls. cURL usually writes
 226    // in 16KB chunks.
 227    if (curl_getinfo($ch, CURLINFO_SIZE_DOWNLOAD) / 65536 > $progress_update) {
 228      $progress_update++;
 229      $progress = array(
 230        'current' => curl_getinfo($ch, CURLINFO_SIZE_DOWNLOAD),
 231        'total' => curl_getinfo($ch, CURLINFO_CONTENT_LENGTH_DOWNLOAD),
 232      );
 233      // Set a cache so that we can retrieve this value from the progress bar.
 234      $cid = 'filefield_transfer:'. session_id() . ':' . $options['key'];
 235      if ($progress['current'] != $progress['total']) {
 236        cache_set($cid, $progress, 'cache', time() + 300);
 237      }
 238      else {
 239        cache_clear_all($cid, 'cache');
 240      }
 241    }
 242  
 243    $data_length = 0;
 244    if ($fp = @fopen($options['filepath'], 'a')) {
 245      fwrite($fp, $data);
 246      fclose($fp);
 247      $data_length = strlen($data);
 248    }
 249  
 250    return $data_length;
 251  }
 252  
 253  /**
 254   * Set a transfer key that can be retreived by the progress function.
 255   */
 256  function filefield_source_remote_set_transfer_options($options = NULL) {
 257    static $current = FALSE;
 258    if (isset($options)) {
 259      $current = $options;
 260    }
 261    return $current;
 262  }
 263  
 264  /**
 265   * Get a transfer key that can be retrieved by the progress function.
 266   */
 267  function filefield_source_remote_get_transfer_options() {
 268    return filefield_source_remote_set_transfer_options();
 269  }
 270  
 271  /**
 272   * Theme the output of the autocomplete field.
 273   */
 274  function theme_filefield_source_remote_element($element) {
 275    $element['url']['#field_suffix'] = theme('submit', $element['transfer']);
 276    return '<div class="filefield-source filefield-source-remote clear-block">' . theme('textfield', $element['url']) . '</div>';
 277  }
 278  


Generated: Thu Mar 24 11:18:33 2011 Cross-referenced by PHPXref 0.7