/[drupal]/contributions/modules/swfupload/swfupload.module
ViewVC logotype

Contents of /contributions/modules/swfupload/swfupload.module

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.14 - (show annotations) (download) (as text)
Fri Jan 9 10:27:13 2009 UTC (10 months, 2 weeks ago) by skilip
Branch: MAIN
CVS Tags: HEAD
Changes since 1.13: +2 -1 lines
File MIME type: text/x-php
Fixed issue 355966
1 <?php
2 // $Id: swfupload.info, v 0.1, 2008/10/13 10:02:46, skilip Exp $
3
4 /**
5 * @file
6 *
7 * Replaces the default upload fieldset with an implementation of SWFUpload.
8 */
9
10 /**
11 * Implementation of hook_perm().
12 */
13 function swfupload_perm() {
14 return array('use swfupload image button', 'administer swfupload');
15 }
16
17 /**
18 * Implementation of hook_help().
19 */
20 function swfupload_help() {
21 // Dowload tabledrag and jquery plugins
22 }
23
24
25 /**
26 * Implementation of hook_menu().
27 */
28 function swfupload_menu() {
29 $items['admin/settings/swfuploads'] = array(
30 'title' => 'SWF upload settings',
31 'description' => 'Configure SWF upload settings for every nodetype and role.',
32 'page callback' => 'drupal_get_form',
33 'page arguments' => array('swfupload_settings_form'),
34 'access arguments' => array('administer swfupload'),
35 'file' => 'settings/settings.inc',
36 );
37 $items['swfupload'] = array(
38 'page callback' => '_swfupload_swfupload',
39 'access callback' => 'swfupload_access',
40 'type' => MENU_CALLBACK
41 );
42 return $items;
43 }
44
45 /**
46 * Validate access to the swfuploadpath
47 */
48 function swfupload_access() {
49 $result = FALSE;
50 $p = (object) $_POST;
51
52 // Validate the request
53 if($p->sid) {
54 $sid = split("\*", hex2bin($p->sid));
55
56 global $user;
57 $user = user_load($sid[0]);
58
59 if (!user_access('upload files')) {
60 return FALSE;
61 }
62
63 if (!$user->uid) {
64 return ($sid[1] == md5($_SERVER['REMOTE_ADDR']));
65 }
66
67 $result = db_query("SELECT sid FROM {sessions} WHERE uid = %d", $sid[0]);
68 while ($row = db_fetch_object($result)) {
69 $valid_sids[] = md5($row->sid);
70 }
71
72 if (in_array($sid[1], $valid_sids)) {
73 return TRUE;
74 }
75
76 // The sid doesn't exist for this user.
77 return FALSE;
78 }
79 // No session ID is set, we can assume we're still in the same session
80 return (($p->op) && user_access('upload files'));
81 }
82
83 /**
84 * Implementation of hook_theme().
85 */
86 function swfupload_theme() {
87 return array(
88 'swfupload_settings_form' => array(
89 'arguments' => array('form' => array())
90 ),
91 'swfupload_button' => array(
92 'arguments' => array('element' => array())
93 ),
94 );
95 }
96
97 /**
98 * Unset roles that does not belong to the user
99 */
100 function swfupload_filter_roles(&$swfupload_settings) {
101 global $user;
102
103 if($user->uid == 1) {
104 $swfupload_settings = array(t('administrator') => $swfupload_settings[t('administrator')]);
105 } else {
106
107 foreach($swfupload_settings as $role => $settings) {
108 if($role != 'anonymous_user' && $role != 'authenticated_user' && !in_array($role, $user->roles)) {
109 unset($swfupload_settings[$role]);
110 }
111 }
112 return $swfupload_settings;
113 }
114 }
115
116 /**
117 * Implementation of hook_form_alter().
118 */
119 function swfupload_form_alter(&$form, $form_state, $form_id) {
120 // For all node edit/add forms and for all users who have access,
121 // the regular upload form will be replaced by the swfupload form.
122 if (isset($form['#node']) && user_access('upload files')) {
123
124 // Unset the regular upload form
125 unset($form['attachments']);
126
127 // Get the settings
128 $settings = _swfupload_node_settings($form['#node']->type);
129
130 $form['swfattachments'] = array(
131 '#type' => 'fieldset',
132 '#title' => t('File attachments'),
133 '#collapsible' => TRUE,
134 '#collapsed' => TRUE,
135 '#attributes' => array('id' => 'file_attachments_wrapper'),
136 );
137 $form['swfattachments']['upload'] = array(
138 '#type' => 'swfupload_button',
139 '#default_value' => drupal_to_js($form['#node']->files),
140 '#max_files' => $settings['max_files'],
141 '#filepath' => $settings['filepath'],
142 '#file_extensions' => $settings['file_extensions'],
143 '#max_img_resolution' => $settings['max_img_resolution'],
144 '#max_file_size' => $settings['max_file_size'],
145 '#max_queue_size' => $settings['node_max_file_size'],
146 '#node_settings' => $settings,
147 );
148 }
149 }
150
151 /**
152 * Implementation of hook_nodeapi().
153 */
154 function swfupload_nodeapi(&$node, $op, $teaser) {
155 switch ($op) {
156 case 'insert':
157 case 'update':
158 if (user_access('upload files')) {
159 swfupload_node_save($node);
160 }
161 break;
162 }
163 }
164
165 /**
166 * Saves a node - file relation
167 */
168 function swfupload_node_save($node) {
169 // First delete already stored fid's for this node
170 db_query("DELETE FROM {upload} WHERE nid = %d", $node->nid);
171
172 // Get all existing columns in the upload table
173 $result = db_query("SHOW COLUMNS FROM {upload}");
174 while ($column = db_result($result)) $upload_columns[] = $column;
175
176 // Get all existing columns in the files table
177 $result = db_query("SHOW COLUMNS FROM {files}");
178 while ($column = db_result($result)) $files_columns[] = $column;
179
180 // Save the files
181 $stack = _swfupload_parse_json($node->upload);
182 $weight = 0;
183 if (!empty($stack)) {
184 foreach ($stack as $fid => $file) {
185 $file = (object)$file;
186 // Create an array for the default present columns in the upload table
187 $values = array(
188 'fid' => $fid,
189 'nid' => $node->nid,
190 'vid' => $node->vid,
191 'list' => $file->list,
192 'weight' => $weight,
193 'description' => $file->description,
194 );
195
196 // Check if the all elements of the file object can be stored.
197 // If there's no column in the upload table yet, we'll create one.
198 foreach ($file as $column => $value) {
199 if (!in_array($column, $upload_columns) && !in_array($column, $files_columns)) {
200 db_query("ALTER TABLE {upload} ADD %s VARCHAR(255) NOT NULL", $column);
201 $upload_columns[] = $column;
202 }
203 }
204
205 // Get the values of non-default columns
206 foreach ($upload_columns as $column) {
207 if (!in_array($column, array_keys($values))) {
208 $values[$column] = $file->{$column};
209 }
210 }
211
212 // Save the file to the db
213 db_query("INSERT INTO {upload} (". join(', ', array_keys($values)) .") VALUES (%d, %d, %d, %d, %d, '%s'". str_repeat(", '%s'", count($values) - 6) .")", $values);
214 // Set the status of the file to 1, otherwise the file will be deleted after cron
215 file_set_status($file, FILE_STATUS_PERMANENT);
216 $weight++;
217 }
218 }
219 }
220
221 /**
222 * Merge settings, create new key "merged" with the new settings
223 */
224 function _swfupload_node_settings($type) {
225 $swfupload_settings = variable_get("swfupload_setting_$type", array());
226 //swfupload_filter_roles($swfupload_settings);
227 global $user;
228
229 // Store all the settings for this user in a separate array
230 foreach ($user->roles as $role) {
231 $user_settings[] = (!empty($swfupload_settings[t($role)])) ? (array)$swfupload_settings[t($role)] : array(
232 'use_swfupload' => 1,
233 'filepath' => '%file_directory_path',
234 'max_img_resolution' => '800x600',
235 'list' => 1,
236 'file_extensions' => 'jpg jpeg gif png txt',
237 'max_file_size' => 1,
238 'node_max_file_size' => 0,
239 'max_files' => 1,
240 'upload_usersize' => 10,
241 );
242 }
243
244 // Why merge if there is only one key?
245 if(count($user_settings) == 1) {
246 // Change MB's to bytes
247 _mb_to_bytes($user_settings[0], array('max_file_size', 'upload_usersize', 'node_max_file_size'));
248 return $user_settings[0];
249 }
250
251 // Loop though all settings and merge diffrent settings
252 foreach($user_settings as $settings) {
253
254 foreach($settings as $name => $value) {
255
256 // Not all settings can be merged using the same code, think about the allowed_extentions
257 // For some settings we use a differect code for merging
258 switch ($name) {
259
260 // Very simple to merge just look if the value is higher than we already have
261 // but do not overwrite if value is 0, because that's unlimited, so 0 wins over 20
262 case 'upload_usersize':
263 case 'max_file_size':
264 case 'list':
265 case 'node_max_file_size':
266 case 'max_files':
267 if(($value > $result[$name] && $result[$name] != 0) || !isset($result[$name]) or $value == 0) {
268 $result[$name] = (int) $value;
269 }
270 break;
271
272 // Here 0 isn't unlimited, so 1 wins over 0
273 case 'use_swfupload':
274 if($value > $result[$name] or !isset($result[$name])) {
275 $result[$name] = $value;
276 }
277 break;
278
279 // Insert extentions seperated in an array, merge this array afterwards
280 case 'file_extensions':
281 $allowed_extentions = explode(' ', $value);
282 if(!is_array($result[$name])) {
283 $result[$name] = array();
284 }
285 $result[$name] = array_merge($result[$name], array_flip($allowed_extentions));
286 break;
287
288 case 'max_img_resolution':
289 $exploded = explode('x', $value);
290 $max_img_resolution_x = $exploded[0];
291 $max_img_resolution_y = $exploded[1];
292 if(($max_img_resolution_x > $result['max_img_resolution_x'] && $result['max_img_resolution_x'] != 0) or !isset($result['max_img_resolution_x']) or $max_img_resolution_x == 0) {
293 $result['max_img_resolution_x'] = $max_img_resolution_x;
294 }
295
296 if(($max_img_resolution_y > $result['max_img_resolution_y'] && $result['max_img_resolution_y'] != 0) or !isset($result['max_img_resolution_y']) or $max_img_resolution_y == 0) {
297 $result['max_img_resolution_y'] = $max_img_resolution_y;
298 }
299 break;
300
301 case 'filepath';
302 if(!is_array($result[$name])) {
303 $result[$name] = array();
304 }
305 $result[$name] = array_merge($result[$name], array($value));
306 break;
307
308 }
309 }
310 }
311
312 // File extentions from array to string
313 if(count($result['file_extensions']) > 1) {
314 $result['file_extensions'] = implode(' ', array_keys($result['file_extensions']));
315 }
316
317 // Use last role
318 if(!empty($result['filepath'])) {
319 $result['filepath'] = array_unique($result['filepath']);
320 if(count($result['filepath']) > 1) {
321 $result['filepath'] = $result['filepath'][array_pop(array_keys($result['filepath']))];
322 }
323 else {
324 $result['filepath'] = $result['filepath'][0];
325 }
326 }
327
328 // Max img resolution
329 if(isset($result['max_img_resolution_x'])) {
330 $result['max_img_resolution'] = $result['max_img_resolution_x'] .'x'. $result['max_img_resolution_y'];
331 unset($result['max_img_resolution_x'], $result['max_img_resolution_y']);
332 }
333
334 // Change MB's to bytes
335 _mb_to_bytes($result, array('max_file_size', 'upload_usersize', 'node_max_file_size'));
336
337 return $result;
338 }
339
340 /**
341 * This function is executed when SFWUpload.swf requests a file upload
342 */
343 function _swfupload_swfupload() {
344 $p = (object)$_POST;
345 $op = $p->op;
346 $file = _swfupload_parse_json($p->file);
347 $instance = _swfupload_parse_json($p->instance);
348 $node_settings = _swfupload_parse_json($p->node_settings);
349 $filepath = $p->filepath;
350 unset($p);
351
352 switch ($op) {
353 case 'init':
354 // Add the default callback functions for the SWF Upload
355 $instance->type = 'table';
356 $instance->callbacks = array(
357 'swfupload_loaded_handler' => 'ref.swfUploadLoaded',
358 'file_queued_handler' => 'ref.fileQueued',
359 'queue_complete_handler' => 'ref.queueComplete',
360 'file_queue_error_handler' => 'ref.fileQueueError',
361 'file_dialog_complete_handler' => 'ref.dialogComplete',
362 'upload_success_handler' => 'ref.uploadSuccess',
363 'upload_progress_handler' => 'ref.uploadProgress',
364 'upload_error_handler' => 'ref.uploadError',
365 'upload_complete_handler' => 'ref.uploadComplete',
366 'init_complete_handler' => 'ref.initComplete',// This custom javascript callback function is used to place the markup inside the dom
367 );
368 $instance->elements = array(
369 'drag' => array(
370 'class' => 'drag first',
371 'type' => 'drag',
372 'colspan' => 3,
373 'title' => t('Description'),
374 'add_separator' => TRUE,
375 ),
376 'icon' => array(
377 'type' => 'icon',
378 'class' => 'icon',
379 ),
380 'description' => array(
381 'type' => 'text',
382 'default_value' => '{filename}',
383 'class' => 'text title',
384 ),
385 'list' => array(
386 'title' => t('List'),
387 'type' => 'checkbox',
388 'default_value' => $node_settings->list,
389 'class' => 'checkbox',
390 'contains_progressbar' => TRUE,
391 'add_separator' => TRUE,
392 ),
393 'alt' => array(
394 'title' => t('Alternate Text'),
395 'type' => 'textarea',
396 'default_value' => '{filename}',
397 'class' => 'text',
398 'contains_progressbar' => TRUE,
399 ),
400 'cancel' => array(
401 'class' => 'last',
402 'type' => 'cancel',
403 ),
404 );
405 break;
406 case 'move_uploaded_file':
407 $file->validators = array(
408 'file_validate_extensions' => array($node_settings->file_extensions),
409 'file_validate_image_resolution' => array($node_settings->max_img_resolution),
410 'file_validate_size' => array($node_settings->max_file_size, $node_settings->upload_usersize),
411 );
412 $file->filepath = $filepath;
413
414 // Allow other modules to change the filepath an validators
415 foreach (module_implements('swfupload') as $module) {
416 $function = $module .'_swfupload';
417 $function($file, 'move_uploaded_file', $instance);
418 }
419
420 _swfupload_move_uploaded_file($instance->name, $file);
421 unset($file->validators);
422 $op = 'upload_complete';
423 break;
424 }
425 // Allow other modules to change the returned data
426 foreach (module_implements('swfupload') as $module) {
427 $function = $module .'_swfupload';
428 $function($file, $op, $instance);
429 }
430
431 // Replace keys named 'class' to 'classname'
432 if (is_array($instance->elements)) {
433 array_walk($instance->elements, '_class_to_classname');
434 }
435
436 $p->op = $op;
437 $p->file = $file;
438 $p->filepath = $filepath;
439 $p->instance = $instance;
440 $p->node_settings = $node_settings;
441 $p->messages = drupal_get_messages();
442 echo drupal_to_js($p);
443 exit(0);
444 }
445
446 /**
447 *
448 */
449 function _swfupload_move_uploaded_file($source, &$file) {
450 if (isset($_FILES["Filedata"]) && is_uploaded_file($_FILES["Filedata"]["tmp_name"]) && $_FILES["Filedata"]["error"] == 0) {
451 drupal_set_message(t('There was an error uploading the file'), 'error');
452 return;
453 }
454
455 $_FILES['files']['name'][$source] = $_FILES[$source]['name'];
456 $_FILES['files']['type'][$source] = $_FILES[$source]['type'];
457 $_FILES['files']['tmp_name'][$source] = $_FILES[$source]['tmp_name'];
458 $_FILES['files']['error'][$source] = $_FILES[$source]['error'];
459 $_FILES['files']['size'][$source] = $_FILES[$source]['size'];
460
461 // Check if the file directory exists
462 file_check_directory($file->filepath, FILE_CREATE_DIRECTORY);
463
464 if (user_access('upload files') && ($file = file_save_upload($source, $file->validators, $file->filepath))) {
465 return $file;
466 }
467 drupal_set_message(t('There was an error uploading the file'), 'error');
468 }
469
470 /**
471 * Implementation of hook_elements().
472 */
473 function swfupload_elements() {
474 $type['swfupload_button'] = array(
475 '#input' => TRUE,
476 '#after_build' => array('swfupload_check_directory', '_swfupload_add_js'),
477 '#default_value' => '[]',
478 '#max_files' => 1,
479 '#filepath' => file_directory_path(),
480 '#max_img_resolution' => '800x600',
481 '#file_extensions' => 'jpg jpeg gif png txt',
482 '#max_file_size' => intval(ini_get('upload_max_filesize')) .'MB', // The maximum megabytes per file
483 '#max_queue_size' => intval(ini_get('upload_max_filesize')) .'MB', // The maximum megabytes in the queue
484 '#node_settings' => array(), // Used to pass the settings for the current node to hook_swfupload.
485 );
486 return $type;
487 }
488
489 function _swfupload_add_js($element) {
490
491 // Get the path to the swfupload module.
492 $path = drupal_get_path('module', 'swfupload');
493
494 $settings['swfupload_settings'][$element['#id']] = array(
495 'module_path' => $path,
496 'flash_url' => base_path()."$path/swfupload/swfupload.swf",
497 'upload_url' => url('swfupload'), // Relative to the SWF file
498 'file_post_name' => $element['#name'],
499 'file_queue_limit' => $element['#max_files'],
500 'post_params' => array(
501 'sid' => _post_key(),
502 'filepath' => $element['#filepath'],
503 'max_img_resolution' => $element['#max_img_resolution'],
504 'op' => 'move_uploaded_file',
505 'instance' => drupal_to_js(array('name' => $element['#name'])),
506 'node_settings' => drupal_to_js($element['#node_settings']),
507 ),
508 'file_size_limit' => $element['#max_file_size'],
509 'file_types' => '*.'. str_replace(" ", ";*.", $element['#file_extensions']),
510 'file_types_description' => ($element['#description'] ? $element['#description'] : ''),
511 'file_upload_limit' => $element['#max_files'],
512 'custom_settings' => array(
513 'upload_stack_value' => (!empty($element['#value'])) ? $element['#value'] : '[]',
514 'max_queue_size' => $element['#max_queue_size'],
515 ),
516 );
517
518 drupal_add_js("$path/js/swfupload.src.js");
519 drupal_add_js("$path/swfupload/swfupload.js");
520 drupal_add_js($settings, 'setting');
521 jquery_plugin_add('tablednd');
522 jquery_plugin_add('csspngfix');
523
524 return $element;
525 }
526
527 /**
528 * Theme function for the swfupload form element
529 */
530 function theme_swfupload_button($element) {
531 drupal_add_css(drupal_get_path('module', 'swfupload') .'/swfupload.css');
532
533 // Force the classes swfupload_button and disabled to be added to the button
534 $element['#attributes']['class'] .= ' swfupload_button disabled';
535
536 $title = ($element['#title']) ? $element['#title'] : t('Upload new !file', array('!file' => ($element['#max_files'] > 1 ? t('file(s)') : t('file'))));
537 $output[] = '<div id="'. $element['#id'] .'" '. drupal_attributes($element['#attributes']) .'>';
538 $output[] = ' <div class="swfupload-wrapper">';
539 $output[] = ' <div id="'. $element['#name'] .'-swfwrapper">&nbsp;</div>';
540 $output[] = ' </div>';
541 $output[] = ' <div class="left">&nbsp;</div>';
542 $output[] = ' <div class="center">'. $title .'</div>';
543 $output[] = ' <div class="right">&nbsp;</div>';
544 $output[] = '</div>';
545 if ($element['#description']) {
546 $output[] = ' <div class="description">'. $element['#description'] .'</div>';
547 }
548 return join("\n", $output);
549 }
550
551 /**
552 * Checks the existence of the given filepath
553 */
554 function swfupload_check_directory($element) {
555 $file_directory_path = file_directory_path();
556 $filepath = str_replace("%file_directory_path", $file_directory_path, $element['#filepath']);
557 if (($filepath !== $file_directory_path) && (!strstr($filepath, $file_directory_path. '/'))) {
558 if (strpos($filepath, '/') !== 0) {
559 $filepath = "/$filepath";
560 }
561 $filepath = $file_directory_path . $filepath;
562 }
563 file_check_directory($filepath, FILE_CREATE_DIRECTORY);
564
565 $element['#filepath'] = "$filepath/";
566 return $element;
567 }
568
569 /**
570 * Helper function to replace instance elements class keys to classname keys
571 * Safari hangs if you use 'class' in javascript
572 */
573 function _class_to_classname(&$element) {
574 $element['classname'] = $element['class'];
575 unset($element['class']);
576 }
577
578 /**
579 * Calculates the amount of bytes for a given MB
580 */
581 function _mb_to_bytes(&$result, $elements = array()) {
582 foreach ($elements as $key) {
583 $result[$key] = $result[$key] * 1024 *1024;
584 }
585 }
586
587 /**
588 * Generates an unique key, used for validating upload requests
589 */
590 function _post_key() {
591 global $user;
592 return bin2hex("$user->uid*". md5(($user->uid ? $user->sid : $_SERVER['REMOTE_ADDR'])));
593 }
594
595 /**
596 * Converts an hexadecimal string to binairy
597 */
598 function hex2bin($h) {
599 if (!is_string($h)) return null;
600 $r='';
601 for ($a=0; $a<strlen($h); $a+=2) { $r.=chr(hexdec($h{$a}.$h{($a+1)})); }
602 return $r;
603 }
604
605 /**
606 * Copied from json_server module
607 * Decodes a json string for systems with older versions (< PHP 5)
608 */
609 function _swfupload_parse_json($v) {
610 // PHP 5 only
611 if (function_exists('json_decode')) {
612 return json_decode($v);
613 }
614 if ($v{0} == '"') {
615 $v = substr($v, 1, -1);
616 }
617 elseif ($v{0} == '{') {
618 $var = explode(",", substr($v, 1, -2));
619 $v = array();
620 foreach ($var as $value) {
621 $va = explode(":", $value);
622 $v[$va[0]] = drupal_parse_json($va[1]);
623 }
624 }
625 elseif ($v{0} == '[') {
626 $var = explode(",", substr($v, 1, -2));
627 $v = array();
628 foreach ($var as $value) {
629 $v[] = drupal_parse_json($va[0]);
630 }
631 }
632 return $v;
633 }

  ViewVC Help
Powered by ViewVC 1.1.2