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.
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
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
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
/* 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:
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
$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;
?>
h