Parent Directory
|
Revision Log
|
Revision Graph
|
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( '"' ,'!' ,'@' ,'#' ,'$' ,'%' ,'^' ,'&' ,'*' ,'(' ,')', | |
| 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 { |