Revision history for FilesAction


Revision [20302]

Last edited on 2008-11-10 14:06:08 by GlennJackman
Additions:
====detecting php-level disabled uploads====
If you don't control your web server, you might run into the situation where file uploads are disabled in php.ini
http://wush.net/trac/wikka/ticket/825 contains this patch:
106a107,111
> if (! ((bool) ini_get('file_uploads'))) {
> echo "<b>File uploads are disallowed on this server.</b>";
> }
> else
> {
282a288
> }


Revision [19335]

Edited on 2008-01-28 00:15:21 by JavaWoman [Modified links pointing to docs server]

No Differences

Revision [17416]

Edited on 2007-08-15 10:15:51 by JavaWoman [comment on styling upload form (summary: forget it)]
Additions:
~''Not a good solution: it requires JavaScript, and the field itself accepts no (typed) input any more (in a normal file upload field you can type or paste a path - that doesn't work on any of PPK's examples): that beaks basic functionality. The only "frustration" is the lack of styleability of the button - well, too bad, at least it's accessible (provided there's also a label, of course), and that's more important.'' -- JavaWoman


Revision [16897]

Edited on 2007-05-31 23:27:03 by MinusF [Reverted]
Additions:
~&Hillar, can you explain //why// it didn't work for you, and how you solved that? --JavaWoman
===Actual version===
The code below offers a more visually improved layout for this handler and also displays the file size and the date of file upload.
- HeavyK (k m r @ h e a v y k . o r g), 3/27/04
**actions/files.php**
%%(php)
<?php
if (! function_exists('mkdir_r')) {
function mkdir_r ($dir) {
if (strlen($dir) == 0) return 0;
if (is_dir($dir)) return 1;
elseif (dirname($dir) == $dir) return 1;
return (mkdir_r(dirname($dir)) and mkdir($dir,0755));
}
}
if (! function_exists('bytesToHumanReadableUsage')) {
/**
* Converts bytes to a human readable string
* @param int $bytes Number of bytes
* @param int $precision Number of decimal places to include in return string
* @param array $names Custom usage strings
* @return string formatted string rounded to $precision
*/
function bytesToHumanReadableUsage($bytes, $precision = 2, $names = '')
{
if (!is_numeric($bytes) || $bytes < 0) {
return false;
}

for ($level = 0; $bytes >= 1024; $level++) {
$bytes /= 1024;
}

switch ($level)
{
case 0:
$suffix = (isset($names[0])) ? $names[0] : 'Bytes';
break;
case 1:
$suffix = (isset($names[1])) ? $names[1] : 'KB';
break;
case 2:
$suffix = (isset($names[2])) ? $names[2] : 'MB';
break;
case 3:
$suffix = (isset($names[3])) ? $names[3] : 'GB';
break;
case 4:
$suffix = (isset($names[4])) ? $names[4] : 'TB';
break;
default:
$suffix = (isset($names[$level])) ? $names[$level] : '';
break;
}

if (empty($suffix)) {
trigger_error('Unable to find suffix for case ' . $level);
return false;
}

return round($bytes, $precision) . ' ' . $suffix;
}
}
if ($download <> '') {
// link to download a file
if ($text == '') $text = $download;
echo "<a href=\"".$this->href('files.xml',$this->GetPageTag(),'action=download&file='.urlencode($download))."\">".$text."</a>";
} elseif ($this->page AND $this->HasAccess('write') AND ($this->method <> 'print.xml') AND ($this->method <> 'edit')) {
// upload path
if ($this->config['upload_path'] == '') $this->config['upload_path'] = 'files';
$upload_path = $this->config['upload_path'].'/'.$this->GetPageTag();
if (! is_dir($upload_path)) mkdir_r($upload_path);
// upload action
$uploaded = $_FILES['file'];
if ($_REQUEST['action'] == 'upload' AND $uploaded['size'] > 0)
copy ($uploaded['tmp_name'], $upload_path.'/'.$uploaded['name']);
// uploaded files
print "
<table cellspacing=0 cellpadding=0>
<tr>
<td>
 
</td>
<td bgcolor=gray valign=bottom align=center>
<font color=white size=-2>
Attachment
</font>
</td>
<td bgcolor=gray valign=bottom align=center>
<font color=white size=-2>
Size
</font>
</td>
<td bgcolor=gray valign=bottom align=center>
<font color=white size=-2>
Date Added
</font>
</td>
</tr>
";
$dir = opendir($upload_path);
while ($file = readdir($dir)) {
if ($file != '.' && $file != '..') {
$num++;
$delete_link = "<a href=\"".$this->href('files.xml',$this->GetPageTag(),'action=delete&file='.urlencode($file))."\">x</a>";
$download_link = "<a href=\"".$this->href('files.xml',$this->GetPageTag(),'action=download&file='.urlencode($file))."\">".$file."</a>";
$size = bytesToHumanReadableUsage(filesize("$upload_path/$file"));
$date = date("n/d/Y g:i a",filemtime("$upload_path/$file"));
print "
<tr>
<td valign=top align=center>
  
{$delete_link}
  
</td>
<td valign=top>
$download_link
</td>
<td valign=top>
 
<font size=-1 color=gray>
$size
</font>
</td>
<td valign=top>
 
<font size=-1 color=gray>
$date
</font>
</td>
</tr>
";
}
}
closedir($dir);
// print n/a if no files currently exist
if (!$num) print "<tr><td> </td><td colspan=3 align=center><font color=gray size=-1><i>   </i></font></td></tr>";
else print "<tr><td> </td></tr>";
// form
$result = "<form action=\"".$this->href()."\" method=\"post\" enctype=\"multipart/form-data\">\n";
if (!$this->config["rewrite_mode"]) $result .= "<input type=\"hidden\" name=\"wakka\" value=\"".$this->MiniHref()."\">\n";
echo $result;
//<input type="hidden" name="action" value="upload"><input type="file" name="file"><input type="submit" value="+">
echo $this->FormClose();
// close disp table
print "
<tr>
<td>
 
</td>
<td colspan=4 valign=top align=right nowrap>
<i>
$result
<input type=\"hidden\" name=\"action\" value=\"upload\">
<font color=gray size=-2>
add new attachment:
<input type=\"file\" name=\"file\" style=\"padding: 0px; margin: 0px; font-size: 8px; height: 15px\">
<input type=\"Submit\" value=\"+\" style=\"padding: 0px; margin: 0px; font-size: 8px; height: 15px\">
".$this->FormClose()."
</font>
</i>
</td>
</tr>
</table>
";
}
?>
%%
===First version===
==actions/files.php==
%%(php)
<?php
if (! function_exists('mkdir_r')) {
function mkdir_r ($dir) {
if (strlen($dir) == 0) return 0;
if (is_dir($dir)) return 1;
elseif (dirname($dir) == $dir) return 1;
return (mkdir_r(dirname($dir)) and mkdir($dir,0755));
}
}
if ($download <> '') {
// link to download a file
if ($text == '') $text = $download;
echo "<a href=\"".$this->href('files.xml',$this->GetPageTag(),'action=download&file='.urlencode($download))."\">".$text."</a>";
} elseif ($this->page AND $this->HasAccess('write') AND ($this->method <> 'print.xml') AND ($this->method <> 'edit')) {
// upload path
if ($this->config['upload_path'] == '') $this->config['upload_path'] = 'files';
$upload_path = $this->config['upload_path'].'/'.$this->GetPageTag();
if (! is_dir($upload_path)) mkdir_r($upload_path);
// upload action
$uploaded = $_FILES['file'];
if ($_REQUEST['action'] == 'upload' AND $uploaded['size'] > 0)
copy ($uploaded['tmp_name'], $upload_path.'/'.$uploaded['name']);
// form
$result = "<form action=\"".$this->href()."\" method=\"post\" enctype=\"multipart/form-data\">\n";
if (!$this->config["rewrite_mode"]) $result .= "<input type=\"hidden\" name=\"wakka\" value=\"".$this->MiniHref()."\">\n";
echo $result;
?>
<input type="hidden" name="action" value="upload"><input type="file" name="file"><input type="submit" value="+">
<?php
echo $this->FormClose();
// uploaded files
$dir = opendir($upload_path);
while ($file = readdir($dir)) {
if ($file != '.' && $file != '..') {
$delete_link = "<a href=\"".$this->href('files.xml',$this->GetPageTag(),'action=delete&file='.urlencode($file))."\">x</a>";
$download_link = "<a href=\"".$this->href('files.xml',$this->GetPageTag(),'action=download&file='.urlencode($file))."\">".$file."</a>";
print "[ {$delete_link} ] ";
if ($file == $uploaded['name'])
print "<em>{$download_link}</em>\n";
else
print $download_link;
print '<br>';
}
}
closedir($dir);
}
?>
%%
==handlers/page/files.xml.php==
%%(php)
<?php
/* mime stuff take from Paul Southworth */
$mt_f = $this->config['mime_types'];
if ($mt_f == '') $mt_f='mime.types';
/* build an array keyed on the file ext */
if (is_readable($mt_f)) {
$mime_types=array();
/* open our mime.types file for reading */
$mt_fd=fopen($mt_f,"r");
while (!feof($mt_fd)) {
/* pull a line off the file */
$mt_buf=trim(fgets($mt_fd,1024));
/* discard if the line was blank or started with a comment */
if (strlen($mt_buf) > 0) if (substr($mt_buf,0,1) != "#") {
/* make temp array of the mime.types line we just read */
$mt_tmp=preg_split("/[\s]+/", $mt_buf, -1, PREG_SPLIT_NO_EMPTY);
$mt_num=count($mt_tmp);
/* if $mt_num = 1 then we got no file extensions for the type */
if ($mt_num > 1) {
for ($i=1;$i<$mt_num;$i++) {
/* if we find a comment mid-line, stop processing */
if (strstr($mt_tmp[$i],"#")) {
break;
/* otherwise stick the type in an array keyed by extension */
} else {
$mime_types[$mt_tmp[$i]]=$mt_tmp[0];
}
}
/* zero the temporary array */
unset($mt_tmp);
}
}
}
/* close the mime.types file we were reading */
fclose($mt_fd);
} else {
echo "ERROR: unreadable file " . $mt_f . "\n";
}
// upload path
if ($this->config['upload_path'] == '') $this->config['upload_path'] = 'files';
$upload_path = $this->config['upload_path'].'/'.$this->GetPageTag();
if (! is_dir($upload_path)) mkdir_r($upload_path);
// do the action
switch ($_REQUEST['action']) {
case 'download':
$_REQUEST['file'] = urldecode($_REQUEST['file']);
if ($this->HasAccess('read')) {
$path = "{$upload_path}/{$_REQUEST['file']}";
$filename = basename($path);
header('MIME-Version: 1.0');
$afn = split("\.",$filename);
$ext = strtolower($afn[count($afn)-1]);
$mime_type = $mime_types[$ext];
if ($mime_type == '') $mime_type = 'application/octet-stream';
header("Content-Type: {$mime_type}; name=\"{$filename}\"");
header('Content-Length: '. filesize($path));
header("Content-Disposition: filename=\"{$filename}\"");
$fp=fopen($path,'r');
print fread($fp,filesize($path));
fclose($fp);
exit();
}
case 'delete':
if ($this->HasAccess('write')) {
@unlink("{$upload_path}/{$_REQUEST['file']}");
print $this->redirect($this->href());
}
}
?>
%%
Nice.. but shouldn't delete at least check some permissions? ''(answer: I am checking write permission...)''
-- ArnarBirgisson
Why "files.xml"? shouldn't it be "files.php"? ''(answer: .xml actions does not include header and footer)''
(files.xml didn't work, but renaming it to "files.xml.php" helped.)
=> Kommentar::
files-action only works if you copy files.xml and store it as files.xml.php as well as files.xml ??????????
//Jetzt geht es, aber das ist ziemlich irre, weil ::
- files.xml
noch einmal als ::
- files.xml.php
abgespeichert werden muss. ?? es funktioniert .. //
KonradTadesse
----
:: FileUp ::
By the way, having an upload form on a page seems to break the page preview "Store" and "Re-edit" buttons.
''(fixed hidding the form on editing, thanks for your bug information)''
-- Tero
----
Here is the same bug like in ImageAction: the use of ##$vars##. Replace line 11 to 16 in actions/files.php with this:
%%(php)
if ($tokens['download'] ) {
// link to download a file
$text = $this->stripquotes($action_params['download']);
if ($tokens['text'])
{
$text = $this->stripquotes($action_params['text']);
}
echo "<a href=\"".$this->href('files.xml',$this->GetPageTag(),'action=download&file='.urlencode($this->stripquotes($action_params['download'])))."\">".$text."</a>";
}
%%
For the function ##$this->stripquotes## read ImageAction
--SilBaer
----
Fileupload on editing pages see FileUpload
--SilBaer
Fix: Added closing CurlyBrace in last replacement code.
--MarkHissinkMuller
====Code cleanup====
**actions/files.php**
%%(php)
<?php
$output = '';
$output .= '<div class="files">';
//this realy should be in the config
$max_upload_size = 2*1048576;
$allowed_extensions = 'gif|jpeg|jpg|jpe|png|doc|xls|csv|ppt|ppz|pps|pot|pdf|asc|txt|zip|gtar|gz|bz2|tar|rar|vpp|mpp|vsd|mm';
/* $date_format = 'n/d/Y g:i a'; (original) */
/* $date_format = 'd-M-Y H:i'; //01-Feb-2005 05:23 */
$date_format = 'Y-m-d H:i'; //2005-02-01 05:23 (easy javascript table sorting)
// mkdir_r
if (! function_exists('mkdir_r')) {
function mkdir_r ($dir) {
if (strlen($dir) == 0) return 0;
if (is_dir($dir)) return 1;
elseif (dirname($dir) == $dir) return 1;
return (mkdir_r(dirname($dir)) and mkdir($dir,0755));
}
}
// bytesToHumanReadableUsage
if (! function_exists('bytesToHumanReadableUsage')) {
/**
* Converts bytes to a human readable string
* @param int $bytes Number of bytes
* @param int $precision Number of decimal places to include in return string
* @param array $names Custom usage strings
* @return string formatted string rounded to $precision
*/
function bytesToHumanReadableUsage($bytes, $precision = 0, $names = '') {
if (!is_numeric($bytes) || $bytes < 0) {
$bytes = 0;
}

if (!is_numeric($precision) || $precision < 0) {
$precision = 0;
}

if (!is_array($names)) {
/* $names = array(' Bytes',' KB',' MB',' GB',' TB'); //original */
$names = array('B','k','M','G','T','P','E');
}

$level = floor(log($bytes)/log(1024));

$suffix = '';
if ($level < count($names)) {
$suffix = $names[$level];
}

return round($bytes/pow(1024, $level), $precision) . $suffix;
}
}
// error code constants
if (! defined('UPLOAD_ERR_OK')){
define('UPLOAD_ERR_OK', 0);
}
if (! defined('UPLOAD_ERR_INI_SIZE')){
define('UPLOAD_ERR_INI_SIZE', 1);
}
if (! defined('UPLOAD_ERR_FORM_SIZE')){
define('UPLOAD_ERR_FORM_SIZE', 2);
}
if (! defined('UPLOAD_ERR_PARTIAL')){
define('UPLOAD_ERR_PARTIAL', 3);
}
if (! defined('UPLOAD_ERR_NO_FILE')){
define('UPLOAD_ERR_NO_FILE', 4);
}
if (! defined('UPLOAD_ERR_NO_TMP_DIR')){
define('UPLOAD_ERR_NO_TMP_DIR', 6);
}
/*
input:
{{files download="filename.txt" text="important textfile"}}
output:
<a href="http://example.com/wiki/ExamplePage/files.xml?action=download&file=filename.txt">important textfile</a>
*/
/*
input:
{{files}}
output:
<div class="files"><table>
<thead>
<tr>
<td></td>
<th>Name</th>
<th>Last modified</th>
<th>Size</th>
</tr>
</thead>
<tbody>
<tr class="r1 r1m2 r1m3">
<td></td>
<td><a href="http://example.com/wiki/ExamplePage/files.xml?action=download&file=filename.txt">filename.txt</a></td>
<td>2005-02-03 17:57</td>
<td align="right">189k</td>
</tr>
<tr class="r2 r0m2 r2m3">
<td></td>
<td><a href="http://example.com/wiki/ExamplePage/files.xml?action=download&file=another%20file.txt">another file.txt</a></td>
<td>2005-02-03 17:57</td>
<td align="right">34k</td>
</tr>
</tbody>
</table></div>
output if you're admin:
<div class="files"><table>
<thead>
<tr>
<td></td>
<th>Name</th>
<th>Last modified</th>
<th>Size</th>
</tr>
</thead>
<tbody>
<tr class="r1 r1m2 r1m3">
<td>[<a href="http://example.com/wiki/ExamplePage/files.xml?action=delete&file=filename.txt">delete</a>]</td>
<td><a href="http://example.com/wiki/ExamplePage/files.xml?action=download&file=filename.txt">filename.txt</a></td>
<td>2005-02-03 17:57</td>
<td align="right">189k</td>
</tr>
<tr class="r2 r0m2 r2m3">
<td>[<a href="http://example.com/wiki/ExamplePage/files.xml?action=delete&file=another%20file.txt">delete</a>]</td>
<td><a href="http://example.com/wiki/ExamplePage/files.xml?action=download&file=another%20file.txt">another file.txt</a></td>
<td>2005-02-03 17:57</td>
<td align="right">34k</td>
</tr>
</tbody>
</table>
<form action="http://example.com/wiki/HomePage" method="post" enctype="multipart/form-data">
<p>

<input type="hidden" name="action" value="upload" />
<input type="hidden" name="MAX_FILE_SIZE" value="2097152" />
add new attachment:
<input type="file" name="file" />
<input type="submit" value="Upload" />
</p>
</form></div>
*/
if ($vars['download'] != '') {
// link to download a file
if ($vars['text'] == '') $text = $vars['download'];
$output .= '<a href="'
. $this->Href(
'files.xml',
$this->GetPageTag(),
'action=download&file='.
rawurlencode($vars['download'])
)
. '">'
. $vars['text']
. '</a>';
// Show files to anyone with read access, we'll check for write access if they try to delete a file.
} elseif ($this->page && $this->HasAccess('read') && $this->method != 'print.xml' && $this->method != 'edit') {
// upload path
if ($this->config['upload_path'] == '') {
$this->config['upload_path'] = 'files';
}

$upload_path = $this->config['upload_path'].'/'.$this->GetPageTag();

if (! is_dir($upload_path)) {
mkdir_r($upload_path);
}

// upload action
if ($_POST['action'] == 'upload') {

$status_text = '';

switch ($_FILES['file']['error']) {
case UPLOAD_ERR_OK:
if ($_FILES['file']['size'] > $max_upload_size) {
$status_text = 'Attempted file upload was too big. '
. 'Maximum allowed size is '
. bytesToHumanReadableUsage($max_upload_size) . '.';
unlink($_FILES['file']['tmp_name']);
}
elseif (preg_match('/.+\.('.$allowed_extensions.')$/i', $_FILES['file']['name'])) {
$strippedname = str_replace('\'', '', $_FILES['file']['name']);
$strippedname = stripslashes($strippedname);
$destfile = $upload_path.'/'.$strippedname;
if (!file_exists($destfile)) {
if (move_uploaded_file($_FILES['file']['tmp_name'], $destfile)) {
$status_text = 'File was successfully uploaded.';
}
else {
$status_text = 'There was an error uploading your file.';
}
}
else {
$status_text = 'There is already a file named "' . $strippedname . '".';
}
} else {
$status_text = 'This file\'s extension is unknown.';
unlink($_FILES['file']['tmp_name']);
}
break;
case UPLOAD_ERR_INI_SIZE:
case UPLOAD_ERR_FORM_SIZE:
$status_text = 'Attempted file upload was too big. '
. 'Maximum allowed size is '
. bytesToHumanReadableUsage($max_upload_size).'.';
break;
case UPLOAD_ERR_PARTIAL:
$status_text = 'File upload incomplete. Please try again.';
break;
case UPLOAD_ERR_NO_FILE:
$status_text = 'No file uploaded.';
break;
case UPLOAD_ERR_NO_TMP_DIR:
$status_text = 'File uploads impossible due to misconfigured server.';
break;
}
if ($status_text != '') {
$output .= '<p class="status">' . $status_text . '</p>';
}
}

// uploaded files
$output .= <<<HEREDOC
<table>
<thead>
<tr>
<td></td> <!-- For the delete link. Only needed when user is admin or has write rights. -->
<th>Name</th>
<th>Last modified</th>
<th>Size</th>
</tr>
</thead>
<tbody>
HEREDOC;
$dir = opendir($upload_path);
$num = 0;
while ($file = readdir($dir)) {
/* if ( $file != '.' && $file != '..') { */
if ($file{0} != '.') {
$num++;
$delete_link = '<!-- delete -->';
/* if ($this->HasAccess('write')) { */
if ($this->IsAdmin()) {
$delete_link = '[<a href="'
. $this->Href('files.xml',$this->GetPageTag(),'action=delete&file='.rawurlencode($file))
. '">delete</a>]';
}
$download_link = '<a href="'
. $this->Href('files.xml',$this->GetPageTag(),'action=download&file='.rawurlencode($file))
. '">'.$file.'</a>';
$size = bytesToHumanReadableUsage(filesize($upload_path . '/' . $file));
$date = date($date_format, filemtime($upload_path . '/' . $file));
// easy even/odd zebra table
// also possible to zebra color every three rows
$row_class = 'r'.$num.' r'.($num % 2).'m2 r'.($num % 3).'m3';
$output .= <<<HEREDOC
<tr class="{$row_class}">
<td>{$delete_link}</td>
<td>{$download_link}</td>
<td>{$date}</td>
<td align="right">{$size}</td>
</tr>
HEREDOC;
}
}
closedir($dir);
// print n/a if no files currently exist
if ($num < 1) {
$output .= <<<HEREDOC
<tr><td colspan="4">no files here</td></tr>
HEREDOC;
}
$output .= <<<HEREDOC
</tbody>
</table>
HEREDOC;
/* if ($this->HasAccess('write')) { */
if ($this->IsAdmin()) {
// form
$input_for_rewrite_mode = '<!-- rewrite mode disabled -->';
if (!$this->config['rewrite_mode']){
$input_for_rewrite_mode = '<input type="hidden" name="wakka" value="'.$this->MiniHref().'" />';
}
// close disp table
$href = $this->Href();
$output .= <<<HEREDOC
<form action="{$href}" method="post" enctype="multipart/form-data">
<p>
{$input_for_rewrite_mode}
<input type="hidden" name="action" value="upload" />
<input type="hidden" name="MAX_FILE_SIZE" value="{$max_upload_size}" />
add new attachment:
<input type="file" name="file" />
<input type="submit" value="Upload" />
</p>
</form>
HEREDOC;
}
}
$output .= '</div>';
$output = $this->ReturnSafeHTML($output);
echo $output;
?>
%%
**handlers/page/files.xml.php**
%%(php)
<?php
// upload path
if ($this->config['upload_path'] == '') {
$this->config['upload_path'] = 'files';
}
$upload_path = $this->config['upload_path'].'/'.$this->GetPageTag();
if (!is_dir($upload_path)) {
mkdir_r($upload_path);
}
$allowed_extensions = 'gif|jpeg|jpg|jpe|png|doc|xls|csv|ppt|ppz|pps|pot|pdf|asc|txt|zip|gtar|gz|bz2|tar|rar|vpp|mpp|vsd|mm';
$mime_types_file = $this->config['mime_types'];
$base_name = basename(urldecode($_REQUEST['file']));
$parts = explode('.', $base_name );
$extension = '';
if(count($parts) > 1){
$extension = array_pop($parts);
}
$first_letter = $base_name{0};
if ($first_letter != '.' && stristr('|'.$allowed_extensions.'|', '|'.$extension.'|')) {

$path = $upload_path.'/'.basename(urldecode($_REQUEST['file']));

// do the action
switch ($_REQUEST['action']) {
case 'download':
if ($this->HasAccess('read')) {
$filename = basename($path);
$mimetype = 'application/x-download';
$mimes = file($mime_types_file);
foreach($mimes as $line){
if(preg_match('/^(\w+\/\S+)\b.*\s'.$extension.'\b/i', $line, $matches)){
$mimetype = $matches[1];
break;
}
}
Header('Content-Length: '.filesize($path));
Header('Content-Type: '.$mimetype);
Header('Content-Disposition: attachment; filename="'.$filename.'"; '
.'modification-date="'.date('r', filemtime($path)).'";');
Header('Connection: close');
@readfile($path);
exit();
}
break;
case 'delete':
// if ($this->HasAccess('write')) {
if ($this->IsAdmin()) {
@unlink($path);
}
print $this->redirect($this->Href());
break;
}
}
?>
%%
**css**
%%(css)
.files table{
border: 1px solid #ccc;
border-collapse: collapse;
}
.files thead th, .files thead td {
color: #fff;
background: #999;
}
.files td, .files th {
padding: 0 3px 0 3px;
}
.files tr.r0m2 {
background: #efe;
color: #000;
}
%%
I cleaned up the code and added:
~- mime types when downloading a file
~- security check on file extension
~- more error checking
~- semanticly correct output for easier styling
Hope you like it.
--CryDust
----
====yet another actions/files.php====
http://wush.net/trac/wikka/ticket/72
it is not said in the ticket, but of course my version is also fully css skinable.
some other changes:
~- parameter **total** which gives a line of total number of files
~- the delete column is shown based on access rights
as i state in the ticket also, the upload file limit is not working for me. see the ticket
----
====styling the file upload form====
people might get frustrated by the browse button and the file input field.
this page offers a solution: http://www.quirksmode.org/dom/inputfile.html
----
=====making uploaded images useful=====
to make the wiki a truly useful documentation tool, one needs pictures, uploaded pictures.
at the moment pictures uploaded using FilesAction are accessible **only** for download
(unless i am missing something). to let a department manage it's own pictures and be
able to include them in the page, one needs to access ##$upload_path##. the current
##.htaccess## file makes this impossible.
so here is what i did:
**.htaccess**
%%
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^(.*/[^\./]*[^/])$ $1/
RewriteCond %{REQUEST_FILENAME} !robots.txt
RewriteCond %{REQUEST_FILENAME} !favicon.ico
RewriteCond %{REQUEST_FILENAME} !files/.*$
RewriteRule ^(.*)$ wikka.php?wakka=$1 [QSA,L]
</IfModule>
%%
**in the wikka page:**
##""{{image alt="db model" title="db model" url="files/CostCenters/costcenters.png"}}""##
this way i can include the images for viewing in the page.
Deletions:
~


Revision [16695]

Edited on 2007-05-31 10:37:35 by OehC09 [Reverted]
Additions:
~
Deletions:
~&Hillar, can you explain //why// it didn't work for you, and how you solved that? --JavaWoman
===Actual version===
The code below offers a more visually improved layout for this handler and also displays the file size and the date of file upload.
- HeavyK (k m r @ h e a v y k . o r g), 3/27/04
**actions/files.php**
%%(php)
<?php
if (! function_exists('mkdir_r')) {
function mkdir_r ($dir) {
if (strlen($dir) == 0) return 0;
if (is_dir($dir)) return 1;
elseif (dirname($dir) == $dir) return 1;
return (mkdir_r(dirname($dir)) and mkdir($dir,0755));
}
}
if (! function_exists('bytesToHumanReadableUsage')) {
/**
* Converts bytes to a human readable string
* @param int $bytes Number of bytes
* @param int $precision Number of decimal places to include in return string
* @param array $names Custom usage strings
* @return string formatted string rounded to $precision
*/
function bytesToHumanReadableUsage($bytes, $precision = 2, $names = '')
{
if (!is_numeric($bytes) || $bytes < 0) {
return false;
}

for ($level = 0; $bytes >= 1024; $level++) {
$bytes /= 1024;
}

switch ($level)
{
case 0:
$suffix = (isset($names[0])) ? $names[0] : 'Bytes';
break;
case 1:
$suffix = (isset($names[1])) ? $names[1] : 'KB';
break;
case 2:
$suffix = (isset($names[2])) ? $names[2] : 'MB';
break;
case 3:
$suffix = (isset($names[3])) ? $names[3] : 'GB';
break;
case 4:
$suffix = (isset($names[4])) ? $names[4] : 'TB';
break;
default:
$suffix = (isset($names[$level])) ? $names[$level] : '';
break;
}

if (empty($suffix)) {
trigger_error('Unable to find suffix for case ' . $level);
return false;
}

return round($bytes, $precision) . ' ' . $suffix;
}
}
if ($download <> '') {
// link to download a file
if ($text == '') $text = $download;
echo "<a href=\"".$this->href('files.xml',$this->GetPageTag(),'action=download&file='.urlencode($download))."\">".$text."</a>";
} elseif ($this->page AND $this->HasAccess('write') AND ($this->method <> 'print.xml') AND ($this->method <> 'edit')) {
// upload path
if ($this->config['upload_path'] == '') $this->config['upload_path'] = 'files';
$upload_path = $this->config['upload_path'].'/'.$this->GetPageTag();
if (! is_dir($upload_path)) mkdir_r($upload_path);
// upload action
$uploaded = $_FILES['file'];
if ($_REQUEST['action'] == 'upload' AND $uploaded['size'] > 0)
copy ($uploaded['tmp_name'], $upload_path.'/'.$uploaded['name']);
// uploaded files
print "
<table cellspacing=0 cellpadding=0>
<tr>
<td>
 
</td>
<td bgcolor=gray valign=bottom align=center>
<font color=white size=-2>
Attachment
</font>
</td>
<td bgcolor=gray valign=bottom align=center>
<font color=white size=-2>
Size
</font>
</td>
<td bgcolor=gray valign=bottom align=center>
<font color=white size=-2>
Date Added
</font>
</td>
</tr>
";
$dir = opendir($upload_path);
while ($file = readdir($dir)) {
if ($file != '.' && $file != '..') {
$num++;
$delete_link = "<a href=\"".$this->href('files.xml',$this->GetPageTag(),'action=delete&file='.urlencode($file))."\">x</a>";
$download_link = "<a href=\"".$this->href('files.xml',$this->GetPageTag(),'action=download&file='.urlencode($file))."\">".$file."</a>";
$size = bytesToHumanReadableUsage(filesize("$upload_path/$file"));
$date = date("n/d/Y g:i a",filemtime("$upload_path/$file"));
print "
<tr>
<td valign=top align=center>
  
{$delete_link}
  
</td>
<td valign=top>
$download_link
</td>
<td valign=top>
 
<font size=-1 color=gray>
$size
</font>
</td>
<td valign=top>
 
<font size=-1 color=gray>
$date
</font>
</td>
</tr>
";
}
}
closedir($dir);
// print n/a if no files currently exist
if (!$num) print "<tr><td> </td><td colspan=3 align=center><font color=gray size=-1><i>   </i></font></td></tr>";
else print "<tr><td> </td></tr>";
// form
$result = "<form action=\"".$this->href()."\" method=\"post\" enctype=\"multipart/form-data\">\n";
if (!$this->config["rewrite_mode"]) $result .= "<input type=\"hidden\" name=\"wakka\" value=\"".$this->MiniHref()."\">\n";
echo $result;
//<input type="hidden" name="action" value="upload"><input type="file" name="file"><input type="submit" value="+">
echo $this->FormClose();
// close disp table
print "
<tr>
<td>
 
</td>
<td colspan=4 valign=top align=right nowrap>
<i>
$result
<input type=\"hidden\" name=\"action\" value=\"upload\">
<font color=gray size=-2>
add new attachment:
<input type=\"file\" name=\"file\" style=\"padding: 0px; margin: 0px; font-size: 8px; height: 15px\">
<input type=\"Submit\" value=\"+\" style=\"padding: 0px; margin: 0px; font-size: 8px; height: 15px\">
".$this->FormClose()."
</font>
</i>
</td>
</tr>
</table>
";
}
?>
%%
===First version===
==actions/files.php==
%%(php)
<?php
if (! function_exists('mkdir_r')) {
function mkdir_r ($dir) {
if (strlen($dir) == 0) return 0;
if (is_dir($dir)) return 1;
elseif (dirname($dir) == $dir) return 1;
return (mkdir_r(dirname($dir)) and mkdir($dir,0755));
}
}
if ($download <> '') {
// link to download a file
if ($text == '') $text = $download;
echo "<a href=\"".$this->href('files.xml',$this->GetPageTag(),'action=download&file='.urlencode($download))."\">".$text."</a>";
} elseif ($this->page AND $this->HasAccess('write') AND ($this->method <> 'print.xml') AND ($this->method <> 'edit')) {
// upload path
if ($this->config['upload_path'] == '') $this->config['upload_path'] = 'files';
$upload_path = $this->config['upload_path'].'/'.$this->GetPageTag();
if (! is_dir($upload_path)) mkdir_r($upload_path);
// upload action
$uploaded = $_FILES['file'];
if ($_REQUEST['action'] == 'upload' AND $uploaded['size'] > 0)
copy ($uploaded['tmp_name'], $upload_path.'/'.$uploaded['name']);
// form
$result = "<form action=\"".$this->href()."\" method=\"post\" enctype=\"multipart/form-data\">\n";
if (!$this->config["rewrite_mode"]) $result .= "<input type=\"hidden\" name=\"wakka\" value=\"".$this->MiniHref()."\">\n";
echo $result;
?>
<input type="hidden" name="action" value="upload"><input type="file" name="file"><input type="submit" value="+">
<?php
echo $this->FormClose();
// uploaded files
$dir = opendir($upload_path);
while ($file = readdir($dir)) {
if ($file != '.' && $file != '..') {
$delete_link = "<a href=\"".$this->href('files.xml',$this->GetPageTag(),'action=delete&file='.urlencode($file))."\">x</a>";
$download_link = "<a href=\"".$this->href('files.xml',$this->GetPageTag(),'action=download&file='.urlencode($file))."\">".$file."</a>";
print "[ {$delete_link} ] ";
if ($file == $uploaded['name'])
print "<em>{$download_link}</em>\n";
else
print $download_link;
print '<br>';
}
}
closedir($dir);
}
?>
%%
==handlers/page/files.xml.php==
%%(php)
<?php
/* mime stuff take from Paul Southworth */
$mt_f = $this->config['mime_types'];
if ($mt_f == '') $mt_f='mime.types';
/* build an array keyed on the file ext */
if (is_readable($mt_f)) {
$mime_types=array();
/* open our mime.types file for reading */
$mt_fd=fopen($mt_f,"r");
while (!feof($mt_fd)) {
/* pull a line off the file */
$mt_buf=trim(fgets($mt_fd,1024));
/* discard if the line was blank or started with a comment */
if (strlen($mt_buf) > 0) if (substr($mt_buf,0,1) != "#") {
/* make temp array of the mime.types line we just read */
$mt_tmp=preg_split("/[\s]+/", $mt_buf, -1, PREG_SPLIT_NO_EMPTY);
$mt_num=count($mt_tmp);
/* if $mt_num = 1 then we got no file extensions for the type */
if ($mt_num > 1) {
for ($i=1;$i<$mt_num;$i++) {
/* if we find a comment mid-line, stop processing */
if (strstr($mt_tmp[$i],"#")) {
break;
/* otherwise stick the type in an array keyed by extension */
} else {
$mime_types[$mt_tmp[$i]]=$mt_tmp[0];
}
}
/* zero the temporary array */
unset($mt_tmp);
}
}
}
/* close the mime.types file we were reading */
fclose($mt_fd);
} else {
echo "ERROR: unreadable file " . $mt_f . "\n";
}
// upload path
if ($this->config['upload_path'] == '') $this->config['upload_path'] = 'files';
$upload_path = $this->config['upload_path'].'/'.$this->GetPageTag();
if (! is_dir($upload_path)) mkdir_r($upload_path);
// do the action
switch ($_REQUEST['action']) {
case 'download':
$_REQUEST['file'] = urldecode($_REQUEST['file']);
if ($this->HasAccess('read')) {
$path = "{$upload_path}/{$_REQUEST['file']}";
$filename = basename($path);
header('MIME-Version: 1.0');
$afn = split("\.",$filename);
$ext = strtolower($afn[count($afn)-1]);
$mime_type = $mime_types[$ext];
if ($mime_type == '') $mime_type = 'application/octet-stream';
header("Content-Type: {$mime_type}; name=\"{$filename}\"");
header('Content-Length: '. filesize($path));
header("Content-Disposition: filename=\"{$filename}\"");
$fp=fopen($path,'r');
print fread($fp,filesize($path));
fclose($fp);
exit();
}
case 'delete':
if ($this->HasAccess('write')) {
@unlink("{$upload_path}/{$_REQUEST['file']}");
print $this->redirect($this->href());
}
}
?>
%%
Nice.. but shouldn't delete at least check some permissions? ''(answer: I am checking write permission...)''
-- ArnarBirgisson
Why "files.xml"? shouldn't it be "files.php"? ''(answer: .xml actions does not include header and footer)''
(files.xml didn't work, but renaming it to "files.xml.php" helped.)
=> Kommentar::
files-action only works if you copy files.xml and store it as files.xml.php as well as files.xml ??????????
//Jetzt geht es, aber das ist ziemlich irre, weil ::
- files.xml
noch einmal als ::
- files.xml.php
abgespeichert werden muss. ?? es funktioniert .. //
KonradTadesse
----
:: FileUp ::
By the way, having an upload form on a page seems to break the page preview "Store" and "Re-edit" buttons.
''(fixed hidding the form on editing, thanks for your bug information)''
-- Tero
----
Here is the same bug like in ImageAction: the use of ##$vars##. Replace line 11 to 16 in actions/files.php with this:
%%(php)
if ($tokens['download'] ) {
// link to download a file
$text = $this->stripquotes($action_params['download']);
if ($tokens['text'])
{
$text = $this->stripquotes($action_params['text']);
}
echo "<a href=\"".$this->href('files.xml',$this->GetPageTag(),'action=download&file='.urlencode($this->stripquotes($action_params['download'])))."\">".$text."</a>";
}
%%
For the function ##$this->stripquotes## read ImageAction
--SilBaer
----
Fileupload on editing pages see FileUpload
--SilBaer
Fix: Added closing CurlyBrace in last replacement code.
--MarkHissinkMuller
====Code cleanup====
**actions/files.php**
%%(php)
<?php
$output = '';
$output .= '<div class="files">';
//this realy should be in the config
$max_upload_size = 2*1048576;
$allowed_extensions = 'gif|jpeg|jpg|jpe|png|doc|xls|csv|ppt|ppz|pps|pot|pdf|asc|txt|zip|gtar|gz|bz2|tar|rar|vpp|mpp|vsd|mm';
/* $date_format = 'n/d/Y g:i a'; (original) */
/* $date_format = 'd-M-Y H:i'; //01-Feb-2005 05:23 */
$date_format = 'Y-m-d H:i'; //2005-02-01 05:23 (easy javascript table sorting)
// mkdir_r
if (! function_exists('mkdir_r')) {
function mkdir_r ($dir) {
if (strlen($dir) == 0) return 0;
if (is_dir($dir)) return 1;
elseif (dirname($dir) == $dir) return 1;
return (mkdir_r(dirname($dir)) and mkdir($dir,0755));
}
}
// bytesToHumanReadableUsage
if (! function_exists('bytesToHumanReadableUsage')) {
/**
* Converts bytes to a human readable string
* @param int $bytes Number of bytes
* @param int $precision Number of decimal places to include in return string
* @param array $names Custom usage strings
* @return string formatted string rounded to $precision
*/
function bytesToHumanReadableUsage($bytes, $precision = 0, $names = '') {
if (!is_numeric($bytes) || $bytes < 0) {
$bytes = 0;
}

if (!is_numeric($precision) || $precision < 0) {
$precision = 0;
}

if (!is_array($names)) {
/* $names = array(' Bytes',' KB',' MB',' GB',' TB'); //original */
$names = array('B','k','M','G','T','P','E');
}

$level = floor(log($bytes)/log(1024));

$suffix = '';
if ($level < count($names)) {
$suffix = $names[$level];
}

return round($bytes/pow(1024, $level), $precision) . $suffix;
}
}
// error code constants
if (! defined('UPLOAD_ERR_OK')){
define('UPLOAD_ERR_OK', 0);
}
if (! defined('UPLOAD_ERR_INI_SIZE')){
define('UPLOAD_ERR_INI_SIZE', 1);
}
if (! defined('UPLOAD_ERR_FORM_SIZE')){
define('UPLOAD_ERR_FORM_SIZE', 2);
}
if (! defined('UPLOAD_ERR_PARTIAL')){
define('UPLOAD_ERR_PARTIAL', 3);
}
if (! defined('UPLOAD_ERR_NO_FILE')){
define('UPLOAD_ERR_NO_FILE', 4);
}
if (! defined('UPLOAD_ERR_NO_TMP_DIR')){
define('UPLOAD_ERR_NO_TMP_DIR', 6);
}
/*
input:
{{files download="filename.txt" text="important textfile"}}
output:
<a href="http://example.com/wiki/ExamplePage/files.xml?action=download&file=filename.txt">important textfile</a>
*/
/*
input:
{{files}}
output:
<div class="files"><table>
<thead>
<tr>
<td></td>
<th>Name</th>
<th>Last modified</th>
<th>Size</th>
</tr>
</thead>
<tbody>
<tr class="r1 r1m2 r1m3">
<td></td>
<td><a href="http://example.com/wiki/ExamplePage/files.xml?action=download&file=filename.txt">filename.txt</a></td>
<td>2005-02-03 17:57</td>
<td align="right">189k</td>
</tr>
<tr class="r2 r0m2 r2m3">
<td></td>
<td><a href="http://example.com/wiki/ExamplePage/files.xml?action=download&file=another%20file.txt">another file.txt</a></td>
<td>2005-02-03 17:57</td>
<td align="right">34k</td>
</tr>
</tbody>
</table></div>
output if you're admin:
<div class="files"><table>
<thead>
<tr>
<td></td>
<th>Name</th>
<th>Last modified</th>
<th>Size</th>
</tr>
</thead>
<tbody>
<tr class="r1 r1m2 r1m3">
<td>[<a href="http://example.com/wiki/ExamplePage/files.xml?action=delete&file=filename.txt">delete</a>]</td>
<td><a href="http://example.com/wiki/ExamplePage/files.xml?action=download&file=filename.txt">filename.txt</a></td>
<td>2005-02-03 17:57</td>
<td align="right">189k</td>
</tr>
<tr class="r2 r0m2 r2m3">
<td>[<a href="http://example.com/wiki/ExamplePage/files.xml?action=delete&file=another%20file.txt">delete</a>]</td>
<td><a href="http://example.com/wiki/ExamplePage/files.xml?action=download&file=another%20file.txt">another file.txt</a></td>
<td>2005-02-03 17:57</td>
<td align="right">34k</td>
</tr>
</tbody>
</table>
<form action="http://example.com/wiki/HomePage" method="post" enctype="multipart/form-data">
<p>

<input type="hidden" name="action" value="upload" />
<input type="hidden" name="MAX_FILE_SIZE" value="2097152" />
add new attachment:
<input type="file" name="file" />
<input type="submit" value="Upload" />
</p>
</form></div>
*/
if ($vars['download'] != '') {
// link to download a file
if ($vars['text'] == '') $text = $vars['download'];
$output .= '<a href="'
. $this->Href(
'files.xml',
$this->GetPageTag(),
'action=download&file='.
rawurlencode($vars['download'])
)
. '">'
. $vars['text']
. '</a>';
// Show files to anyone with read access, we'll check for write access if they try to delete a file.
} elseif ($this->page && $this->HasAccess('read') && $this->method != 'print.xml' && $this->method != 'edit') {
// upload path
if ($this->config['upload_path'] == '') {
$this->config['upload_path'] = 'files';
}

$upload_path = $this->config['upload_path'].'/'.$this->GetPageTag();

if (! is_dir($upload_path)) {
mkdir_r($upload_path);
}

// upload action
if ($_POST['action'] == 'upload') {

$status_text = '';

switch ($_FILES['file']['error']) {
case UPLOAD_ERR_OK:
if ($_FILES['file']['size'] > $max_upload_size) {
$status_text = 'Attempted file upload was too big. '
. 'Maximum allowed size is '
. bytesToHumanReadableUsage($max_upload_size) . '.';
unlink($_FILES['file']['tmp_name']);
}
elseif (preg_match('/.+\.('.$allowed_extensions.')$/i', $_FILES['file']['name'])) {
$strippedname = str_replace('\'', '', $_FILES['file']['name']);
$strippedname = stripslashes($strippedname);
$destfile = $upload_path.'/'.$strippedname;
if (!file_exists($destfile)) {
if (move_uploaded_file($_FILES['file']['tmp_name'], $destfile)) {
$status_text = 'File was successfully uploaded.';
}
else {
$status_text = 'There was an error uploading your file.';
}
}
else {
$status_text = 'There is already a file named "' . $strippedname . '".';
}
} else {
$status_text = 'This file\'s extension is unknown.';
unlink($_FILES['file']['tmp_name']);
}
break;
case UPLOAD_ERR_INI_SIZE:
case UPLOAD_ERR_FORM_SIZE:
$status_text = 'Attempted file upload was too big. '
. 'Maximum allowed size is '
. bytesToHumanReadableUsage($max_upload_size).'.';
break;
case UPLOAD_ERR_PARTIAL:
$status_text = 'File upload incomplete. Please try again.';
break;
case UPLOAD_ERR_NO_FILE:
$status_text = 'No file uploaded.';
break;
case UPLOAD_ERR_NO_TMP_DIR:
$status_text = 'File uploads impossible due to misconfigured server.';
break;
}
if ($status_text != '') {
$output .= '<p class="status">' . $status_text . '</p>';
}
}

// uploaded files
$output .= <<<HEREDOC
<table>
<thead>
<tr>
<td></td> <!-- For the delete link. Only needed when user is admin or has write rights. -->
<th>Name</th>
<th>Last modified</th>
<th>Size</th>
</tr>
</thead>
<tbody>
HEREDOC;
$dir = opendir($upload_path);
$num = 0;
while ($file = readdir($dir)) {
/* if ( $file != '.' && $file != '..') { */
if ($file{0} != '.') {
$num++;
$delete_link = '<!-- delete -->';
/* if ($this->HasAccess('write')) { */
if ($this->IsAdmin()) {
$delete_link = '[<a href="'
. $this->Href('files.xml',$this->GetPageTag(),'action=delete&file='.rawurlencode($file))
. '">delete</a>]';
}
$download_link = '<a href="'
. $this->Href('files.xml',$this->GetPageTag(),'action=download&file='.rawurlencode($file))
. '">'.$file.'</a>';
$size = bytesToHumanReadableUsage(filesize($upload_path . '/' . $file));
$date = date($date_format, filemtime($upload_path . '/' . $file));
// easy even/odd zebra table
// also possible to zebra color every three rows
$row_class = 'r'.$num.' r'.($num % 2).'m2 r'.($num % 3).'m3';
$output .= <<<HEREDOC
<tr class="{$row_class}">
<td>{$delete_link}</td>
<td>{$download_link}</td>
<td>{$date}</td>
<td align="right">{$size}</td>
</tr>
HEREDOC;
}
}
closedir($dir);
// print n/a if no files currently exist
if ($num < 1) {
$output .= <<<HEREDOC
<tr><td colspan="4">no files here</td></tr>
HEREDOC;
}
$output .= <<<HEREDOC
</tbody>
</table>
HEREDOC;
/* if ($this->HasAccess('write')) { */
if ($this->IsAdmin()) {
// form
$input_for_rewrite_mode = '<!-- rewrite mode disabled -->';
if (!$this->config['rewrite_mode']){
$input_for_rewrite_mode = '<input type="hidden" name="wakka" value="'.$this->MiniHref().'" />';
}
// close disp table
$href = $this->Href();
$output .= <<<HEREDOC
<form action="{$href}" method="post" enctype="multipart/form-data">
<p>
{$input_for_rewrite_mode}
<input type="hidden" name="action" value="upload" />
<input type="hidden" name="MAX_FILE_SIZE" value="{$max_upload_size}" />
add new attachment:
<input type="file" name="file" />
<input type="submit" value="Upload" />
</p>
</form>
HEREDOC;
}
}
$output .= '</div>';
$output = $this->ReturnSafeHTML($output);
echo $output;
?>
%%
**handlers/page/files.xml.php**
%%(php)
<?php
// upload path
if ($this->config['upload_path'] == '') {
$this->config['upload_path'] = 'files';
}
$upload_path = $this->config['upload_path'].'/'.$this->GetPageTag();
if (!is_dir($upload_path)) {
mkdir_r($upload_path);
}
$allowed_extensions = 'gif|jpeg|jpg|jpe|png|doc|xls|csv|ppt|ppz|pps|pot|pdf|asc|txt|zip|gtar|gz|bz2|tar|rar|vpp|mpp|vsd|mm';
$mime_types_file = $this->config['mime_types'];
$base_name = basename(urldecode($_REQUEST['file']));
$parts = explode('.', $base_name );
$extension = '';
if(count($parts) > 1){
$extension = array_pop($parts);
}
$first_letter = $base_name{0};
if ($first_letter != '.' && stristr('|'.$allowed_extensions.'|', '|'.$extension.'|')) {

$path = $upload_path.'/'.basename(urldecode($_REQUEST['file']));

// do the action
switch ($_REQUEST['action']) {
case 'download':
if ($this->HasAccess('read')) {
$filename = basename($path);
$mimetype = 'application/x-download';
$mimes = file($mime_types_file);
foreach($mimes as $line){
if(preg_match('/^(\w+\/\S+)\b.*\s'.$extension.'\b/i', $line, $matches)){
$mimetype = $matches[1];
break;
}
}
Header('Content-Length: '.filesize($path));
Header('Content-Type: '.$mimetype);
Header('Content-Disposition: attachment; filename="'.$filename.'"; '
.'modification-date="'.date('r', filemtime($path)).'";');
Header('Connection: close');
@readfile($path);
exit();
}
break;
case 'delete':
// if ($this->HasAccess('write')) {
if ($this->IsAdmin()) {
@unlink($path);
}
print $this->redirect($this->Href());
break;
}
}
?>
%%
**css**
%%(css)
.files table{
border: 1px solid #ccc;
border-collapse: collapse;
}
.files thead th, .files thead td {
color: #fff;
background: #999;
}
.files td, .files th {
padding: 0 3px 0 3px;
}
.files tr.r0m2 {
background: #efe;
color: #000;
}
%%
I cleaned up the code and added:
~- mime types when downloading a file
~- security check on file extension
~- more error checking
~- semanticly correct output for easier styling
Hope you like it.
--CryDust
----
====yet another actions/files.php====
http://wush.net/trac/wikka/ticket/72
it is not said in the ticket, but of course my version is also fully css skinable.
some other changes:
~- parameter **total** which gives a line of total number of files
~- the delete column is shown based on access rights
as i state in the ticket also, the upload file limit is not working for me. see the ticket
----
====styling the file upload form====
people might get frustrated by the browse button and the file input field.
this page offers a solution: http://www.quirksmode.org/dom/inputfile.html
----
=====making uploaded images useful=====
to make the wiki a truly useful documentation tool, one needs pictures, uploaded pictures.
at the moment pictures uploaded using FilesAction are accessible **only** for download
(unless i am missing something). to let a department manage it's own pictures and be
able to include them in the page, one needs to access ##$upload_path##. the current
##.htaccess## file makes this impossible.
so here is what i did:
**.htaccess**
%%
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^(.*/[^\./]*[^/])$ $1/
RewriteCond %{REQUEST_FILENAME} !robots.txt
RewriteCond %{REQUEST_FILENAME} !favicon.ico
RewriteCond %{REQUEST_FILENAME} !files/.*$
RewriteRule ^(.*)$ wikka.php?wakka=$1 [QSA,L]
</IfModule>
%%
**in the wikka page:**
##""{{image alt="db model" title="db model" url="files/CostCenters/costcenters.png"}}""##
this way i can include the images for viewing in the page.


Revision [12518]

Edited on 2006-01-05 10:06:46 by MinusF [Reverted]
Additions:
=====making uploaded images useful=====
to make the wiki a truly useful documentation tool, one needs pictures, uploaded pictures.
at the moment pictures uploaded using FilesAction are accessible **only** for download
(unless i am missing something). to let a department manage it's own pictures and be
able to include them in the page, one needs to access ##$upload_path##. the current
##.htaccess## file makes this impossible.
so here is what i did:
**.htaccess**
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^(.*/[^\./]*[^/])$ $1/
RewriteCond %{REQUEST_FILENAME} !robots.txt
RewriteCond %{REQUEST_FILENAME} !favicon.ico
RewriteCond %{REQUEST_FILENAME} !files/.*$
RewriteRule ^(.*)$ wikka.php?wakka=$1 [QSA,L]
</IfModule>
**in the wikka page:**
##""{{image alt="db model" title="db model" url="files/CostCenters/costcenters.png"}}""##
this way i can include the images for viewing in the page.


Revision [12496]

Edited on 2006-01-04 09:26:30 by MinusF [Reverted]
Additions:
====styling the file upload form====
people might get frustrated by the browse button and the file input field.
this page offers a solution: http://www.quirksmode.org/dom/inputfile.html


Revision [12495]

Edited on 2006-01-04 09:18:09 by MinusF [Reverted]
Additions:
some other changes:
~- parameter **total** which gives a line of total number of files
~- the delete column is shown based on access rights
as i state in the ticket also, the upload file limit is not working for me. see the ticket


Revision [12494]

Edited on 2006-01-03 16:31:02 by MinusF [Reverted]
Additions:
it is not said in the ticket, but of course my version is also fully css skinable.


Revision [12493]

Edited on 2006-01-03 16:29:55 by MinusF [Reverted]
Additions:
<tr>
<td>
 
</td>
<td bgcolor=gray valign=bottom align=center>
<font color=white size=-2>
Attachment
</font>
</td>
<td bgcolor=gray valign=bottom align=center>
<font color=white size=-2>
Size
</font>
</td>
<td bgcolor=gray valign=bottom align=center>
<font color=white size=-2>
Date Added
</font>
</td>
</tr>
<tr>
<td valign=top align=center>
  
{$delete_link}
  
</td>
<td valign=top>
$download_link
</td>
<td valign=top>
 
<font size=-1 color=gray>
$size
</font>
</td>
<td valign=top>
 
<font size=-1 color=gray>
$date
</font>
</td>
</tr>
";
<tr>
<td>
 
</td>
<td colspan=4 valign=top align=right nowrap>
<i>
$result
<input type=\"hidden\" name=\"action\" value=\"upload\">
<font color=gray size=-2>
add new attachment:
<input type=\"file\" name=\"file\" style=\"padding: 0px; margin: 0px; font-size: 8px; height: 15px\">
<input type=\"Submit\" value=\"+\" style=\"padding: 0px; margin: 0px; font-size: 8px; height: 15px\">
".$this->FormClose()."
</font>
</i>
</td>
</tr>
$bytes = 0;
$precision = 0;
/* $names = array(' Bytes',' KB',' MB',' GB',' TB'); //original */
$names = array('B','k','M','G','T','P','E');
$suffix = $names[$level];
<td></td>
<th>Name</th>
<th>Last modified</th>
<th>Size</th>
<td></td>
<td><a href="http://example.com/wiki/ExamplePage/files.xml?action=download&file=filename.txt">filename.txt</a></td>
<td>2005-02-03 17:57</td>
<td align="right">189k</td>
<td></td>
<td><a href="http://example.com/wiki/ExamplePage/files.xml?action=download&file=another%20file.txt">another file.txt</a></td>
<td>2005-02-03 17:57</td>
<td align="right">34k</td>
<td></td>
<th>Name</th>
<th>Last modified</th>
<th>Size</th>
<td>[<a href="http://example.com/wiki/ExamplePage/files.xml?action=delete&file=filename.txt">delete</a>]</td>
<td><a href="http://example.com/wiki/ExamplePage/files.xml?action=download&file=filename.txt">filename.txt</a></td>
<td>2005-02-03 17:57</td>
<td align="right">189k</td>
<td>[<a href="http://example.com/wiki/ExamplePage/files.xml?action=delete&file=another%20file.txt">delete</a>]</td>
<td><a href="http://example.com/wiki/ExamplePage/files.xml?action=download&file=another%20file.txt">another file.txt</a></td>
<td>2005-02-03 17:57</td>
<td align="right">34k</td>
case UPLOAD_ERR_OK:
if ($_FILES['file']['size'] > $max_upload_size) {
$status_text = 'Attempted file upload was too big. '
. 'Maximum allowed size is '
. bytesToHumanReadableUsage($max_upload_size) . '.';
unlink($_FILES['file']['tmp_name']);
}
elseif (preg_match('/.+\.('.$allowed_extensions.')$/i', $_FILES['file']['name'])) {
$strippedname = str_replace('\'', '', $_FILES['file']['name']);
$strippedname = stripslashes($strippedname);
$destfile = $upload_path.'/'.$strippedname;
if (!file_exists($destfile)) {
if (move_uploaded_file($_FILES['file']['tmp_name'], $destfile)) {
$status_text = 'File was successfully uploaded.';
}
else {
$status_text = 'There was an error uploading your file.';
}
}
else {
$status_text = 'There is already a file named "' . $strippedname . '".';
}
} else {
$status_text = 'This file\'s extension is unknown.';
unlink($_FILES['file']['tmp_name']);
}
break;
case UPLOAD_ERR_INI_SIZE:
case UPLOAD_ERR_FORM_SIZE:
$status_text = 'Attempted file upload was too big. '
. 'Maximum allowed size is '
. bytesToHumanReadableUsage($max_upload_size).'.';
break;
case UPLOAD_ERR_PARTIAL:
$status_text = 'File upload incomplete. Please try again.';
break;
case UPLOAD_ERR_NO_FILE:
$status_text = 'No file uploaded.';
break;
case UPLOAD_ERR_NO_TMP_DIR:
$status_text = 'File uploads impossible due to misconfigured server.';
break;
$output .= '<p class="status">' . $status_text . '</p>';
<td></td> <!-- For the delete link. Only needed when user is admin or has write rights. -->
<th>Name</th>
<th>Last modified</th>
<th>Size</th>
$num++;
$delete_link = '<!-- delete -->';
/* if ($this->HasAccess('write')) { */
if ($this->IsAdmin()) {
$delete_link = '[<a href="'
. $this->Href('files.xml',$this->GetPageTag(),'action=delete&file='.rawurlencode($file))
. '">delete</a>]';
}
$download_link = '<a href="'
. $this->Href('files.xml',$this->GetPageTag(),'action=download&file='.rawurlencode($file))
. '">'.$file.'</a>';
$size = bytesToHumanReadableUsage(filesize($upload_path . '/' . $file));
$date = date($date_format, filemtime($upload_path . '/' . $file));
// easy even/odd zebra table
// also possible to zebra color every three rows
$row_class = 'r'.$num.' r'.($num % 2).'m2 r'.($num % 3).'m3';
$output .= <<<HEREDOC
<td>{$delete_link}</td>
<td>{$download_link}</td>
<td>{$date}</td>
<td align="right">{$size}</td>
$input_for_rewrite_mode = '<input type="hidden" name="wakka" value="'.$this->MiniHref().'" />';
if ($this->HasAccess('read')) {
$filename = basename($path);
$mimetype = 'application/x-download';
$mimes = file($mime_types_file);
foreach($mimes as $line){
if(preg_match('/^(\w+\/\S+)\b.*\s'.$extension.'\b/i', $line, $matches)){
$mimetype = $matches[1];
break;
}
}
Header('Content-Length: '.filesize($path));
Header('Content-Type: '.$mimetype);
Header('Content-Disposition: attachment; filename="'.$filename.'"; '
.'modification-date="'.date('r', filemtime($path)).'";');
Header('Connection: close');
@readfile($path);
exit();
}
break;
case 'delete':
// if ($this->HasAccess('write')) {
if ($this->IsAdmin()) {
@unlink($path);
}
print $this->redirect($this->Href());
break;
====yet another actions/files.php====
http://wush.net/trac/wikka/ticket/72
Deletions:
<tr>
<td>
 
</td>
<td bgcolor=gray valign=bottom align=center>
<font color=white size=-2>
Attachment
</font>
</td>
<td bgcolor=gray valign=bottom align=center>
<font color=white size=-2>
Size
</font>
</td>
<td bgcolor=gray valign=bottom align=center>
<font color=white size=-2>
Date Added
</font>
</td>
</tr>
<tr>
<td valign=top align=center>
  
{$delete_link}
  
</td>
<td valign=top>
$download_link
</td>
<td valign=top>
 
<font size=-1 color=gray>
$size
</font>
</td>
<td valign=top>
 
<font size=-1 color=gray>
$date
</font>
</td>
</tr>
";
<tr>
<td>
 
</td>
<td colspan=4 valign=top align=right nowrap>
<i>
$result
<input type=\"hidden\" name=\"action\" value=\"upload\">
<font color=gray size=-2>
add new attachment:
<input type=\"file\" name=\"file\" style=\"padding: 0px; margin: 0px; font-size: 8px; height: 15px\">
<input type=\"Submit\" value=\"+\" style=\"padding: 0px; margin: 0px; font-size: 8px; height: 15px\">
".$this->FormClose()."
</font>
</i>
</td>
</tr>
$bytes = 0;
$precision = 0;
/* $names = array(' Bytes',' KB',' MB',' GB',' TB'); //original */
$names = array('B','k','M','G','T','P','E');
$suffix = $names[$level];
<td></td>
<th>Name</th>
<th>Last modified</th>
<th>Size</th>
<td></td>
<td><a href="http://example.com/wiki/ExamplePage/files.xml?action=download&file=filename.txt">filename.txt</a></td>
<td>2005-02-03 17:57</td>
<td align="right">189k</td>
<td></td>
<td><a href="http://example.com/wiki/ExamplePage/files.xml?action=download&file=another%20file.txt">another file.txt</a></td>
<td>2005-02-03 17:57</td>
<td align="right">34k</td>
<td></td>
<th>Name</th>
<th>Last modified</th>
<th>Size</th>
<td>[<a href="http://example.com/wiki/ExamplePage/files.xml?action=delete&file=filename.txt">delete</a>]</td>
<td><a href="http://example.com/wiki/ExamplePage/files.xml?action=download&file=filename.txt">filename.txt</a></td>
<td>2005-02-03 17:57</td>
<td align="right">189k</td>
<td>[<a href="http://example.com/wiki/ExamplePage/files.xml?action=delete&file=another%20file.txt">delete</a>]</td>
<td><a href="http://example.com/wiki/ExamplePage/files.xml?action=download&file=another%20file.txt">another file.txt</a></td>
<td>2005-02-03 17:57</td>
<td align="right">34k</td>
case UPLOAD_ERR_OK:
if ($_FILES['file']['size'] > $max_upload_size) {
$status_text = 'Attempted file upload was too big. '
. 'Maximum allowed size is '
. bytesToHumanReadableUsage($max_upload_size) . '.';
unlink($_FILES['file']['tmp_name']);
}
elseif (preg_match('/.+\.('.$allowed_extensions.')$/i', $_FILES['file']['name'])) {
$strippedname = str_replace('\'', '', $_FILES['file']['name']);
$strippedname = stripslashes($strippedname);
$destfile = $upload_path.'/'.$strippedname;
if (!file_exists($destfile)) {
if (move_uploaded_file($_FILES['file']['tmp_name'], $destfile)) {
$status_text = 'File was successfully uploaded.';
}
else {
$status_text = 'There was an error uploading your file.';
}
}
else {
$status_text = 'There is already a file named "' . $strippedname . '".';
}
} else {
$status_text = 'This file\'s extension is unknown.';
unlink($_FILES['file']['tmp_name']);
}
break;
case UPLOAD_ERR_INI_SIZE:
case UPLOAD_ERR_FORM_SIZE:
$status_text = 'Attempted file upload was too big. '
. 'Maximum allowed size is '
. bytesToHumanReadableUsage($max_upload_size).'.';
break;
case UPLOAD_ERR_PARTIAL:
$status_text = 'File upload incomplete. Please try again.';
break;
case UPLOAD_ERR_NO_FILE:
$status_text = 'No file uploaded.';
break;
case UPLOAD_ERR_NO_TMP_DIR:
$status_text = 'File uploads impossible due to misconfigured server.';
break;
$output .= '<p class="status">' . $status_text . '</p>';
<td></td> <!-- For the delete link. Only needed when user is admin or has write rights. -->
<th>Name</th>
<th>Last modified</th>
<th>Size</th>
$num++;
$delete_link = '<!-- delete -->';
/* if ($this->HasAccess('write')) { */
if ($this->IsAdmin()) {
$delete_link = '[<a href="'
. $this->Href('files.xml',$this->GetPageTag(),'action=delete&file='.rawurlencode($file))
. '">delete</a>]';
}
$download_link = '<a href="'
. $this->Href('files.xml',$this->GetPageTag(),'action=download&file='.rawurlencode($file))
. '">'.$file.'</a>';
$size = bytesToHumanReadableUsage(filesize($upload_path . '/' . $file));
$date = date($date_format, filemtime($upload_path . '/' . $file));
// easy even/odd zebra table
// also possible to zebra color every three rows
$row_class = 'r'.$num.' r'.($num % 2).'m2 r'.($num % 3).'m3';
$output .= <<<HEREDOC
<td>{$delete_link}</td>
<td>{$download_link}</td>
<td>{$date}</td>
<td align="right">{$size}</td>
$input_for_rewrite_mode = '<input type="hidden" name="wakka" value="'.$this->MiniHref().'" />';
if ($this->HasAccess('read')) {
$filename = basename($path);
$mimetype = 'application/x-download';
$mimes = file($mime_types_file);
foreach($mimes as $line){
if(preg_match('/^(\w+\/\S+)\b.*\s'.$extension.'\b/i', $line, $matches)){
$mimetype = $matches[1];
break;
}
}
Header('Content-Length: '.filesize($path));
Header('Content-Type: '.$mimetype);
Header('Content-Disposition: attachment; filename="'.$filename.'"; '
.'modification-date="'.date('r', filemtime($path)).'";');
Header('Connection: close');
@readfile($path);
exit();
}
break;
case 'delete':
// if ($this->HasAccess('write')) {
if ($this->IsAdmin()) {
@unlink($path);
}
print $this->redirect($this->Href());
break;


Revision [5807]

Edited on 2005-02-08 15:18:11 by CryDust [typo]
Additions:
- HeavyK (k m r @ h e a v y k . o r g), 3/27/04
function mkdir_r ($dir) {
if (strlen($dir) == 0) return 0;
if (is_dir($dir)) return 1;
elseif (dirname($dir) == $dir) return 1;
return (mkdir_r(dirname($dir)) and mkdir($dir,0755));
}
/**
* Converts bytes to a human readable string
* @param int $bytes Number of bytes
* @param int $precision Number of decimal places to include in return string
* @param array $names Custom usage strings
* @return string formatted string rounded to $precision
*/
function bytesToHumanReadableUsage($bytes, $precision = 2, $names = '')
{
if (!is_numeric($bytes) || $bytes < 0) {
return false;
}
for ($level = 0; $bytes >= 1024; $level++) {
$bytes /= 1024;
}
switch ($level)
{
case 0:
$suffix = (isset($names[0])) ? $names[0] : 'Bytes';
break;
case 1:
$suffix = (isset($names[1])) ? $names[1] : 'KB';
break;
case 2:
$suffix = (isset($names[2])) ? $names[2] : 'MB';
break;
case 3:
$suffix = (isset($names[3])) ? $names[3] : 'GB';
break;
case 4:
$suffix = (isset($names[4])) ? $names[4] : 'TB';
break;
default:
$suffix = (isset($names[$level])) ? $names[$level] : '';
break;
}
if (empty($suffix)) {
trigger_error('Unable to find suffix for case ' . $level);
return false;
}
return round($bytes, $precision) . ' ' . $suffix;
}
// link to download a file
if ($text == '') $text = $download;
echo "<a href=\"".$this->href('files.xml',$this->GetPageTag(),'action=download&file='.urlencode($download))."\">".$text."</a>";
// upload path
if ($this->config['upload_path'] == '') $this->config['upload_path'] = 'files';
$upload_path = $this->config['upload_path'].'/'.$this->GetPageTag();
if (! is_dir($upload_path)) mkdir_r($upload_path);
// upload action
$uploaded = $_FILES['file'];
if ($_REQUEST['action'] == 'upload' AND $uploaded['size'] > 0)
copy ($uploaded['tmp_name'], $upload_path.'/'.$uploaded['name']);
// uploaded files
print "
<table cellspacing=0 cellpadding=0>
<td>
 
</td>
<td bgcolor=gray valign=bottom align=center>
<font color=white size=-2>
Attachment
</font>
</td>
<td bgcolor=gray valign=bottom align=center>
<font color=white size=-2>
Size
</font>
</td>
<td bgcolor=gray valign=bottom align=center>
<font color=white size=-2>
Date Added
</font>
</td>
";
$dir = opendir($upload_path);
while ($file = readdir($dir)) {
if ($file != '.' && $file != '..') {
$num++;
$delete_link = "<a href=\"".$this->href('files.xml',$this->GetPageTag(),'action=delete&file='.urlencode($file))."\">x</a>";
$download_link = "<a href=\"".$this->href('files.xml',$this->GetPageTag(),'action=download&file='.urlencode($file))."\">".$file."</a>";
$size = bytesToHumanReadableUsage(filesize("$upload_path/$file"));
$date = date("n/d/Y g:i a",filemtime("$upload_path/$file"));
print "
<tr>
<td valign=top align=center>
  
{$delete_link}
  
</td>
<td valign=top>
$download_link
</td>
<td valign=top>
 
<font size=-1 color=gray>
$size
</font>
</td>
<td valign=top>
 
<font size=-1 color=gray>
$date
</font>
</td>
</tr>
";
}
}
closedir($dir);
// print n/a if no files currently exist
if (!$num) print "<tr><td> </td><td colspan=3 align=center><font color=gray size=-1><i>   </i></font></td></tr>";
else print "<tr><td> </td></tr>";
// form
$result = "<form action=\"".$this->href()."\" method=\"post\" enctype=\"multipart/form-data\">\n";
if (!$this->config["rewrite_mode"]) $result .= "<input type=\"hidden\" name=\"wakka\" value=\"".$this->MiniHref()."\">\n";
echo $result;
//<input type="hidden" name="action" value="upload"><input type="file" name="file"><input type="submit" value="+">
echo $this->FormClose();
// close disp table
print "
<td>
 
</td>
<td colspan=4 valign=top align=right nowrap>
<i>
$result
<input type=\"hidden\" name=\"action\" value=\"upload\">
<font color=gray size=-2>
add new attachment:
<input type=\"file\" name=\"file\" style=\"padding: 0px; margin: 0px; font-size: 8px; height: 15px\">
<input type=\"Submit\" value=\"+\" style=\"padding: 0px; margin: 0px; font-size: 8px; height: 15px\">
".$this->FormClose()."
</font>
</i>
</td>
</table>
";
function mkdir_r ($dir) {
if (strlen($dir) == 0) return 0;
if (is_dir($dir)) return 1;
elseif (dirname($dir) == $dir) return 1;
return (mkdir_r(dirname($dir)) and mkdir($dir,0755));
}
// link to download a file
if ($text == '') $text = $download;
echo "<a href=\"".$this->href('files.xml',$this->GetPageTag(),'action=download&file='.urlencode($download))."\">".$text."</a>";
// upload path
if ($this->config['upload_path'] == '') $this->config['upload_path'] = 'files';
$upload_path = $this->config['upload_path'].'/'.$this->GetPageTag();
if (! is_dir($upload_path)) mkdir_r($upload_path);
// upload action
$uploaded = $_FILES['file'];
if ($_REQUEST['action'] == 'upload' AND $uploaded['size'] > 0)
copy ($uploaded['tmp_name'], $upload_path.'/'.$uploaded['name']);
// form
$result = "<form action=\"".$this->href()."\" method=\"post\" enctype=\"multipart/form-data\">\n";
if (!$this->config["rewrite_mode"]) $result .= "<input type=\"hidden\" name=\"wakka\" value=\"".$this->MiniHref()."\">\n";
echo $result;
?>
<input type="hidden" name="action" value="upload"><input type="file" name="file"><input type="submit" value="+">
<?php
echo $this->FormClose();
// uploaded files
$dir = opendir($upload_path);
while ($file = readdir($dir)) {
if ($file != '.' && $file != '..') {
$delete_link = "<a href=\"".$this->href('files.xml',$this->GetPageTag(),'action=delete&file='.urlencode($file))."\">x</a>";
$download_link = "<a href=\"".$this->href('files.xml',$this->GetPageTag(),'action=download&file='.urlencode($file))."\">".$file."</a>";
print "[ {$delete_link} ] ";
if ($file == $uploaded['name'])
print "<em>{$download_link}</em>\n";
else
print $download_link;
print '<br>';
}
}
closedir($dir);
$mime_types=array();
/* open our mime.types file for reading */
$mt_fd=fopen($mt_f,"r");
while (!feof($mt_fd)) {
/* pull a line off the file */
$mt_buf=trim(fgets($mt_fd,1024));
/* discard if the line was blank or started with a comment */
if (strlen($mt_buf) > 0) if (substr($mt_buf,0,1) != "#") {
/* make temp array of the mime.types line we just read */
$mt_tmp=preg_split("/[\s]+/", $mt_buf, -1, PREG_SPLIT_NO_EMPTY);
$mt_num=count($mt_tmp);
/* if $mt_num = 1 then we got no file extensions for the type */
if ($mt_num > 1) {
for ($i=1;$i<$mt_num;$i++) {
/* if we find a comment mid-line, stop processing */
if (strstr($mt_tmp[$i],"#")) {
break;
/* otherwise stick the type in an array keyed by extension */
} else {
$mime_types[$mt_tmp[$i]]=$mt_tmp[0];
}
/* zero the temporary array */
unset($mt_tmp);
}
}
/* close the mime.types file we were reading */
fclose($mt_fd);
echo "ERROR: unreadable file " . $mt_f . "\n";
case 'download':
$_REQUEST['file'] = urldecode($_REQUEST['file']);
if ($this->HasAccess('read')) {
$path = "{$upload_path}/{$_REQUEST['file']}";
$filename = basename($path);
header('MIME-Version: 1.0');
$afn = split("\.",$filename);
$ext = strtolower($afn[count($afn)-1]);
$mime_type = $mime_types[$ext];
if ($mime_type == '') $mime_type = 'application/octet-stream';
header("Content-Type: {$mime_type}; name=\"{$filename}\"");
header('Content-Length: '. filesize($path));
header("Content-Disposition: filename=\"{$filename}\"");
$fp=fopen($path,'r');
print fread($fp,filesize($path));
fclose($fp);
exit();
case 'delete':
if ($this->HasAccess('write')) {
@unlink("{$upload_path}/{$_REQUEST['file']}");
print $this->redirect($this->href());
- files.xml
- files.xml.php
if ($tokens['download'] ) {
// link to download a file
$text = $this->stripquotes($action_params['download']);
if ($tokens['text'])
{
$text = $this->stripquotes($action_params['text']);
}
echo "<a href=\"".$this->href('files.xml',$this->GetPageTag(),'action=download&file='.urlencode($this->stripquotes($action_params['download'])))."\">".$text."</a>";
function mkdir_r ($dir) {
if (strlen($dir) == 0) return 0;
if (is_dir($dir)) return 1;
elseif (dirname($dir) == $dir) return 1;
return (mkdir_r(dirname($dir)) and mkdir($dir,0755));
}
/**
* Converts bytes to a human readable string
* @param int $bytes Number of bytes
* @param int $precision Number of decimal places to include in return string
* @param array $names Custom usage strings
* @return string formatted string rounded to $precision
*/
function bytesToHumanReadableUsage($bytes, $precision = 0, $names = '') {
if (!is_numeric($bytes) || $bytes < 0) {
$bytes = 0;
}

if (!is_numeric($precision) || $precision < 0) {
$precision = 0;
}

if (!is_array($names)) {
/* $names = array(' Bytes',' KB',' MB',' GB',' TB'); //original */
$names = array('B','k','M','G','T','P','E');
}

$level = floor(log($bytes)/log(1024));

$suffix = '';
if ($level < count($names)) {
$suffix = $names[$level];
}

return round($bytes/pow(1024, $level), $precision) . $suffix;
}
define('UPLOAD_ERR_OK', 0);
define('UPLOAD_ERR_INI_SIZE', 1);
define('UPLOAD_ERR_FORM_SIZE', 2);
define('UPLOAD_ERR_PARTIAL', 3);
define('UPLOAD_ERR_NO_FILE', 4);
define('UPLOAD_ERR_NO_TMP_DIR', 6);
<thead>
<tr>
<td></td>
<th>Name</th>
<th>Last modified</th>
<th>Size</th>
</tr>
</thead>
<tbody>
<tr class="r1 r1m2 r1m3">
<td></td>
<td><a href="http://example.com/wiki/ExamplePage/files.xml?action=download&file=filename.txt">filename.txt</a></td>
<td>2005-02-03 17:57</td>
<td align="right">189k</td>
</tr>
<tr class="r2 r0m2 r2m3">
<td></td>
<td><a href="http://example.com/wiki/ExamplePage/files.xml?action=download&file=another%20file.txt">another file.txt</a></td>
<td>2005-02-03 17:57</td>
<td align="right">34k</td>
</tr>
<thead>
<tr>
<td></td>
<th>Name</th>
<th>Last modified</th>
<th>Size</th>
</tr>
</thead>
<tbody>
<tr class="r1 r1m2 r1m3">
<td>[<a href="http://example.com/wiki/ExamplePage/files.xml?action=delete&file=filename.txt">delete</a>]</td>
<td><a href="http://example.com/wiki/ExamplePage/files.xml?action=download&file=filename.txt">filename.txt</a></td>
<td>2005-02-03 17:57</td>
<td align="right">189k</td>
</tr>
<tr class="r2 r0m2 r2m3">
<td>[<a href="http://example.com/wiki/ExamplePage/files.xml?action=delete&file=another%20file.txt">delete</a>]</td>
<td><a href="http://example.com/wiki/ExamplePage/files.xml?action=download&file=another%20file.txt">another file.txt</a></td>
<td>2005-02-03 17:57</td>
<td align="right">34k</td>
</tr>
<p>

<input type="hidden" name="action" value="upload" />
<input type="hidden" name="MAX_FILE_SIZE" value="2097152" />
add new attachment:
<input type="file" name="file" />
<input type="submit" value="Upload" />
</p>
// link to download a file
if ($vars['text'] == '') $text = $vars['download'];
$output .= '<a href="'
. $this->Href(
'files.xml',
$this->GetPageTag(),
'action=download&file='.
rawurlencode($vars['download'])
)
. '">'
. $vars['text']
. '</a>';
// upload path
if ($this->config['upload_path'] == '') {
$this->config['upload_path'] = 'files';
}

$upload_path = $this->config['upload_path'].'/'.$this->GetPageTag();

if (! is_dir($upload_path)) {
mkdir_r($upload_path);
}

// upload action
if ($_POST['action'] == 'upload') {

$status_text = '';

switch ($_FILES['file']['error']) {
case UPLOAD_ERR_OK:
if ($_FILES['file']['size'] > $max_upload_size) {
$status_text = 'Attempted file upload was too big. '
. 'Maximum allowed size is '
. bytesToHumanReadableUsage($max_upload_size) . '.';
unlink($_FILES['file']['tmp_name']);
}
elseif (preg_match('/.+\.('.$allowed_extensions.')$/i', $_FILES['file']['name'])) {
$strippedname = str_replace('\'', '', $_FILES['file']['name']);
$strippedname = stripslashes($strippedname);
$destfile = $upload_path.'/'.$strippedname;
if (!file_exists($destfile)) {
if (move_uploaded_file($_FILES['file']['tmp_name'], $destfile)) {
$status_text = 'File was successfully uploaded.';
}
else {
$status_text = 'There was an error uploading your file.';
}
}
else {
$status_text = 'There is already a file named "' . $strippedname . '".';
}
} else {
$status_text = 'This file\'s extension is unknown.';
unlink($_FILES['file']['tmp_name']);
}
break;
case UPLOAD_ERR_INI_SIZE:
case UPLOAD_ERR_FORM_SIZE:
$status_text = 'Attempted file upload was too big. '
. 'Maximum allowed size is '
. bytesToHumanReadableUsage($max_upload_size).'.';
break;
case UPLOAD_ERR_PARTIAL:
$status_text = 'File upload incomplete. Please try again.';
break;
case UPLOAD_ERR_NO_FILE:
$status_text = 'No file uploaded.';
break;
case UPLOAD_ERR_NO_TMP_DIR:
$status_text = 'File uploads impossible due to misconfigured server.';
break;
}
if ($status_text != '') {
$output .= '<p class="status">' . $status_text . '</p>';
}
}

// uploaded files
$output .= <<<HEREDOC
<thead>
<tr>
<td></td> <!-- For the delete link. Only needed when user is admin or has write rights. -->
<th>Name</th>
<th>Last modified</th>
<th>Size</th>
</tr>
</thead>
<tbody>
$dir = opendir($upload_path);
$num = 0;
while ($file = readdir($dir)) {
/* if ( $file != '.' && $file != '..') { */
if ($file{0} != '.') {
$num++;
$delete_link = '<!-- delete -->';
/* if ($this->HasAccess('write')) { */
if ($this->IsAdmin()) {
$delete_link = '[<a href="'
. $this->Href('files.xml',$this->GetPageTag(),'action=delete&file='.rawurlencode($file))
. '">delete</a>]';
}
$download_link = '<a href="'
. $this->Href('files.xml',$this->GetPageTag(),'action=download&file='.rawurlencode($file))
. '">'.$file.'</a>';
$size = bytesToHumanReadableUsage(filesize($upload_path . '/' . $file));
$date = date($date_format, filemtime($upload_path . '/' . $file));
// easy even/odd zebra table
// also possible to zebra color every three rows
$row_class = 'r'.$num.' r'.($num % 2).'m2 r'.($num % 3).'m3';
$output .= <<<HEREDOC
<tr class="{$row_class}">
<td>{$delete_link}</td>
<td>{$download_link}</td>
<td>{$date}</td>
<td align="right">{$size}</td>
</tr>
}
}
closedir($dir);
// print n/a if no files currently exist
if ($num < 1) {
$output .= <<<HEREDOC
<tr><td colspan="4">no files here</td></tr>
}
$input_for_rewrite_mode = '<!-- rewrite mode disabled -->';
if (!$this->config['rewrite_mode']){
$input_for_rewrite_mode = '<input type="hidden" name="wakka" value="'.$this->MiniHref().'" />';
// close disp table
$href = $this->Href();
$output .= <<<HEREDOC
<p>
{$input_for_rewrite_mode}
<input type="hidden" name="action" value="upload" />
<input type="hidden" name="MAX_FILE_SIZE" value="{$max_upload_size}" />
add new attachment:
<input type="file" name="file" />
<input type="submit" value="Upload" />
</p>
$this->config['upload_path'] = 'files';
mkdir_r($upload_path);
$extension = array_pop($parts);

$path = $upload_path.'/'.basename(urldecode($_REQUEST['file']));

// do the action
switch ($_REQUEST['action']) {
case 'download':
if ($this->HasAccess('read')) {
$filename = basename($path);
$mimetype = 'application/x-download';
$mimes = file($mime_types_file);
foreach($mimes as $line){
if(preg_match('/^(\w+\/\S+)\b.*\s'.$extension.'\b/i', $line, $matches)){
$mimetype = $matches[1];
break;
}
}
Header('Content-Length: '.filesize($path));
Header('Content-Type: '.$mimetype);
Header('Content-Disposition: attachment; filename="'.$filename.'"; '
.'modification-date="'.date('r', filemtime($path)).'";');
Deletions:
- HeavyK (k m r @ h e a v y k . o r g), 3/27/04
function mkdir_r ($dir) {
if (strlen($dir) == 0) return 0;
if (is_dir($dir)) return 1;
elseif (dirname($dir) == $dir) return 1;
return (mkdir_r(dirname($dir)) and mkdir($dir,0755));
/**
* Converts bytes to a human readable string
* @param int $bytes Number of bytes
* @param int $precision Number of decimal places to include in return string
* @param array $names Custom usage strings
* @return string formatted string rounded to $precision
*/
function bytesToHumanReadableUsage($bytes, $precision = 2, $names = '')
{
if (!is_numeric($bytes) || $bytes < 0) {
return false;
}

for ($level = 0; $bytes >= 1024; $level++) {
$bytes /= 1024;
}
switch ($level)
{
case 0:
$suffix = (isset($names[0])) ? $names[0] : 'Bytes';
break;
case 1:
$suffix = (isset($names[1])) ? $names[1] : 'KB';
break;
case 2:
$suffix = (isset($names[2])) ? $names[2] : 'MB';
break;
case 3:
$suffix = (isset($names[3])) ? $names[3] : 'GB';
break;
case 4:
$suffix = (isset($names[4])) ? $names[4] : 'TB';
break;
default:
$suffix = (isset($names[$level])) ? $names[$level] : '';
break;
}
if (empty($suffix)) {
trigger_error('Unable to find suffix for case ' . $level);
return false;
}
return round($bytes, $precision) . ' ' . $suffix;
}
// link to download a file
if ($text == '') $text = $download;
echo "<a href=\"".$this->href('files.xml',$this->GetPageTag(),'action=download&file='.urlencode($download))."\">".$text."</a>";
// upload path
if ($this->config['upload_path'] == '') $this->config['upload_path'] = 'files';
$upload_path = $this->config['upload_path'].'/'.$this->GetPageTag();
if (! is_dir($upload_path)) mkdir_r($upload_path);
// upload action
$uploaded = $_FILES['file'];
if ($_REQUEST['action'] == 'upload' AND $uploaded['size'] > 0)
copy ($uploaded['tmp_name'], $upload_path.'/'.$uploaded['name']);
// uploaded files
print "
<table cellspacing=0 cellpadding=0>
<tr>
<td>
 
</td>
<td bgcolor=gray valign=bottom align=center>
<font color=white size=-2>
Attachment
</font>
</td>
<td bgcolor=gray valign=bottom align=center>
<font color=white size=-2>
Size
</font>
</td>
<td bgcolor=gray valign=bottom align=center>
<font color=white size=-2>
Date Added
</font>
</td>
</tr>
";
$dir = opendir($upload_path);
while ($file = readdir($dir)) {
if ($file != '.' && $file != '..') {
$num++;
$delete_link = "<a href=\"".$this->href('files.xml',$this->GetPageTag(),'action=delete&file='.urlencode($file))."\">x</a>";
$download_link = "<a href=\"".$this->href('files.xml',$this->GetPageTag(),'action=download&file='.urlencode($file))."\">".$file."</a>";
$size = bytesToHumanReadableUsage(filesize("$upload_path/$file"));
$date = date("n/d/Y g:i a",filemtime("$upload_path/$file"));
print "
<tr>
<td valign=top align=center>
  
{$delete_link}
  
</td>
<td valign=top>
$download_link
</td>
<td valign=top>
 
<font size=-1 color=gray>
$size
</font>
</td>
<td valign=top>
 
<font size=-1 color=gray>
$date
</font>
</td>
</tr>
";
}
closedir($dir);
// print n/a if no files currently exist
if (!$num) print "<tr><td> </td><td colspan=3 align=center><font color=gray size=-1><i>   </i></font></td></tr>";
else print "<tr><td> </td></tr>";
$result = "<form action=\"".$this->href()."\" method=\"post\" enctype=\"multipart/form-data\">\n";
if (!$this->config["rewrite_mode"]) $result .= "<input type=\"hidden\" name=\"wakka\" value=\"".$this->MiniHref()."\">\n";
echo $result;
//<input type="hidden" name="action" value="upload"><input type="file" name="file"><input type="submit" value="+">
echo $this->FormClose();
// close disp table
print "
<tr>
<td>
 
</td>
<td colspan=4 valign=top align=right nowrap>
<i>
$result
<input type=\"hidden\" name=\"action\" value=\"upload\">
<font color=gray size=-2>
add new attachment:
<input type=\"file\" name=\"file\" style=\"padding: 0px; margin: 0px; font-size: 8px; height: 15px\">
<input type=\"Submit\" value=\"+\" style=\"padding: 0px; margin: 0px; font-size: 8px; height: 15px\">
".$this->FormClose()."
</font>
</i>
</td>
</tr>
</table>
";
function mkdir_r ($dir) {
if (strlen($dir) == 0) return 0;
if (is_dir($dir)) return 1;
elseif (dirname($dir) == $dir) return 1;
return (mkdir_r(dirname($dir)) and mkdir($dir,0755));
// link to download a file
if ($text == '') $text = $download;
echo "<a href=\"".$this->href('files.xml',$this->GetPageTag(),'action=download&file='.urlencode($download))."\">".$text."</a>";
// upload path
if ($this->config['upload_path'] == '') $this->config['upload_path'] = 'files';
$upload_path = $this->config['upload_path'].'/'.$this->GetPageTag();
if (! is_dir($upload_path)) mkdir_r($upload_path);
// upload action
$uploaded = $_FILES['file'];
if ($_REQUEST['action'] == 'upload' AND $uploaded['size'] > 0)
copy ($uploaded['tmp_name'], $upload_path.'/'.$uploaded['name']);
$result = "<form action=\"".$this->href()."\" method=\"post\" enctype=\"multipart/form-data\">\n";
if (!$this->config["rewrite_mode"]) $result .= "<input type=\"hidden\" name=\"wakka\" value=\"".$this->MiniHref()."\">\n";
echo $result;
?>
<input type="hidden" name="action" value="upload"><input type="file" name="file"><input type="submit" value="+">
<?php
echo $this->FormClose();
// uploaded files
$dir = opendir($upload_path);
while ($file = readdir($dir)) {
if ($file != '.' && $file != '..') {
$delete_link = "<a href=\"".$this->href('files.xml',$this->GetPageTag(),'action=delete&file='.urlencode($file))."\">x</a>";
$download_link = "<a href=\"".$this->href('files.xml',$this->GetPageTag(),'action=download&file='.urlencode($file))."\">".$file."</a>";
print "[ {$delete_link} ] ";
if ($file == $uploaded['name'])
print "<em>{$download_link}</em>\n";
else
print $download_link;
print '<br>';
}
closedir($dir);
$mime_types=array();
/* open our mime.types file for reading */
$mt_fd=fopen($mt_f,"r");
while (!feof($mt_fd)) {
/* pull a line off the file */
$mt_buf=trim(fgets($mt_fd,1024));
/* discard if the line was blank or started with a comment */
if (strlen($mt_buf) > 0) if (substr($mt_buf,0,1) != "#") {
/* make temp array of the mime.types line we just read */
$mt_tmp=preg_split("/[\s]+/", $mt_buf, -1, PREG_SPLIT_NO_EMPTY);
$mt_num=count($mt_tmp);
/* if $mt_num = 1 then we got no file extensions for the type */
if ($mt_num > 1) {
for ($i=1;$i<$mt_num;$i++) {
/* if we find a comment mid-line, stop processing */
if (strstr($mt_tmp[$i],"#")) {
break;
/* otherwise stick the type in an array keyed by extension */
} else {
$mime_types[$mt_tmp[$i]]=$mt_tmp[0];
}
}
/* zero the temporary array */
unset($mt_tmp);
}
}
/* close the mime.types file we were reading */
fclose($mt_fd);
echo "ERROR: unreadable file " . $mt_f . "\n";
case 'download':
$_REQUEST['file'] = urldecode($_REQUEST['file']);
if ($this->HasAccess('read')) {
$path = "{$upload_path}/{$_REQUEST['file']}";
$filename = basename($path);
header('MIME-Version: 1.0');
$afn = split("\.",$filename);
$ext = strtolower($afn[count($afn)-1]);
$mime_type = $mime_types[$ext];
if ($mime_type == '') $mime_type = 'application/octet-stream';
header("Content-Type: {$mime_type}; name=\"{$filename}\"");
header('Content-Length: '. filesize($path));
header("Content-Disposition: filename=\"{$filename}\"");
$fp=fopen($path,'r');
print fread($fp,filesize($path));
fclose($fp);
exit();
}
case 'delete':
if ($this->HasAccess('write')) {
@unlink("{$upload_path}/{$_REQUEST['file']}");
print $this->redirect($this->href());
}
- files.xml
- files.xml.php
if ($tokens['download'] ) {
// link to download a file
$text = $this->stripquotes($action_params['download']);
if ($tokens['text'])
{
$text = $this->stripquotes($action_params['text']);
echo "<a href=\"".$this->href('files.xml',$this->GetPageTag(),'action=download&file='.urlencode($this->stripquotes($action_params['download'])))."\">".$text."</a>";
function mkdir_r ($dir) {
if (strlen($dir) == 0) return 0;
if (is_dir($dir)) return 1;
elseif (dirname($dir) == $dir) return 1;
return (mkdir_r(dirname($dir)) and mkdir($dir,0755));
/**
* Converts bytes to a human readable string
* @param int $bytes Number of bytes
* @param int $precision Number of decimal places to include in return string
* @param array $names Custom usage strings
* @return string formatted string rounded to $precision
*/
function bytesToHumanReadableUsage($bytes, $precision = 0, $names = '') {
if (!is_numeric($bytes) || $bytes < 0) {
$bytes = 0;
}

if (!is_numeric($precision) || $precision < 0) {
$precision = 0;
}

if (!is_array($names)) {
/* $names = array(' Bytes',' KB',' MB',' GB',' TB'); //original */
$names = array('B','k','M','G','T','P','E');
}

$level = floor(log($bytes)/log(1024));

$suffix = '';
if ($level < count($names)) {
$suffix = $names[$level];
}

return round($bytes/pow(1024, $level), $precision) . $suffix;
define('UPLOAD_ERR_OK', 0);
define('UPLOAD_ERR_INI_SIZE', 1);
define('UPLOAD_ERR_FORM_SIZE', 2);
define('UPLOAD_ERR_PARTIAL', 3);
define('UPLOAD_ERR_NO_FILE', 4);
define('UPLOAD_ERR_NO_TMP_DIR', 6);
<thead>
<td></td>
<th>Name</th>
<th>Last modified</th>
<th>Size</th>
</thead>
<tbody>
<tr class="r1 r1m2 r1m3">
<td></td>
<td><a href="http://example.com/wiki/ExamplePage/files.xml?action=download&file=filename.txt">filename.txt</a></td>
<td>2005-02-03 17:57</td>
<td align="right">189k</td>
<tr class="r2 r0m2 r2m3">
<td></td>
<td><a href="http://example.com/wiki/ExamplePage/files.xml?action=download&file=another%20file.txt">another file.txt</a></td>
<td>2005-02-03 17:57</td>
<td align="right">34k</td>
<thead>
<td></td>
<th>Name</th>
<th>Last modified</th>
<th>Size</th>
</thead>
<tbody>
<tr class="r1 r1m2 r1m3">
<td>[<a href="http://example.com/wiki/ExamplePage/files.xml?action=delete&file=filename.txt">delete</a>]</td>
<td><a href="http://example.com/wiki/ExamplePage/files.xml?action=download&file=filename.txt">filename.txt</a></td>
<td>2005-02-03 17:57</td>
<td align="right">189k</td>
<tr class="r2 r0m2 r2m3">
<td>[<a href="http://example.com/wiki/ExamplePage/files.xml?action=delete&file=another%20file.txt">delete</a>]</td>
<td><a href="http://example.com/wiki/ExamplePage/files.xml?action=download&file=another%20file.txt">another file.txt</a></td>
<td>2005-02-03 17:57</td>
<td align="right">34k</td>
<p>

<input type="hidden" name="action" value="upload" />
<input type="hidden" name="MAX_FILE_SIZE" value="2097152" />
add new attachment:
<input type="file" name="file" />
<input type="submit" value="Upload" />
</p>
// link to download a file
if ($vars['text'] == '') $text = $vars['download'];
$output .= '<a href="'
. $this->Href(
'files.xml',
$this->GetPageTag(),
'action=download&file='.
rawurlencode($vars['download'])
)
. '">'
. $vars['text']
. '</a>';
// upload path
if ($this->config['upload_path'] == '') {
$this->config['upload_path'] = 'files';
$upload_path = $this->config['upload_path'].'/'.$this->GetPageTag();
if (! is_dir($upload_path)) {
mkdir_r($upload_path);
// upload action
if ($_POST['action'] == 'upload') {

$status_text = '';

switch ($_FILES['file']['error']) {
case UPLOAD_ERR_OK:
if ($_FILES['file']['size'] > $max_upload_size) {
$status_text = 'Attempted file upload was too big. '
. 'Maximum allowed size is '
. bytesToHumanReadableUsage($max_upload_size) . '.';
unlink($_FILES['file']['tmp_name']);
}
elseif (preg_match('/.+\.('.$allowed_extensions.')$/i', $_FILES['file']['name'])) {
$strippedname = str_replace('\'', '', $_FILES['file']['name']);
$strippedname = stripslashes($strippedname);
$destfile = $upload_path.'/'.$strippedname;
if (!file_exists($destfile)) {
if (move_uploaded_file($_FILES['file']['tmp_name'], $destfile)) {
$status_text = 'File was successfully uploaded.';
}
else {
$status_text = 'There was an error uploading your file.';
}
}
else {
$status_text = 'There is already a file named "' . $strippedname . '".';
}
} else {
$status_text = 'This file\'s extension is unknown.';
unlink($_FILES['file']['tmp_name']);
}
break;
case UPLOAD_ERR_INI_SIZE:
case UPLOAD_ERR_FORM_SIZE:
$status_text = 'Attempted file upload was too big. '
. 'Maximum allowed size is '
. bytesToHumanReadableUsage($max_upload_size).'.';
break;
case UPLOAD_ERR_PARTIAL:
$status_text = 'File upload incomplete. Please try again.';
break;
case UPLOAD_ERR_NO_FILE:
$status_text = 'No file uploaded.';
break;
case UPLOAD_ERR_NO_TMP_DIR:
$status_text = 'File uploads impossible due to misconfigured server.';
break;
}
if ($status_text != '') {
$output .= '<p class="status">' . $status_text . '</p>';
}
// uploaded files
$output .= <<<HEREDOC
<thead>
<td></td> <!-- For the delete link. Only needed when user is admin or has write rights. -->
<th>Name</th>
<th>Last modified</th>
<th>Size</th>
</thead>
<tbody>
$dir = opendir($upload_path);
$num = 0;
while ($file = readdir($dir)) {
/* if ( $file != '.' && $file != '..') { */
if ($file{0} != '.') {
$num++;
$delete_link = '<!-- delete -->';
/* if ($this->HasAccess('write')) { */
$delete_link = '[<a href="'
. $this->Href('files.xml',$this->GetPageTag(),'action=delete&file='.rawurlencode($file))
. '">delete</a>]';
$download_link = '<a href="'
. $this->Href('files.xml',$this->GetPageTag(),'action=download&file='.rawurlencode($file))
. '">'.$file.'</a>';
$size = bytesToHumanReadableUsage(filesize($upload_path . '/' . $file));
$date = date($date_format, filemtime($upload_path . '/' . $file));
// easy even/odd zebra table
// also possible to zebra color every three rows
$row_class = 'r'.$num.' r'.($num % 2).'m2 r'.($num % 3).'m3';
$output .= <<<HEREDOC
<tr class="{$row_class}">
<td>{$delete_link}</td>
<td>{$download_link}</td>
<td>{$date}</td>
<td align="right">{$size}</td>
}
closedir($dir);
// print n/a if no files currently exist
if ($num < 1) {
$output .= <<<HEREDOC
<tr><td colspan="4">no files here</td></tr>
// form
$input_for_rewrite_mode = '<!-- rewrite mode disabled -->';
if (!$this->config['rewrite_mode']){
$input_for_rewrite_mode = '<input type="hidden" name="wakka" value="'.$this->MiniHref().'" />';
}
// close disp table
$href = $this->Href();
$output .= <<<HEREDOC
<p>
{$input_for_rewrite_mode}
<input type="hidden" name="action" value="upload" />
<input type="hidden" name="MAX_FILE_SIZE" value="{$max_upload_size}" />
add new attachment:
<input type="file" name="file" />
<input type="submit" value="Upload" />
</p>
$this->config['upload_path'] = 'files';
mkdir_r($upload_path);
$extension = array_pop($parts);
$path = $upload_path.'/'.basename(urldecode($_REQUEST['file']));
// do the action
switch ($_REQUEST['action']) {
case 'download':
if ($this->HasAccess('read')) {
$filename = basename($path);
$mimetype = 'application/x-download';
$mimes = file($mime_types_file);
foreach($mimes as $line){
if(preg_match('/^(\w+/\S+)\b.*\s'.$extension.'\b/i', $line, $matches)){
$mimetype = $matches[1];
break;
}
}
Header('Content-Length: '.filesize($path));
Header('Content-Type: '.$mimetype);
Header('Content-Disposition: attachment; filename="'.$filename.'"; '
.'modification-date="'.date('r', filemtime($path)).'";');


Revision [5801]

Edited on 2005-02-08 12:53:59 by CryDust [oops, small mistakes in code]
Additions:
$base_name = basename(urldecode($_REQUEST['file']));
if ($first_letter != '.' && stristr('|'.$allowed_extensions.'|', '|'.$extension.'|')) {
Deletions:
$base_name = basename(urldecode($_REQUEST['file']))
if ($first_letter != '.' && stristr('|'.$allowed_extensions.'|', '|'.$extension.'|') {


Revision [5800]

Edited on 2005-02-08 12:37:12 by CryDust [add explanation]
Additions:
I cleaned up the code and added:
~- mime types when downloading a file
~- security check on file extension
~- more error checking
~- semanticly correct output for easier styling


Revision [5798]

Edited on 2005-02-08 12:25:04 by CryDust [add explanation]
Additions:
=====Development of Files action=====

<<This is the development page for the ""{{files}}"" action.
~-For info about the version currently included in Wikka, take a look at Mod015fFilesAction.
~-For a documentation of how to use the current version, look at FilesActionInfo.
<<::c::

handlers/page/files.xml.php didn't work for me, so i use FilesActionHillar
~&Hillar, can you explain //why// it didn't work for you, and how you solved that? --JavaWoman

===Actual version===

The code below offers a more visually improved layout for this handler and also displays the file size and the date of file upload.
- HeavyK (k m r @ h e a v y k . o r g), 3/27/04

**actions/files.php**
%%(php)
<?php
if (! function_exists('mkdir_r')) {
function mkdir_r ($dir) {
if (strlen($dir) == 0) return 0;
if (is_dir($dir)) return 1;
elseif (dirname($dir) == $dir) return 1;
return (mkdir_r(dirname($dir)) and mkdir($dir,0755));
}
}

if (! function_exists('bytesToHumanReadableUsage')) {
/**
* Converts bytes to a human readable string
* @param int $bytes Number of bytes
* @param int $precision Number of decimal places to include in return string
* @param array $names Custom usage strings
* @return string formatted string rounded to $precision
*/
function bytesToHumanReadableUsage($bytes, $precision = 2, $names = '')
{
if (!is_numeric($bytes) || $bytes < 0) {
return false;
}

for ($level = 0; $bytes >= 1024; $level++) {
$bytes /= 1024;
}

switch ($level)
{
case 0:
$suffix = (isset($names[0])) ? $names[0] : 'Bytes';
break;
case 1:
$suffix = (isset($names[1])) ? $names[1] : 'KB';
break;
case 2:
$suffix = (isset($names[2])) ? $names[2] : 'MB';
break;
case 3:
$suffix = (isset($names[3])) ? $names[3] : 'GB';
break;
case 4:
$suffix = (isset($names[4])) ? $names[4] : 'TB';
break;
default:
$suffix = (isset($names[$level])) ? $names[$level] : '';
break;
}

if (empty($suffix)) {
trigger_error('Unable to find suffix for case ' . $level);
return false;
}

return round($bytes, $precision) . ' ' . $suffix;
}
}


if ($download <> '') {

// link to download a file
if ($text == '') $text = $download;
echo "<a href=\"".$this->href('files.xml',$this->GetPageTag(),'action=download&file='.urlencode($download))."\">".$text."</a>";

} elseif ($this->page AND $this->HasAccess('write') AND ($this->method <> 'print.xml') AND ($this->method <> 'edit')) {

// upload path
if ($this->config['upload_path'] == '') $this->config['upload_path'] = 'files';
$upload_path = $this->config['upload_path'].'/'.$this->GetPageTag();
if (! is_dir($upload_path)) mkdir_r($upload_path);

// upload action
$uploaded = $_FILES['file'];
if ($_REQUEST['action'] == 'upload' AND $uploaded['size'] > 0)
copy ($uploaded['tmp_name'], $upload_path.'/'.$uploaded['name']);

// uploaded files
print "

<table cellspacing=0 cellpadding=0>
<tr>
<td>
 
</td>
<td bgcolor=gray valign=bottom align=center>
<font color=white size=-2>
Attachment
</font>
</td>
<td bgcolor=gray valign=bottom align=center>
<font color=white size=-2>
Size
</font>
</td>
<td bgcolor=gray valign=bottom align=center>
<font color=white size=-2>
Date Added
</font>
</td>
</tr>

";

$dir = opendir($upload_path);
while ($file = readdir($dir)) {
if ($file != '.' && $file != '..') {
$num++;
$delete_link = "<a href=\"".$this->href('files.xml',$this->GetPageTag(),'action=delete&file='.urlencode($file))."\">x</a>";
$download_link = "<a href=\"".$this->href('files.xml',$this->GetPageTag(),'action=download&file='.urlencode($file))."\">".$file."</a>";
$size = bytesToHumanReadableUsage(filesize("$upload_path/$file"));
$date = date("n/d/Y g:i a",filemtime("$upload_path/$file"));

print "

<tr>
<td valign=top align=center>
  
{$delete_link}
  
</td>
<td valign=top>
$download_link
</td>
<td valign=top>
 
<font size=-1 color=gray>
$size
</font>
</td>
<td valign=top>
 
<font size=-1 color=gray>
$date
</font>
</td>
</tr>

";
}
}
closedir($dir);

// print n/a if no files currently exist
if (!$num) print "<tr><td> </td><td colspan=3 align=center><font color=gray size=-1><i>   </i></font></td></tr>";
else print "<tr><td> </td></tr>";

// form
$result = "<form action=\"".$this->href()."\" method=\"post\" enctype=\"multipart/form-data\">\n";
if (!$this->config["rewrite_mode"]) $result .= "<input type=\"hidden\" name=\"wakka\" value=\"".$this->MiniHref()."\">\n";
echo $result;
//<input type="hidden" name="action" value="upload"><input type="file" name="file"><input type="submit" value="+">
echo $this->FormClose();

// close disp table
print "

<tr>
<td>
 
</td>
<td colspan=4 valign=top align=right nowrap>
<i>
$result
<input type=\"hidden\" name=\"action\" value=\"upload\">
<font color=gray size=-2>
add new attachment:
<input type=\"file\" name=\"file\" style=\"padding: 0px; margin: 0px; font-size: 8px; height: 15px\">
<input type=\"Submit\" value=\"+\" style=\"padding: 0px; margin: 0px; font-size: 8px; height: 15px\">
".$this->FormClose()."
</font>
</i>
</td>
</tr>
</table>

";
}
?>
%%

===First version===

==actions/files.php==
%%(php)
<?php
if (! function_exists('mkdir_r')) {
function mkdir_r ($dir) {
if (strlen($dir) == 0) return 0;
if (is_dir($dir)) return 1;
elseif (dirname($dir) == $dir) return 1;
return (mkdir_r(dirname($dir)) and mkdir($dir,0755));
}
}

if ($download <> '') {

// link to download a file
if ($text == '') $text = $download;
echo "<a href=\"".$this->href('files.xml',$this->GetPageTag(),'action=download&file='.urlencode($download))."\">".$text."</a>";

} elseif ($this->page AND $this->HasAccess('write') AND ($this->method <> 'print.xml') AND ($this->method <> 'edit')) {

// upload path
if ($this->config['upload_path'] == '') $this->config['upload_path'] = 'files';
$upload_path = $this->config['upload_path'].'/'.$this->GetPageTag();
if (! is_dir($upload_path)) mkdir_r($upload_path);

// upload action
$uploaded = $_FILES['file'];
if ($_REQUEST['action'] == 'upload' AND $uploaded['size'] > 0)
copy ($uploaded['tmp_name'], $upload_path.'/'.$uploaded['name']);

// form
$result = "<form action=\"".$this->href()."\" method=\"post\" enctype=\"multipart/form-data\">\n";
if (!$this->config["rewrite_mode"]) $result .= "<input type=\"hidden\" name=\"wakka\" value=\"".$this->MiniHref()."\">\n";
echo $result;
?>
<input type="hidden" name="action" value="upload"><input type="file" name="file"><input type="submit" value="+">
<?php
echo $this->FormClose();

// uploaded files
$dir = opendir($upload_path);
while ($file = readdir($dir)) {
if ($file != '.' && $file != '..') {
$delete_link = "<a href=\"".$this->href('files.xml',$this->GetPageTag(),'action=delete&file='.urlencode($file))."\">x</a>";
$download_link = "<a href=\"".$this->href('files.xml',$this->GetPageTag(),'action=download&file='.urlencode($file))."\">".$file."</a>";
print "[ {$delete_link} ] ";
if ($file == $uploaded['name'])
print "<em>{$download_link}</em>\n";
else
print $download_link;
print '<br>';
}
}
closedir($dir);
}
?>
%%

==handlers/page/files.xml.php==
%%(php)
<?php
/* mime stuff take from Paul Southworth */
$mt_f = $this->config['mime_types'];
if ($mt_f == '') $mt_f='mime.types';

/* build an array keyed on the file ext */
if (is_readable($mt_f)) {
$mime_types=array();
/* open our mime.types file for reading */
$mt_fd=fopen($mt_f,"r");
while (!feof($mt_fd)) {
/* pull a line off the file */
$mt_buf=trim(fgets($mt_fd,1024));
/* discard if the line was blank or started with a comment */
if (strlen($mt_buf) > 0) if (substr($mt_buf,0,1) != "#") {
/* make temp array of the mime.types line we just read */
$mt_tmp=preg_split("/[\s]+/", $mt_buf, -1, PREG_SPLIT_NO_EMPTY);
$mt_num=count($mt_tmp);
/* if $mt_num = 1 then we got no file extensions for the type */
if ($mt_num > 1) {
for ($i=1;$i<$mt_num;$i++) {
/* if we find a comment mid-line, stop processing */
if (strstr($mt_tmp[$i],"#")) {
break;
/* otherwise stick the type in an array keyed by extension */
} else {
$mime_types[$mt_tmp[$i]]=$mt_tmp[0];
}
}
/* zero the temporary array */
unset($mt_tmp);
}
}
}
/* close the mime.types file we were reading */
fclose($mt_fd);
} else {
echo "ERROR: unreadable file " . $mt_f . "\n";
}

// upload path
if ($this->config['upload_path'] == '') $this->config['upload_path'] = 'files';
$upload_path = $this->config['upload_path'].'/'.$this->GetPageTag();
if (! is_dir($upload_path)) mkdir_r($upload_path);

// do the action
switch ($_REQUEST['action']) {
case 'download':
$_REQUEST['file'] = urldecode($_REQUEST['file']);
if ($this->HasAccess('read')) {
$path = "{$upload_path}/{$_REQUEST['file']}";
$filename = basename($path);
header('MIME-Version: 1.0');
$afn = split("\.",$filename);
$ext = strtolower($afn[count($afn)-1]);
$mime_type = $mime_types[$ext];
if ($mime_type == '') $mime_type = 'application/octet-stream';
header("Content-Type: {$mime_type}; name=\"{$filename}\"");
header('Content-Length: '. filesize($path));
header("Content-Disposition: filename=\"{$filename}\"");
$fp=fopen($path,'r');
print fread($fp,filesize($path));
fclose($fp);
exit();
}
case 'delete':
if ($this->HasAccess('write')) {
@unlink("{$upload_path}/{$_REQUEST['file']}");
print $this->redirect($this->href());
}
}
?>
%%

Nice.. but shouldn't delete at least check some permissions? ''(answer: I am checking write permission...)''
-- ArnarBirgisson

Why "files.xml"? shouldn't it be "files.php"? ''(answer: .xml actions does not include header and footer)''
(files.xml didn't work, but renaming it to "files.xml.php" helped.)
=> Kommentar::
files-action only works if you copy files.xml and store it as files.xml.php as well as files.xml ??????????

//Jetzt geht es, aber das ist ziemlich irre, weil ::
- files.xml
noch einmal als ::
- files.xml.php
abgespeichert werden muss. ?? es funktioniert .. //

KonradTadesse
----

:: FileUp ::
By the way, having an upload form on a page seems to break the page preview "Store" and "Re-edit" buttons.
''(fixed hidding the form on editing, thanks for your bug information)''
-- Tero
----
Here is the same bug like in ImageAction: the use of ##$vars##. Replace line 11 to 16 in actions/files.php with this:
%%(php)

if ($tokens['download'] ) {

// link to download a file
$text = $this->stripquotes($action_params['download']);
if ($tokens['text'])
{
$text = $this->stripquotes($action_params['text']);
}
echo "<a href=\"".$this->href('files.xml',$this->GetPageTag(),'action=download&file='.urlencode($this->stripquotes($action_params['download'])))."\">".$text."</a>";
}
%%

For the function ##$this->stripquotes## read ImageAction
--SilBaer
----
Fileupload on editing pages see FileUpload
--SilBaer

Fix: Added closing CurlyBrace in last replacement code.

====Code cleanup====

**actions/files.php**
%%(php)
<?php
$output = '';
$output .= '<div class="files">';

//this realy should be in the config
$max_upload_size = 2*1048576;
$allowed_extensions = 'gif|jpeg|jpg|jpe|png|doc|xls|csv|ppt|ppz|pps|pot|pdf|asc|txt|zip|gtar|gz|bz2|tar|rar|vpp|mpp|vsd|mm';

/* $date_format = 'n/d/Y g:i a'; (original) */
/* $date_format = 'd-M-Y H:i'; //01-Feb-2005 05:23 */
$date_format = 'Y-m-d H:i'; //2005-02-01 05:23 (easy javascript table sorting)

// mkdir_r
if (! function_exists('mkdir_r')) {
function mkdir_r ($dir) {
if (strlen($dir) == 0) return 0;
if (is_dir($dir)) return 1;
elseif (dirname($dir) == $dir) return 1;
return (mkdir_r(dirname($dir)) and mkdir($dir,0755));
}
}

// bytesToHumanReadableUsage
if (! function_exists('bytesToHumanReadableUsage')) {
/**
* Converts bytes to a human readable string
* @param int $bytes Number of bytes
* @param int $precision Number of decimal places to include in return string
* @param array $names Custom usage strings
* @return string formatted string rounded to $precision
*/
function bytesToHumanReadableUsage($bytes, $precision = 0, $names = '') {
if (!is_numeric($bytes) || $bytes < 0) {
$bytes = 0;
}

if (!is_numeric($precision) || $precision < 0) {
$precision = 0;
}

if (!is_array($names)) {
/* $names = array(' Bytes',' KB',' MB',' GB',' TB'); //original */
$names = array('B','k','M','G','T','P','E');
}

$level = floor(log($bytes)/log(1024));

$suffix = '';
if ($level < count($names)) {
$suffix = $names[$level];
}

return round($bytes/pow(1024, $level), $precision) . $suffix;
}
}

// error code constants
if (! defined('UPLOAD_ERR_OK')){
define('UPLOAD_ERR_OK', 0);
}
if (! defined('UPLOAD_ERR_INI_SIZE')){
define('UPLOAD_ERR_INI_SIZE', 1);
}
if (! defined('UPLOAD_ERR_FORM_SIZE')){
define('UPLOAD_ERR_FORM_SIZE', 2);
}
if (! defined('UPLOAD_ERR_PARTIAL')){
define('UPLOAD_ERR_PARTIAL', 3);
}
if (! defined('UPLOAD_ERR_NO_FILE')){
define('UPLOAD_ERR_NO_FILE', 4);
}
if (! defined('UPLOAD_ERR_NO_TMP_DIR')){
define('UPLOAD_ERR_NO_TMP_DIR', 6);
}

/*
input:
{{files download="filename.txt" text="important textfile"}}

output:
<a href="http://example.com/wiki/ExamplePage/files.xml?action=download&file=filename.txt">important textfile</a>
*/
/*
input:
{{files}}

output:
<div class="files"><table>
<thead>
<tr>
<td></td>
<th>Name</th>
<th>Last modified</th>
<th>Size</th>
</tr>
</thead>
<tbody>
<tr class="r1 r1m2 r1m3">
<td></td>
<td><a href="http://example.com/wiki/ExamplePage/files.xml?action=download&file=filename.txt">filename.txt</a></td>
<td>2005-02-03 17:57</td>
<td align="right">189k</td>
</tr>
<tr class="r2 r0m2 r2m3">
<td></td>
<td><a href="http://example.com/wiki/ExamplePage/files.xml?action=download&file=another%20file.txt">another file.txt</a></td>
<td>2005-02-03 17:57</td>
<td align="right">34k</td>
</tr>
</tbody>
</table></div>

output if you're admin:
<div class="files"><table>
<thead>
<tr>
<td></td>
<th>Name</th>
<th>Last modified</th>
<th>Size</th>
</tr>
</thead>
<tbody>
<tr class="r1 r1m2 r1m3">
<td>[<a href="http://example.com/wiki/ExamplePage/files.xml?action=delete&file=filename.txt">delete</a>]</td>
<td><a href="http://example.com/wiki/ExamplePage/files.xml?action=download&file=filename.txt">filename.txt</a></td>
<td>2005-02-03 17:57</td>
<td align="right">189k</td>
</tr>
<tr class="r2 r0m2 r2m3">
<td>[<a href="http://example.com/wiki/ExamplePage/files.xml?action=delete&file=another%20file.txt">delete</a>]</td>
<td><a href="http://example.com/wiki/ExamplePage/files.xml?action=download&file=another%20file.txt">another file.txt</a></td>
<td>2005-02-03 17:57</td>
<td align="right">34k</td>
</tr>
</tbody>
</table>
<form action="http://example.com/wiki/HomePage" method="post" enctype="multipart/form-data">
<p>

<input type="hidden" name="action" value="upload" />
<input type="hidden" name="MAX_FILE_SIZE" value="2097152" />
add new attachment:
<input type="file" name="file" />
<input type="submit" value="Upload" />
</p>
</form></div>

*/
if ($vars['download'] != '') {

// link to download a file
if ($vars['text'] == '') $text = $vars['download'];
$output .= '<a href="'
. $this->Href(
'files.xml',
$this->GetPageTag(),
'action=download&file='.
rawurlencode($vars['download'])
)
. '">'
. $vars['text']
. '</a>';

// Show files to anyone with read access, we'll check for write access if they try to delete a file.
} elseif ($this->page && $this->HasAccess('read') && $this->method != 'print.xml' && $this->method != 'edit') {

// upload path
if ($this->config['upload_path'] == '') {
$this->config['upload_path'] = 'files';
}

$upload_path = $this->config['upload_path'].'/'.$this->GetPageTag();

if (! is_dir($upload_path)) {
mkdir_r($upload_path);
}

// upload action
if ($_POST['action'] == 'upload') {

$status_text = '';

switch ($_FILES['file']['error']) {
case UPLOAD_ERR_OK:
if ($_FILES['file']['size'] > $max_upload_size) {
$status_text = 'Attempted file upload was too big. '
. 'Maximum allowed size is '
. bytesToHumanReadableUsage($max_upload_size) . '.';
unlink($_FILES['file']['tmp_name']);
}
elseif (preg_match('/.+\.('.$allowed_extensions.')$/i', $_FILES['file']['name'])) {
$strippedname = str_replace('\'', '', $_FILES['file']['name']);
$strippedname = stripslashes($strippedname);

$destfile = $upload_path.'/'.$strippedname;

if (!file_exists($destfile)) {
if (move_uploaded_file($_FILES['file']['tmp_name'], $destfile)) {
$status_text = 'File was successfully uploaded.';
}
else {
$status_text = 'There was an error uploading your file.';
}
}
else {
$status_text = 'There is already a file named "' . $strippedname . '".';
}
} else {
$status_text = 'This file\'s extension is unknown.';
unlink($_FILES['file']['tmp_name']);
}
break;
case UPLOAD_ERR_INI_SIZE:
case UPLOAD_ERR_FORM_SIZE:
$status_text = 'Attempted file upload was too big. '
. 'Maximum allowed size is '
. bytesToHumanReadableUsage($max_upload_size).'.';
break;
case UPLOAD_ERR_PARTIAL:
$status_text = 'File upload incomplete. Please try again.';
break;
case UPLOAD_ERR_NO_FILE:
$status_text = 'No file uploaded.';
break;
case UPLOAD_ERR_NO_TMP_DIR:
$status_text = 'File uploads impossible due to misconfigured server.';
break;
}
if ($status_text != '') {
$output .= '<p class="status">' . $status_text . '</p>';
}
}

// uploaded files
$output .= <<<HEREDOC
<table>
<thead>
<tr>
<td></td> <!-- For the delete link. Only needed when user is admin or has write rights. -->
<th>Name</th>
<th>Last modified</th>
<th>Size</th>
</tr>
</thead>
<tbody>
HEREDOC;

$dir = opendir($upload_path);
$num = 0;
while ($file = readdir($dir)) {
/* if ( $file != '.' && $file != '..') { */
if ($file{0} != '.') {
$num++;
$delete_link = '<!-- delete -->';
/* if ($this->HasAccess('write')) { */
if ($this->IsAdmin()) {
$delete_link = '[<a href="'
. $this->Href('files.xml',$this->GetPageTag(),'action=delete&file='.rawurlencode($file))
. '">delete</a>]';
}
$download_link = '<a href="'
. $this->Href('files.xml',$this->GetPageTag(),'action=download&file='.rawurlencode($file))
. '">'.$file.'</a>';
$size = bytesToHumanReadableUsage(filesize($upload_path . '/' . $file));
$date = date($date_format, filemtime($upload_path . '/' . $file));
// easy even/odd zebra table
// also possible to zebra color every three rows
$row_class = 'r'.$num.' r'.($num % 2).'m2 r'.($num % 3).'m3';
$output .= <<<HEREDOC

<tr class="{$row_class}">
<td>{$delete_link}</td>
<td>{$download_link}</td>
<td>{$date}</td>
<td align="right">{$size}</td>
</tr>
HEREDOC;
}
}
closedir($dir);

// print n/a if no files currently exist
if ($num < 1) {
$output .= <<<HEREDOC

<tr><td colspan="4">no files here</td></tr>
HEREDOC;
}
$output .= <<<HEREDOC

</tbody>
</table>
HEREDOC;

/* if ($this->HasAccess('write')) { */
if ($this->IsAdmin()) {
// form
$input_for_rewrite_mode = '<!-- rewrite mode disabled -->';
if (!$this->config['rewrite_mode']){
$input_for_rewrite_mode = '<input type="hidden" name="wakka" value="'.$this->MiniHref().'" />';
}
// close disp table
$href = $this->Href();
$output .= <<<HEREDOC

<form action="{$href}" method="post" enctype="multipart/form-data">
<p>
{$input_for_rewrite_mode}
<input type="hidden" name="action" value="upload" />
<input type="hidden" name="MAX_FILE_SIZE" value="{$max_upload_size}" />
add new attachment:
<input type="file" name="file" />
<input type="submit" value="Upload" />
</p>
</form>
HEREDOC;
}
}
$output .= '</div>';
$output = $this->ReturnSafeHTML($output);
echo $output;
?>
%%

**handlers/page/files.xml.php**
%%(php)
<?php
// upload path
if ($this->config['upload_path'] == '') {
$this->config['upload_path'] = 'files';
}
$upload_path = $this->config['upload_path'].'/'.$this->GetPageTag();
if (!is_dir($upload_path)) {
mkdir_r($upload_path);
}
$allowed_extensions = 'gif|jpeg|jpg|jpe|png|doc|xls|csv|ppt|ppz|pps|pot|pdf|asc|txt|zip|gtar|gz|bz2|tar|rar|vpp|mpp|vsd|mm';
$mime_types_file = $this->config['mime_types'];

$base_name = basename(urldecode($_REQUEST['file']))

$parts = explode('.', $base_name );

$extension = '';
if(count($parts) > 1){
$extension = array_pop($parts);
}

$first_letter = $base_name{0};

if ($first_letter != '.' && stristr('|'.$allowed_extensions.'|', '|'.$extension.'|') {

$path = $upload_path.'/'.basename(urldecode($_REQUEST['file']));

// do the action
switch ($_REQUEST['action']) {
case 'download':
if ($this->HasAccess('read')) {
$filename = basename($path);
$mimetype = 'application/x-download';
$mimes = file($mime_types_file);
foreach($mimes as $line){
if(preg_match('/^(\w+/\S+)\b.*\s'.$extension.'\b/i', $line, $matches)){
$mimetype = $matches[1];
break;
}
}
Header('Content-Length: '.filesize($path));
Header('Content-Type: '.$mimetype);
Header('Content-Disposition: attachment; filename="'.$filename.'"; '
.'modification-date="'.date('r', filemtime($path)).'";');
Header('Connection: close');
@readfile($path);
exit();
}
break;
case 'delete':
// if ($this->HasAccess('write')) {
if ($this->IsAdmin()) {
@unlink($path);
}
print $this->redirect($this->Href());
break;
}
}
?>
%%

**css**
%%(css)
.files table{
border: 1px solid #ccc;
border-collapse: collapse;
}
.files thead th, .files thead td {
color: #fff;
background: #999;
}
.files td, .files th {
padding: 0 3px 0 3px;
}
.files tr.r0m2 {
background: #efe;
color: #000;
}
%%

Hope you like it.
--CryDust
Deletions:
=====Development of Files action=====

<<This is the development page for the ""{{files}}"" action.
~-For info about the version currently included in Wikka, take a look at Mod015fFilesAction.
~-For a documentation of how to use the current version, look at FilesActionInfo.
<<::c::

handlers/page/files.xml.php didn't work for me, so i use FilesActionHillar
~&Hillar, can you explain //why// it didn't work for you, and how you solved that? --JavaWoman

===Actual version===

The code below offers a more visually improved layout for this handler and also displays the file size and the date of file upload.
- HeavyK (k m r @ h e a v y k . o r g), 3/27/04

**actions/files.php**
%%(php)
<?php
if (! function_exists('mkdir_r')) {
function mkdir_r ($dir) {
if (strlen($dir) == 0) return 0;
if (is_dir($dir)) return 1;
elseif (dirname($dir) == $dir) return 1;
return (mkdir_r(dirname($dir)) and mkdir($dir,0755));
}
}

if (! function_exists('bytesToHumanReadableUsage')) {
/**
* Converts bytes to a human readable string
* @param int $bytes Number of bytes
* @param int $precision Number of decimal places to include in return string
* @param array $names Custom usage strings
* @return string formatted string rounded to $precision
*/
function bytesToHumanReadableUsage($bytes, $precision = 2, $names = '')
{
if (!is_numeric($bytes) || $bytes < 0) {
return false;
}

for ($level = 0; $bytes >= 1024; $level++) {
$bytes /= 1024;
}

switch ($level)
{
case 0:
$suffix = (isset($names[0])) ? $names[0] : 'Bytes';
break;
case 1:
$suffix = (isset($names[1])) ? $names[1] : 'KB';
break;
case 2:
$suffix = (isset($names[2])) ? $names[2] : 'MB';
break;
case 3:
$suffix = (isset($names[3])) ? $names[3] : 'GB';
break;
case 4:
$suffix = (isset($names[4])) ? $names[4] : 'TB';
break;
default:
$suffix = (isset($names[$level])) ? $names[$level] : '';
break;
}

if (empty($suffix)) {
trigger_error('Unable to find suffix for case ' . $level);
return false;
}

return round($bytes, $precision) . ' ' . $suffix;
}
}


if ($download <> '') {

// link to download a file
if ($text == '') $text = $download;
echo "<a href=\"".$this->href('files.xml',$this->GetPageTag(),'action=download&file='.urlencode($download))."\">".$text."</a>";

} elseif ($this->page AND $this->HasAccess('write') AND ($this->method <> 'print.xml') AND ($this->method <> 'edit')) {

// upload path
if ($this->config['upload_path'] == '') $this->config['upload_path'] = 'files';
$upload_path = $this->config['upload_path'].'/'.$this->GetPageTag();
if (! is_dir($upload_path)) mkdir_r($upload_path);

// upload action
$uploaded = $_FILES['file'];
if ($_REQUEST['action'] == 'upload' AND $uploaded['size'] > 0)
copy ($uploaded['tmp_name'], $upload_path.'/'.$uploaded['name']);

// uploaded files
print "

<table cellspacing=0 cellpadding=0>
<tr>
<td>
 
</td>
<td bgcolor=gray valign=bottom align=center>
<font color=white size=-2>
Attachment
</font>
</td>
<td bgcolor=gray valign=bottom align=center>
<font color=white size=-2>
Size
</font>
</td>
<td bgcolor=gray valign=bottom align=center>
<font color=white size=-2>
Date Added
</font>
</td>
</tr>

";

$dir = opendir($upload_path);
while ($file = readdir($dir)) {
if ($file != '.' && $file != '..') {
$num++;
$delete_link = "<a href=\"".$this->href('files.xml',$this->GetPageTag(),'action=delete&file='.urlencode($file))."\">x</a>";
$download_link = "<a href=\"".$this->href('files.xml',$this->GetPageTag(),'action=download&file='.urlencode($file))."\">".$file."</a>";
$size = bytesToHumanReadableUsage(filesize("$upload_path/$file"));
$date = date("n/d/Y g:i a",filemtime("$upload_path/$file"));

print "

<tr>
<td valign=top align=center>
  
{$delete_link}
  
</td>
<td valign=top>
$download_link
</td>
<td valign=top>
 
<font size=-1 color=gray>
$size
</font>
</td>
<td valign=top>
 
<font size=-1 color=gray>
$date
</font>
</td>
</tr>

";
}
}
closedir($dir);

// print n/a if no files currently exist
if (!$num) print "<tr><td> </td><td colspan=3 align=center><font color=gray size=-1><i>   </i></font></td></tr>";
else print "<tr><td> </td></tr>";

// form
$result = "<form action=\"".$this->href()."\" method=\"post\" enctype=\"multipart/form-data\">\n";
if (!$this->config["rewrite_mode"]) $result .= "<input type=\"hidden\" name=\"wakka\" value=\"".$this->MiniHref()."\">\n";
echo $result;
//<input type="hidden" name="action" value="upload"><input type="file" name="file"><input type="submit" value="+">
echo $this->FormClose();

// close disp table
print "

<tr>
<td>
 
</td>
<td colspan=4 valign=top align=right nowrap>
<i>
$result
<input type=\"hidden\" name=\"action\" value=\"upload\">
<font color=gray size=-2>
add new attachment:
<input type=\"file\" name=\"file\" style=\"padding: 0px; margin: 0px; font-size: 8px; height: 15px\">
<input type=\"Submit\" value=\"+\" style=\"padding: 0px; margin: 0px; font-size: 8px; height: 15px\">
".$this->FormClose()."
</font>
</i>
</td>
</tr>
</table>

";
}
?>
%%

===First version===

==actions/files.php==
%%(php)
<?php
if (! function_exists('mkdir_r')) {
function mkdir_r ($dir) {
if (strlen($dir) == 0) return 0;
if (is_dir($dir)) return 1;
elseif (dirname($dir) == $dir) return 1;
return (mkdir_r(dirname($dir)) and mkdir($dir,0755));
}
}

if ($download <> '') {

// link to download a file
if ($text == '') $text = $download;
echo "<a href=\"".$this->href('files.xml',$this->GetPageTag(),'action=download&file='.urlencode($download))."\">".$text."</a>";

} elseif ($this->page AND $this->HasAccess('write') AND ($this->method <> 'print.xml') AND ($this->method <> 'edit')) {

// upload path
if ($this->config['upload_path'] == '') $this->config['upload_path'] = 'files';
$upload_path = $this->config['upload_path'].'/'.$this->GetPageTag();
if (! is_dir($upload_path)) mkdir_r($upload_path);

// upload action
$uploaded = $_FILES['file'];
if ($_REQUEST['action'] == 'upload' AND $uploaded['size'] > 0)
copy ($uploaded['tmp_name'], $upload_path.'/'.$uploaded['name']);

// form
$result = "<form action=\"".$this->href()."\" method=\"post\" enctype=\"multipart/form-data\">\n";
if (!$this->config["rewrite_mode"]) $result .= "<input type=\"hidden\" name=\"wakka\" value=\"".$this->MiniHref()."\">\n";
echo $result;
?>
<input type="hidden" name="action" value="upload"><input type="file" name="file"><input type="submit" value="+">
<?php
echo $this->FormClose();

// uploaded files
$dir = opendir($upload_path);
while ($file = readdir($dir)) {
if ($file != '.' && $file != '..') {
$delete_link = "<a href=\"".$this->href('files.xml',$this->GetPageTag(),'action=delete&file='.urlencode($file))."\">x</a>";
$download_link = "<a href=\"".$this->href('files.xml',$this->GetPageTag(),'action=download&file='.urlencode($file))."\">".$file."</a>";
print "[ {$delete_link} ] ";
if ($file == $uploaded['name'])
print "<em>{$download_link}</em>\n";
else
print $download_link;
print '<br>';
}
}
closedir($dir);
}
?>
%%

==handlers/page/files.xml.php==
%%(php)
<?php
/* mime stuff take from Paul Southworth */
$mt_f = $this->config['mime_types'];
if ($mt_f == '') $mt_f='mime.types';

/* build an array keyed on the file ext */
if (is_readable($mt_f)) {
$mime_types=array();
/* open our mime.types file for reading */
$mt_fd=fopen($mt_f,"r");
while (!feof($mt_fd)) {
/* pull a line off the file */
$mt_buf=trim(fgets($mt_fd,1024));
/* discard if the line was blank or started with a comment */
if (strlen($mt_buf) > 0) if (substr($mt_buf,0,1) != "#") {
/* make temp array of the mime.types line we just read */
$mt_tmp=preg_split("/[\s]+/", $mt_buf, -1, PREG_SPLIT_NO_EMPTY);
$mt_num=count($mt_tmp);
/* if $mt_num = 1 then we got no file extensions for the type */
if ($mt_num > 1) {
for ($i=1;$i<$mt_num;$i++) {
/* if we find a comment mid-line, stop processing */
if (strstr($mt_tmp[$i],"#")) {
break;
/* otherwise stick the type in an array keyed by extension */
} else {
$mime_types[$mt_tmp[$i]]=$mt_tmp[0];
}
}
/* zero the temporary array */
unset($mt_tmp);
}
}
}
/* close the mime.types file we were reading */
fclose($mt_fd);
} else {
echo "ERROR: unreadable file " . $mt_f . "\n";
}

// upload path
if ($this->config['upload_path'] == '') $this->config['upload_path'] = 'files';
$upload_path = $this->config['upload_path'].'/'.$this->GetPageTag();
if (! is_dir($upload_path)) mkdir_r($upload_path);

// do the action
switch ($_REQUEST['action']) {
case 'download':
$_REQUEST['file'] = urldecode($_REQUEST['file']);
if ($this->HasAccess('read')) {
$path = "{$upload_path}/{$_REQUEST['file']}";
$filename = basename($path);
header('MIME-Version: 1.0');
$afn = split("\.",$filename);
$ext = strtolower($afn[count($afn)-1]);
$mime_type = $mime_types[$ext];
if ($mime_type == '') $mime_type = 'application/octet-stream';
header("Content-Type: {$mime_type}; name=\"{$filename}\"");
header('Content-Length: '. filesize($path));
header("Content-Disposition: filename=\"{$filename}\"");
$fp=fopen($path,'r');
print fread($fp,filesize($path));
fclose($fp);
exit();
}
case 'delete':
if ($this->HasAccess('write')) {
@unlink("{$upload_path}/{$_REQUEST['file']}");
print $this->redirect($this->href());
}
}
?>
%%

Nice.. but shouldn't delete at least check some permissions? ''(answer: I am checking write permission...)''
-- ArnarBirgisson

Why "files.xml"? shouldn't it be "files.php"? ''(answer: .xml actions does not include header and footer)''
(files.xml didn't work, but renaming it to "files.xml.php" helped.)
=> Kommentar::
files-action only works if you copy files.xml and store it as files.xml.php as well as files.xml ??????????

//Jetzt geht es, aber das ist ziemlich irre, weil ::
- files.xml
noch einmal als ::
- files.xml.php
abgespeichert werden muss. ?? es funktioniert .. //

KonradTadesse
----

:: FileUp ::
By the way, having an upload form on a page seems to break the page preview "Store" and "Re-edit" buttons.
''(fixed hidding the form on editing, thanks for your bug information)''
-- Tero
----
Here is the same bug like in ImageAction: the use of ##$vars##. Replace line 11 to 16 in actions/files.php with this:
%%(php)

if ($tokens['download'] ) {

// link to download a file
$text = $this->stripquotes($action_params['download']);
if ($tokens['text'])
{
$text = $this->stripquotes($action_params['text']);
}
echo "<a href=\"".$this->href('files.xml',$this->GetPageTag(),'action=download&file='.urlencode($this->stripquotes($action_params['download'])))."\">".$text."</a>";
}
%%

For the function ##$this->stripquotes## read ImageAction
--SilBaer
----
Fileupload on editing pages see FileUpload
--SilBaer

Fix: Added closing CurlyBrace in last replacement code.


Revision [5642]

Edited on 2005-02-05 02:48:52 by JavaWoman [question for HillarAarelaid]
Additions:
~&Hillar, can you explain //why// it didn't work for you, and how you solved that? --JavaWoman
Deletions:
~&Hillar, can you explain //why// it didn't work for you, and how you solved that? --JavaWoman


Revision [5641]

Edited on 2005-02-04 23:39:12 by JavaWoman [question for HillarAarelaid]
Additions:
~&Hillar, can you explain //why// it didn't work for you, and how you solved that? --JavaWoman


Revision [5576]

Edited on 2005-02-04 13:16:07 by HillarAarelaid [question for HillarAarelaid]
Additions:
handlers/page/files.xml.php didn't work for me, so i use FilesActionHillar
Deletions:
actual version didnt work for me, so i use FilesActionHillar


Revision [5573]

Edited on 2005-02-04 12:59:16 by HillarAarelaid [question for HillarAarelaid]
Additions:
actual version didnt work for me, so i use FilesActionHillar


Revision [3914]

Edited on 2005-01-03 10:27:16 by DarTar [Layout]

No Differences

Revision [3913]

Edited on 2005-01-03 10:26:51 by DarTar [Layout]
Additions:
~-For a documentation of how to use the current version, look at FilesActionInfo.
<<::c::
Deletions:
~-For a documentation of how to use the current version, look at FilesActionInfo.<<
::c::


Revision [3624]

Edited on 2004-12-23 16:34:17 by JavaWoman [Layout]
Additions:
Here is the same bug like in ImageAction: the use of ##$vars##. Replace line 11 to 16 in actions/files.php with this:
For the function ##$this->stripquotes## read ImageAction
Deletions:
Here is the same bug like in ImgAction: the use of ##$vars##. Replace line 11 to 16 in actions/files.php with this:
For the function ##$this->stripquotes## read ImgAction


Revision [3613]

Edited on 2004-12-22 12:49:57 by JavaWoman [edit intro note]
Additions:
<<This is the development page for the ""{{files}}"" action.
~-For info about the version currently included in Wikka, take a look at Mod015fFilesAction.
~-For a documentation of how to use the current version, look at FilesActionInfo.<<
===Actual version===
Deletions:
<<This is the development page for the files-action. For info about the inclusion in wikka, take a look at Mod015fFilesAction.
For a documentation of how to use it, look at FilesActionInfo.<<
===Actuall version===


Revision [3606]

The oldest known version of this page was created on 2004-12-22 12:19:50 by NilsLindenberg [edit intro note]
Valid XHTML :: Valid CSS: :: Powered by WikkaWiki