| [ Index ] |
PHP Cross Reference of Drupal 6 (gatewave) |
[Summary view] [Print] [Text view]
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
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated: Thu Mar 24 11:18:33 2011 | Cross-referenced by PHPXref 0.7 |