swfupload.module 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285
  1. <?php
  2. // $Id: swfupload.info, v 0.1, 2008/10/13 10:02:46, skilip Exp $
  3. include_once dirname(__FILE__) . '/swfupload_widget.inc';
  4. /**
  5. * @file
  6. *
  7. * A widget for file field which enables multiple file uploads using the SWFUpload library.
  8. */
  9. /**
  10. * Implements hook_perm().
  11. */
  12. function swfupload_perm() {
  13. return array('upload files with swfupload');
  14. }
  15. /**
  16. * Implements hook_menu().
  17. */
  18. function swfupload_menu() {
  19. $items['swfupload'] = array(
  20. 'page callback' => 'swfupload_js',
  21. 'access callback' => 'swfupload_upload_access',
  22. 'type' => MENU_CALLBACK,
  23. 'file' => 'swfupload.admin.inc',
  24. );
  25. return $items;
  26. }
  27. /**
  28. * Validate access to the swfuploadpath
  29. */
  30. function swfupload_upload_access() {
  31. $result = FALSE;
  32. $p = (object) $_POST;
  33. // Validate the request.
  34. if (!empty($p->sid)) {
  35. // $hash_arr[0] is the uid the user wants to athenticate for.
  36. // $hash_arr[1] is the md5-hashed sid of drupals authetication token.
  37. $hash_arr = explode('*', _swfupload_hex2bin($p->sid));
  38. $uid = $hash_arr[0];
  39. $token = $hash_arr[1];
  40. if ($uid == 0) {
  41. // If the uid is 0, there will be no session id.
  42. // We'll check if the hash of the current remote address matches the sent one.
  43. return ($token == md5($_SERVER['REMOTE_ADDR']));
  44. }
  45. // Get all session for the provided user
  46. $result = db_query('SELECT sid FROM {sessions} WHERE uid = :uid', array(':uid' => $uid));
  47. // There is no user with that uid, deny permission.
  48. if ($result == FALSE) {
  49. return FALSE;
  50. }
  51. $valid_sids = array();
  52. // create our hashes we need for verification
  53. foreach ($result as $row) {
  54. $valid_sids[$row->sid] = md5($row->sid);
  55. }
  56. // If the hashed session is is present in the stored hashed session ids from the database,
  57. // and if there weren't more that 5 invalid attempts for matching,
  58. // make the user account global so other modules can use its credentials.
  59. if (in_array($token, $valid_sids) && flood_is_allowed('swfupload_restore_session', 5)) {
  60. // Use the global user, as we are about to store the loaded account object in it.
  61. global $user;
  62. // Now load the global user object to "login". We use the $uid provided, as we verfified
  63. // that the token is correct (and matches this user)
  64. $user = user_load($uid);
  65. // This is needed. Most people forget about this - thats why forms wont work anymore ... the validation fails (token).
  66. session_id(array_search($token, $valid_sids));
  67. // As the user session is restored, check for general rights to use swfupload
  68. return user_access('upload files with swfupload');
  69. }
  70. else {
  71. // Register unwanted attempts to rstore the session.
  72. flood_register_event('swfupload_restore_session');
  73. }
  74. // The sid doesn't exist for this user or its a flood attack
  75. return FALSE;
  76. }
  77. // No session ID is set, we can assume we're still in the same session
  78. return (!empty($p->op) && user_access('upload files with swfupload'));
  79. }
  80. /**
  81. * Implements hook_theme().
  82. */
  83. function swfupload_theme() {
  84. return array(
  85. 'swfupload_widget' => array(
  86. 'render element' => 'element',
  87. ),
  88. );
  89. }
  90. /**
  91. * Implements hook_elements().
  92. */
  93. function swfupload_element_info() {
  94. $path = drupal_get_path('module', 'swfupload');
  95. return array(
  96. 'swfupload_widget' => array(
  97. '#process' => array('swfupload_widget_process'),
  98. '#value_callback' => 'swfupload_widget_value',
  99. '#input' => TRUE,
  100. '#attached' => array(
  101. 'js' => array(
  102. 'misc/tabledrag.js' => array('weight' => -10),
  103. $path . '/js/swfupload_widget.js' => array('weight' => 10),
  104. ),
  105. 'css' => array(
  106. $path . '/swfupload.css',
  107. ),
  108. ),
  109. '#theme' => 'swfupload_widget',
  110. '#theme_wrappers' => array('form_element'),
  111. ),
  112. );
  113. }
  114. /**
  115. * Implements hook_swfupload().
  116. */
  117. function swfupload_swfupload(&$file, $op, &$instance, $instance_settings) {
  118. switch ($op) {
  119. case 'init':
  120. $columns = 0;
  121. if ($instance_settings->description_field) {
  122. $instance->elements['description'] = $instance->elements['filename'];
  123. $instance->elements['description']['type'] = 'textfield';
  124. $instance->elements['drag']['title'] = t('Description');
  125. unset($instance->elements['filename']);
  126. }
  127. if ($instance_settings->display_field) {
  128. $instance->elements['display'] = array(
  129. 'title' => t('Display'),
  130. 'type' => 'checkbox',
  131. 'default_value' => $instance_settings->display_default,
  132. 'class' => 'checkbox',
  133. 'contains_progressbar' => TRUE,
  134. 'add_separator' => TRUE,
  135. );
  136. $columns++;
  137. }
  138. foreach (array('alt' => t('Alt'), 'title' => t('Title')) as $elem => $title) {
  139. if (!empty($instance_settings->{$elem . '_field'})) {
  140. $instance->elements[$elem] = array(
  141. 'title' => $title,
  142. 'type' => ($instance_settings->{$elem . '_type'} ? $instance_settings->{$elem . '_type'} : 'textfield'),
  143. 'default_value' => $instance_settings->{$elem},
  144. 'class' => 'text',
  145. 'contains_progressbar' => TRUE,
  146. 'add_separator' => TRUE,
  147. );
  148. // Replace tokens.
  149. if (module_exists('token')) {
  150. $instance->elements[$elem]['default_value'] = token_replace($instance->elements[$elem]['default_value']);
  151. }
  152. $columns++;
  153. }
  154. }
  155. if ($columns == 0) {
  156. $instance->elements['progress'] = array(
  157. 'type' => 'markup',
  158. 'value' => '<span>&nbsp;</span>',
  159. 'class' => 'checkbox',
  160. 'contains_progressbar' => TRUE,
  161. );
  162. }
  163. unset($instance->elements[$elem]['add_separator']);
  164. break;
  165. case 'move_uploaded_file':
  166. if (isset($_FILES["Filedata"]) && is_uploaded_file($_FILES["Filedata"]["tmp_name"]) && $_FILES["Filedata"]["error"] == 0) {
  167. // Set a message of the type 'swfupload_error' in order to place the message in the progressbar.
  168. drupal_set_message(t('There was an error uploading the file'), 'swfupload_error');
  169. return;
  170. }
  171. $_FILES['files']['name'][$instance->name] = reset($_FILES[$instance->name]['name']);
  172. $_FILES['files']['type'][$instance->name] = reset($_FILES[$instance->name]['type']);
  173. $_FILES['files']['tmp_name'][$instance->name] = reset($_FILES[$instance->name]['tmp_name']);
  174. $_FILES['files']['error'][$instance->name] = reset($_FILES[$instance->name]['error']);
  175. $_FILES['files']['size'][$instance->name] = reset($_FILES[$instance->name]['size']);
  176. // Replace tokens.
  177. if (module_exists('token')) {
  178. $file->file_path = token_replace($file->file_path, 'user');
  179. }
  180. // Check if the file directory exists
  181. file_prepare_directory($file->file_path, FILE_CREATE_DIRECTORY);
  182. if (user_access('upload files with swfupload') && ($file = file_save_upload($instance->name, $file->validators, $file->file_path))) {
  183. if (image_get_info($file->uri)) {
  184. $file->thumb = swfupload_thumb($file);
  185. }
  186. break;
  187. }
  188. drupal_set_message(t('There was an error uploading the file'), 'swfupload_error');
  189. break;
  190. }
  191. }
  192. /**
  193. * Implements hook_library().
  194. */
  195. function swfupload_libraries_info() {
  196. $libraries = array(
  197. 'swfupload' => array(
  198. 'name' => 'SWFUpload',
  199. 'vendor url' => 'http://code.google.com/p/swfupload/',
  200. 'version arguments' => array(
  201. 'file' => 'swfupload.js',
  202. 'pattern' => '/SWFUpload.version \= \"([0-9.]{1,}) ([0-9-]{1,})\"/',
  203. 'lines' => 60,
  204. ),
  205. 'files' => array(
  206. 'js' => array('swfupload.js'),
  207. ),
  208. ),
  209. );
  210. return $libraries;
  211. }
  212. /**
  213. * Implements hook_requirements().
  214. */
  215. function swfupload_requirements($phase) {
  216. $requirements = array();
  217. $library = libraries_load('swfupload');
  218. // Ensure translations don't break at install time
  219. $t = get_t();
  220. // Report Drupal version
  221. if ($phase == 'runtime') {
  222. $requirements['swfupload'] = array(
  223. 'title' => $t('SWFUpload'),
  224. 'value' => empty($library) ? t('SWFUpload library was not found!') : $library['version'],
  225. 'severity' => empty($library) ? REQUIREMENT_ERROR : REQUIREMENT_OK,
  226. );
  227. }
  228. return $requirements;
  229. }
  230. /**
  231. * Generates an unique key, used for validating upload requests
  232. */
  233. function _swfupload_post_key() {
  234. global $user;
  235. return bin2hex($user->uid . '*' . md5(($user->uid && $user->sid) ? $user->sid : $_SERVER['REMOTE_ADDR']));
  236. }
  237. /**
  238. * Converts an hexadecimal string to binairy
  239. */
  240. function _swfupload_hex2bin($h) {
  241. if (!is_string($h)) {
  242. return NULL;
  243. }
  244. $r = '';
  245. for ($a = 0; $a < drupal_strlen($h); $a += 2) {
  246. $r .= chr(hexdec($h{$a} . $h{($a + 1)}));
  247. }
  248. return $r;
  249. }
  250. /**
  251. * Create a thumbnail to be shown in the swfupload table.
  252. */
  253. function swfupload_thumb($file) {
  254. // Force an object.
  255. $file = (object) $file;
  256. return image_style_url('thumbnail', $file->uri);
  257. }