| 1 |
<?php
|
| 2 |
|
| 3 |
// $Id: disknode.module,v 1.7 2006/02/17 18:35:48 elmuerte Exp $
|
| 4 |
|
| 5 |
function disknode_help($section = "admin/help#weblink") {
|
| 6 |
switch ($section) {
|
| 7 |
case "admin/help#disknode":
|
| 8 |
return t("<p>The diskfile module is used to attach files allready on the system to nodes. It's ideal for hosting downloads.</p>");
|
| 9 |
case "admin/modules#description":
|
| 10 |
return t("Allows articles with an associated file");
|
| 11 |
case 'node/add#disknode':
|
| 12 |
return t("Add a new node for a file already on disk. It's ideal for hosting downloads.");
|
| 13 |
break;
|
| 14 |
}
|
| 15 |
}
|
| 16 |
|
| 17 |
function disknode_settings() {
|
| 18 |
// Restrict administration of this module
|
| 19 |
if (!user_access('administer')) {
|
| 20 |
return message_access();
|
| 21 |
}
|
| 22 |
$form['disknode_base'] = array(
|
| 23 |
'#type' => 'textfield',
|
| 24 |
'#title' => t('Base directory'),
|
| 25 |
'#default_value' => variable_get('disknode_base', ''),
|
| 26 |
'#size' => 72,
|
| 27 |
'#maxlength' => 65535,
|
| 28 |
'#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).'),
|
| 29 |
);
|
| 30 |
/*
|
| 31 |
$form[] = array(
|
| 32 |
'#type' => 'fieldset',
|
| 33 |
'#title' => t('Disknode'),
|
| 34 |
'#description' => t(''),
|
| 35 |
);*/
|
| 36 |
return $form;
|
| 37 |
}
|
| 38 |
|
| 39 |
/**
|
| 40 |
* Implementation of hook_menu().
|
| 41 |
*/
|
| 42 |
function disknode_menu($may_cache) {
|
| 43 |
$items = array();
|
| 44 |
if ($may_cache) {
|
| 45 |
$items[] = array(
|
| 46 |
'path' => 'node/add/disknode',
|
| 47 |
'title' => t('disknode'),
|
| 48 |
'access' => user_access('create disknode'));
|
| 49 |
$items[] = array(
|
| 50 |
'path' => 'disknode/browse',
|
| 51 |
'callback' => 'disknode_browse',
|
| 52 |
'type' => MENU_CALLBACK,
|
| 53 |
'access' => user_access('create disknode'));
|
| 54 |
$items[] = array(
|
| 55 |
'path' => 'disknode/get',
|
| 56 |
'callback' => 'disknode_get',
|
| 57 |
'type' => MENU_CALLBACK,
|
| 58 |
'callback arguments' => arg(2),
|
| 59 |
'access' => user_access('access content'));
|
| 60 |
$items[] = array(
|
| 61 |
'path' => 'disknode/upload',
|
| 62 |
'callback' => 'disknode_upload',
|
| 63 |
'type' => MENU_CALLBACK,
|
| 64 |
'access' => user_access('upload files'));
|
| 65 |
$items[] = array(
|
| 66 |
'path' => 'disknode/mkdir',
|
| 67 |
'callback' => 'disknode_mkdir',
|
| 68 |
'type' => MENU_CALLBACK,
|
| 69 |
'access' => user_access('create directory'));
|
| 70 |
$items[] = array(
|
| 71 |
'path' => 'disknode/info',
|
| 72 |
'callback' => 'disknode_info',
|
| 73 |
'type' => MENU_CALLBACK,
|
| 74 |
'access' => user_access('create disknode'));
|
| 75 |
}
|
| 76 |
return $items;
|
| 77 |
}
|
| 78 |
|
| 79 |
function disknode_link($type, $node = 0, $main = 0) {
|
| 80 |
$links = array();
|
| 81 |
// Node links for a weblink
|
| 82 |
if ($type == 'node' && $node->type == 'disknode' && $node->filepath) {
|
| 83 |
$links[] = t('Downloads: %counter', array('%counter' => $node->downloads));
|
| 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).")";
|
| 85 |
}
|
| 86 |
return $links;
|
| 87 |
}
|
| 88 |
|
| 89 |
function disknode_perm() {
|
| 90 |
return array('download files', 'create disknode', 'edit own disknodes', 'upload files', 'create directory');
|
| 91 |
}
|
| 92 |
|
| 93 |
function disknode_node_info() {
|
| 94 |
return array('disknode' => array('name' => t('disknode'), 'base' => 'disknode'));
|
| 95 |
}
|
| 96 |
|
| 97 |
function disknode_access($op, $node) {
|
| 98 |
global $user;
|
| 99 |
|
| 100 |
switch($op) {
|
| 101 |
case 'view':
|
| 102 |
return $node->status; // see book.module for reference
|
| 103 |
|
| 104 |
case 'create':
|
| 105 |
return user_access("create disknode");
|
| 106 |
|
| 107 |
case 'delete':
|
| 108 |
case 'update':
|
| 109 |
return user_access("edit own disknodes") && ($user->uid == $node->uid);
|
| 110 |
}
|
| 111 |
}
|
| 112 |
|
| 113 |
function disknode_form(&$node, &$param) {
|
| 114 |
$form['title'] = array('#type' => 'textfield',
|
| 115 |
'#title' => t('Subject'),
|
| 116 |
'#default_value' => $node->title,
|
| 117 |
'#size' => 60,
|
| 118 |
'#maxlength' => 128,
|
| 119 |
'#required' => TRUE
|
| 120 |
);
|
| 121 |
$form["filepath"] = array(
|
| 122 |
'#type' => 'textfield',
|
| 123 |
'#title' => t("File path"),
|
| 124 |
'#default_value' => $node->filepath,
|
| 125 |
'#size' => 60,
|
| 126 |
'#maxlength' => 65535,
|
| 127 |
'#description' => t("The relative filepath in the files directory") . ($error['filepath'] ? $error['filepath'] : ''),
|
| 128 |
'#attributes' => NULL,
|
| 129 |
'#required' => TRUE,
|
| 130 |
);
|
| 131 |
$form["browsebtn"] = array(
|
| 132 |
'#type' => 'button',
|
| 133 |
'#button_type' => 'button',
|
| 134 |
'#attributes' => array(
|
| 135 |
"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;",
|
| 136 |
),
|
| 137 |
'#value' => 'browse files',
|
| 138 |
);
|
| 139 |
$form['body_filter']['body'] = array(
|
| 140 |
'#type' => 'textarea',
|
| 141 |
'#title' => t("Body"),
|
| 142 |
'#default_value' => $node->body,
|
| 143 |
'#cols' => 60,
|
| 144 |
'#rows' => 10,
|
| 145 |
'#description' => t("Textual description of the file") . ($error['body'] ? $error['body'] : ''),
|
| 146 |
);
|
| 147 |
$form['body_filter']['format'] = filter_form($node->format);
|
| 148 |
|
| 149 |
return $form;
|
| 150 |
}
|
| 151 |
|
| 152 |
function disknode_get($fid, $fname="") {
|
| 153 |
$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));
|
| 154 |
if ($result->counter) {
|
| 155 |
db_query("UPDATE {downloads} SET counter = counter + 1 WHERE fid=%d", $fid);
|
| 156 |
}
|
| 157 |
else {
|
| 158 |
db_query("INSERT INTO {downloads} (fid, counter) VALUES (%d, 1)", $fid);
|
| 159 |
}
|
| 160 |
$url = file_create_url(str_replace("%2F", "/", rawurlencode($result->filepath)));
|
| 161 |
if (strstr($url, "?") === false) $url .= "?";
|
| 162 |
else $url .= "&";
|
| 163 |
$url .= "download";
|
| 164 |
header("Location: ".$url);
|
| 165 |
exit();
|
| 166 |
}
|
| 167 |
|
| 168 |
function disknode_file_download($file) {
|
| 169 |
if (user_access('download files')) {
|
| 170 |
$result = db_query(db_rewrite_sql("SELECT f.nid, f.* FROM {files} f WHERE filepath = '%s'", 'f'), $file);
|
| 171 |
if ($file = db_fetch_object($result)) {
|
| 172 |
$name = mime_header_encode($file->filename);
|
| 173 |
$type = mime_header_encode($file->filemime);
|
| 174 |
$disposition = preg_match("#(\?|&)download(&|$)#", $_SERVER["REQUEST_URI"]) ? 'attachment' : 'inline';
|
| 175 |
return array('Content-Type: '. $type .'; name='. $name,
|
| 176 |
'Content-Length: '. $file->filesize,
|
| 177 |
'Content-Disposition: '. $disposition .'; filename='. $name);
|
| 178 |
}
|
| 179 |
}
|
| 180 |
}
|
| 181 |
|
| 182 |
function __sanitize_subdir()
|
| 183 |
{
|
| 184 |
$subdir = $_GET["subdir"];
|
| 185 |
if ($subdir == "." || empty($subdir) || (strcmp($subdir, variable_get('disknode_base', '')) < 0)) $subdir = variable_get('disknode_base', '');
|
| 186 |
return $subdir;
|
| 187 |
}
|
| 188 |
|
| 189 |
function disknode_browse()
|
| 190 |
{
|
| 191 |
$title = "Browse files";
|
| 192 |
$filebase = file_create_path();
|
| 193 |
if (!empty($_GET["selection"]))
|
| 194 |
{
|
| 195 |
$_GET["subdir"] = dirname($_GET["selection"]);
|
| 196 |
}
|
| 197 |
$subdir = __sanitize_subdir();
|
| 198 |
$entries = file_scan_directory(file_create_path($subdir), ".*", array(".", "..", "CVS"), 0, false);
|
| 199 |
ksort($entries);
|
| 200 |
foreach ($entries as $k => $_)
|
| 201 |
{
|
| 202 |
$entries[$k]->isdir = is_dir($entries[$k]->filename);
|
| 203 |
$entries[$k]->filename = preg_replace("#^(".preg_quote($filebase)."/)#", "", $entries[$k]->filename);
|
| 204 |
if (!$entries[$k]->isdir) $entries[$k]->dbentry = db_fetch_object(db_query("SELECT * FROM {files} WHERE filepath = '".$entries[$k]->filename."'"));
|
| 205 |
else $entries[$k]->dbentry = false;
|
| 206 |
}
|
| 207 |
include(dirname(__FILE__)."/disknode.browse.tpl.inc");
|
| 208 |
}
|
| 209 |
|
| 210 |
function disknode_insert($node) {
|
| 211 |
$fid = db_next_id('{files}_fid');
|
| 212 |
db_query("INSERT INTO {files} (fid, nid, filename, filepath, filemime, filesize, list) VALUES (%d, %d, '%s', '%s', '%s', '%s', %d)",
|
| 213 |
$fid, $node->nid, $node->filename, $node->filepath, $node->filemime, $node->filesize, 0);
|
| 214 |
}
|
| 215 |
|
| 216 |
function disknode_update($node) {
|
| 217 |
db_query("UPDATE {files} SET filename = '%s', filepath = '%s', filemime = '%s', filesize = '%s' WHERE nid = '%d'",
|
| 218 |
$node->filename, $node->filepath, $node->filemime, $node->filesize, $node->nid);
|
| 219 |
}
|
| 220 |
|
| 221 |
function disknode_delete(&$node) {
|
| 222 |
db_query("DELETE FROM {files} WHERE nid=%d", $node->nid);
|
| 223 |
}
|
| 224 |
|
| 225 |
function disknode_submit(&$node) {
|
| 226 |
$fp = file_create_path($node->filepath);
|
| 227 |
$node->filename = basename($node->filepath);
|
| 228 |
$node->filesize = filesize($fp);
|
| 229 |
$node->filemime = mime_content_type($fp);
|
| 230 |
}
|
| 231 |
|
| 232 |
function disknode_load(&$node) {
|
| 233 |
$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));
|
| 234 |
$node->fid = $result->fid;
|
| 235 |
$node->filename = $result->filename;
|
| 236 |
$node->filepath = $result->filepath;
|
| 237 |
$node->filesize = $result->filesize;
|
| 238 |
$node->filemime = $result->filemime;
|
| 239 |
$node->downloads = intval($result->counter);
|
| 240 |
}
|
| 241 |
|
| 242 |
function disknode_upload() {
|
| 243 |
$title = "Upload file";
|
| 244 |
$subdir = __sanitize_subdir();
|
| 245 |
if ($file = file_check_upload('file')) {
|
| 246 |
$dest = $subdir."/".$file->filename;
|
| 247 |
$file = file_save_upload('file', $dest, $_POST["edit"]["overwrite1"]=="1"?FILE_EXISTS_REPLACE:FILE_EXISTS_ERROR);
|
| 248 |
if ($file) {
|
| 249 |
drupal_set_message("File saved to $file->filepath", 'status');
|
| 250 |
}
|
| 251 |
else {
|
| 252 |
drupal_set_message("Failed to save $dest", 'error');
|
| 253 |
}
|
| 254 |
}
|
| 255 |
if (!empty($_POST["edit"]["url"])) {
|
| 256 |
$file = _disknode_downloadfile($_POST["edit"]["url"]);
|
| 257 |
if (empty($file->error))
|
| 258 |
{
|
| 259 |
$bname = preg_replace("#^(.*)(\?(.*))?$#iU", "\\1", basename($_POST["edit"]["url"]));
|
| 260 |
$dest = $subdir."/".$bname;
|
| 261 |
if (file_move($file, $dest, $_POST["edit"]["overwrite2"]=="1"?FILE_EXISTS_REPLACE:FILE_EXISTS_ERROR)) {
|
| 262 |
drupal_set_message("File saved to $file->filepath");
|
| 263 |
}
|
| 264 |
else {
|
| 265 |
drupal_set_message("Failed to save $dest", 'error');
|
| 266 |
}
|
| 267 |
}
|
| 268 |
else {
|
| 269 |
drupal_set_message("Download error: ".$file->error, 'error');
|
| 270 |
}
|
| 271 |
}
|
| 272 |
|
| 273 |
$form1['file'] = array(
|
| 274 |
'#type' => 'file',
|
| 275 |
'#title' => t('File'),
|
| 276 |
'#size' => 40,
|
| 277 |
'#description' => t('Click "Browse..." to select an file to upload.'),
|
| 278 |
);
|
| 279 |
$form1['overwrite1'] = array(
|
| 280 |
'#type' => 'checkbox',
|
| 281 |
'#title' => t('Overwrite'),
|
| 282 |
'#return_value' => 1,
|
| 283 |
'#default_value' => false,
|
| 284 |
'#description' => t('Overwrite the file if it exists.'),
|
| 285 |
);
|
| 286 |
$form1[] = array(
|
| 287 |
'#type' => 'submit',
|
| 288 |
'#value' => t('Upload'),
|
| 289 |
);
|
| 290 |
|
| 291 |
$form1['#method'] = 'POST';
|
| 292 |
$form1['#action'] = NULL;
|
| 293 |
$form1['#attributes'] = array('enctype' => 'multipart/form-data');
|
| 294 |
$form = drupal_get_form('uploadForm', $form1);
|
| 295 |
|
| 296 |
$form2['url'] = array(
|
| 297 |
'#type' => 'textfield',
|
| 298 |
'#title' => t('Download URL'),
|
| 299 |
'#default_value' => '',
|
| 300 |
'#size' => 50,
|
| 301 |
'#maxlength' => 65535,
|
| 302 |
'#description' => t('Enter the url to download the file from. NOTE: this could take a while.'),
|
| 303 |
);
|
| 304 |
$form2['overwrite2'] = array(
|
| 305 |
'#type' => 'checkbox',
|
| 306 |
'#title' => t('Overwrite'),
|
| 307 |
'#return_value' => 1,
|
| 308 |
'#default_value' => false,
|
| 309 |
'#description' => t('Overwrite the file if it exists.'),
|
| 310 |
);
|
| 311 |
$form2[] = array(
|
| 312 |
'#type' => 'submit',
|
| 313 |
'#value' => t('Download'),
|
| 314 |
);
|
| 315 |
$form2['#method'] = 'POST';
|
| 316 |
$form .= drupal_get_form('downloadForm', $form2);
|
| 317 |
|
| 318 |
include(dirname(__FILE__)."/disknode.upload.tpl.inc");
|
| 319 |
}
|
| 320 |
|
| 321 |
function disknode_mkdir() {
|
| 322 |
$title = "Create directory";
|
| 323 |
$subdir = __sanitize_subdir();
|
| 324 |
|
| 325 |
if (!empty($_POST["edit"]["dirname"])) {
|
| 326 |
if (!empty($subdir)) $subdir .= "/";
|
| 327 |
$dirname = file_create_path($subdir.$_POST["edit"]["dirname"]);
|
| 328 |
//echo $dirname;
|
| 329 |
if (!file_check_directory($dirname , FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS))
|
| 330 |
{
|
| 331 |
drupal_set_message("Failed to create\\update $dirname", 'error');
|
| 332 |
}
|
| 333 |
}
|
| 334 |
|
| 335 |
$form['dirname'] = array(
|
| 336 |
'#type' => 'textfield',
|
| 337 |
'#title' => t('Directory name'),
|
| 338 |
'#default_value' => '',
|
| 339 |
'#size' => 50,
|
| 340 |
'#maxlength' => 65535,
|
| 341 |
'#description' => t('Enter the name of the directory.'),
|
| 342 |
);
|
| 343 |
$form[] = array(
|
| 344 |
'#type' => 'submit',
|
| 345 |
'#value' => t('Create'),
|
| 346 |
);
|
| 347 |
$form['#method'] = 'POST';
|
| 348 |
$form = drupal_get_form('your_form_id', $form);
|
| 349 |
|
| 350 |
include(dirname(__FILE__)."/disknode.upload.tpl.inc");
|
| 351 |
}
|
| 352 |
|
| 353 |
function disknode_info() {
|
| 354 |
$title = "File information";
|
| 355 |
$subdir = __sanitize_subdir();
|
| 356 |
|
| 357 |
$file = new StdClass();
|
| 358 |
$file->filename = $_GET["target"];
|
| 359 |
|
| 360 |
include(dirname(__FILE__)."/disknode.info.tpl.inc");
|
| 361 |
}
|
| 362 |
|
| 363 |
/*
|
| 364 |
not OS safe
|
| 365 |
*/
|
| 366 |
if (!function_exists("mime_content_type")) {
|
| 367 |
function mime_content_type($f)
|
| 368 |
{
|
| 369 |
$f = escapeshellarg($f);
|
| 370 |
return trim( exec("file -bi ".$f) );
|
| 371 |
}
|
| 372 |
}
|
| 373 |
|
| 374 |
function _disknode_downloadfile($url){
|
| 375 |
define("DOWNLOAD_CHUNK", 8192);
|
| 376 |
|
| 377 |
$result = new StdClass();
|
| 378 |
$result->url = $url;
|
| 379 |
$result->size = 0;
|
| 380 |
$result->error = "";
|
| 381 |
|
| 382 |
$inp = @fopen($url, "rb");
|
| 383 |
if (!$inp) {
|
| 384 |
$result->error = "Unable to open ".$url;
|
| 385 |
drupal_set_message(t($result->error), 'error');
|
| 386 |
return $result;
|
| 387 |
}
|
| 388 |
$result->filepath = tempnam(file_create_path(variable_get('file_directory_temp', FILE_DIRECTORY_TEMP)), "disknode_");
|
| 389 |
$outp = fopen($result->filepath, "wb");
|
| 390 |
if (!$outp) {
|
| 391 |
fclose($inp);
|
| 392 |
$result->error = "Unable to open temporary file ".$result->filepath;
|
| 393 |
drupal_set_message(t($result->error), 'error');
|
| 394 |
return $result;
|
| 395 |
}
|
| 396 |
ignore_user_abort(true);
|
| 397 |
set_time_limit(0); // no limit
|
| 398 |
|
| 399 |
while (!feof($inp))
|
| 400 |
{
|
| 401 |
$result->size += fwrite($outp, fread($inp, DOWNLOAD_CHUNK));
|
| 402 |
}
|
| 403 |
fclose($inp);
|
| 404 |
fclose($outp);
|
| 405 |
return $result;
|
| 406 |
}
|
| 407 |
|