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

Diff of /contributions/modules/disknode/disknode.module

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

revision 1.8, Fri Feb 17 18:36:48 2006 UTC revision 1.8.6.1, Thu May 14 01:06:51 2009 UTC
# Line 1  Line 1 
1  <?php  <?php
2    // $Id$
3    /**
4     * @file
5     * Displays, uploads and attaches files to nodes
6     *
7     * Example: files/motto/base.png
8     *
9     * $filename = 'base.png'
10     * $filepath = 'files/motto/base.png'
11     * $filedir  = 'files/motto/'
12     * $name     = 'base'
13     *
14     * TODO: there are malformed filepaths in files-table. ''files'' does not belong into the filepath-field
15     * TODO: set t() for all titles, and other texts?
16     */
17    
18  // $Id: disknode.module,v 1.7 2006/02/17 18:35:48 elmuerte Exp $  // ini_set('error_reporting', 1);
19    // error_log('This error is from settings.php.');
20    // use file_directory_path() instead of __disknode_getbasedir()
21    
 function disknode_help($section = "admin/help#weblink") {  
   switch ($section) {  
     case "admin/help#disknode":  
       return t("<p>The diskfile module is used to attach files allready on the system to nodes. It's ideal for hosting downloads.</p>");  
     case "admin/modules#description":  
       return t("Allows articles with an associated file");  
     case 'node/add#disknode':  
       return t("Add a new node for a file already on disk. It's ideal for hosting downloads.");  
       break;  
   }  
 }  
22    
23  function disknode_settings() {  /**
24    // Restrict administration of this module   * Implementation of hook_menu()
25    if (!user_access('administer')) {   *
26      return message_access();   * @return array of menu items
27    }   */
28    $form['disknode_base'] = array(  function disknode_menu() {
29      '#type' => 'textfield',    $items = array();
30      '#title' => t('Base directory'),    $items['admin/settings/disknode'] = array(
31      '#default_value' => variable_get('disknode_base', ''),      'title' => 'Disknode',
32      '#size' => 72,      'description' => 'Change Disknode behavior',
33      '#maxlength' => 65535,      'page callback' => 'drupal_get_form',
34      '#description' => t('The base directory in the files directory. This is used for the browser, users can not escape the base directory, but are able to link to files outside the base directory (but not outside the files directory).'),      'page arguments' => array('disknode_settings'),
35        'access callback' => TRUE,
36        'type' => MENU_NORMAL_ITEM,
37    );    );
38    /*    $items['disknode/browse'] = array(
39    $form[] = array(      'page callback' => '_disknode_browse',
40      '#type' => 'fieldset',      'type' => MENU_CALLBACK,
41      '#title' => t('Disknode'),      'access callback' => TRUE,
42      '#description' => t(''),    );
43    );*/    $items['disknode/upload'] = array(
44    return $form;      'page callback' => '_disknode_upload',
45        'type' => MENU_CALLBACK,
46        'access callback' => TRUE,)
47      ;
48      $items['disknode/mkdir'] = array(
49        'page callback' => '_disknode_mkdir',
50        'type' => MENU_CALLBACK,
51        'access callback' => TRUE,
52      );
53      $items['disknode/rmdir'] = array(
54        'page callback' => '_disknode_rmdir',
55        'type' => MENU_CALLBACK,
56        'access callback' => TRUE,
57      );
58      $items['disknode/info'] = array(
59        'page callback' => '_disknode_info',
60        'type' => MENU_CALLBACK,
61        'access callback' => TRUE,
62      );
63      $items['disknode/get'] = array(
64        'page callback' => '_disknode_get',
65        'type' => MENU_CALLBACK,
66        'access callback' => TRUE,
67      );
68      return $items;
69  }  }
70    
71    
72  /**  /**
73   * Implementation of hook_menu().   * Implementation of hook_perm()
74   */   */
75  function disknode_menu($may_cache) {  function disknode_perm() {
76    $items = array();    return array('administer all disknode files');
   if ($may_cache) {  
     $items[] = array(  
       'path' => 'node/add/disknode',  
       'title' => t('disknode'),  
       'access' => user_access('create disknode'));  
     $items[] = array(  
       'path' => 'disknode/browse',  
       'callback' => 'disknode_browse',  
       'type' => MENU_CALLBACK,  
       'access' => user_access('create disknode'));  
     $items[] = array(  
       'path' => 'disknode/get',  
       'callback' => 'disknode_get',  
       'type' => MENU_CALLBACK,  
       'callback arguments' => arg(2),  
       'access' => user_access('access content'));  
     $items[] = array(  
       'path' => 'disknode/upload',  
       'callback' => 'disknode_upload',  
       'type' => MENU_CALLBACK,  
       'access' => user_access('upload files'));  
     $items[] = array(  
       'path' => 'disknode/mkdir',  
       'callback' => 'disknode_mkdir',  
       'type' => MENU_CALLBACK,  
       'access' => user_access('create directory'));  
     $items[] = array(  
       'path' => 'disknode/info',  
       'callback' => 'disknode_info',  
       'type' => MENU_CALLBACK,  
       'access' => user_access('create disknode'));  
     }  
   return $items;  
77  }  }
78    
79  function disknode_link($type, $node = 0, $main = 0) {  
80    $links = array();  /**
81    // Node links for a weblink   * Callback functions for downloads and counter increment
82    if ($type == 'node' && $node->type == 'disknode' && $node->filepath) {   */
83      $links[] = t('Downloads: %counter', array('%counter' => $node->downloads));  function _disknode_get($fid, $fname="") {
84      $links[] = l(t('download', array('%title' => $node->title)), "disknode/get/".$node->fid."/".rawurlencode($node->filename), array("title" => "Download ".$node->filename , "rel" => "nofollow" ), "download")." (".format_size($node->filesize).")";    $fid = intval($fid);
85      $result = db_fetch_object(db_query("SELECT f.filepath, d.counter FROM {files} f LEFT JOIN {downloads} d ON f.fid = d.fid WHERE f.fid = %d", $fid));
86      if (!$result) {
87        drupal_not_found();
88        return;
89    }    }
90    return $links;    if (is_numeric($result->counter)) {
91        db_query("UPDATE {downloads} SET counter = counter + 1 WHERE fid=%d", $fid);
92      }
93      else {
94        db_query("INSERT IGNORE INTO {downloads} (fid, counter) VALUES (%d, 1)", $fid);
95      }
96    //  $url = file_create_url(str_replace("%2F", "/", rawurlencode($result->filepath)));
97      $url = file_create_url($result->filepath);
98      drupal_goto($url);
99  }  }
100    
 function disknode_perm() {  
   return array('download files', 'create disknode', 'edit own disknodes', 'upload files', 'create directory');  
 }  
101    
102  function disknode_node_info() {  /**
103    return array('disknode' => array('name' => t('disknode'), 'base' => 'disknode'));   * Insert list of files attached to the node that is displayed.
104     * hook_nodeapi() is called when the node is beeing prepared
105     *
106     * @param reference $node
107     * @param string $op
108     * @param unknown_type $a3
109     * @param bool $a4
110     */
111    function disknode_nodeapi(&$node, $op, $a3 = NULL, $a4 = NULL) {
112      // Only display if node is displayed
113      // $a4 is TRUE if the full node is displayed as an own page and not only the teaser!
114      switch ($op) {
115        case "view":
116          if ($a4) {
117            $node->content['attachments'] = array(
118              '#value' => _disknode_display_links(&$node),
119              '#weight' => 10,
120            );
121          }
122          break;
123                    case "insert":
124                      // A new node has been created
125        case "update":
126          /**
127           * The user is done editing the node and submits his changes
128           *
129           * We're scanning what files should be attached and delete all old attachments.
130           */
131          // delete all old references according to the given node-id
132          $query =  'DELETE FROM disknode ';
133          $query .= 'WHERE nid="' . $node->nid . '" ';
134          db_query($query);
135          // parse every line, query it, collect file-ids and connect them in 'disknode' table
136          // This regex splits the data from the textarea. Lines are separated be '\r\n'
137          $filepaths = preg_split('/[\r\n]+/', trim($_POST['filepaths']), -1, PREG_SPLIT_NO_EMPTY);
138          foreach ($filepaths as $path) {
139            // To assign the file we need it's file-id
140            $query = 'SELECT f.fid fid FROM files f WHERE f.filepath="' . $path . '" LIMIT 1;';
141            $results = db_query($query);
142            $row = db_fetch_object($results);
143            if ($row == false) {
144              // File is not found in 'files' table und has been added manually and not uploaded
145              drupal_set_message('<strong>' . $path . '</strong> has not been found in the database. It will not appear under your post. Please download the file and upload it again to solve this problem.', 'error');
146            }
147            else {
148              // link file to node by fid - what's why there has to be an entry in the files-table
149              $fid = $row->fid;
150              $query =  'INSERT INTO disknode (fid, nid) VALUES (';
151              $query .= '"' . $fid . '", ';
152              $query .= '"' . $node->nid . '");';
153              db_query($query);
154            }
155          }
156          break;
157        case "delete":
158          // Node is being deleted
159          // Remove any relations to files
160          db_query("DELETE FROM {disknode} WHERE nid=%d", $node->nid);
161          break;
162      }
163  }  }
164    
 function disknode_access($op, $node) {  
   global $user;  
165    
166    switch($op) {  /**
167      case 'view':   * Display the ''files'' box in Insert and Edit forms.
168        return $node->status;   // see book.module for reference   * hook_form_alter() is called when the user requests 'node/add' or 'node/$id/edit'
169     *
170     * @param unknown_type $form
171     * @param unknown_type $form_state
172     * @param unknown_type $form_id
173     * @return unknown
174     */
175    function disknode_form_alter(&$form, &$form_state, $form_id) {
176      // Alter the form if it's any node-form (create, edit), but not if it's a
177      // subscriptions-ui-node-form (which is displayed when viewing a node)
178      if ( endsWith($form_id, "_node_form") && $form['#id'] == 'node-form' ) {
179        $node = $form['nid'];
180        $filepaths = "";
181        if (isset($form_state['node'])) {
182          // If temp data of filepath textarea exist, take it rather than the (maybe) outdated DB records
183          $filepaths = $form_state['node']['filepaths'];
184          }
185        elseif ( isset($node['#value']) ) {
186          // If ''nid'' is set, than we're editing an existing node / otherwise we add content
187          $nid = $node['#value'];
188          // Fetch all files that are already attached to node that is being edited
189    
190          $query  = "SELECT filepath filepath FROM files ";
191          $query .= "JOIN disknode ON disknode.fid = files.fid ";
192          $query .= "WHERE disknode.nid = $nid";
193          $results = db_query($query);
194          while ( $row = db_fetch_object($results) ) {
195            // We only need the filepath here
196            $filepath = $row->filepath;
197            $filepaths .= $filepath . "\n";
198          }
199        }
200        else {
201          $filepaths = "";
202        }
203        // Buiding the fieldset
204        $form['disknode'] = array(
205          '#type' => 'fieldset',
206          '#title' => t('File attachments'),
207          '#collapsible' => TRUE,
208          '#collapsed' => FALSE,
209        );
210        // Building the "Browse" button
211        $form['disknode']['disknode-browse-button'] = array(
212          '#type' => 'button',
213          '#button_type' => 'button',
214          '#attributes' => array('style' => 'display: none;'),
215          '#value' => t('   Browse files on server / upload your own   '),
216        );
217        // Building the textarea "filepaths"
218        $form['disknode']["filepaths"] = array(
219          '#type' => 'textarea',
220          '#title' => t("Files that have been selected for this article"),
221          '#default_value' => trim($filepaths),
222          '#cols' => 80,
223          '#rows' => 5,
224          '#description' => t("Each line represents a file download. Each one is the relative file path in the files directory."),
225        );
226        // Prepare URL for the 'Browse files' button and add JavaScript handler
227        $fbURL = url("disknode/browse", array('query' => "disknodeutil", 'absolute' => TRUE));
228        $jsfile = drupal_get_path('module', 'disknode') .'/disknode.js';
229        drupal_add_js($jsfile);
230        $js = "$(function() {
231          disknodeFiles = new disknodeCallback($('#edit-filepaths').get(0), -1, '$fbURL');
232          $('#edit-disknode-browse-button').show().click(function() {
233            disknodeFiles.openWindow();
234            return false;
235          });});";
236        drupal_add_js($js, 'inline');
237    
238      case 'create':      return $form;
       return user_access("create disknode");  
   
     case 'delete':  
     case 'update':  
       return user_access("edit own disknodes") && ($user->uid == $node->uid);  
239    }    }
240  }  }
241    
 function disknode_form(&$node, &$param) {  
   $form['title'] = array('#type' => 'textfield',  
     '#title' => t('Subject'),  
     '#default_value' => $node->title,  
     '#size' => 60,  
     '#maxlength' => 128,  
     '#required' => TRUE  
   );  
   $form["filepath"] = array(  
     '#type' => 'textfield',  
     '#title' => t("File path"),  
     '#default_value' => $node->filepath,  
     '#size' => 60,  
     '#maxlength' => 65535,  
     '#description' => t("The relative filepath in the files directory") . ($error['filepath'] ? $error['filepath'] : ''),  
     '#attributes' => NULL,  
     '#required' => TRUE,  
   );  
   $form["browsebtn"] = array(  
     '#type' => 'button',  
     '#button_type' => 'button',  
     '#attributes' => array(  
       "onclick" => "window.open('".url("disknode/browse", "disknodeutil", NULL, true)."&selection='+document.getElementById('edit-filepath').value, 'filebrowser', 'width=400, height=600, resizable=yes, scrollbars=yes'); return false;",  
     ),  
     '#value' => 'browse files',  
   );  
   $form['body_filter']['body'] = array(  
     '#type' => 'textarea',  
     '#title' => t("Body"),  
     '#default_value' => $node->body,  
     '#cols' => 60,  
     '#rows' => 10,  
     '#description' => t("Textual description of the file") . ($error['body'] ? $error['body'] : ''),  
   );  
   $form['body_filter']['format'] = filter_form($node->format);  
242    
243    return $form;  /**
244     * This helper function is used by the hook_form_alter() to determine if the name of the form ends with 'node-form'
245     *
246     * @param string $FullStr
247     * @param string $EndStr
248     * @return bool
249     */
250    function endsWith($FullStr, $EndStr) {
251      // Get the length of the end string
252      $StrLen = strlen($EndStr);
253      // Look at the end of FullStr for the substring the size of EndStr
254      $FullStrEnd = substr($FullStr, strlen($FullStr) - $StrLen);
255      // If it matches, it does end with EndStr
256      return $FullStrEnd == $EndStr;
257  }  }
258    
259  function disknode_get($fid, $fname="") {  
260    $result = db_fetch_object(db_query("SELECT f.filepath, d.counter FROM {files} f LEFT JOIN {downloads} d ON f.fid = d.fid WHERE f.fid=%d", $fid));  /**
261    if ($result->counter) {   * Prepare HTML code to display the files that are attached to the node.
262      db_query("UPDATE {downloads} SET counter = counter + 1 WHERE fid=%d", $fid);   * This helper function returns the code to hook_nodeapi()
263     *
264     * @param class $node
265     * @return string
266     */
267    function _disknode_display_links(&$node) {
268      $PREFIX = '<hr /><p><h2>Attachments:</h2></p><p><ul class="links">';
269      $data = "";
270      $POSTFIX .= "</ul></p><br />";
271      // Ask the database if files are attached to the nid that is about to be displayed
272      // 'downloads' table provides the download count
273      $nid = $node->nid;
274      // Query for 'name, path, size and counter' of any attached files
275      //  $query  = "SELECT filename filename, filepath filepath, filesize filesize, counter downloads FROM files ";
276      $query =  'SELECT files.filename filename, files.filepath filepath, files.filesize filesize, downloads.counter downloads, files.fid fid '
277              . 'FROM disknode '
278              . 'LEFT JOIN downloads ON downloads.fid = disknode.fid '
279              . 'LEFT JOIN files ON files.fid = disknode.fid '
280              . "WHERE disknode.nid =\"$nid\"";
281      $results = db_query($query);
282      while ( $row = db_fetch_object($results) ) {
283        $filename = $row->filename;
284        // Build relative path that calls ''get'' callback (needed to increment download counter)
285        $fid = $row->fid;                                                                                             //http://10.0.10.12/gnosis/index.php?q=disknode/get/3720
286        $path = 'disknode/get/' . $fid;
287        // Display filesize human readable.
288        $filesize = format_size($row->filesize);
289        if (isset($row->downloads) && $row->downloads >= 0) {
290          $downloads = $row->downloads;
291        }
292        else {
293          $downloads = 0;
294        }
295        $data .= "<li>" . l($filename, $path) . " (Size: " . $filesize . " - Downloads: " . $downloads . ")</li><br />";
296    }    }
297    else {    // If links present: return HTML code - Otherwise return nothing.
298      db_query("INSERT INTO {downloads} (fid, counter) VALUES (%d, 1)", $fid);    if ($data) {
299        return $PREFIX . $data . $POSTFIX;
300    }    }
   $url = file_create_url(str_replace("%2F", "/", rawurlencode($result->filepath)));  
   if (strstr($url, "?") === false) $url .= "?";  
   else $url .= "&";  
   $url .= "download";  
   header("Location: ".$url);  
   exit();  
301  }  }
302    
303  function disknode_file_download($file) {  
304    if (user_access('download files')) {  /**
305      $result = db_query(db_rewrite_sql("SELECT f.nid, f.* FROM {files} f WHERE filepath = '%s'", 'f'), $file);   * ------------------------------------------------------------------------------------------------------
306      if ($file = db_fetch_object($result)) {   * ------------------------------------------------------------------------------------------------------
307        $name = mime_header_encode($file->filename);   *                                       hook_menu() callbacks
308        $type = mime_header_encode($file->filemime);   * ------------------------------------------------------------------------------------------------------
309        $disposition = preg_match("#(\?|&)download(&|$)#", $_SERVER["REQUEST_URI"]) ? 'attachment' : 'inline';   * ------------------------------------------------------------------------------------------------------
310        return array('Content-Type: '. $type .'; name='. $name,   */
311                     'Content-Length: '. $file->filesize,  /**
312                     'Content-Disposition: '. $disposition .'; filename='. $name);   * This function is provides the 'Browse' view
313     * 1. The JavaScript handler (of the 'Browse files' button) points to ?q=disknode/browse
314     * And then the hook_menu() calls this function
315     *
316     * We first look for all files that are in the current subdirectory. This includes even files in sub-folders,
317     * that we don't want to display. But we need all the fields, that are provided by the 'files'-table in the
318     * database. To display only files in that directory, we use a drupal function, that returns a list of files
319     * in that directory. Having those two information we simply match them and store them either in the array for
320     * directories or for the files. We now have the right entries with all the fields from the DB and they are
321     * devided by type. After merging those arrays the directories are on top and the files are on the bottom.
322     *
323     * TODO: check out if it is really necessary to fetch DBentries. Most data like size and type is found by \
324     *           drupal scan-function
325     * TODO: mention that folders do not appear in the DB!
326     *
327     */
328    function _disknode_browse() {
329      // TODO: display size and downloads in Browse-view (maybe switch to display it as a table to make it easier to read)
330      $title = "Browse files";
331      $filebase = file_directory_path();
332      $breadcrumb = "";
333      // Get current subdirectory from the GET-parameter
334      // It's global to have let the links (Create folder, delete folder, upload) know what folder we have browsed last.
335      global $subdir;
336      $subdir = $_GET["subdir"];
337      // Returns an relative path to the ''files'' directory - in our case it returns just 'files'
338      $subdir = preg_replace("#^" . $filebase . DIRECTORY_SEPARATOR . "?" . "(.*)$#", "\\1", file_create_path($subdir));
339      // If subdir is '.' or '' or 'files' => we are in the files directory
340      if ($subdir == "." || empty($subdir)) {
341        $subdir = file_directory_path();
342      }
343      // Fetch all files that are in the current ''subdir'' (children AND grandchildren are displayed)
344      // Form in ''dbentries'' is: $dbentries[path] = Object (fid, uid, filename, ......)
345      $dbres = db_query("SELECT * FROM {files} WHERE filepath LIKE '".$subdir."%'");
346      while ($entry = db_fetch_object($dbres)) {
347        $dbentries[$entry->filepath] = $entry;
348      }
349      // Two separate Arrays to split according to type (is_dir())
350      $entries_file = array();
351      $entries_dir  = array();
352      // Find all files and folders in the given subdir.
353      // Exclude: . .. CVS
354      $entries = file_scan_directory(file_create_path($subdir), ".*", array(".", "..", "CVS"), 0, false);
355      // uksort() in comparison to ksort() sortes case-insensitive
356      uksort($entries, 'strnatcasecmp');
357      // iterate only over the files/dirs that are acutally in the current dir
358      foreach ($entries as $key => $properties) {
359        $entries[$key]->isdir = is_dir($entries[$key]->filename);
360        // When choosing a file in the root-directory, cut off the 'files' prefix of the filepath
361        // 'files/test.png' will apear as 'test.png'
362        $entries[$key]->filename = preg_replace("#^(".preg_quote($filebase)."/)#", "", $entries[$key]->filename);
363        if (!$entries[$key]->isdir) {
364          // The entry is a file!
365          if (isset($dbentries[$entries[$key]->filename]))
366            // if same object is found in database, map the db-result to the visible files
367            $entries_file[$key]->dbentry = $dbentries[$entries[$key]->filename];
368          else {
369            $entries_file[$key]->dbentry = false;
370          }
371          // copy values from 'mixed array' to 'separated array'
372          $entries_file[$key]->isdir    = $entries[$key]->isdir;
373          $entries_file[$key]->filename = $entries[$key]->filename;
374          $entries_file[$key]->basename = $entries[$key]->basename;
375          $entries_file[$key]->name     = $entries[$key]->name;
376          $entries_file[$key]->filepath = dirname($key);
377        }
378        else {
379          // The file is a directory
380          $entries_dir[$key]->dbentry  = false;
381          $entries_dir[$key]->isdir    = $entries[$key]->isdir;
382          $entries_dir[$key]->filename = $entries[$key]->filename;
383          $entries_dir[$key]->basename = $entries[$key]->basename;
384          $entries_dir[$key]->name     = $entries[$key]->name;
385      }      }
386    }    }
387      unset($dbentries);
388      // Directories on top, files on the bottom
389      $entries = array_merge($entries_dir, $entries_file);
390      // Prepare HTML code here to inject it into the template afterwards
391      // By doing this we only need one template instead of a hole bunch
392      if (!is_writable(file_create_path($subdir))) {
393        $dirmodlink = array("class" => "disabled", "title" => "Directory is not writeable");
394      }
395      else {
396        $dirmodlink = null;
397      }
398      $html = '<ul>';
399      // When we are in a subdir display '..' for going one level up in the hierachy
400      if ( $subdir != file_directory_path() ) {
401        $html .= "<li>" . l("..", "disknode/browse", array('attributes' => array('class' => ''),
402                                                                                                       'query' => "subdir=".dirname($subdir),
403                                                           'absolute' => true)) . "</li>";
404      }
405      // Iterate through all files and directorys; they already are sorted alphabetically
406      $myid = 0;
407      foreach ($entries as $entry) {
408          // Entry is directory
409          if ($entry->isdir) {
410              $html .= "<li title=\"Browse directory\" class=\"disknode-entry\"><a href=\""
411                    . url("disknode/browse", array('query' => "subdir=".$entry->filename, 'absolute' => true))
412                    . "\">$entry->basename</a></li>\n";
413          }
414          // Entry is a file
415          else {
416              $__temp = addslashes($entry->filename);
417              $html .= "<li class=\"disknode-entry\"><span onclick=\"selectPath('"
418                    . addslashes($entry->filename) . "', " . $myid
419                    . ")\" "
420                    . "title=\"Select this file\" "
421                    . "id=\"" . $myid++ . "\" "
422                    . ">".$entry->basename."</span><span class=\"filecontrols\">"
423                    . l("info", "disknode/info", array('query' => "target=".rawurlencode($entry->filename), 'absolute' => true))
424                    // target = '_blank' opens the link in a new browser window
425                    . l("preview", file_create_url($entry->filename), array('attributes' => array('class' => 'disknode-preview'),
426                                                                                                                                    'absolute' => true,
427                                                                            ))
428                    . "</span></li>\n";
429          }
430      }
431      $html .= "</ul>";
432      // Call display_template function that handles the rest.
433      _disknode_display_template($title, $subdir, $html);
434  }  }
435    
 function __sanitize_subdir()  
 {  
   $subdir = $_GET["subdir"];  
   if ($subdir == "." || empty($subdir) || (strcmp($subdir, variable_get('disknode_base', '')) < 0)) $subdir = variable_get('disknode_base', '');  
   return $subdir;  
 }  
436    
437  function disknode_browse()  /**
438  {   * This callback function is called when ?q=disknode/info is requested
439    $title = "Browse files";   * (see the hook_menu())
440    $filebase = file_create_path();   *
441    if (!empty($_GET["selection"]))   * The following variables are accessible withing the template-file:
442    {   * - $title
443     * - $disknode_breadcrumb provides the filename in this case
444     * - $file
445     * - $file->filename; $file->size; $file->filepath; $file->mimetype; $file->filetime
446     * - $file->nodes
447     * - $file->nodes->link (string with HTML code)
448     * - $file->nodes->author (string)
449     */
450    function _disknode_info() {
451      global $title;
452      $title = "File information";
453      if (!empty($_GET["selection"])) {
454      $_GET["subdir"] = dirname($_GET["selection"]);      $_GET["subdir"] = dirname($_GET["selection"]);
455    }    }
456    $subdir = __sanitize_subdir();    $subdir = $_GET["subdir"];
457    $entries = file_scan_directory(file_create_path($subdir), ".*", array(".", "..", "CVS"), 0, false);    global $disknode_file;
458    ksort($entries);    $disknode_file = new StdClass();
459    foreach ($entries as $k => $_)    $disknode_file->filepath = $_GET["target"];
460    {    $disknode_file->filename = $file->filepath;
461      $entries[$k]->isdir = is_dir($entries[$k]->filename);    $fp = file_create_path($disknode_file->filepath);
462      $entries[$k]->filename = preg_replace("#^(".preg_quote($filebase)."/)#", "", $entries[$k]->filename);    $disknode_file->filetime = filemtime($fp);
463      if (!$entries[$k]->isdir) $entries[$k]->dbentry = db_fetch_object(db_query("SELECT * FROM {files} WHERE filepath = '".$entries[$k]->filename."'"));    $disknode_file->size = filesize($fp);
464      else $entries[$k]->dbentry = false;    $disknode_file->mimetype = file_get_mimetype($fp);
465    
466      $results = db_query('SELECT u.name FROM files f JOIN users u ON u.uid = f.uid WHERE filepath = "%s"', $disknode_file->filepath);
467      $disknode_file->fileowner = db_fetch_object($results)->name;
468      if (!__disknode_validate_fileaccess($disknode_file->filepath)) {
469        echo theme_status_messages();
470        return;
471    }    }
472    include(dirname(__FILE__)."/disknode.browse.tpl.inc");    // Find nodes that are attached to a file, found by filepath
473      $disknode_file->nodes = array();
474      // This query returns id, title and author of nodes that are attached to the given file
475      // The JOIN with the disknode table is not a LEFT JOIN to have no results when there is no entry instead of empty entries.
476      $query  = 'SELECT d.nid nid, n.title title, u.name author FROM files f ';
477      $query .= 'JOIN disknode d ON f.fid = d.fid ';
478      $query .= 'LEFT JOIN node n ON n.nid = d.nid ';
479      $query .= 'LEFT JOIN users u ON u.uid = n.uid ';
480      $query .= "WHERE f.filepath = '%s'";
481      // Set 'files' as a prefix, because in the DB it's stored with the prefix as well
482      $res = db_query($query, $disknode_file->filepath);
483      while ( $node = db_fetch_object($res) ) {
484        if (count($node->author)) {
485          $node->link = l($node->title, "node/".$node->nid, $options = array('attributes' => array('class' => 'disknode-associated-nodes'), 'absolute' => true)) . ' by ' . $node->author;
486        }
487        else {
488          $node->link = l($node->title, "node/".$node->nid, $options = array('attributes' => array('class' => 'disknode-associated-nodes'), 'absolute' => true));
489        }
490        $disknode_file->nodes[] = $node;
491      }
492      if (isset($_POST['op'])) {
493        switch ($_POST['op']) {
494          case "move":
495            __disknode_info_move($disknode_file);
496            break;
497          case "copy":
498            __disknode_info_copy($disknode_file);
499            break;
500          case "delete":
501            __disknode_info_delete($disknode_file);
502            break;
503        }
504      }
505      // Generate the breadcrumb, what is normally done by _disknode_display_template()
506      $subdir = dirname($fp);
507      global $disknode_breadcrumb;
508      $relpath = "";
509      if (!empty($subdir)) {
510        $_r = "/".$subdir;
511      }
512      else {
513        $_r = "";
514      }
515      foreach (explode("/", $_r) as $elm) {
516          if ($elm == "") $dirtitle = "root";
517          else $dirtitle = $elm;
518          if (!empty($relpath)) $relpath .= "/";
519          $relpath .= $elm;
520          if (strcmp($relpath, file_directory_path()) < 0) {
521            $breadcrumb .= $dirtitle;
522          }
523          else {
524            $breadcrumb .= l($dirtitle, 'disknode/browse', array('query' => "subdir=".$relpath, 'absolute' => true));
525          }
526          $breadcrumb .= " / ";
527      }
528      // Display the filename in the breadcrumb
529      $disknode_breadcrumb = $breadcrumb . " " . file_check_path($fp);
530      // In this case we call an own template. If we would prepare the view in this file, it would get too messy.
531      module_load_include('inc', 'disknode', 'disknode.info.tpl');
532  }  }
533    
 function disknode_insert($node) {  
   $fid = db_next_id('{files}_fid');  
   db_query("INSERT INTO {files} (fid, nid, filename, filepath, filemime, filesize, list) VALUES (%d, %d, '%s', '%s', '%s', '%s', %d)",  
     $fid, $node->nid, $node->filename, $node->filepath, $node->filemime, $node->filesize, 0);  
 }  
534    
535  function disknode_update($node) {  function __disknode_info_move(&$file) {
536    db_query("UPDATE {files} SET filename = '%s', filepath = '%s', filemime = '%s', filesize = '%s' WHERE nid = '%d'",    if (!__disknode_validate_fileaccess($file->filepath, DISKNODE_OP_MOVE)) return;
537      $node->filename, $node->filepath, $node->filemime, $node->filesize, $node->nid);    $newname = trim($_POST["newname"]);
538  }    if (strcmp($newname, $file->filepath) == 0) {
539        drupal_set_message(t("No change made since the new name is identical to the current name"), 'error');
540        return;
541      }
542      if (!__disknode_validate_fileaccess($newname, DISKNODE_OP_MOVE)) return;
543    
544  function disknode_delete(&$node) {    $source  = file_create_path($file->filepath);
545    db_query("DELETE FROM {files} WHERE nid=%d", $node->nid);    $newname = file_create_path($newname);
546      if (!is_dir(dirname($newname))) {
547        drupal_set_message(t("Target directory doesn't exist."), 'error');
548        return;
549      }
550      if (file_move($source, $newname, FILE_EXISTS_ERROR)) {
551        $source = preg_replace("#^".file_create_path("")."/(.*)$#", "\\1", $source);
552        db_query("UPDATE {files} SET filepath = '%s', filename = '%s' WHERE filepath = '%s'", $source, basename($source), $file->filepath);
553        $file->filepath = $source;
554        drupal_set_message(t("Moved file to %loc", array("%loc" => $file->filepath)));
555        if (dirname($file->filepath) == '.') {
556          $goto_subdir = '';
557        }
558        else {
559          $goto_subdir = dirname($file->filepath);
560        }
561        drupal_goto("disknode/browse", "subdir=" . $goto_subdir);
562      }
563  }  }
564    
565  function disknode_submit(&$node) {  
566    $fp = file_create_path($node->filepath);  function __disknode_info_copy(&$file) {
567    $node->filename = basename($node->filepath);    if (!__disknode_validate_fileaccess($file->filepath, DISKNODE_OP_COPY)) {
568    $node->filesize = filesize($fp);      return;
569    $node->filemime = mime_content_type($fp);    }
570      $newname = trim($_POST["newname"]);
571      if (!__disknode_validate_fileaccess($newname, DISKNODE_OP_COPY)) {
572        return;
573      }
574      $source = file_create_path($file->filepath);
575      $filepath = $newname;
576      $newname = file_create_path($newname);
577      // Take the last part of the path (filename)
578      $filename = array_slice(explode('/', $filepath), -1, 1);
579      $filename = $filename[0];
580      if (!is_dir(dirname($newname))) {
581        drupal_set_message(t("Target directory doesn't exist."), 'error');
582        return;
583      }
584      if (file_copy($source, $newname, FILE_EXISTS_ERROR)) {
585        $source = preg_replace("#^".file_create_path("")."/(.*)$#", "\\1", $source);
586        drupal_set_message(t("Copied %orig to %new", array("%new" => $source, "%orig" => $file->filepath)));
587    
588        // Save it to the database
589        $file = new StdClass();
590                // fid
591                $file->uid = user_uid_optional_to_arg('');
592                $file->filename = $filename;
593                $file->filepath = $newname;
594                $fp = file_create_path($disknode_file->filepath);
595                $file->filemime = file_get_mimetype(realpath($fp));
596                $file->size = filesize(realpath($fp));
597                $file->filetime = filemtime($fp);
598                echo "";
599    
600                $query = 'INSERT INTO files (uid, filename, filepath, filemime, filesize, status, timestamp) VALUES ('
601                       . '"' . $file->uid . '", '
602                       . '"' . $file->filename . '", '
603                       . '"' . $file->filepath . '", '
604                       . '"' . $file->filemime . '", '
605                       . '"' . $file->size . '", '
606                       . '"1", ' //status
607                       . '"' . $file->filetime . '" ' //timestamp
608                       . ');';
609               db_query($query);
610    
611        if (dirname($newname) == '.') {
612          $goto_subdir = '';
613        }
614        else {
615          $goto_subdir = dirname($newname);
616        }
617        drupal_goto("disknode/browse", "subdir=" . $goto_subdir);
618      }
619  }  }
620    
621  function disknode_load(&$node) {  
622    $result = db_fetch_object(db_query("SELECT f.fid, f.filename, f.filepath, f.filesize, f.filemime, d.counter FROM {files} f LEFT JOIN {downloads} d ON f.fid = d.fid WHERE nid=%d", $node->nid));  function __disknode_info_delete(&$file) {
623    $node->fid = $result->fid;    // Check if the user has priviledges to delete this files
624    $node->filename = $result->filename;    if (!__disknode_validate_fileaccess($file->filepath, DISKNODE_OP_DELETE)) {
625    $node->filepath = $result->filepath;      return;
626    $node->filesize = $result->filesize;    }
627    $node->filemime = $result->filemime;    if (intval($_POST["yesimsure"]) != 1) {
628    $node->downloads = intval($result->counter);      drupal_set_message(t("Please check 'I am sure' to delete the file."), 'error');
629        return;
630      }
631      $result = db_query("SELECT f.fid, f.uid FROM {files} f WHERE filepath = '%s'", $file->filepath);
632      while ($res = db_fetch_object($result)) {
633        if (!_disknode_validate_ownership($res->uid)) {
634          // If you don't get permission. Break up right here.
635          drupal_set_message('You are not the owner of this file, therefore you can not modify it.', 'error');
636          drupal_goto("disknode/browse", "subdir=" . dirname($file->filepath));
637        }
638        // Delete rows in all three tables that contain the file-id
639        db_query("DELETE FROM {downloads} WHERE fid=%d", $res->fid);
640        db_query("DELETE FROM {files} WHERE fid=%d", $res->fid);
641        db_query("DELETE FROM {disknode} WHERE fid=%d", $res->fid);
642      }
643      $fp = file_create_path($file->filepath);
644      file_delete($fp);
645      drupal_set_message(t("File '%name' deleted.", array("%name" => $file->filepath)));
646      if (dirname($file->filepath) == '.') {
647        $goto_subdir = '';
648      }
649      else {
650        $goto_subdir = dirname($file->filepath);
651      }
652      drupal_goto("disknode/browse", "subdir=" . $goto_subdir);
653  }  }
654    
655  function disknode_upload() {  
656    $title = "Upload file";  /**
657    $subdir = __sanitize_subdir();   * Fill the template with a form for creating folders and handle errors.
658    if ($file = file_check_upload('file')) {   *
659      $dest = $subdir."/".$file->filename;   */
660      $file = file_save_upload('file', $dest, $_POST["edit"]["overwrite1"]=="1"?FILE_EXISTS_REPLACE:FILE_EXISTS_ERROR);  function _disknode_mkdir() {
661      if ($file) {    $title = "Create directory";
662        drupal_set_message("File saved to $file->filepath", 'status');    if (!empty($_GET["selection"])) {
663        $_GET["subdir"] = dirname($_GET["selection"]);
664      }
665      global $subdir;
666      $subdir = $_GET["subdir"];
667      $dirparam = $_POST['dirname']; // get the value from form (new way)
668      if (!empty($dirparam)) {
669        if (!empty($subdir)) {
670          $subdir .= "/";
671        }
672        $dirname = file_create_path($subdir.$dirparam);
673        if (!file_check_directory($dirname , FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS)) {
674          // Creation failed
675          drupal_set_message( t("Failed to create\\update %dirname", array("%dirname" => $dirname)), 'error' );
676      }      }
677      else {      else {
678        drupal_set_message("Failed to save $dest", 'error');        // Folder has been created successfully
679          drupal_goto("disknode/browse", "subdir=" . $dirname);
680      }      }
681    }    }
682    if (!empty($_POST["edit"]["url"])) {    $form .= drupal_get_form('_disknode_mkdir_form');
683      $file = _disknode_downloadfile($_POST["edit"]["url"]);    if (!is_writable(file_create_path($subdir))) {
684      if (empty($file->error))      drupal_set_message("$subdir is not writeable", 'error');
685      {    }
686        $bname = preg_replace("#^(.*)(\?(.*))?$#iU", "\\1", basename($_POST["edit"]["url"]));    // Call display_template function that handles the rest.
687        $dest = $subdir."/".$bname;    _disknode_display_template($title, $subdir, $form);
688        if (file_move($file, $dest, $_POST["edit"]["overwrite2"]=="1"?FILE_EXISTS_REPLACE:FILE_EXISTS_ERROR)) {  }
689          drupal_set_message("File saved to $file->filepath");  
690    
691    function _disknode_rmdir() {
692      $title = "Remove directory";
693      if (!empty($_GET["selection"])) {
694        $_GET["subdir"] = dirname($_GET["selection"]);
695      }
696      global $subdir;
697      $subdir = $_GET["subdir"];
698      if (file_directory_path() == $subdir) {
699        drupal_set_message(t("You can not remove the base directory"), 'error');
700      }
701      else {
702        if (!empty($_POST["iamsure"])) {
703          if (count(file_scan_directory($subdir, ".*", array(".", ".."), 0, false)) > 0) {
704            drupal_set_message(t("Failed to remove folder %dirname. Folder is not empty.", array("%dirname" => $subdir)), 'error');
705            drupal_goto("disknode/browse", "subdir=" . $subdir);
706          }
707          else if (!rmdir(file_create_path($subdir))) {
708            drupal_set_message(t("Failed to remove %dirname", array("%dirname" => $subdir)), 'error');
709        }        }
710        else {        else {
711          drupal_set_message("Failed to save $dest", 'error');          $subdir = dirname($subdir);
712            if ($subdir == '.') {
713              $subdir = '';
714            }
715            drupal_set_message(t("Folder %dirname has been deleted.", array("%dirname" => $subdir)), 'status');
716            drupal_goto("disknode/browse", "subdir=" . $subdir);
717        }        }
718      }      }
719      else {     $form .= drupal_get_form('_disknode_rmdir_form');
       drupal_set_message("Download error: ".$file->error, 'error');  
     }  
720    }    }
721      if (!is_writable(file_create_path($subdir))) {
722        drupal_set_message("$subdir is not writeable", 'error');
723      }
724      // Call display_template function that handles the rest.
725      _disknode_display_template($title, $subdir, $form);
726    }
727    
   $form1['file'] = array(  
     '#type' => 'file',  
     '#title' => t('File'),  
     '#size' => 40,  
     '#description' => t('Click "Browse..." to select an file to upload.'),  
   );  
   $form1['overwrite1'] = array(  
     '#type' => 'checkbox',  
     '#title' => t('Overwrite'),  
     '#return_value' => 1,  
     '#default_value' => false,  
     '#description' => t('Overwrite the file if it exists.'),  
   );  
   $form1[] = array(  
     '#type' => 'submit',  
     '#value' => t('Upload'),  
   );  
   
   $form1['#method'] = 'POST';  
   $form1['#action'] = NULL;  
   $form1['#attributes'] = array('enctype' => 'multipart/form-data');  
   $form = drupal_get_form('uploadForm', $form1);  
728    
729    $form2['url'] = array(  function _disknode_rmdir_form() {
730      '#type' => 'textfield',      $form['iamsure'] = array(
731      '#title' => t('Download URL'),        '#type' => 'checkbox',
732      '#default_value' => '',        '#title' => t('Yes, I am absolutely sure I want to do this.'),
733      '#size' => 50,        '#return_value' => 1,
734      '#maxlength' => 65535,        '#default_value' => false,
735      '#description' => t('Enter the url to download the file from. NOTE: this could take a while.'),      );
736    );      $form[] = array(
737    $form2['overwrite2'] = array(        '#type' => 'submit',
738      '#type' => 'checkbox',        '#value' => t('Remove directory'),
739      '#title' => t('Overwrite'),      );
740      '#return_value' => 1,      $form['#method'] = 'POST';
741      '#default_value' => false,          return $form;
     '#description' => t('Overwrite the file if it exists.'),  
   );  
   $form2[] = array(  
     '#type' => 'submit',  
     '#value' => t('Download'),  
   );  
   $form2['#method'] = 'POST';  
   $form .= drupal_get_form('downloadForm', $form2);  
   
   include(dirname(__FILE__)."/disknode.upload.tpl.inc");  
742  }  }
743    
 function disknode_mkdir() {  
   $title = "Create directory";  
   $subdir = __sanitize_subdir();  
   
   if (!empty($_POST["edit"]["dirname"])) {  
     if (!empty($subdir)) $subdir .= "/";  
     $dirname = file_create_path($subdir.$_POST["edit"]["dirname"]);  
     //echo $dirname;  
     if (!file_check_directory($dirname , FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS))  
     {  
       drupal_set_message("Failed to create\\update $dirname", 'error');  
     }  
   }  
744    
745    /**
746     * Callback to make a "Create directory" form
747     *
748     */
749    function _disknode_mkdir_form() {
750    $form['dirname'] = array(    $form['dirname'] = array(
751      '#type' => 'textfield',      '#type' => 'textfield',
752      '#title' => t('Directory name'),      '#title' => t('Directory name'),
753      '#default_value' => '',      '#default_value' => '',
754      '#size' => 50,      '#size' => 50,
755      '#maxlength' => 65535,      '#maxlength' => 65535,
756      '#description' => t('Enter the name of the directory.'),      '#description' => t('Enter the name of the directory.')
757    );    );
758    $form[] = array(    $form[] = array(
759      '#type' => 'submit',      '#type' => 'submit',
760      '#value' => t('Create'),      '#value' => t('Create'),
761    );    );
762    $form['#method'] = 'POST';    $form['#method'] = 'POST';
763    $form = drupal_get_form('your_form_id', $form);    return $form;
   
   include(dirname(__FILE__)."/disknode.upload.tpl.inc");  
764  }  }
765    
 function disknode_info() {  
   $title = "File information";  
   $subdir = __sanitize_subdir();  
766    
767    $file = new StdClass();  /**
768    $file->filename = $_GET["target"];   * Verify that user is in the files-directory
769     * Access to directories on the outside of ''files'' is denied
770    include(dirname(__FILE__)."/disknode.info.tpl.inc");   *
771     * @param string $filepath
772     * @param string $operation
773     * @return bool
774     *
775     * TODO: Do I have to compare strcmp($filepath, file_directory_path() > 0? Is always true otherwise?
776     *               Why is $filepath only current dir-name and not the fullpath?
777     *
778     */
779    function __disknode_validate_fileaccess($filepath, $operation = NULL) {
780      if (strcmp($filepath, file_directory_path()) || $filepath == '.') {
781        return true;
782      }
783      else {
784        drupal_set_message(t("You are not allowed to operate outside the base environment set by the system operator."), 'error');
785        return false;
786      }
787  }  }
788    
789  /*  
790    not OS safe  /**
791  */   * Upload function loads the upload-template and adds a custom form to it
792  if (!function_exists("mime_content_type")) {   *
793    function mime_content_type($f)   */
794    {  function _disknode_upload() {
795      $f = escapeshellarg($f);    $title = 'Upload';
796      return trim( exec("file -bi ".$f) );    if (count($_POST) > 0) {
797        // when it's a POST request when the SUBMIT button has been clicked.
798        $zipfile = false;
799        if (isset($_POST['zipfile']) && $_POST['zipfile'] == '1') {
800          $zipfile = true;
801        }
802        if (isset($_GET['subdir']) && $_GET['subdir'] != '') {
803          $destdir = $_GET['subdir'];
804        }
805        else {
806          drupal_set_message(t("No destination selected"), 'error');
807        }
808        /* TODO Modify the validators array to suit your needs.
809         This array is used in the revised file_save_upload */
810        $validators = array();
811        foreach ($_FILES as $key => $properties) {
812          // Keep original filename to compare and announce in case the filename has been cleaned
813          $orig_filename = $_FILES['files']['name']['file'];
814          // TODO: Find a solution to clean filenames if there is more than one upload at a time
815          $_FILES['files']['name']['file'] = __disknode_clean_filename($properties['name']['file']);
816          $dest = $destdir . "/" . $_FILES['files']['name']['file'];
817    
818          if (!$zipfile) {
819            if (file_exists($dest)) {
820              if (!($_POST["overwrite1"]=="1")) {
821                // Overwrite is not TRUE
822                drupal_set_message(t("File %path already exists. Choose 'overwrite' to replace it.", array("%path" => $file->filepath)), 'error');
823                drupal_goto("disknode/upload", "subdir=" . $destdir . "&lastselection=" . $name);
824              }
825              $filename_without_dirpath = ltrim($dest, file_directory_path() . '/');
826              $result = db_query("SELECT f.uid FROM {files} f WHERE filepath = '%s'", $filename_without_dirpath);
827              while ($res = db_fetch_object($result)) {
828                if (!_disknode_validate_ownership($res->uid)) {
829                  // If you don't get permission. Break up right here.
830                  drupal_set_message('You are not the owner of this file, therefore you can not modify it.', 'error');
831                  drupal_goto("disknode/browse", "subdir=" . $destdir);
832                }
833              }
834            }
835            $file = file_save_upload('file', $validators, $dest, $_POST["overwrite1"]=="1"?FILE_EXISTS_REPLACE:FILE_EXISTS_ERROR);
836            if ($file) {
837              drupal_set_message(t("File saved to %path", array("%path" => $file->filepath)), 'status');
838              $basepath = file_directory_path(); // for us it is: 'files/'
839              // delete the 'files/' prefix from the filepath (the +1 is for the separator '/')
840              if (substr($file->filepath, 0, strlen($basepath . '/')) === $basepath . '/') {
841                $new_filepath = substr( $file->filepath, strlen($basepath . '/'));
842              }
843              else {
844                $new_filepath = $file->filepath;
845              }
846              $query =  'UPDATE files SET ';
847              $query .= 'filepath="'  . $new_filepath  . '", ';
848              $query .= 'status="1" ';
849              $query .= 'WHERE filepath="' . $file->filepath . '" ';
850              db_query($query);
851              $query =  'INSERT IGNORE INTO downloads (fid, counter) VALUES (';
852              $query .= '"'  . $file->fid  . '", ';
853              $query .= '"0");';
854              db_query($query);
855    
856              if ($orig_filename != $_FILES['files']['name']['file']) {
857                drupal_set_message(t('Your filename has been renamed to conform to site policy.'));
858              }
859              if ($_POST['attach'] == '1') {
860                drupal_set_message(t('The file has been attached to your post.'));
861                drupal_goto("disknode/browse", "subdir=" . $destdir . "&uploaded=" . $new_filepath);
862              }
863              else {
864                drupal_goto("disknode/browse", "subdir=" . $destdir);
865              }
866            }
867            else {
868              drupal_set_message(t("Failed to upload %dest. Please check that the chosen file doesn't exeed the maximum file size of %size", array("%dest" => $dest, '%size' => format_size(file_upload_max_size()))), 'error');
869              drupal_goto("disknode/upload", "subdir=" . $destdir);
870            }
871          }
872        else {
873            // Is it really a ZIP file that has been uploaded?
874            // if ($_FILES['files']['type']['file'] != 'application/zip') {
875            //   drupal_set_message(t('Uploaded file is not a ZIP file. Please select a ZIP file or deselect the \'ZIP archive\' checkbox'), 'error');
876            //   drupal_goto("disknode/upload", "subdir=" . $destdir);
877            // }
878    
879            // Path for ZIP extraction
880            $zipdest = file_create_path($dest . '/');
881            $retval = file_check_directory($zipdest, 0);
882            // file_check_directory() returns FALSE, if the path does not exists and TRUE if there is already a folder with that name.
883            if ($retval) {
884                // Folder already exists -> Generate new folder name
885                $zipdest = $zipdest . date("_Y-n-j_H-i-s");
886            }
887            // No matter if we had to change the folder's name or not - now it is the time to create that folder
888            file_check_directory($zipdest, FILE_CREATE_DIRECTORY);
889            $zipfile = $zipdest . '/' . $_FILES['files']['name']['file'];
890            $file = file_save_upload('file', $validators, $zipdest, FILE_EXISTS_ERROR);
891            if ($file) {
892              // If we have a file object, the upload was successful
893              //$full_path_to_zipfile = realpath($zipfile);
894                                            $full_path_to_zipfile = $zipfile;
895              // Open the zip file
896              $zip = new ZipArchive;
897              if ($zip->open($full_path_to_zipfile) === TRUE) {
898                $names = array();
899                $i = 0;
900                // Iterate above all names and throw all files out that are in subdirs
901                while ($zip->getNameIndex($i) != NULL) {
902                  $temp = $zip->getNameIndex($i);
903                  // If a file path contains a '/' than it is in a subdir
904                  if  ( strpos($zip->getNameIndex($i), '/') == false ) {
905                    $names[] = $zip->getNameIndex($i);
906                  }
907                  $i++;
908                }
909                // Extract all files that has been chosen
910                $zip->extractTo($zipdest, $names);
911                // Close the ZIP file
912                $zip->close();
913              }
914    
915              // Delete ZIP file and deregister from database
916              $result = db_query("SELECT f.fid FROM {files} f WHERE filepath = '%s'", $file->filepath);
917              while ($res = db_fetch_object($result)) {
918                // Delete rows in all three tables that contain the file-id
919                db_query("DELETE FROM {downloads} WHERE fid=\"%d\"", $res->fid);
920                db_query("DELETE FROM {files} WHERE fid=\"%d\"", $res->fid);
921                db_query("DELETE FROM {disknode} WHERE fid=\"%d\"", $res->fid);
922              }
923              $fp = file_create_path($zipfile);
924              file_delete($fp);
925              drupal_set_message(t("File '%name' deleted.", array("%name" => $file->filepath)));
926    
927              // TODO: clean filenames
928    
929              // Register all files in the database
930    
931              foreach ($names as $name) {
932                $file = new StdClass();
933                // fid
934                $file->uid = user_uid_optional_to_arg('');
935                $file->filename = $name;
936    
937                $basepath = file_directory_path(); // for us it is: 'files/'
938                $file->filepath = $zipdest . '/' . $name;
939                // delete the 'files/' prefix from the filepath (the +1 is for the separator '/')
940                if (substr($file->filepath, 0, strlen($basepath . '/')) === $basepath . '/') {
941                  $file->filepath = substr( $file->filepath, strlen($basepath . '/'));
942                }
943    
944                $fp = file_create_path($file->filepath);
945                $file->filemime = file_get_mimetype($fp);
946                $file->size = 0; //filesize($fp);
947                $file->filetime = 0; //filemtime($fp);
948                echo "";
949    
950                $query = 'INSERT INTO files (uid, filename, filepath, filemime, filesize, status, timestamp) VALUES ('
951                       . '"' . $file->uid . '", '
952                       . '"' . $file->filename . '", '
953                       . '"' . $file->filepath . '", '
954                       . '"' . $file->filemime . '", '
955                       . '"' . $file->size . '", '
956                       . '"1", ' //status
957                       . '"' . $file->filetime . '" ' //timestamp
958                       . ');';
959               db_query($query);
960               }
961    
962             }
963                drupal_goto("disknode/browse", "subdir=" . $destdir);
964            }
965          }
966        }
967      else {
968        // No upload is happening. Display the upload form!
969        if (!empty($_GET["selection"])) {
970          $_GET["subdir"] = dirname($_GET["selection"]);
971        }
972        $subdir = $_GET["subdir"];
973        $htmldata = drupal_get_form('_disknode_upload_form');
974        // Load the upload-template
975        _disknode_display_template($title, $subdir, $htmldata);
976    }    }
977  }  }
978    
 function _disknode_downloadfile($url){  
   define("DOWNLOAD_CHUNK", 8192);  
979    
980    $result = new StdClass();  function _disknode_upload_form() {
981    $result->url = $url;      $form1['file'] = array(
982    $result->size = 0;        '#type' => 'file',
983    $result->error = "";        '#title' => t('File'),
984          '#size' => 40,
985        // TODO: IMPORTANT - display the last file selected....!
986          '#default_value' => t($_GET['subdir'] . $_GET['lastselection']),
987          '#description' => t('Click "Browse..." to select an file to upload.'),
988        );
989        $form1['upload_max_size'] = array(
990          '#value' => '<p>'. t('The maximum file size per upload is set to %size.', array('%size' => format_size(file_upload_max_size()))).'</p>'
991        );
992        $form1['attach'] = array(
993          '#type' => 'checkbox',
994          '#title' => t('Attach to current article'),
995          '#return_value' => 1,
996          '#default_value' => true,
997          '#description' => t('Hit this checkbox to attach the files you upload directly to the article you are editing.'),
998        );
999        $form1['overwrite1'] = array(
1000          '#type' => 'checkbox',
1001          '#title' => t('Overwrite'),
1002          '#return_value' => 1,
1003          '#default_value' => false,
1004          '#description' => t('Overwrite the file if it exists.'),
1005        );
1006        $form1['zipfile'] = array(
1007          '#type' => 'checkbox',
1008          '#title' => t('This upload is a ZIP archive'),
1009          '#return_value' => 1,
1010          '#default_value' => false,
1011          '#description' => t('Check this checkbox to upload an archive that contains a bunch of files. The files will be extracted after the upload succeeded and they will all appear in the selected directory. <br />'),
1012        );
1013        $form1[] = array(
1014          '#type' => 'submit',
1015          '#value' => t('Upload'),
1016          '#size' => 300,
1017        );
1018        $form1['#method'] = 'POST';
1019        $form1['#action'] = NULL;
1020        $form1['#attributes'] = array('enctype' => 'multipart/form-data');
1021      return $form1;
1022    }
1023    
1024    
1025    function __disknode_clean_filename($filename) {
1026      $original = trim($filename);
1027      $code_entities_match = array( '&quot;' ,'!' ,'@' ,'#' ,'$' ,'%' ,'^' ,'&' ,'*' ,'(' ,')',
1028                                                                    '+' ,'{' ,'}' ,'|' ,':' ,'"' ,'<' ,'>' ,'?' ,'[' ,']' ,'' ,
1029                                                                    ';' ,"'" ,',' ,'_' ,'/' ,'*' ,'+' ,'~' ,'`' ,'=' ,' ' ,
1030                                                                    '---' ,'--','--');
1031      $code_entities_replace = array('' ,'-' ,'-' ,'' ,'' ,'' ,'-' ,'-' ,'' ,'' ,'' ,'' ,'' ,
1032                                                                     '' ,'' ,'-' ,'' ,'' ,'' ,'' ,'' ,'' ,'' ,'' ,'' ,'-' ,'-',
1033                                                                     '-' ,'' ,'' ,'' ,'' ,'' ,'-' ,'-' ,'-','-');
1034      $newname = str_replace($code_entities_match, $code_entities_replace, $original);
1035      return $newname;
1036    }
1037    
1038    
1039    $inp = @fopen($url, "rb");  /**
1040    if (!$inp) {   * One function for including always the same template-file
1041      $result->error = "Unable to open ".$url;   * but providing it with different variables which are
1042      drupal_set_message(t($result->error), 'error');   * handed over via hook_preprocessor()
1043      return $result;   *
1044     * @param String $title
1045     * @param String $htmldata
1046     *
1047     */
1048    function _disknode_display_template($title_ = "Disknode", $subdir = "", $htmldata = "") {
1049      // Prepare all variable to be read out by preprocessor function
1050      global $title;
1051      $title = t($title_);
1052      global $disknode_breadcrumb;
1053      $relpath = "";
1054      if (!empty($subdir)) {
1055        $_r = "/".$subdir;
1056    }    }
1057    $result->filepath = tempnam(file_create_path(variable_get('file_directory_temp', FILE_DIRECTORY_TEMP)), "disknode_");    else {
1058    $outp = fopen($result->filepath, "wb");      $_r = "";
   if (!$outp) {  
     fclose($inp);  
     $result->error = "Unable to open temporary file ".$result->filepath;  
     drupal_set_message(t($result->error), 'error');  
     return $result;  
1059    }    }
1060    ignore_user_abort(true);    foreach (explode("/", $_r) as $elm) {
1061    set_time_limit(0); // no limit      if ($elm == "") {
1062          $dirtitle = "root";
1063    while (!feof($inp))      }
1064    {      else {