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

Contents of /contributions/modules/webfm/webfm.module

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


Revision 1.39 - (show annotations) (download) (as text)
Sun Sep 20 00:36:48 2009 UTC (2 months, 1 week ago) by cweagans
Branch: MAIN
CVS Tags: HEAD
Changes since 1.38: +2 -1 lines
File MIME type: text/x-php
#577070 by cweagans, Niels Hackius: fix webfm_rename and webfm_mkdir so that they actually work.
1 <?php
2 // $Id: webfm.module,v 1.38 2009/09/02 15:10:10 robmilne Exp $
3
4 /**
5 * @file
6 * This module implements a user accessible heirarchical file system located
7 * in a subdirectory of the site file system path.
8 */
9
10 $modulepath = drupal_get_path('module', 'webfm');
11 require_once "./" . $modulepath . "/webfm_file.inc";
12
13 define('WEBFM_FLUSH', -1);
14
15 define('WEBFM_REPLACE_RENAME', 0);
16 define('WEBFM_REPLACE_DELETE', 1);
17 define('WEBFM_RENAME_NEW', 2);
18 define('WEBFM_CANCEL', 3);
19
20 define('WEBFM_ADMIN', 1);
21 define('WEBFM_USER', 2);
22 define('WEBFM_ATTACH_VIEW', 3);
23
24 // file access bits
25 define('WEBFM_FILE_ACCESS_PUBLIC_VIEW', 1); //publicly viewable via webfm_send link
26 define('WEBFM_FILE_ACCESS_ROLE_VIEW', 2); //role can view/download file (owner/admin can always view)
27 define('WEBFM_FILE_ACCESS_ROLE_ATTACH', 4); //role attach permitted (owner/admin can always attach)
28 define('WEBFM_FILE_ACCESS_ROLE_FULL', 8); //role modification of file permitted (owner/admin can always modify)
29 define('WEBFM_MAX_FILE_ACCESS', WEBFM_FILE_ACCESS_PUBLIC_VIEW + WEBFM_FILE_ACCESS_ROLE_VIEW + WEBFM_FILE_ACCESS_ROLE_ATTACH + WEBFM_FILE_ACCESS_ROLE_FULL);
30
31 define('WEBFM_DATE_FORMAT_DAY', 1);
32 define('WEBFM_DATE_FORMAT_MONTH', 2);
33
34 /**
35 * Implementation of hook_help().
36 */
37 function webfm_help($path, $args) {
38 switch ($path) {
39 case 'admin/help#webfm':
40 $output = t('
41 <p>Web File Manager (WebFM) implements a hierarchical filesystem unlike the traditional flat filesystem used to date by Drupal. WebFM allows administrators to arrange files on the server in the same way they do on their local storage drives which greatly enhances the manageability of large collections of documents. Directory access is set by role and file access is controllable by file owners or module administrators.</p>
42 <p>WebFM uses Ajax to provide application intensive functionality such as drag-and-drop and context-sensitive menuing. JavaScript must be enabled for WebFM to function - functionality will not gracefully degrade for clients that have JavaScript disabled.</p>
43 <h2>Installation & Configuration</h2>
44 <ul>
45 <li>Download the official release from the <a href="http://drupal.org/project/webfm">project page</a>.</li>
46 <li>Unzip the archive and copy the \'webfm\' directory to your modules directory (ie:/sites/all/modules). Alternatively copy the tarball to the module directory if you can unzip it on the server.</li>
47 <li>Enable the module on Drupal\'s admin/build/modules page. An install file updates the database with the necessary table additions.</li>
48 <li>Set the <i>\'File system path:\'</i> at <i>.../admin/settings/file-system</i>. The WebFM root directory is always a sub-directory of this \'File System\' path. <i>\'Download method:\'</i> has no effect on the module since WebFM implements its own download security.</li>
49 <li>Configure the module at admin/settings/webfm.
50 <ul>
51 <li><b>Create the <i>\'WebFM root directory\'</i></b>. If this directory doesn\'t already exist, the system will create it in the \'File System\' root. Directory creation is not recursive so multi directory root paths must already exist inside the \'File System\' directory. Set the directory permissions to 775 if the server is linux/bsd.</li>
52 <li>The icon path allows the user to substitute their own gifs. File names are hardcoded in the javascript so the icons will have to have identical names.</li>
53 <li>The <i>\'Maximum resolution for uploaded images\'</i> input functions in the same fashion as the upload.module.</li>
54 <li>The <i>\'Date Format\'</i> radio buttons set the day/month order in the browser listing date field.</li>
55 <li>The <i>\'Display metadata title\'</i> checkbox sets the browser to display metadata titles rather than the actual filename if the metadata tile exists. Renaming files that use the metadata title must be done via the metadata editor. Note that node attachments always display the metadata title if available.</li>
56 <li><b><i>Default File Permissions</i></b> set the file level permissions for files inserted into the database. The exception is file uploads that create a version overwrite whereby the new file inherits the permissions from the previous file.</li>
57 <li><b><i>Settings for xxx role</i></b> fieldsets are added for roles that are granted the <i>\'access webfm\'</i> permission. Each role receives additional configuration fields for root path, extension white list, max upload file size and max total upload size. Roles with the \'access webfm\' right but without a root directory cannot access the filesystem.</li>
58 <li><b><i>WebFM attachments</i></b> controls attachment of files to node content as well as format. <br /><b>Note:</b> Each content type that will be using WebFM attachments must enable attachments in the Workflow section of <i>.../admin/settings/content-types/*type*</i> (default is \'WebFM attachments\' disabled).</li>
59 <li><b><i>IE Drag-and-Drop Normalization</i></b> is a sub-optimal solution for compensating for relative positioning in theme css. This feature is only available to #1 user.</li>
60 <li><b><i>WebFM debug</i></b> contains a <i>\'Webfm javascript debug\'</i> checkbox which is only useful for users interested in looking under the covers or who want to develop the module. The <i>\'WebFM cron\'</i> is a "stored procedure" used for database cleanup of file records that are deleted outside of the WebFM interface (ie: OS shell, ftp). This feature is only available to #1 user.</li>
61 </ul>
62 </li>
63 <li>Set WebFM rights in admin/user/access per role.
64 <ul>
65 <li><b><i>administer webfm</i></b> confers full rights to a role. Admins can see and operate on all files, including files not in the database. Only admins can create directories and access admin/settings/webfm.</li>
66 <li><b><i>access webfm</i></b> allows a role to download/view files via the WebFM browser. Only files referenced by the webfm_file table in the database are accessible. Only owners of a file (and admins) can move a file or modify it\'s metadata.<br /><b>Note:</b> Each role granted <i>\'access webfm\'</i> will receive a separate fieldset in the module settings where a root directory must be created to permit access to the browser.</li>
67 <li><b><i>view webfm attachments</i></b> allows a role to see files attached to nodes via WebFM.</li>
68 <li><b><i>webfm upload</i></b> allows a role with the <i>\'access webfm\'</i> right to upload files via the WebFM browser. The user who uploads a file is the the owner of that file.</li>
69 </ul>
70 </li>
71 <li>Admins and File owners can set the following file level permissions from the context menu of each file:
72 <ul>
73 <li><b><i>Public download</i></b>: Allows the file to be downloaded anonymously even if .htaccess exists.</li>
74 <li><b><i>Role View/Download</i></b>: Allows users of the same role to view/download the file.</li>
75 <li><b><i>Role Attach</i></b>: Allows users of the same role to attach the file to nodes.</li>
76 <li><b><i>Role Full Access</i></b>: Allows users of the same role to have the same rights to the file as the owner with the exception of permission edits.</li>
77 </ul>
78 </li>
79 <li>A .htaccess file (apache servers) can be placed in the WebFM root (or sub-path) to secure file access. Webfm streams downloads and thus your browser doesn\'t require direct http access to the directories</li>
80 <li>Updating the menu cache by navigating to admin/build/menu may be necessary if upgrading from an earlier version of the module with different internal paths.</li>
81 <li>Translations of the module require revising the string array at the top of webfm.js.</li>
82 </ul>
83 <h2>File Access Setup & Examples</h2>
84 <p>There are many ways to setup a file system hierarchy. The rules of any given system must be applied carefully if security of data is important.</p>
85 <p>The basic rules for users in a role with <i>\'access webfm\'</i> rights:</p>
86 <ul>
87 <li>The role root directory defines the domain and all subdirectories are accessible to the user.</li>
88 <li>The user cannot navigate above the role root directory.</li>
89 <li>Only files in the webfm_file table are accessible. Files uploaded by the user are owned by the user and are automatically in the database. Only module admins can view/operate on files not in the database.</li>
90 <li>The user has full control over files that he/she owns that stay within an accessible role root domain. File permissions can be locked down so that only the owner/admins can see or operate on a file. File permissions can be opened up so that anyone within the role can view or operate on the file.</li>
91 <li>Users with <i>\'access webfm\'</i> rights cannot create/delete/move/rename directories. Only module administrators (users with \'administer webfm\' permission or #1 user) can control the directory structure.</li>
92 </ul>
93 <p>Roles with <i>\'access webfm\'</i> rights can be subsets of other roles with <i>\'access webfm\'</i> rights or they can be exclusive. Users can be members of multiple roles and will consequently have a separate left-hand tree for each unique root directory (roles can even share the same root directory). It is difficult to foresee how diverse users of the module will choose to set up their systems but the following simple examples are typical arrangements. Both examples presume that the <i>drupal file-system directory</i> is set to \'files\', the WebFM module is installed and the <i>\'WebFM root directory\'</i> is set to \'webfm\'.</p>
94 <h3> Example 1</h3>
95 <p>The site requires 1 class of privileged users (A) to administer the file system and 2 classes of WebFM users (B & C) with access to file resources. Both roles will be able to upload files. Some WebFM users are members of both B & C while others are members of only one. Uploaded files are by default only accessible by the file owner and admins.</p>
96 <ul>
97 <li>A site administrator will create 3 the roles A, B and C. Role A will have the <i>\'administer webfm\'</i> permission set in .../admin/user/access. B & C will have the <i>\'access webfm\'</i> and the <i>\'webfm upload\'</i> permission set.</li>
98 <li>WebFM settings will now have a fieldset for roles B & C where the root directory for each role is set. The root of B is set to \'B\' which automatically creates the \'files/webfm/B\' directory. The root of C is set to \'C\' which creates the directory \'files/webfm/C\'. A user who is a member of only one of B or C will see a single left-hand directory tree that contains their domain. They will have no access to files within the other role domain. Users who are members of both B & C will have two left-hand directory trees and have the ability to move files they own or control between the two domains. Role A\'s root directory is the \'WebFM root directory\' and thus A users see only a single left-hand tree of the entire module file-sys.</li>
99 <li>In WebFM settings, the <i>\'Default File Permissions\'</i> are configured with all checkboxes unset. This combination of default file permissions means that files that are uploaded will initially only be viewable by the B or C user doing the upload (owner) and by A users. Individual file permissions are editable by the file owner or A user to permit other users to view/attach/modify the file. One consequence of granting the permission <i>\'Role Full Access\'</i> is that a non-admin user with a single domain could lose contact with their own file if a dual domain non-admin user moves it to the other domain.</li>
100 </ul>
101 <h3> Example 2</h3>
102 <p>The site requires 1 class of privileged users (A) to administer the file system and 2 classes of users (B & C) with access to file resources. C is determined to be a subset of B such that B can access it\'s own files as well as those of C. C will not be able to upload files to the browser but will only be able to view/download or attach files to nodes. B will be able to upload files.</p>
103 <ul>
104 <li>A site administrator will create 3 the roles A, B and C. Role A will have the <i>\'administer webfm\'</i> permission set in .../admin/user/access. B & C will have the <i>\'access webfm\'</i> permission set. B will also have the <i>\'webfm upload\'</i> permission set.</li>
105 <li>WebFM settings will now have a fieldset for roles B & C where the root directory for each role is set. First the root of B is set to \'B\' which automatically creates the \'files/webfm/B\' directory. Next the root of C is set to \'B/C\' which creates the directory \'files/webfm/B/C\'. Since C is a sub-dir of B, role B will have access to C but C will not be able to navigate above it\'s root to see B\'s files. The left-hand directory tree will appear different for B & C. B\'s tree will start at \'B\' and have a \'C\' sub-directory (and potentially other sub-directories as set up by A). C\'s tree is a subset of B\'s tree. Role A\'s root directory is the <i>\'WebFM root directory\'</i>.</li>
106 <li>In WebFM settings, the <i>\'Default File Permissions\'</i> are configured with <i>\'Role View Access\'</i> and <i>\'Role Attach Access\'</i> set. This combination of file permissions means that files that a B user uploads/moves into the C realm will by default be viewable by C and be attachable to nodes that C creates. A B file owner can manually modify the file permissions of each individual file to hide it or prevent it from being attached to content by a C user. Likewise the file permissions can be opened so that a C user can edit file attributes or move the file into another sub-directory of C.</li>
107 </ul>
108 <p>In the above examples the site administrator may simply create the roles/access rules and then let an A user configure WebFM for B & C.</p>
109 <h2>Uninstall</h2>
110 <ol>
111 <li>Disable the module on the /admin/build/modules page</li>
112 <li>Click on the uninstall tab and select the module for removal. This will automatically drop the webfm_file and webfm_attach tables as well as all configuration variables. <i><strong>NOTE:</strong></i> This action will permanently discard all attachment and metedata information and cannot be undone. Execute the first step only if you wish to restore WebFM later without loss of data.</li>
113 </ol>
114 ');
115 return $output;
116
117 case 'admin/modules#description':
118 return t('Enable the Web File Manager.');
119 }
120 }
121
122 /**
123 * Implementation of hook_link().
124 */
125 function webfm_link($type, $node = NULL, $teaser = FALSE) {
126 $links = array();
127
128 // Display a link with the number of attachments
129 if ($teaser && $type == 'node' && isset($node->webfm_files) && user_access('view webfm attachments')) {
130 if($num_files = count($node->webfm_files)) {
131 $links['webfm_attachments'] = array(
132 'title' => format_plural($num_files, '1 attachment', '@count attachments'),
133 'href' => "node/$node->nid",
134 'attributes' => array('title' => t('Read full article to view attachments.')),
135 'fragment' => 'attachments');
136 }
137 }
138 return $links;
139 }
140
141 /**
142 * Implementation of hook_node_type().
143 */
144 function webfm_node_type($op, $info) {
145 switch ($op) {
146 case 'delete':
147 variable_del('webfm_attach_'. $info->type);
148 break;
149 }
150 }
151
152 /**
153 * Implementation of hook_perm().
154 */
155 function webfm_perm() {
156 return array('access webfm', 'view webfm attachments', 'administer webfm', 'webfm upload');
157 }
158
159 /**
160 * Implementation of hook_menu().
161 */
162 function webfm_menu() {
163 $items = array();
164
165 $items['webfm'] = array(
166 'title' => 'Web File Manager',
167 'page callback' => 'webfm_main',
168 'access callback' => 'user_access',
169 'access arguments' => array('access webfm'),
170 'type' => MENU_NORMAL_ITEM,
171 );
172 $items['admin/settings/webfm'] = array(
173 'title' => 'Web File Manager',
174 'description' => 'Configure root directories, default file permissions for uploads, upload size limits, attachments, permitted file extensions and formatting.',
175 'file' => 'webfm.admin.inc',
176 'page callback' => 'drupal_get_form',
177 'page arguments' => array('webfm_admin_settings'),
178 'access arguments' => array('administer webfm'),
179 'type' => MENU_NORMAL_ITEM,
180 );
181 $items['webfm_js'] = array(
182 'title' => 'Web File Manager',
183 'page callback' => 'webfm_ajax',
184 'access callback' => 'user_access',
185 'access arguments' => array('access webfm'),
186 'type' => MENU_CALLBACK,
187 );
188 $items['webfm/upload'] = array(
189 'title' => 'Web File Manager',
190 'page callback' => 'webfm_upload',
191 'access callback' => 'user_access',
192 'access arguments' => array('access webfm'),
193 'type' => MENU_CALLBACK,
194 );
195 $items['webfm_send'] = array(
196 'title' => 'File Not Found',
197 'page callback' => 'webfm_send_file',
198 'access callback' => TRUE,
199 'type' => MENU_CALLBACK,
200 );
201 $items['webfm_popup'] = array(
202 'title' => 'Web File Manager',
203 'page callback' => 'webfm_popup',
204 'access arguments' => array('access webfm'),
205 'type' => MENU_CALLBACK,
206 );
207
208 return $items;
209 }
210
211 /**
212 * Implementation of hook_block().
213 */
214 function webfm_block($op = 'list', $delta = 0) {
215 if ($op == 'list') {
216 $blocks[0]['info'] = t('WebFM File Attachments');
217 return $blocks;
218
219 }
220 else if ($op == 'view' &&
221 user_access('access content') &&
222 user_access('view webfm attachments')) {
223 $block['content'] = webfm_attach_box();
224 $block['subject'] = t('Attachments');
225 return $block;
226 }
227 }
228
229 /**
230 * Implementation of hook_cron().
231 */
232 function webfm_cron() {
233 //cleanup any corrupted file records that have no physical files
234 //Warning - running this after renaming a directory outside of WebFM will
235 // delete all file records contained in that directory
236 if(variable_get('webfm_cron','')) {
237 $result = db_query('SELECT fpath, fid FROM {webfm_file}');
238 while ($f = db_fetch_array($result)) {
239 if(!(is_file($f['fpath']))) {
240 _webfm_dbdelete_file_fid($f['fid']);
241 }
242 }
243 }
244 }
245
246 /**
247 * Implementation of hook_comment().
248 *
249 * Similar to webfm_nodeapi, but for comments instead of nodes.
250 * Note: Enabling webfm in the edit form is done in form_alter. Keeping the
251 * attachments while preview or a failing form_validate is done by form_alter
252 * and webfm_ajax.
253 * webfm_comment is only needed to save the attachments to the table and
254 * for viewing and previewing comments.
255 * We don't need to initialize js in 'validate' here because a failing form
256 * validation re-initializes the whole node, including js.
257 */
258 function webfm_comment(&$comment, $op) {
259 if (is_object($comment)) {
260 $cid = $comment->cid;
261 $nid = $comment->nid;
262 }
263 else {
264 $cid = $comment['cid'];
265 $nid = $comment['nid'];
266 }
267
268 # We need the parent node for checking its permission to view attachments etc.
269 $node = node_load($nid);
270
271 switch ($op) {
272 case 'view':
273 if (variable_get("wfm_attach_$node->type", 1) == 1 &&
274 user_access('view webfm attachments') &&
275 variable_get('webfm_attach_body', '')) {
276 // If we preview a comment, $comment->preview is defined because the preview button
277 // for comments is added with $form['preview']. Thus we know that $_POST['attachlist']
278 // is ours. If we are previewing another comment and just "view" this one,
279 // the preview flag is not set and $_POST['attachlist'] belongs to someone else.
280 // This happens when previewing or editing a comment and the node and/or
281 // other comments might be shown, too.
282 // If we preview without 'acces webfm' permissions, we fetch from database,
283 // cf. nodeapi below.
284 if ($comment->preview && user_access('access webfm')) {
285 if ($_POST['attachlist']) {
286 $show_files = webfm_get_temp_attachments($_POST['attachlist']);
287 }
288 }
289 else {
290 // Normal view. Try to load attachments. There is no 'load' op for hook_comment.
291 if (!isset($comment->webfm_files)) {
292 $comment->webfm_files = webfm_get_attachments($cid, 'cid');
293 }
294 if (is_array($comment->webfm_files) && count($comment->webfm_files)) {
295 $show_files = $comment->webfm_files;
296 }
297 }
298 if ($show_files) {
299 $comment->comment .= theme('webfm_attachments', $show_files);
300 drupal_add_css(drupal_get_path('module', 'webfm').'/css/webfm.css');
301 }
302 }
303 break;
304
305 case 'insert':
306 if ($_POST['attachlist']) {
307 $files = explode(',', $_POST['attachlist']);
308 $i = 0;
309 foreach ($files as $fid) {
310 if ($fid)
311 // weight argument determined by position in csv
312 webfm_dbinsert_attach(0, $fid, $i++, $cid);
313 }
314 }
315 break;
316
317 case 'update':
318 // If the user cannot access webfm, $_POST['attachlist'] is always empty
319 // and therefore will delete existing attachments from the node.
320 if (user_access('access webfm') && array_key_exists('attachlist', $_POST)) {
321 $files = explode(',', $_POST['attachlist']);
322 webfm_dbupdate_attach(0, $files, $cid);
323 }
324 break;
325
326 case 'delete':
327 webfm_dbdelete_attachments($cid, 'cid');
328 break;
329 }
330 }
331
332 /**
333 * Implementation of hook_nodeapi().
334 */
335 function webfm_nodeapi(&$node, $op, $teaser) {
336 global $user, $base_url, $base_path;
337
338 switch ($op) {
339 case 'load':
340 if((variable_get("wfm_attach_$node->type", 1) == 1) &&
341 user_access('view webfm attachments')) {
342 $output['webfm_files'] = webfm_get_attachments($node->nid);
343 return $output;
344 }
345 break;
346
347 case 'view':
348 // Add the attachments list to node body if configured to appear in body.
349 if(variable_get('webfm_attach_body', '')) {
350 // We could be viewing or previewing this node.
351 // Loading a node defines $node->webfm_files, possibly as empty list,
352 // but loading an edit form unsets $node->webfm_files again. Thus, if
353 // $node->webfm is not set, we are previewing this node.
354 // Two cases then:
355 // 1) The user has no webfm access rights, so he can't change anything
356 // and $_POST['attachlist'] is empty. Simulate the 'load' operation
357 // to get the files from the database to show them in the preview.
358 // 2) If user has webfm access, all attachments (saved/unsaved)
359 // are in $_POST['attachlist']. But $_POST['attachlist'] is also set if
360 // we preview e.g. a comment where this node is shown, too, but then
361 // the attachlist is not ours. So we check for webfm_files *before*
362 // checking for $_POST to get around this.
363 if (!user_access('access webfm') && (variable_get("wfm_attach_$node->type", 1) == 1)
364 && user_access('view webfm attachments')) {
365 $node->webfm_files = webfm_get_attachments($node->nid);
366 }
367 if(isset($node->webfm_files) && is_array($node->webfm_files)) {
368 if(count($node->webfm_files) && !$teaser) {
369 $show_files = $node->webfm_files;
370 }
371 }
372 // We must check for view permissions in a preview, but wfm_attach_$node->type
373 // is true if we already have attachments here.
374 elseif(isset($_POST['attachlist']) && user_access('view webfm attachments')) {
375 $show_files = webfm_get_temp_attachments($_POST['attachlist']);
376 }
377 if(isset($show_files) && is_array($show_files)) {
378 $node->content['webfm_attachments'] = array(
379 '#value' => theme('webfm_attachments', $show_files),
380 '#weight' => module_exists('content') ? content_extra_field_weight($node->type, 'webfm_attachments') : 10,
381 );
382
383 drupal_add_css(drupal_get_path('module', 'webfm').'/css/webfm.css');
384 }
385 }
386 break;
387
388 case 'validate':
389 // When form_validate fails for preview or save, we must reinitialize
390 // javascript, otherwise webfm doesn't work anymore.
391 $modulepath = drupal_get_path('module', 'webfm');
392 drupal_add_js($modulepath .'/js/webfm.js');
393 drupal_add_css($modulepath .'/css/webfm.css');
394 // Output drupal config data as inline javascript
395 $clean_url = variable_get('clean_url', 0);
396 $clean = (($clean_url == 0) || ($clean_url == '0')) ? FALSE : TRUE;
397 webfm_inline_js($base_url, $base_path, $clean, $user->uid);
398 break;
399
400 case 'insert':
401 // We saved the attachment list for preview. Remove before saving.
402 unset($node->attachlist);
403 if($_POST['attachlist']) {
404 $files = explode(',', $_POST['attachlist']);
405 $i = 0;
406 foreach($files as $fid) {
407 if($fid)
408 // weight argument determined by position in csv
409 webfm_dbinsert_attach($node->nid, $fid, $i++);
410 }
411 }
412 if (module_exists('og') && variable_get('webfm_og_auto', 0) == 1) {
413 $groups = og_all_groups_options();
414 if ($groups[$node->nid]) {
415 // make the node title into a suitable directory name
416 $group_directory = webfm_get_group_directory($node);
417 $group_root_dir = file_directory_path().webfm_get_root_path().'/'.$group_directory;
418 file_check_directory($group_root_dir, FILE_CREATE_DIRECTORY, 'root_dir_group_'.$node->nid);
419 variable_set('root_dir_group_'. $node->nid, $group_directory);
420 }
421 }
422 break;
423
424 case 'update':
425 // If the user cannot access webfm, $_POST['attachlist'] is always empty
426 // and therefore will delete existing attachments from the node.
427 if(user_access('access webfm')) {
428 $files = explode(',', $_POST['attachlist']);
429 webfm_dbupdate_attach($node->nid, $files);
430 }
431 break;
432
433 case 'delete':
434 webfm_dbdelete_attachments($node->nid);
435 break;
436 }
437 }
438
439 /**
440 * Implementation of hook_content_extra_fields().
441 */
442 function webfm_content_extra_fields($type) {
443 $extras['webfm_attachments'] = array(
444 'label' => t('Webfm Attachments'),
445 'description' => t('Displays the attachments as table'),
446 'weight' => 10,
447 );
448 return $extras;
449 }
450
451
452 /**
453 * Implementation of hook_form_alter().
454 */
455 function webfm_form_alter(&$form, &$form_state, $form_id) {
456 global $base_url, $base_path, $user;
457
458 if(($user->uid == 1) || user_access('administer webfm') || user_access('access webfm'))
459 $access = TRUE;
460 else
461 $access = FALSE;
462 if ($form_id == 'node_type_form' && $access) {
463 $form['workflow']['webfm_attach'] = array(
464 '#type' => 'radios',
465 '#title' => t('WebFM Attachments'),
466 '#default_value' => variable_get('webfm_attach_'.$form['#node_type']->type, 0),
467 '#options' => array(0 => t('Disabled'), 1 => t('Enabled')),
468 '#description' => t('Should this content type allow upload & file attachment via WebFM?'),
469 );
470 }
471
472 if (isset($form['type']) || $form_id == 'comment_form') {
473 // For a comment form, the webfm permissions are inherited from the comments node.
474 if ($form_id == 'comment_form') {
475 $node = node_load($form['nid']['#value']);
476 $formcheck = TRUE;
477 }
478 else {
479 $node = $form['#node'];
480 $formcheck = ($form['type']['#value'] .'_node_form' == $form_id);
481 }
482 if ($access && $formcheck && variable_get('webfm_attach_'. $node->type, 0)) {
483 $modulepath = drupal_get_path('module', 'webfm');
484 drupal_add_js($modulepath.'/js/webfm.js');
485 drupal_add_css($modulepath.'/css/webfm.css');
486 // Output drupal config data as inline javascript
487 $clean_url = variable_get('clean_url', 0);
488 $clean = (($clean_url == 0) || ($clean_url == '0')) ? FALSE : TRUE;
489 webfm_inline_js($base_url, $base_path, $clean, $user->uid);
490
491 // Attachments fieldset
492 $form['webfm-attach']['#theme'] = 'webfm_upload_form';
493 $form['webfm-attach']['attach'] = array(
494 '#type' => 'fieldset',
495 '#title' => t('WebFM Attachments'),
496 '#description' => t('Drag attachments to set order.<br />Changes made to the attachments are not permanent until you save this post.'),
497 '#collapsible' => TRUE,
498 '#collapsed' => TRUE,
499 '#weight' => 29,
500 );
501 $form['webfm-attach']['attach']['attachedfiles'] = array(
502 '#prefix' => '<div id="webfm-attach">',
503 '#suffix' => '</div>',
504 );
505 $form['webfm-attach']['attach']['attachedfiles'] += webfm_attach_attached_form($node);
506 $form['webfm-attach']['attach']['browser'] = array(
507 '#type' => 'fieldset',
508 '#title' => t('File Browser'),
509 '#collapsible' => TRUE,
510 '#collapsed' => TRUE
511 );
512 if($user->uid == 1 ||
513 user_access('administer webfm')) {
514 $form['webfm-attach']['attach']['browser'] += webfm_links();
515 }
516 if($user->uid == 1 ||
517 user_access('administer webfm') ||
518 user_access('webfm upload')) {
519 $form['webfm-attach']['attach']['browser']['wrapper'] = array(
520 '#type' => 'fieldset',
521 '#title' => t('File Upload'),
522 '#collapsible' => TRUE,
523 '#collapsed' => TRUE,
524 '#description' => t('Uploaded file will be saved to the current directory.'),
525 '#prefix' => '<div id="webfm-inline">',
526 '#suffix' => '</div>'
527 );
528 $form['webfm-attach']['attach']['browser']['wrapper']['wrapper'] = array(
529 '#prefix' => '<div id="wfmatt-wrapper">',
530 '#suffix' => '</div>');
531 $form['webfm-attach']['attach']['browser']['wrapper']['wrapper'] += webfm_upload_form('webfm/upload');
532 $form['#attributes']['enctype'] = 'multipart/form-data';
533 } else {
534 // Disable upload
535 $form['webfm-attach']['attach']['browser']['wrapper'] = array(
536 '#type' => 'fieldset',
537 '#collapsible' => TRUE,
538 '#collapsed' => TRUE,
539 '#prefix' => '<div id="webfm-inline">',
540 '#suffix' => '</div>'
541 );
542 }
543 }
544 }
545 }
546
547 function webfm_get_group_directory($node) {
548 $group_directory = drupal_strtolower(trim($node->title));
549 $group_directory = str_replace(array(' ', '-'), '_', $group_directory);
550 return preg_replace('/[^a-z0-9_]/', '', $group_directory);
551 }
552
553 function webfm_link_output() {
554 global $user;
555
556 if($user->uid == 1 || user_access('administer webfm')) {
557 // Settings link - accessible only #1 user or module administrator
558 $settings_link = t('[<a href="@link">settings...</a>]',array('@link'=>url("admin/settings/webfm")));
559 // Admin Help link - available only if help module enabled
560 $help_link = module_hook('help', 'help') ? t('[<a href="@link">more help...</a>]',array('@link'=>url("admin/help/webfm"))) : '';
561 } else {
562 $settings_link = '';
563 $help_link = '';
564 }
565 // Debug link - available only if enabled in settings
566 $debug_link = (drupal_to_js(variable_get('webfm_debug',''))) ? t('[<a href=# id="webfm-debug-link">debug</a>]') : '';
567
568 return $debug_link.$settings_link.$help_link;
569 }
570
571 function webfm_links() {
572 $form['#theme'] = 'webfm_attach_attached_form';
573 $output = webfm_link_output();
574
575 if($output) {
576 $form['links'] = array(
577 '#prefix' => '<div class="more-help-link">',
578 '#suffix' => '</div>'
579 );
580 $form['links']['content'] = array(
581 '#type' => 'markup',
582 '#value' => $output
583 );
584 }
585
586 return $form;
587 }
588
589 function webfm_attach_attached_form($node) {
590 $form['#theme'] = 'webfm_attach_attached_form';
591
592 // This form input (id = edit-attachlist) will hold the comma-separated
593 // ordered list of attached fids. We need to store the attachments (which
594 // might not yet been saved to the database) in two cases:
595 // 1) A form_validate fails when trying to save/preview. The form is not
596 // rebuild by form_alter, but form values are refilled. #value => '' would
597 // delete the attachlist collected so far, so use #default_value => '' instead.
598 $form['new']['attachlist'] = array(
599 '#type' => 'hidden',
600 '#default_value' => '');
601
602 // 2) If form_validate didn't fail, the form is rebuild with form_alter
603 // and the value is reset. But we have the list in the POST parameters.
604 // Use default_value here, too, so that it can still be changed if we get
605 // a form_validate error *after* a successful preview.
606 if ($_POST['attachlist']) {
607 $form['new']['attachlist']['#default_value'] = $_POST['attachlist'];
608 }
609
610 return $form;
611 }
612
613 /**
614 * Theme the attachment form.
615 * Note: required to output prefix/suffix.
616 */
617 function theme_webfm_attach_attached_form($form) {
618 $output = drupal_render($form);
619 return $output;
620 }
621
622 /**
623 * Get and theme node attachments
624 */
625 function webfm_attach_box() {
626 if (arg(0) == 'node' && is_numeric(arg(1)) && !arg(2)) {
627 $node = node_load(arg(1));
628 }
629 $files = webfm_get_attachments($node->nid);
630 return theme('webfm_attachments', $files);
631 }
632
633 /**
634 * Implementation of hook_theme
635 */
636 function webfm_theme() {
637 return array(
638 'webfm_browser' => array(
639 'arguments' => array('links' => NULL, 'upload' => NULL),
640 'template' => 'webfm-browser',
641 ),
642 'webfm_attachments' => array(
643 'file' => 'webfm_theme.inc',
644 'arguments' => array('files'),
645 ),
646 'webfm_popup' => array(
647 'arguments' => array('content' => ''),
648 'template' => 'webfm-popup',
649 ),
650 );
651 }
652
653 /**
654 * Helper func to associate the listing icon with the mime type
655 */
656 function _webfm_get_icon($ext) {
657 // Try and find appropriate type
658 switch(strtolower($ext)) {
659 case 'image/gif':
660 case 'image/png':
661 case 'image/jpg':
662 case 'image/jpeg':
663 case 'image/bmp':
664 case 'image/tiff':
665 case 'jpg':
666 case 'gif':
667 case 'png':
668 case 'jpeg':
669 case 'bmp':
670 case 'tiff':
671 $icon = 'i.gif';
672 break;
673 case 'video/mpeg':
674 case 'video/x-msvideo':
675 case 'avi':
676 $icon = 'avi.gif';
677 break;
678 case 'video/quicktime':
679 case 'mov':
680 $icon = 'qt.gif';
681 break;
682 case 'audio/mpeg':
683 case 'mpeg':
684 case 'mp3':
685 $icon = 'mp3.gif';
686 break;
687 case 'application/pdf':
688 case 'pdf':
689 $icon = 'pdf.gif';
690 break;
691 case 'application/zip':
692 case 'application/x-zip':
693 case 'application/x-gzip':
694 case 'zip':
695 $icon = 'zip.gif';
696 break;
697 case 'application/msword':
698 case 'doc':
699 case 'odt':
700 $icon = 'doc.gif';
701 break;
702 case 'application/vnd.ms-excel':
703 case 'xls':
704 case 'ods':
705 $icon = 'xls.gif';
706 break;
707 case 'application/vnd.ms-powerpoint':
708 case 'pps':
709 case 'ppt':
710 case 'odp':
711 $icon = 'pps.gif';
712 break;
713 default:
714 $icon = 'f.gif';
715 break;
716 }
717 return $icon;
718 }
719
720 function webfm_roles_alter($rid, $name, $op) {
721 if ($op == t('Save role')) {
722 // db_query("UPDATE {role} SET name = '%s' WHERE rid = %d", $form_values['name'], $form_values['rid']);{
723 drupal_set_message(t('The webfm role has been renamed.'));
724 }
725 else if ($op == t('Delete role')) {
726 // db_query('DELETE FROM {role} WHERE rid = %d', $form_values['rid']);
727 // db_query('DELETE FROM {permission} WHERE rid = %d', $form_values['rid']);
728 // Update the users who have this role set:
729 // db_query('DELETE FROM {users_roles} WHERE rid = %d', $form_values['rid']);{
730
731 drupal_set_message(t('The webfm role has been deleted.'));
732 }
733 else if ($op == t('Add role')) {
734 // db_query("INSERT INTO {role} (name) VALUES ('%s')", $form_values['name']);
735 drupal_set_message(t('The webfm role has been added.'));
736 }
737 }
738
739 /**
740 * Check an upload, if it is an image, make sure it fits within the
741 * maximum dimensions allowed.
742 */
743 function _webfm_image(&$file) {
744 $info = image_get_info($file->filepath);
745
746 if($info) {
747 $res = variable_get('webfm_max_resolution', 0);
748 if($res != 0) {
749 list($width, $height) = explode('x', strtolower($res));
750 if($info['width'] > $width || $info['height'] > $height) {
751 // Try to resize the image to fit the dimensions.
752 if(image_get_toolkit() && image_scale($file->filepath, $file->filepath, $width, $height)) {
753 drupal_set_message(t('The image was resized to fit within the maximum allowed resolution of %resolution pixels.', array('%resolution' => variable_get('webfm_max_resolution', 0))));
754 // Clear the cached filesize and refresh the image information.
755 clearstatcache();
756 $info = image_get_info($file->filepath);
757 $file->filesize = $info['file_size'];
758 } else {
759 drupal_set_message(t('The image is too large.'));
760 }
761 }
762 }
763 }
764 }
765
766 /**
767 * Called by upload form submit
768 */
769 function webfm_upload () {
770 global $user;
771
772 //Get the destination path from the edit-webfmuploadpath hidden field in the upload form
773 $json_data = array();
774 $fid = '';
775 if(isset($_POST['webfmuploadpath'])) {
776 $root_dir = (($user->uid == 1) || user_access('administer webfm'))? file_directory_path() : file_directory_path().webfm_get_root_path();
777 $dest = $root_dir.$_POST['webfmuploadpath'];
778 // Save new file uploads to tmp dir.
779 if(($file = file_save_upload('webfm_upload')) != FALSE) {
780 // Scale image uploads.
781 _webfm_image($file);
782 $err_arr = array();
783 if(webfm_upload_validate($file, $err_arr) === TRUE) {
784 // file has been put in temp and we have a valid file object
785 // Cache filepath as $_SESSION var for ajax confirm when name conflict
786 // positive response will swap fid and munged name
787 $upload_path = $dest.'/'.$file->filename;
788 if(is_file($upload_path)) {
789 $file->in_db = ($webfm_file_row = webfm_get_file_record('', $upload_path)) ? TRUE : FALSE;
790 $file->dest = $dest;
791 $_SESSION['temp_upload'] = $file;
792 $json_data['file'] = $file->filename;
793 if($file->in_db) {
794 // Overwrite of an existing file that is in the database
795 // Only admins, file owners or files marked as modifiable by role can be overwritten
796 if(($webfm_file_row->uid == $user->uid) ||
797 user_access('administer webfm') ||
798 webfm_file_mod_access($webfm_file_row)) {
799 $json_data['html'] = webfm_reload_upload('webfm/upload', webfm_version_form($file->filename));
800 } else {
801 drupal_set_message(t('Permission denied to overwrite existing file'), 'error');
802 }
803 } else {
804 // Overwrite of an existing file that is not in the database
805 $msg = '';
806 if(($fid = webfm_version_upload(WEBFM_REPLACE_RENAME, $msg)) !== FALSE) {
807 // file was inserted into the database
808 drupal_set_message($msg);
809 } else {
810 drupal_set_message($msg, 'error');
811 }
812 }
813 } else if(file_move($file, $dest)) {
814 // file was moved to its final destination
815 // Insert file into database
816 if(($fid = webfm_dbinsert_file($file, $db_err)) !== FALSE) {
817 drupal_set_message(t('Upload Success'));
818 } else {
819 file_delete($file->filepath);
820 drupal_set_message($db_err, 'error');
821 }
822 } else {
823 drupal_set_message(t('file_move to %path failed', array('%path' => $dest)), 'error');
824 }
825 } else {
826 foreach($err_arr as $err) {
827 drupal_set_message($err, 'error');
828 }
829 }
830 } else {
831 if(!isset($_FILES['files']) || $_FILES['files']['name']['webfm_upload'] == '') {
832 drupal_set_message(t('Please click "Browse" and select a file to upload before clicking the upload button.'), 'error');
833 }
834 }
835 } else {
836 drupal_set_message(t('Invalid upload path'), 'error');
837 }
838
839 if(!isset($json_data['html']))
840 $json_data['html'] = webfm_reload_upload('webfm/upload');
841 if($fid)
842 $json_data['fid'] = $fid;
843 print drupal_to_js(array('status' => TRUE, 'data' => $json_data));
844 exit();
845 }
846
847 /**
848 * Rebuild upload form for upload iframe
849 */
850 function webfm_reload_upload ($url, $confirm_form = '') {
851 $form = array();
852 if($confirm_form)
853 array_push($form, $confirm_form);
854 array_push($form, webfm_upload_form($url));
855 $form = form_builder('upload_js', $form, $form_state);
856 $output = theme('status_messages') . drupal_render($form);
857 return $output;
858 }
859
860 /**
861 * Ajax post requests
862 */
863 function webfm_ajax () {
864 global $user;
865
866 //3 possible outcomes - the user is either an admin, user or prohibited
867 if(($user->uid == 1) || user_access('administer webfm')) {
868 // Admins have total access
869 $webfm_perm = WEBFM_ADMIN;
870 } else if(user_access('access webfm')) {
871 $webfm_perm = WEBFM_USER;
872 } else {
873 //no feedback
874 exit();
875 }
876
877 $webfm_root_path = webfm_get_root_path();
878 if($webfm_root_path == NULL) {
879 //WebFM root dir must exist
880 webfm_json(array('status' => FALSE, 'err' => t('WebFM root not set')));
881 exit();
882 }
883 $root_dir = ($webfm_perm == WEBFM_ADMIN)? file_directory_path() : file_directory_path().$webfm_root_path;
884
885 if(isset($_POST["action"])) {
886 switch(trim(strtolower($_POST["action"]))) {
887 //Read directory trees
888 case "readtrees":
889 $trees = array();
890 $err = '';
891 if($webfm_perm == WEBFM_ADMIN) {
892 //Build webfm directory tree
893 unset($_SESSION['tree_'.$webfm_root_path]);
894 $trees[0] = webfm_tree($root_dir, $webfm_root_path);
895 } else {
896 //clear static array of roles with webfm access ($webfm_roots cached only for 'read' op)
897 $webfm_roots = webfm_get_root_dirs(TRUE);
898 if(count($webfm_roots)) {
899 foreach($webfm_roots as $key => $sub_root) {
900 //Build webfm directory tree(s) for WEBFM_USER
901 if(!empty($sub_root)) {
902 $sub_root_path = $root_dir.$sub_root;
903 if(is_dir($sub_root_path)) {
904 $current = $sub_root;
905 unset($_SESSION['tree_'.$current]);
906 $trees[$key] = webfm_tree($root_dir, $current);
907 } else {
908 $err .= ' '.$sub_root_path.t(' root dir not found.');
909 }
910 } else {
911 $err .= t('Root directory not set for @role role ', array('@role' => $webfm_access_roles[$key]));
912 }
913 }
914 } else {
915 $err = t('No root directory set in WebFM settings for this role');
916 }
917 if(module_exists('og')) {
918 //clear static array of groups with directories ($webfm_roots cached only for 'read' op)
919 $webfm_group_roots = webfm_get_group_root_dirs(TRUE);
920 if(count($webfm_group_roots)) {
921 foreach ($webfm_group_roots as $key => $sub_root) {
922 //Build webfm directory tree(s) for WEBFM_USER
923 if(!empty($sub_root)) {
924 $sub_root_path = $root_dir.$sub_root;
925 if(is_dir($sub_root_path)) {
926 $current = $sub_root;
927 unset($_SESSION['tree_'.$current]);
928 $trees[$key] = webfm_tree($root_dir, $current);
929 }
930 }
931 }
932 } else {
933 $err = t('No root directory set in WebFM settings for this group');
934 }
935 }
936 }
937
938 if(count($trees)) {
939 webfm_json(array('status' => TRUE, 'tree' => $trees, 'current' => $webfm_root_path, 'admin' => $webfm_perm == WEBFM_ADMIN, 'err' => $err));
940 } else {
941 webfm_json(array('status' => FALSE, 'err' => t('No trees found')));
942 }
943 exit();
944 break;
945
946 //Read directory tree
947 case "readtree":
948 $tree = '';
949 unset($current);
950 if($webfm_perm == WEBFM_ADMIN) {
951 //Build webfm directory tree
952 $current = $webfm_root_path;
953 } else if(isset($_POST["param0"])) {
954 //role root must exist and this user must be a member of that role
955 $webfm_roots = webfm_get_root_dirs();
956 $root_role = trim(rawurldecode($_POST["param0"]));
957 if(($root = variable_get("root_dir_".$root_role, '')) &&
958 (array_key_exists($root_role, $webfm_roots))) {
959 $current = "/".$root;
960 }
961 if(module_exists('og')) {
962 $webfm_group_roots = webfm_get_group_root_dirs();
963 $root_group = trim(rawurldecode($_POST["param0"]));
964 if(($root = variable_get("root_dir_group_". $root_group, '')) &&
965 (array_key_exists($root_group, $webfm_group_roots))) {
966 $current = "/". $root;
967 }
968 }
969 }
970 if(!isset($current)) {
971 webfm_json(array('status' => FALSE, 'data' => t('unknown tree')));
972 exit();
973 break;
974 }
975 if(isset($_POST["param1"]))
976 unset($_SESSION['tree_'.$current]);
977 if(!is_dir($root_dir.$current)) {
978 webfm_json(array('status' => FALSE, 'data' => t('unknown role')));
979 } else {
980 $tree = webfm_tree($root_dir, $current);
981 webfm_json(array('status' => isset($tree) ? TRUE : FALSE, 'tree' => $tree, 'current' => $current, 'admin' => $webfm_perm == WEBFM_ADMIN));
982 }
983 exit();
984 break;
985
986
987 //Read directory set in $_POST["param0"]
988 case "read":
989 if(isset($_POST["param0"])) {
990 $param0 = trim(rawurldecode($_POST["param0"]));
991 if(ereg('\.\.', $param0)) {
992 webfm_json(array('status' => FALSE, 'data' => t('illegal read dir')));
993 exit();
994 }
995
996 if(!is_dir($root_dir.$param0)) {
997 webfm_json(array('status' => FALSE, 'data' => $root_dir.$param0.t(' path does not exist - refresh required')));
998 exit();
999 }
1000
1001 //Build current directory listings
1002 $dirlist = new webfm_build_dir_list($param0, $webfm_perm);
1003 if($dirlist->get_breadcrumb()) {
1004 webfm_json(array('status' => TRUE, 'current' => $param0, 'bcrumb' => $dirlist->get_breadcrumb(), 'dirs' => $dirlist->get_dir_listing(), 'files' => $dirlist->get_file_listing(), 'user' => $user->uid, 'admin' => $webfm_perm == WEBFM_ADMIN));
1005 } else {
1006 //invalid directory
1007 webfm_json(array('status' => FALSE, 'data' => t('invalid dir')));
1008 }
1009 } else {
1010 webfm_json(array('status' => FALSE, 'data' => t('insufficient params')));
1011 }
1012 exit();
1013 break;
1014
1015 case "delete":
1016 // Get path of object to be deleted
1017 if(isset($_POST["param0"])) {
1018 $param0 = trim(rawurldecode($_POST["param0"]));
1019 // prevent any .. shenanigans
1020 if($param0 && !ereg('\.\.', $param0)) {
1021 $source = $root_dir.$param0;
1022
1023 if(is_dir($source)) {
1024 //Only admins can delete directories (and contained files)
1025 if($webfm_perm == WEBFM_ADMIN) {
1026 $err_arr[] = array();
1027 $ret = webfm_delete_dir_recur($source, TRUE, $err_arr);
1028 webfm_json(array('status' => $ret, 'data' => $err_arr));
1029 exit();
1030 break;
1031 }
1032 } else if(is_file($source)) {
1033 $permit = FALSE;
1034 $file = webfm_get_file_record('', $source);
1035 if($webfm_perm == WEBFM_ADMIN) {
1036 // Admins can delete files
1037 $permit = TRUE;
1038 } else if($file) {
1039 if($user->uid == $file->uid || webfm_file_mod_access($file)) {
1040 // File owner can delete the file
1041 // Files marked as modifiable by role can be deleted
1042 $permit = TRUE;
1043 }
1044 }
1045 if($permit) {
1046 // Delete file and file record if in db
1047 $error = "";
1048 $ret = TRUE;
1049 if(@unlink($source)) {
1050 if($file && !webfm_dbdelete_file($file->fid)) {
1051 $error = t('webfm_dbdelete_file() fail for ').$source;
1052 $ret = FALSE;
1053 }
1054 } else if(file_exists($source)) {
1055 $error = $source.t(' could not be deleted');
1056 $ret = FALSE;
1057 }
1058 webfm_json(array('status' => $ret, 'data' => $error));
1059 exit();
1060 break;
1061 }
1062 }
1063 }
1064 webfm_json(array('status' => FALSE, 'data' => t('permission denied')));
1065 } else {
1066 webfm_json(array('status' => FALSE, 'data' => t('insufficient params')));
1067 }
1068 exit();
1069 break;
1070
1071 //Create new directory
1072 case "mkdir":
1073 //Only admins can create directories
1074 if($webfm_perm == WEBFM_ADMIN) {
1075 if(isset($_POST["param0"])) {
1076 $source = $root_dir.trim(rawurldecode($_POST["param0"]));
1077 $dest = t("New_Folder");
1078 $err_arr[] = array();
1079 // third param is right to rename if a dir of same name already
1080 // exixts in current folder
1081 if(($ret = webfm_mkdir($source, $dest, TRUE, $err_arr))!== FALSE) {
1082 $ret = ltrim($ret, $root_dir);
1083 webfm_json(array('status' => TRUE, 'data' => $ret));
1084 } else {
1085 webfm_json(array('status' => FALSE, 'data' => $err_arr));
1086 }
1087 if($ret)
1088 unset($_SESSION['tree_'.$webfm_root_path]);
1089 } else {
1090 webfm_json(array('status' => FALSE, 'data' => t('insufficient params')));
1091 }
1092 } else {
1093 webfm_json(array('status' => FALSE, 'data' => t('permission denied')));
1094 }
1095 exit();
1096 break;
1097
1098 //Move a file or directory (drag and drop)
1099 case "move":
1100 if(isset($_POST["param0"]) && isset($_POST["param1"])) {
1101 $source = $root_dir.trim(rawurldecode($_POST["param0"]));
1102 $dest = $root_dir.trim(rawurldecode($_POST["param1"]));
1103 if(is_dir($source) && ($webfm_perm != WEBFM_ADMIN)) {
1104 //Only admins can manipulate directories
1105 webfm_json(array('status' => FALSE, 'data' => t('permission denied')));
1106 exit();
1107 break;
1108 }
1109 if($source != $dest) {
1110 // prevent any ../ shenanigans
1111 if(!ereg('\.\.', $dest)) {
1112 $err_arr[] = array();
1113 $ret = webfm_move($source, $dest, ($webfm_perm == WEBFM_USER) ? $user->uid : 1, $err_arr);
1114 webfm_json(array('status' => $ret, 'data' => $err_arr));
1115 } else {
1116 webfm_json(