Revision history for WikiFile


Revision [20253]

Last edited on 2008-09-19 05:03:44 by ChewBakka
Additions:
It showed, however, that for large websites, it would have required further improvements for which I do not have the time to do.
Deletions:
It showed, however, that for large websites, it would hav required further improvements for which I do not have the time to do.


Revision [20252]

Edited on 2008-09-19 05:02:25 by ChewBakka
Additions:
... was a working hack for saving files in wiki pages, useful for small teams.
It showed, however, that for large websites, it would hav required further improvements for which I do not have the time to do.
Therefore, I took it off this server.
//ChewBakka//
Deletions:
This module allows you to put images (and other files) anywhere on any page (provided you have write access to that page).
I did everything in Wikka 1.1.6.2 so I can not tell whether it will work in older versions.
==== How to use it ====
**Example**: assume you have a photograph of the //Millennium Falcon// in a file named IMG_1234.JPG on your computer. You want to put it in the wiki into the ""MillenniumFalcon"" page
So you edit the respective page and put the **""{{file}}""** placeholder at the place where you want to see the image.
%%(text;;MillenniumFalcon)
===== Millennium Falcon =====
Below you see a photograph of the Millennium Falcon, last year on Tatooine.
There was lots of sand, as always.
{{file}}
%%
The page now shows a form which allows you to upload the file.
After uploading, you see the image in the page. A click on the image displays another form, allowing you to replace the photo with another one or just to delete it.
Now, suppose you want to add more images to the same page. Then you need to distinguish the files by adding an **id**.
%%(text;;MillenniumFalcon)
===== Millennium Falcon =====
Below you see a photograph of the Millennium Falcon, last year on Tatooine.
There was lots of sand, as always.
{{file}}
On the next images, some Jawas admire the mighty space vessel:
{{file id="jawas1"}}
{{file id="jawas2"}}
%%
As you see above, it is allowed to have one file per page which has no id. Also, don't worry about id of images on other pages - the id just need to be unique inside the wiki page.
==== Advanced usage ====
To display an image also on another page, you do not need to upload it twice. Instead, you can tell the file placeholder to fetch the image from a different page:
""{{file page="PageWhichContainsTheFile"}}""
==== How it works ====
Behind the scenes, an uploaded file is stored in the //uploads// directory along with a metadata file. In the example above, Wikka stores the second file as ""MillenniumFalcon~jawas1"".jpg along with ""MillenniumFalcon~javas1"".file which is a plain ascii file containing some metadata.
==== How to install it ====
We are going to add two program files to the Wikka software, and create a folder.
In your Wikka root directory, there is a folder named //actions// which contains several php files. Save the following code (use the grab button) as //file.php// in the //actions// folder.
%%(php;1;actions/file.php)
<?php
/**
* WikiFile action
*
* Displays a file in the page (as image or link) and optinally an upload form.
*
* Syntax: {{file [id="idvalue"] [page="PageToTakeFileFrom"]}}
*
* Save this PHP file in the actions subdirectory.
*
* @package Actions
* @name File
*
* @author {@link http://wikkawiki.org/ChewBakka ChewBakka} (first draft)
*/
/**
* Reads the file's metadata file and returns it as an array.
*
* @author {@link http://wikkawiki.org/ChewBakka ChewBakka} (first draft)
* @input $tag name of the page; default = current page.
* @output Array or (if no file in page) null.
*/
if( !function_exists('getFile') ) // for pages which include multiple files
{
function getFile( $tag, $wikka, $id )
{
$data = null; // this variable will be returned
$sep = ($id ? '~' : '' ); // Separator between tag and id in filename

// Read the metadata from the file TagName~id.file
$metafile = $wikka->config['upload_path'].'/'.$tag.$sep.$id.'.file';
if (file_exists($metafile) && $contents = file_get_contents($metafile))
{
$lines = explode( "\n", $contents );
// Lines look like "key: value" -> convert them to an array
$data = array(
'extension' => '', // file extension, e.g. 'png', 'jpg', 'ogg'
'content-type' => '', // mime content type, e.g. 'image/png'
'uploaded' => '?', // date and time, . e.g. '2007-01-31 18:00'
'uploader' => '?', // wikiname, e.g. 'ChewBakka'
'image' => 'false', // 'true' for image files
'width' => '', // width in pixels (images only)
'height' => '' // height in pixels (images only)
);
foreach ($lines as $line)
{
$a = explode( ':', trim($line), 2 );
if( count($a) == 2 )
{
$data[ $a[0] ] = trim( $a[1] );
}
}
// Add convenient attributes which can not be stored permanently
$url = $wikka->config['base_url'] . $tag . '/file';
if( $id )
{
// append ?id=value or &id=value
$url = $url . (strpos($url,'?')?'&':'?') . 'id=' . $id;
}
$data['filename'] = $tag.$sep.$id . '.' . $data['extension'];
$data['path'] = $wikka->config['upload_path'] .'/' . $data['filename'];
$data['metafile'] = $metafile;
$data['url'] = $url;
// Final check: file must exist.
if (! file_exists( $data['path'] ) )
{
$data = null;
}
}
return $data;
}
}
/**
* Here the real action starts
*/
// Initialize variables
$language = 'DE' ; // change to 'DE' for german messages
$output = ''; // The HTML code that is being generated by this action
$tag = $this->GetPageTag(); // The page that the user requested
$id = ''; // Optional file id, appended to the tag name
$editid = '!NONE!'; // id of the image to which an upload/delete form is shown
// Read the parameters from {{file id="..." page="..."}}
if (is_array($vars) )
{
if( array_key_exists('page', $vars)) { $tag = $vars['page']; }
if( array_key_exists( 'id', $vars)) { $id = $vars[ 'id' ]; }
}
if( array_key_exists('editid', $_REQUEST))
{
$editid = $_REQUEST['editid'];
}
if( $id )
{
// A file ID was submitted.
// Check if it is alphanumeric and not longer than 100 characters
// in order to prevent security issues.
if (ereg('[^a-zA-Z0-9_]',$id) || strlen($id) > 100)
{
$id = '!BAD!';
$output = 'An illegal file ID was submittet';
}
}
if( $id != '!BAD!' )
{
$data = getFile($tag,$this,$id);
// The user is allowed to edit (= replace or delete) the file,
// if it is attached to the same page that the user is viewing,
// and the user may edit the page.
$mayEdit = $this->HasAccess('write',$tag) && $tag == $this->GetPageTag();
// The user is allowed to see the image (or download the file),
// if he would also be allowed to read the page to which it is attached.
if ($this->HasAccess( 'read', $tag ) && $data )
{
// Build an URL that shows the upload form: http://server/WikiPage?editid=id
// (actually it reloads the page with an upload form below the file)
$urlToEdit = '';
if ($mayEdit && $id != $editid)
{
$tmp = $this->Href('', $tag);
$urlToEdit = $tmp . (strpos($tmp,'?')?'&':'?') . 'editid='.$id;
}
// Create an img tage or a link
if ($data['image'] == 'true')
{
// Image file - create an <img> tag
$alt = ($urlToEdit ? 'Toggle edit' : 'Go to '.$tag );
$output = '<img src="' . $data['url'] . '"'
. ' width="' . $data['width'] . '"'
. ' height="' . $data['height'] . '"'
. ' alt="' . $alt . '"'
. ' border="0">';
if( $urlToEdit )
{
// Add an URL to show the upload form
$output = '<a href="' . $urlToEdit . '">' . $output . '</a>';
}
else
{
// Add an URL to go to the page which embeds the file
$output = '<a href="' . $this->Href('',$tag) . '">' . $output . '</a>';
}
}
else
{
// Other file types - create a download link
$output = '<a href="' . $data['url'] . '">' . $data['url'] . '</a>';
if ($urlToEdit)
{
// Add an URL to show the upload form
$output .= ' <a href="'.$urlToEdit.'">' . ($language=='DE'?'[BEARBEITEN]':'[EDIT]') . '</a>';
}
}
}
if ($mayEdit && ($id == $editid || $data == null))
{
// If on the same page and requested, also show an upload/delete form
$deletelink = '';
$hidelink = '';
switch($language)
{
case 'DE':
$headline = 'Eine Datei hochladen, so dass sie an dieser Stelle erscheint';
$buttonlabel = 'Hochladen';
if( $data )
{
$headline = ($data['image'] == 'true' ? 'Obiges Bild' : 'Obige Datei' )
. ' durch Hochladen einer neuen Datei ÜBERSCHREIBEN';
$deletelink = '<br />'
. ($data['image'] == 'true' ? 'Obiges Bild' : 'Obige Datei' )
. ' aus dem Wiki '
. '<a href="' . $data['url'] . (strpos($data['url'],'?')?'&':'?')
. 'cmd=delete">LÖSCHEN</a>';
$hidelink = '<br />Dieses Formular <a href="' . $this->Href() . '">AUSBLENDEN</a>';
}
break;
default:
$headline = 'Upload a file to appear here';
$buttonlabel = 'Upload';
if( $data )
{
$headline = 'REPLACE the '
. ($data['image'] == 'true' ? 'image' : 'file' )
. ' above by uploading a new file';
$buttonlabel = 'Upload';
$deletelink = '<br /><a href="' . $data['url'] . (strpos($data['url'],'?')?'&':'?')
. 'cmd=delete">DELETE</a>'
. ' the '
. ($data['image'] == 'true' ? 'image' : 'file' )
. ' above from the wiki';
$hidelink = '<br /><a href="' . $this->Href() . '">HIDE</a> this form';
}
}
$miniref = $this->Href('file', $tag);
$output = $output
. '<br />' . $headline . ' <br />'
. '<form action="' . $miniref . '" method="POST" enctype="multipart/form-data">'
. (!$this->config["rewrite_mode"] ? '<input type="hidden" name="wakka" value="' . $miniref . '" />' : '')
. '<input name="file" type="file" size="72">'
. '<input type="hidden" name="id" value="' . $id . '">'
. '<input type="submit" value="' . $buttonlabel . '">'
. $deletelink
. $hidelink
. '</form><br />'
;
}
}
print $this->ReturnSafeHTML($output);
?>
%%
Also in your Wikka root directory, there is a folder named //handlers//, which in turn contains a folder names //page// which contains several php files. Save the following code (use the grab button) as //file.php// in the //handlers/page// folder. (Yes, we have two files with the same name, but in different locations and with different function).
%%(php;1;handlers/page/file.php)
<?php
/**
* WikiFile handler
*
* Supports file retrieval and upload.
*
* Syntax: http://server/WikiName/file[?id=someid]
*
* Save this PHP file in the handlers/page subdirectory.
*
* @package Handlers
* @name File
*
* @author {@link http://wikkawiki.org/ChewBakka ChewBakka} (first draft)
*/
/**
* Reads the file's metadata file and returns it as an array.
*
* @author {@link http://wikkawiki.org/ChewBakka ChewBakka} (first draft)
* @input $tag name of the page; default = current page.
* @output Array or (if no file) null.
*/
function getFile( $tag, $wikka, $id )
{
$data = null; // this variable will be returned
$sep = ($id ? '~' : '' ); // Separator between tag and id in filename
// Read the metadata from the file TagName~id.file
$metafile = $wikka->config['upload_path'].'/'.$tag.$sep.$id.'.file';
if (file_exists($metafile) && $contents = file_get_contents($metafile))
{
$lines = explode( "\n", $contents );
// Lines look like "key: value" -> convert them to an array
$data = array(
'extension' => '', // file extension, e.g. 'png', 'jpg', 'ogg'
'content-type' => '', // mime content type, e.g. 'image/png'
'uploaded' => '?', // date and time, . e.g. '2007-01-31 18:00'
'uploader' => '?', // wikiname, e.g. 'ChewBakka'
'image' => 'false', // 'true' for image files
'width' => '', // width in pixels (images only)
'height' => '' // height in pixels (images only)
);
foreach ($lines as $line)
{
$a = explode( ':', trim($line), 2 );
if( count($a) == 2 )
{
$data[ $a[0] ] = trim( $a[1] );
}
}
// Add convenient attributes which can not be stored permanently
$data['filename'] = $tag.$sep.$id . '.' . $data['extension'];
$data['path'] = $wikka->config['upload_path'] .'/' . $data['filename'];
$data['metafile'] = $metafile;
$data['url'] = $wikka->config['base_url'] . $tag . '/file' . ($id?'?id='.$id:'');
// Final check: file must exist.
if (! file_exists( $data['path'] ) )
{
$data = null;
}
}
return $data;
}
/**
* Store an http-uploaded file.
*
* @author {@link http://wikkawiki.org/ChewBakka ChewBakka} (first draft)
* @input $uploaded_file An item from PHP's $_FILES array (see there)
* @output None
*/
function saveFile( $uploaded_file, $wikka, $id )
{
$pathinfo = pathinfo( $uploaded_file['name'] );
$extension = strtolower( $pathinfo['extension'] );
$pathname = $wikka->config['upload_path'] . '/' . $wikka->tag . ($id?'~':'') . $id;
$path = $pathname . '.' . $extension;
$contenttype = '';
// Remove existing file if it already exists
if ($data = getFile( $wikka->GetPageTag(), $wikka, $id ) )
{
// File exists; remove it first
// E.g. if a GIF exists and the user replaces it with a PNG now.
unlink( $data['path'] );
unlink( $data['metafile'] );
$data = null;
}
if (move_uploaded_file( $uploaded_file['tmp_name'], $path ))
{
// Find the mime type (it will be stored in the metadata)
if( function_exists('mime_content_type') )
{
$contenttype = mime_content_type($path);
}
if( ! $contenttype )
{
switch( $extension )
{
// Quick resonse for most frequently used file types
case 'png':
$contenttype = 'image/png';
break;
case 'jpg':
$contenttype = 'image/jpeg';
break;
case 'ogg':
$contenttype = 'application/ogg';
break;
case 'zip':
$contenttype = 'application/zip';
break;
default:
// Use wikka's own mime_types.txt
if (file_exists( $wikka->config['mime_types'] ))
{
foreach (explode("\n",file_get_contents($wikka->config['mime_types'])) as $line)
{
$line = trim($line);
if ($line != '' && substr($line,0,1) != '#' && strpos($line,$extension))
{
$a = explode( ' ', str_replace(chr(9),' ',$line) );
if (in_array( $extension, $a ))
{
$contenttype = $a[0];
break;
}
}
}
}
}
}
// build an array with metadata
$data = array(
'extension' => $extension,
'content-type' => $contenttype,
'uploaded' => date('Y-m-d H:i'),
'uploader' => $wikka->GetUserName(),
'image' => 'false'
);
if( substr($data['content-type'],0,6) == 'image/' )
{
$data['image'] = 'true';
$size = getimagesize($path);
$data['width'] = $size[0];
$data['height'] = $size[1];
}
// Save the data array in the metadata file
$contents = '';
foreach ($data as $key => $value)
{
$contents .= ($key . ': ' . $value . "\n");
}
file_put_contents( $pathname . '.file', $contents );
}
}
/**
* Here the real handler starts
*/
$handled = False;
$cmd = (isset($_REQUEST['cmd']) ? $_REQUEST['cmd'] : 'get');
if ($id = (isset($_REQUEST['id']) ? $_REQUEST['id'] : ''))
{
// A file ID was submitted.
// Check if it is alphanumeric and not longer than 100 characters
// in order to prevent security issues.
if (ereg('[^a-zA-Z0-9_]',$id) || strlen($id) > 100)
{
$cmd = 'nothing';
}
}
if (isset($_FILES['file']))
{
$cmd = 'upload';
}
switch( $cmd )
{
case 'upload':
// User uploaded a file
if ($this->HasAccess('write'))
{
$uploadedfile = $_FILES['file'];
if ($uploadedfile['error'] > 0)
{
// redirect to page
$this->redirect( $this->Href(), 'Transmitted file was damaged' );
}
else
{
saveFile( $uploadedfile, $this, $id );
$this->Redirect( $this->Href() );
}
$handled = True;
}
break;
case 'get':
// Return the file
if ($this->HasAccess('read') && $data = getFile($this->GetPageTag(),$this,$id))
{
header( 'Content-Type: ' . $data['content-type'] );
if ($data['image'] != 'true')
{
header( 'Content-Disposition: attachment; filename="' . $data['filename'] . '"');
}
@readfile($data['path']);
exit();
$handled = True;
}
break;
case 'delete':
// Delete the file permanently from the wiki
if ($this->HasAccess('write') && $data = getFile($this->GetPageTag(),$this,$id))
{
unlink( $data['metafile'] );
unlink( $data['path'] );
}
$this->Redirect( $this->Href() );
$handled = True;
break;
}
if( !$handled )
{
$this->Redirect( $this->Href() );
}
?>
%%
And now for the last step - read your wikka.config.php, it should contain a line like this:
%%(php;40;wikka.config.php)
// ...
'upload_path' => 'uploads',
// ...
%%
This means that the Wikka root folder should contain a folder named //uploads//; please create this folder if it does not exist.
Should the above line not be in your config file, please add the line too.
**Ready!** If something does not work yet, leave me a comment. --ChewBakka
==== Credits ====
While developing the above code, I browsed through many Wikka sources in order to learn how to write a good extension, and how to document it. They were too many to remember, so I just want to say thanks to all the people who made Wikka.
----
Category: [[CategoryUserContributions User contributions]]


Revision [20150]

Edited on 2008-08-15 17:02:58 by ChewBakka [New version]
Additions:
**Example**: assume you have a photograph of the //Millennium Falcon// in a file named IMG_1234.JPG on your computer. You want to put it in the wiki into the ""MillenniumFalcon"" page
After uploading, you see the image in the page. A click on the image displays another form, allowing you to replace the photo with another one or just to delete it.
Behind the scenes, an uploaded file is stored in the //uploads// directory along with a metadata file. In the example above, Wikka stores the second file as ""MillenniumFalcon~jawas1"".jpg along with ""MillenniumFalcon~javas1"".file which is a plain ascii file containing some metadata.
* Syntax: {{file [id="idvalue"] [page="PageToTakeFileFrom"]}}
* Save this PHP file in the actions subdirectory.
$url = $wikka->config['base_url'] . $tag . '/file';
if( $id )
// append ?id=value or &id=value
$url = $url . (strpos($url,'?')?'&':'?') . 'id=' . $id;
$data['url'] = $url;
$language = 'DE' ; // change to 'DE' for german messages
$editid = '!NONE!'; // id of the image to which an upload/delete form is shown
// Read the parameters from {{file id="..." page="..."}}
if (is_array($vars) )
if( array_key_exists('page', $vars)) { $tag = $vars['page']; }
if( array_key_exists( 'id', $vars)) { $id = $vars[ 'id' ]; }
if( array_key_exists('editid', $_REQUEST))
$editid = $_REQUEST['editid'];
// The user is allowed to edit (= replace or delete) the file,
// if it is attached to the same page that the user is viewing,
// and the user may edit the page.
$mayEdit = $this->HasAccess('write',$tag) && $tag == $this->GetPageTag();
// The user is allowed to see the image (or download the file),
// if he would also be allowed to read the page to which it is attached.
// Build an URL that shows the upload form: http://server/WikiPage?editid=id
// (actually it reloads the page with an upload form below the file)
$urlToEdit = '';
if ($mayEdit && $id != $editid)
$tmp = $this->Href('', $tag);
$urlToEdit = $tmp . (strpos($tmp,'?')?'&':'?') . 'editid='.$id;
// Create an img tage or a link
$alt = ($urlToEdit ? 'Toggle edit' : 'Go to '.$tag );
$output = '<img src="' . $data['url'] . '"'
. ' alt="' . $alt . '"'
. ' border="0">';
if( $urlToEdit )
// Add an URL to show the upload form
$output = '<a href="' . $urlToEdit . '">' . $output . '</a>';
// Add an URL to go to the page which embeds the file
$output = '<a href="' . $this->Href('',$tag) . '">' . $output . '</a>';
// Other file types - create a download link
if ($urlToEdit)
// Add an URL to show the upload form
$output .= ' <a href="'.$urlToEdit.'">' . ($language=='DE'?'[BEARBEITEN]':'[EDIT]') . '</a>';
if ($mayEdit && ($id == $editid || $data == null))
// If on the same page and requested, also show an upload/delete form
$hidelink = '';
switch($language)
case 'DE':
$headline = 'Eine Datei hochladen, so dass sie an dieser Stelle erscheint';
$buttonlabel = 'Hochladen';
if( $data )
$headline = ($data['image'] == 'true' ? 'Obiges Bild' : 'Obige Datei' )
. ' durch Hochladen einer neuen Datei ÜBERSCHREIBEN';
$deletelink = '<br />'
. ($data['image'] == 'true' ? 'Obiges Bild' : 'Obige Datei' )
. ' aus dem Wiki '
. '<a href="' . $data['url'] . (strpos($data['url'],'?')?'&':'?')
. 'cmd=delete">LÖSCHEN</a>';
$hidelink = '<br />Dieses Formular <a href="' . $this->Href() . '">AUSBLENDEN</a>';
break;
default:
$headline = 'Upload a file to appear here';
$buttonlabel = 'Upload';
if( $data )
$headline = 'REPLACE the '
. ($data['image'] == 'true' ? 'image' : 'file' )
. ' above by uploading a new file';
$buttonlabel = 'Upload';
$deletelink = '<br /><a href="' . $data['url'] . (strpos($data['url'],'?')?'&':'?')
. 'cmd=delete">DELETE</a>'
. ' the '
. ($data['image'] == 'true' ? 'image' : 'file' )
. ' above from the wiki';
$hidelink = '<br /><a href="' . $this->Href() . '">HIDE</a> this form';
. (!$this->config["rewrite_mode"] ? '<input type="hidden" name="wakka" value="' . $miniref . '" />' : '')
. $hidelink
* Save this PHP file in the handlers/page subdirectory.
// Save the data array in the metadata file
And now for the last step - read your wikka.config.php, it should contain a line like this:
Deletions:
**Example**: assume you have a photograph of the //Millennium Falcon// in a file named IMG_1234.JPG on your computer. You want to put it in the wiki.
After uploading, you see the image in the page, and below the image another upload form is visible, in case you want to replace the photo with another one later. You can also delete the file.
* Syntax: {{file [id="IdUniqueInPage"] [page="PageToTakeFileFrom"]}}
$data['url'] = $wikka->config['base_url'] . $tag . '/file' . ($id?'?id='.$id:'');
$uploadform = False; // Show an upload form instead of the file?
if (is_array($vars) && array_key_exists('page', $vars))
$tag = $vars['page'];
if (is_array($vars) && array_key_exists('id', $vars))
$id = $vars['id'];
// Check whether current user has read access and if there is a file.
$output = '<a href="' . $tag . '">'
. '<img src="' . $data['url'] . '"'
. ' alt="' . $tag . '"'
. ' border="0">'
. '</a>';
// Plain file - create a download link
if ($this->HasAccess( 'write', $tag ) && $tag == $this->GetPageTag())
// If on the same page, also show an upload form
$headline = 'Upload a file to appear here';
$buttonlabel = 'Upload';
if( $data )
$headline = 'REPLACE the '
. ($data['image'] == 'true' ? 'image' : 'file' )
. ' above by uploading a new file';
$buttonlabel = 'Upload';
$deletelink = '<br /><a href="' . $data['url'] . (strpos($data['url'],'?')?'&':'?')
. 'cmd=delete">DELETE</a>'
. ' the '
. ($data['image'] == 'true' ? 'image' : 'file' )
. ' above from the wiki';
. (!$this->config["rewrite_mode"] ? '<input type="hidden" name="wakka" value="' . $miniref . '" />' : '')
// Save the dat aarry in the metadata file
And now for the really last step - read your wikka.config.php, it should contain a line like this:
Behind the scenes, an uploaded file is stored in the //uploads// directory along with a metadata file. In the example above, Wikka stores the uploaded file IMG_1234.JPG as ""MillenniumFalconOnTatooine"".jpg along with ""MillenniumFalconOnTatooine"".file which contains the metadata. The latter is a plain ascii file which tells Wikka that the actual file is a jpg file.
==== History ====
2007-Feb-05
handlers/page/file.php: bugfix (switch without break, now if/elseif); sends filename with download (makes download easier)
libs/Wakka.class.php: supports *.*.gz
2008-Jul-15
Complete rewrite.
Only ACTION and HANDLER; no more Wikka.class.php modifications.
2008-Jul-18
Multiple files per page now possible.


Revision [20137]

Edited on 2008-07-18 14:13:36 by ChewBakka [Fixed another headline]
Additions:
==== How to install it ====
Deletions:
=== How to install it ===


Revision [20136]

Edited on 2008-07-18 14:08:26 by ChewBakka [Updated introduction; fixed headlines]
Additions:
This module allows you to put images (and other files) anywhere on any page (provided you have write access to that page).
==== How to use it ====
==== How it works ====
==== History ====
==== Credits ====
Deletions:
This pair of files allows you to attach files to wikipages.
=== How to use it ===
=== How it works ===
=== History ===
=== Credits ===


Revision [20133]

Edited on 2008-07-18 05:18:16 by ChewBakka [Updated introduction; fixed headlines]
Additions:
To display an image also on another page, you do not need to upload it twice. Instead, you can tell the file placeholder to fetch the image from a different page:
""{{file page="PageWhichContainsTheFile"}}""
2008-Jul-18
Multiple files per page now possible.
Deletions:
To display an image also on another page, you do not need to upload it twice. Instead, you can tell the file placeholder to fetch the image from a different place:
{{file page="PageWhichContainsTheFile"}}


Revision [20132]

Edited on 2008-07-18 05:16:42 by ChewBakka [Added advanced usage section]
Additions:
So you edit the respective page and put the **""{{file}}""** placeholder at the place where you want to see the image.
==== Advanced usage ====
To display an image also on another page, you do not need to upload it twice. Instead, you can tell the file placeholder to fetch the image from a different place:
{{file page="PageWhichContainsTheFile"}}
Deletions:
So you edit the repective page and put the **""{{file}}""** placeholder at the place where you want to see the image.


Revision [20131]

Edited on 2008-07-18 05:10:04 by ChewBakka [Multiple files]
Additions:
This pair of files allows you to attach files to wikipages.
So you edit the repective page and put the **""{{file}}""** placeholder at the place where you want to see the image.
%%(text;;MillenniumFalcon)
===== Millennium Falcon =====
Below you see a photograph of the Millennium Falcon, last year on Tatooine.
After uploading, you see the image in the page, and below the image another upload form is visible, in case you want to replace the photo with another one later. You can also delete the file.
Now, suppose you want to add more images to the same page. Then you need to distinguish the files by adding an **id**.
%%(text;;MillenniumFalcon)
===== Millennium Falcon =====
Below you see a photograph of the Millennium Falcon, last year on Tatooine.
On the next images, some Jawas admire the mighty space vessel:
{{file id="jawas1"}}
{{file id="jawas2"}}
As you see above, it is allowed to have one file per page which has no id. Also, don't worry about id of images on other pages - the id just need to be unique inside the wiki page.
* Displays a file in the page (as image or link) and optinally an upload form.
* Syntax: {{file [id="IdUniqueInPage"] [page="PageToTakeFileFrom"]}}
* Reads the file's metadata file and returns it as an array.
* @output Array or (if no file in page) null.
function getFile( $tag, $wikka, $id )
$sep = ($id ? '~' : '' ); // Separator between tag and id in filename
// Read the metadata from the file TagName~id.file
$metafile = $wikka->config['upload_path'].'/'.$tag.$sep.$id.'.file';
// Lines look like "key: value" -> convert them to an array
'extension' => '', // file extension, e.g. 'png', 'jpg', 'ogg'
'content-type' => '', // mime content type, e.g. 'image/png'
'uploaded' => '?', // date and time, . e.g. '2007-01-31 18:00'
'uploader' => '?', // wikiname, e.g. 'ChewBakka'
'image' => 'false', // 'true' for image files
'width' => '', // width in pixels (images only)
'height' => '' // height in pixels (images only)
// Add convenient attributes which can not be stored permanently
$data['filename'] = $tag.$sep.$id . '.' . $data['extension'];
$data['path'] = $wikka->config['upload_path'] .'/' . $data['filename'];
$data['metafile'] = $metafile;
$data['url'] = $wikka->config['base_url'] . $tag . '/file' . ($id?'?id='.$id:'');
$id = ''; // Optional file id, appended to the tag name
if (is_array($vars) && array_key_exists('id', $vars))
$id = $vars['id'];
if( $id )
// A file ID was submitted.
// Check if it is alphanumeric and not longer than 100 characters
// in order to prevent security issues.
if (ereg('[^a-zA-Z0-9_]',$id) || strlen($id) > 100)
$id = '!BAD!';
$output = 'An illegal file ID was submittet';
if( $id != '!BAD!' )
$data = getFile($tag,$this,$id);
// Check whether current user has read access and if there is a file.
if ($this->HasAccess( 'read', $tag ) && $data )
if ($data['image'] == 'true')
// Image file - create an <img> tag
$output = '<a href="' . $tag . '">'
. '<img src="' . $data['url'] . '"'
. ' width="' . $data['width'] . '"'
. ' height="' . $data['height'] . '"'
. ' alt="' . $tag . '"'
. ' border="0">'
. '</a>';
// Plain file - create a download link
$output = '<a href="' . $data['url'] . '">' . $data['url'] . '</a>';
if ($this->HasAccess( 'write', $tag ) && $tag == $this->GetPageTag())
// If on the same page, also show an upload form
$headline = 'Upload a file to appear here';
$buttonlabel = 'Upload';
$deletelink = '';
if( $data )
$headline = 'REPLACE the '
. ($data['image'] == 'true' ? 'image' : 'file' )
. ' above by uploading a new file';
$buttonlabel = 'Upload';
$deletelink = '<br /><a href="' . $data['url'] . (strpos($data['url'],'?')?'&':'?')
. 'cmd=delete">DELETE</a>'
. ' the '
. ($data['image'] == 'true' ? 'image' : 'file' )
. ' above from the wiki';
$miniref = $this->Href('file', $tag);
$output = $output
. '<br />' . $headline . ' <br />'
. '<form action="' . $miniref . '" method="POST" enctype="multipart/form-data">'
. (!$this->config["rewrite_mode"] ? '<input type="hidden" name="wakka" value="' . $miniref . '" />' : '')
. '<input name="file" type="file" size="72">'
. '<input type="hidden" name="id" value="' . $id . '">'
. '<input type="submit" value="' . $buttonlabel . '">'
. $deletelink
. '</form><br />'
;
* Supports file retrieval and upload.
* Syntax: http://server/WikiName/file[?id=someid]
* Reads the file's metadata file and returns it as an array.
* @output Array or (if no file) null.
function getFile( $tag, $wikka, $id )
$sep = ($id ? '~' : '' ); // Separator between tag and id in filename
// Read the metadata from the file TagName~id.file
$metafile = $wikka->config['upload_path'].'/'.$tag.$sep.$id.'.file';
// Lines look like "key: value" -> convert them to an array
'extension' => '', // file extension, e.g. 'png', 'jpg', 'ogg'
'content-type' => '', // mime content type, e.g. 'image/png'
'uploaded' => '?', // date and time, . e.g. '2007-01-31 18:00'
'uploader' => '?', // wikiname, e.g. 'ChewBakka'
'image' => 'false', // 'true' for image files
'width' => '', // width in pixels (images only)
'height' => '' // height in pixels (images only)
// Add convenient attributes which can not be stored permanently
$data['filename'] = $tag.$sep.$id . '.' . $data['extension'];
$data['path'] = $wikka->config['upload_path'] .'/' . $data['filename'];
$data['metafile'] = $metafile;
$data['url'] = $wikka->config['base_url'] . $tag . '/file' . ($id?'?id='.$id:'');
* Store an http-uploaded file.
function saveFile( $uploaded_file, $wikka, $id )
$pathname = $wikka->config['upload_path'] . '/' . $wikka->tag . ($id?'~':'') . $id;
$contenttype = '';
// Remove existing file if it already exists
if ($data = getFile( $wikka->GetPageTag(), $wikka, $id ) )
// File exists; remove it first
// E.g. if a GIF exists and the user replaces it with a PNG now.
unlink( $data['path'] );
unlink( $data['metafile'] );
$data = null;
// Find the mime type (it will be stored in the metadata)
switch( $extension )
// Quick resonse for most frequently used file types
case 'png':
$contenttype = 'image/png';
break;
case 'jpg':
$contenttype = 'image/jpeg';
break;
case 'ogg':
$contenttype = 'application/ogg';
break;
case 'zip':
$contenttype = 'application/zip';
break;
default:
// Use wikka's own mime_types.txt
if (file_exists( $wikka->config['mime_types'] ))
{
foreach (explode("\n",file_get_contents($wikka->config['mime_types'])) as $line)
{
$line = trim($line);
if ($line != '' && substr($line,0,1) != '#' && strpos($line,$extension))
{
$a = explode( ' ', str_replace(chr(9),' ',$line) );
if (in_array( $extension, $a ))
{
$contenttype = $a[0];
break;
}
}
}
}
'uploaded' => date('Y-m-d H:i'),
'uploader' => $wikka->GetUserName(),
// Save the dat aarry in the metadata file
$cmd = (isset($_REQUEST['cmd']) ? $_REQUEST['cmd'] : 'get');
if ($id = (isset($_REQUEST['id']) ? $_REQUEST['id'] : ''))
// A file ID was submitted.
// Check if it is alphanumeric and not longer than 100 characters
// in order to prevent security issues.
if (ereg('[^a-zA-Z0-9_]',$id) || strlen($id) > 100)
$cmd = 'nothing';
$cmd = 'upload';
switch( $cmd )
case 'upload':
// User uploaded a file
if ($this->HasAccess('write'))
$uploadedfile = $_FILES['file'];
if ($uploadedfile['error'] > 0)
// redirect to page
$this->redirect( $this->Href(), 'Transmitted file was damaged' );
else
saveFile( $uploadedfile, $this, $id );
$this->Redirect( $this->Href() );
$handled = True;
break;
case 'get':
// Return the file
if ($this->HasAccess('read') && $data = getFile($this->GetPageTag(),$this,$id))
header( 'Content-Type: ' . $data['content-type'] );
if ($data['image'] != 'true')
header( 'Content-Disposition: attachment; filename="' . $data['filename'] . '"');
@readfile($data['path']);
exit();
$handled = True;
break;
case 'delete':
// Delete the file permanently from the wiki
if ($this->HasAccess('write') && $data = getFile($this->GetPageTag(),$this,$id))
unlink( $data['metafile'] );
unlink( $data['path'] );
$this->Redirect( $this->Href() );
break;
$this->Redirect( $this->Href() );
Deletions:
In Wikka, almost everything is a **page**.
For example, a **category** is a page to which other pages link. If you want to start a new category, you do not need to learn something new - just create the category page and link your pages to it.
Here I would like to present a solution where a **file** is represented by a page too. I will first give a description on how to use it, then the necessary pieces of code.
You can also think of files as attachments; any wikka page can have at most one attachment.
First you create a page for the image, say ""MillenniumFalconOnTatooine"", as follows, and save it.
%%(text;;MillenniumFalconOnTatooine)
===== Millennium Falcon photograph =====
Photograph of the Millennium Falcon, last year on Tatooine.
After uploading, you see the image in the page, and below the image another upload form is visible, in case you want to replace the photo with another one later.
In order to display the image on other pages, include the following modified file action in the other page:
%%(text;;Code for embedding an image from another page)
{{file page="MillenniumFalconOnTatooine"}}
This will display the image on another page.
And of cause all of this works with other file types too. If a file is not an image, then the file action displays an URL through which you can download the file.
* Display the page's file, either inline or as link.
* If the file is an image, then it is displayed inline.
* For other file types, a download link is printed.
* Note that at most one file can be stored in a page.
* Syntax:
* {{file [page="SomeWikkaName"]}}
* @input string $page: name of the page whose file is to be displayed.
* optional; default is the current page itself.
* Return an array describing the file which is stored in a page.
* @output Array or (if no file in page) null. Keys:
* extension file extension, e.g. 'png', 'jpg', 'ogg'
* content-type mime content type, e.g. 'image/png'
* uploaded when and who,. e.g. '2007-01-31 ChewBakka'
* image 'yes' or 'no'
* width Width in pixels (images only)
* height Height in pixels (images only)
* filename PageName.ext
* path upload_path/PageName.extension
* url 'http://..../PageName/file'
function getFile( $tag, $wikka )
$metafile = $wikka->config['upload_path'].'/'.$tag.'.file'; // metadata
// Lines look like "key: value" -> convert into array
'extension' => '',
'content-type' => '',
'uploaded' => '<unknown> <unknown>',
'image' => 'false',
'width' => '',
'height' => '',
'filename' => '',
'path' => '',
'url' => ''
// Convenient attributes which can not be stored permanently
$data['filename'] = $tag . '.' . $data['extension'];
$data['path'] = $wikka->config['upload_path'] .'/' . $data['filename'];
$data['url'] = $wikka->config['base_url'] . $tag . '/file';
$data = getFile($tag,$this);
// Check whether current user has read access and if there is a file.
if ($this->HasAccess( 'read', $tag ) && $data )
if ($data['image'] == 'true')
// Image file - create an <img> tag
$output = '<a href="' . $tag . '">'
. '<img src="' . $data['url'] . '"'
. ' width="' . $data['width'] . '"'
. ' height="' . $data['height'] . '"'
. ' alt="' . $tag . '"'
. ' border="0">'
. '</a>';
else
// Plain file - create a download link
$output = '<a href="' . $data['url'] . '">' . $data['url'] . '</a>';
if ($this->HasAccess( 'write', $tag ) && $tag == $this->GetPageTag())
// If on the same page, also show an upload form
$headline = 'Attach a file to this page';
$buttonlabel = 'Attach selected file';
if( $data )
$headline = 'Replace above file/image with another one'
. '<br />'
. '(Note: if you do this, the new file/image will appear '
. 'INSTEAD of the existing file/image everywhere in the wiki!)'
;
$buttonlabel = 'REPLACE FILE/IMAGE (THINK TWICE!!!)';
$miniref = $this->Href('file', $tag);
$output = $output
. '<br />' . $headline . ' <br />'
. '<form action="' . $miniref . '" method="POST" enctype="multipart/form-data">'
. (!$this->config["rewrite_mode"] ? '<input type="hidden" name="wakka" value="' . $miniref . '" />' : '')
. '<input name="file" type="file" size="72">'
. '<input type="submit" value="' . $buttonlabel . '">'
. '</form><br />'
;
* @input ?action=get returns the file via http
* uploading a file causes storage of the file "in the page",
* overwriting any previous page file.
* mimeTypeFromExtension()
* Return mime type for the given file extension.
* Slow, but useful if PHP's mime_content_type() cannot be used.
* Uses Wikka's mime_types.txt and some hardcoded associations.
* @input $extension file extension, e.g. 'png', 'jpg', 'ogg'
* @output mime content type, e.g. 'image/png', or empty string.
function mimeTypeFromExtension( $extension, $wikka )
// Quick resonse for most frequently used file types
if ($extension == 'png') return 'image/png';
if ($extension == 'jpg') return 'image/jpeg';
if ($extension == 'ogg') return 'application/ogg';
// If not recoginzed, use mime_types.txt
if (file_exists( $wikka->config['mime_types'] ))
foreach (explode("\n",file_get_contents($wikka->config['mime_types'])) as $line)
$line = trim($line);
if ($line != '' && substr($line,0,1) != '#' && strpos($line,$extension))
$a = explode( ' ', str_replace(chr(9),' ',$line) );
if (in_array( $extension, $a ))
return $a[0];
return ''; // if nothing was found
* saveFile()
* Store an http-uploaded file in the current page.
* Any previous file will be replaced with the new file.
function saveFile( $uploaded_file, $wikka )
$pathname = $wikka->config['upload_path'] . '/' . $wikka->tag;
$contenttyp = '';
$contenttype = mimeTypeFromExtension( $extension );
'uploaded' => date('Y-m-d H:i') . ' ' . $wikka->GetUserName(),
// Create metadata file
* Return an array describing the file which is stored in a page.
* @output Array or (if no file in page) null. Keys:
* extension file extension, e.g. 'png', 'jpg', 'ogg'
* content-type mime content type, e.g. 'image/png'
* uploaded when and who,. e.g. '2007-01-31 ChewBakka'
* image 'yes' or 'no'
* width Width in pixels (images only)
* height Height in pixels (images only)
* filename PageName.ext
* path upload_path/PageName.extension
* url 'http://..../PageName/file'
function getFile( $tag, $wikka )
$metafile = $wikka->config['upload_path'].'/'.$tag.'.file'; // metadata
// Lines look like "key: value" -> convert into array
'extension' => '',
'content-type' => '',
'uploaded' => '<unknown> <unknown>',
'image' => 'false',
'width' => '',
'height' => '',
'filename' => '',
'path' => '',
'url' => ''
// Convenient attributes which can not be stored permanently
$data['filename'] = $tag . '.' . $data['extension'];
$data['path'] = $wikka->config['upload_path'] .'/' . $data['filename'];
$data['url'] = $wikka->config['base_url'] . $tag . '/file';
// User uploaded a file
if ($this->HasAccess('write'))
$uploadedfile = $_FILES['file'];
if ($uploadedfile['error'] > 0)
// redirect to page
$this->redirect( $this->Href(), 'Transmitted file was damaged' );
saveFile( $uploadedfile, $this );
$this->Redirect( $this->Href() );
else
// No upload => return the file
if ($this->HasAccess('read') && $data = getFile($this->GetPageTag(),$this))
header( 'Content-Type: ' . $data['content-type'] );
if ($data['image'] != 'true')
header( 'Content-Disposition: attachment; filename="' . $data['filename'] . '"');
@readfile($data['path']);
exit();
$this->Redirect( $this->Href(), 'Unknown' );


Revision [20129]

Edited on 2008-07-16 01:50:39 by ChewBakka [some german-language strings replaced with english ones]
Additions:
$headline = 'Attach a file to this page';
$buttonlabel = 'Attach selected file';
$headline = 'Replace above file/image with another one'
. '(Note: if you do this, the new file/image will appear '
. 'INSTEAD of the existing file/image everywhere in the wiki!)'
$buttonlabel = 'REPLACE FILE/IMAGE (THINK TWICE!!!)';
Deletions:
$headline = 'An diesen Artikel eine Datei anhängen';
$buttonlabel = 'Daten anhängen';
$headline = 'Obige Datei durch eine andere überschreiben'
. '(Wenn Sie das tun, dann erscheint anstelle der '
. 'obigen Datei die neue Datei!)'
$buttonlabel = 'Datei ÜBERSCHREIBEN (VORSICHT!!!)';


Revision [20128]

Edited on 2008-07-15 10:05:24 by ChewBakka [Fixed a bug in the action which occured in pages with multiple images]
Additions:
if( !function_exists('getFile') ) // for pages which include multiple files
function getFile( $tag, $wikka )
$data = null; // this variable will be returned
$metafile = $wikka->config['upload_path'].'/'.$tag.'.file'; // metadata
if (file_exists($metafile) && $contents = file_get_contents($metafile))
$lines = explode( "\n", $contents );
// Lines look like "key: value" -> convert into array
$data = array(
'extension' => '',
'content-type' => '',
'uploaded' => '<unknown> <unknown>',
'image' => 'false',
'width' => '',
'height' => '',
'filename' => '',
'path' => '',
'url' => ''
);
foreach ($lines as $line)
$a = explode( ':', trim($line), 2 );
if( count($a) == 2 )
$data[ $a[0] ] = trim( $a[1] );
// Convenient attributes which can not be stored permanently
$data['filename'] = $tag . '.' . $data['extension'];
$data['path'] = $wikka->config['upload_path'] .'/' . $data['filename'];
$data['url'] = $wikka->config['base_url'] . $tag . '/file';
// Final check: file must exist.
if (! file_exists( $data['path'] ) )
$data = null;
return $data;

$headline = 'An diesen Artikel eine Datei anhängen';
$buttonlabel = 'Daten anhängen';
$headline = 'Obige Datei durch eine andere überschreiben'
. '<br />'
. '(Wenn Sie das tun, dann erscheint anstelle der '
. 'obigen Datei die neue Datei!)'
;
$buttonlabel = 'Datei ÜBERSCHREIBEN (VORSICHT!!!)';
Deletions:
function formOpen( $wikka, $method = "", $tag = "", $formMethod = "post", $withFile = false )
$enctype = '';
if ($withFile) $enctype = ' enctype="multipart/form-data"';
$result = "<form action=\"".$wikka->Href($method, $tag)."\" method=\"".$formMethod."\"$enctype>\n";
if (!$wikka->config["rewrite_mode"]) $result .= "<input type=\"hidden\" name=\"wakka\" value=\"".$wikka->MiniHref($method, $tag)."\" />\n";
return $result;
$headline = 'Attach one file to this article';
$buttonlabel = 'attach file';
$headline = 'REPLACE THIS ATTACHMENT WITH A DIFFENT FILE';
$buttonlabel = 'REPLACE (THINK TWICE!!!)';


Revision [20127]

Edited on 2008-07-15 08:36:35 by ChewBakka [Rewrote the code and the documentation]
Additions:
===== ""WikiFile"" action and handler =====
You can also think of files as attachments; any wikka page can have at most one attachment.
**Example**: assume you have a photograph of the //Millennium Falcon// in a file named IMG_1234.JPG on your computer. You want to put it in the wiki.
First you create a page for the image, say ""MillenniumFalconOnTatooine"", as follows, and save it.
%%(text;;MillenniumFalconOnTatooine)
===== Millennium Falcon photograph =====
Photograph of the Millennium Falcon, last year on Tatooine.
There was lots of sand, as always.
{{file}}
The page now shows a form which allows you to upload the file.
After uploading, you see the image in the page, and below the image another upload form is visible, in case you want to replace the photo with another one later.
In order to display the image on other pages, include the following modified file action in the other page:
%%(text;;Code for embedding an image from another page)
{{file page="MillenniumFalconOnTatooine"}}
This will display the image on another page.
And of cause all of this works with other file types too. If a file is not an image, then the file action displays an URL through which you can download the file.
We are going to add two program files to the Wikka software, and create a folder.
In your Wikka root directory, there is a folder named //actions// which contains several php files. Save the following code (use the grab button) as //file.php// in the //actions// folder.
%%(php;1;actions/file.php)
* WikiFile action
* {{file [page="SomeWikkaName"]}}
* Return an array describing the file which is stored in a page.
* @input $tag name of the page; default = current page.
* @output Array or (if no file in page) null. Keys:
* extension file extension, e.g. 'png', 'jpg', 'ogg'
* content-type mime content type, e.g. 'image/png'
* uploaded when and who,. e.g. '2007-01-31 ChewBakka'
* image 'yes' or 'no'
* width Width in pixels (images only)
* height Height in pixels (images only)
* filename PageName.ext
* path upload_path/PageName.extension
* url 'http://..../PageName/file'
function getFile( $tag, $wikka )
$data = null; // this variable will be returned
$metafile = $wikka->config['upload_path'].'/'.$tag.'.file'; // metadata
if (file_exists($metafile) && $contents = file_get_contents($metafile))
{
$lines = explode( "\n", $contents );
// Lines look like "key: value" -> convert into array
$data = array(
'extension' => '',
'content-type' => '',
'uploaded' => '<unknown> <unknown>',
'image' => 'false',
'width' => '',
'height' => '',
'filename' => '',
'path' => '',
'url' => ''
);
foreach ($lines as $line)
{
$a = explode( ':', trim($line), 2 );
if( count($a) == 2 )
{
$data[ $a[0] ] = trim( $a[1] );
}
}
// Convenient attributes which can not be stored permanently
$data['filename'] = $tag . '.' . $data['extension'];
$data['path'] = $wikka->config['upload_path'] .'/' . $data['filename'];
$data['url'] = $wikka->config['base_url'] . $tag . '/file';
// Final check: file must exist.
if (! file_exists( $data['path'] ) )
{
$data = null;
}
}
return $data;
function formOpen( $wikka, $method = "", $tag = "", $formMethod = "post", $withFile = false )
$enctype = '';
if ($withFile) $enctype = ' enctype="multipart/form-data"';
$result = "<form action=\"".$wikka->Href($method, $tag)."\" method=\"".$formMethod."\"$enctype>\n";
if (!$wikka->config["rewrite_mode"]) $result .= "<input type=\"hidden\" name=\"wakka\" value=\"".$wikka->MiniHref($method, $tag)."\" />\n";
return $result;
* Here the real action starts
// Initialize variables
$output = ''; // The HTML code that is being generated by this action
$uploadform = False; // Show an upload form instead of the file?
$tag = $this->GetPageTag(); // The page that the user requested
if (is_array($vars) && array_key_exists('page', $vars))
$tag = $vars['page'];
$data = getFile($tag,$this);
// Check whether current user has read access and if there is a file.
if ($this->HasAccess( 'read', $tag ) && $data )
if ($data['image'] == 'true')
{
// Image file - create an <img> tag
$output = '<a href="' . $tag . '">'
. '<img src="' . $data['url'] . '"'
. ' width="' . $data['width'] . '"'
. ' height="' . $data['height'] . '"'
. ' alt="' . $tag . '"'
. ' border="0">'
. '</a>';
}
else
{
// Plain file - create a download link
$output = '<a href="' . $data['url'] . '">' . $data['url'] . '</a>';
}
if ($this->HasAccess( 'write', $tag ) && $tag == $this->GetPageTag())
// If on the same page, also show an upload form
$headline = 'Attach one file to this article';
$buttonlabel = 'attach file';
if( $data )
{
$headline = 'REPLACE THIS ATTACHMENT WITH A DIFFENT FILE';
$buttonlabel = 'REPLACE (THINK TWICE!!!)';
}
$miniref = $this->Href('file', $tag);
$output = $output
. '<br />' . $headline . ' <br />'
. '<form action="' . $miniref . '" method="POST" enctype="multipart/form-data">'
. (!$this->config["rewrite_mode"] ? '<input type="hidden" name="wakka" value="' . $miniref . '" />' : '')
. '<input name="file" type="file" size="72">'
. '<input type="submit" value="' . $buttonlabel . '">'
. '</form><br />'
;
%%(php;1;handlers/page/file.php)
* WikiFile handler
* mimeTypeFromExtension()
* Return mime type for the given file extension.
* Slow, but useful if PHP's mime_content_type() cannot be used.
* Uses Wikka's mime_types.txt and some hardcoded associations.
* @input $extension file extension, e.g. 'png', 'jpg', 'ogg'
* @output mime content type, e.g. 'image/png', or empty string.
function mimeTypeFromExtension( $extension, $wikka )
// Quick resonse for most frequently used file types
if ($extension == 'png') return 'image/png';
if ($extension == 'jpg') return 'image/jpeg';
if ($extension == 'ogg') return 'application/ogg';
// If not recoginzed, use mime_types.txt
if (file_exists( $wikka->config['mime_types'] ))
{
foreach (explode("\n",file_get_contents($wikka->config['mime_types'])) as $line)
{
$line = trim($line);
if ($line != '' && substr($line,0,1) != '#' && strpos($line,$extension))
{
$a = explode( ' ', str_replace(chr(9),' ',$line) );
if (in_array( $extension, $a ))
return $a[0];
}
}
}
return ''; // if nothing was found
* saveFile()
* Store an http-uploaded file in the current page.
* Any previous file will be replaced with the new file.
* @input $uploaded_file An item from PHP's $_FILES array (see there)
* @output None
function saveFile( $uploaded_file, $wikka )
$pathinfo = pathinfo( $uploaded_file['name'] );
$extension = strtolower( $pathinfo['extension'] );
$pathname = $wikka->config['upload_path'] . '/' . $wikka->tag;
$path = $pathname . '.' . $extension;
$contenttyp = '';
if (move_uploaded_file( $uploaded_file['tmp_name'], $path ))
{
if( function_exists('mime_content_type') )
{
$contenttype = mime_content_type($path);
}
if( ! $contenttype )
{
$contenttype = mimeTypeFromExtension( $extension );
}
// build an array with metadata
$data = array(
'extension' => $extension,
'content-type' => $contenttype,
'uploaded' => date('Y-m-d H:i') . ' ' . $wikka->GetUserName(),
'image' => 'false'
);
if( substr($data['content-type'],0,6) == 'image/' )
{
$data['image'] = 'true';
$size = getimagesize($path);
$data['width'] = $size[0];
$data['height'] = $size[1];
}
// Create metadata file
$contents = '';
foreach ($data as $key => $value)
{
$contents .= ($key . ': ' . $value . "\n");
}
file_put_contents( $pathname . '.file', $contents );
}
* Return an array describing the file which is stored in a page.
* @input $tag name of the page; default = current page.
* @output Array or (if no file in page) null. Keys:
* extension file extension, e.g. 'png', 'jpg', 'ogg'
* content-type mime content type, e.g. 'image/png'
* uploaded when and who,. e.g. '2007-01-31 ChewBakka'
* image 'yes' or 'no'
* width Width in pixels (images only)
* height Height in pixels (images only)
* filename PageName.ext
* path upload_path/PageName.extension
* url 'http://..../PageName/file'
function getFile( $tag, $wikka )
$data = null; // this variable will be returned
$metafile = $wikka->config['upload_path'].'/'.$tag.'.file'; // metadata
if (file_exists($metafile) && $contents = file_get_contents($metafile))
{
$lines = explode( "\n", $contents );
// Lines look like "key: value" -> convert into array
$data = array(
'extension' => '',
'content-type' => '',
'uploaded' => '<unknown> <unknown>',
'image' => 'false',
'width' => '',
'height' => '',
'filename' => '',
'path' => '',
'url' => ''
);
foreach ($lines as $line)
{
$a = explode( ':', trim($line), 2 );
if( count($a) == 2 )
{
$data[ $a[0] ] = trim( $a[1] );
}
}
// Convenient attributes which can not be stored permanently
$data['filename'] = $tag . '.' . $data['extension'];
$data['path'] = $wikka->config['upload_path'] .'/' . $data['filename'];
$data['url'] = $wikka->config['base_url'] . $tag . '/file';
// Final check: file must exist.
if (! file_exists( $data['path'] ) )
{
$data = null;
}
}
return $data;
* Here the real handler starts
$handled = False;
if (isset($_FILES['file']))
// User uploaded a file
if ($this->HasAccess('write'))
{
$uploadedfile = $_FILES['file'];
if ($uploadedfile['error'] > 0)
{
// redirect to page
$this->redirect( $this->Href(), 'Transmitted file was damaged' );
}
else
{
saveFile( $uploadedfile, $this );
$this->Redirect( $this->Href() );
}
$handled = True;
}
// No upload => return the file
if ($this->HasAccess('read') && $data = getFile($this->GetPageTag(),$this))
{
header( 'Content-Type: ' . $data['content-type'] );
if ($data['image'] != 'true')
{
header( 'Content-Disposition: attachment; filename="' . $data['filename'] . '"');
}
@readfile($data['path']);
exit();
$handled = True;
}
if( !$handled )
$this->Redirect( $this->Href(), 'Unknown' );
%%(php;40;wikka.config.php)
This means that the Wikka root folder should contain a folder named //uploads//; please create this folder if it does not exist.
Should the above line not be in your config file, please add the line too.
2008-Jul-15
Complete rewrite.
Only ACTION and HANDLER; no more Wikka.class.php modifications.
Category: [[CategoryUserContributions User contributions]]
Deletions:
===== WikiFile action =====
Once installed in your Wikka wiki, users will find it very easy to put files in the wiki.
There are no folders and file names - any file is "contained" in a particular page and referenced using only the page name. If the file is an image, it is visible in the page along with explaining text which is writen in the page as usual, and can be embedded in other pages by just referencing the file's page name. The access rights for viewing and modifying files are just the page rights.
**Example**: assume you have a photograph of the //Millennium Falcon// in a file named IMG_1234.JPG on your computer. You want to put it in the wiki and embed it in a general page about the Millennium Falcon. First you create another page for the image itself, say ""MillenniumFalconOnTatooine"", and type
~& Photograph of the Millennium Falcon, last year on Tatooine.
~& ""{{file}}""
into it, and save it.
The page footer reads **Edit page :: File :: Stats :: Referrers** and so on - note the addition of //File//. Clicking on it opens the file handler, which displays informations about the file (if there is already a file in the page) and an upload form;
Note that uploading a file into a page which already contains a file causes the old file to be replaced with the new file - there can be only one file per page.
Now you can include it in the ""MillenniumFalcon"" page and any other page. Just write ""{{file page="MillenniumFalconOnTatooine"}}"" into it, and it shows up in the page.
And of cause all of this works with other file types too. If a file is not an image, then the same action displays an URL through which you can download the file.
We are going to add two program files to the Wikka software, modify two others, and create a folder.
Let us begin with the most easy step. In your Wikka root directory, there is a folder named //actions// which contains several php files. Save the following code (use the grab button) as //file.php// in the //actions// folder.
%%(php;1)
* {{file [page="SomeWikkaName"]}}
$tag = (is_array($vars) && array_key_exists('page',$vars)) ? $vars['page'] : $this->GetPageTag();
$output = '';
// Check whether current has read access and if there is a file.
if ($this->HasAccess( 'read', $tag ) && $data = $this->GetFile($tag))
if ($data['image'] == 'true')
{
// Image file - create an <img> tag
$output = '<img src="' . $data['url'] . '"' .
' width="' . $data['width'] . '"' .
' height="' . $data['height'] . '"' .
' alt="' . $tag . '">';
}
else
{
// Plain file - create a download link
$output = '<a href="' . $data['url'] . '">' . $data['url'] . '</a>';
}
%%(php;1)
* Display file info and a small upload form.
$has_read_access = $this->HasAccess('read');
$has_write_access = $this->HasAccess('write') && $has_read_access;
if ($_REQUEST['action'] == 'get')
// ?action=get
if ($this->HasAccess('read') && $data = $this->GetFile())
{
header( 'Content-Type: ' . $data['content-type'] );
if ($data['image'] != 'true')
{
header( 'Content-Disposition: attachment; filename="' . $data['filename'] . '"');
}
@readfile($data['path']);
exit();
}
elseif (isset($_FILES['file']))
// User uploaded a file
if ($has_write_access)
{
$uploadedfile = $_FILES['file'];
if ($uploadedfile['error'] > 0)
{
// redirect to page
$this->redirect( $this->Href(), 'Transmitted file was damaged' );
}
else
{
$this->SaveFile( $uploadedfile );
$this->Redirect( $this->Href() );
}
}
// Display file info and an upload form
if ($has_read_access)
{
$upload_form = ( $has_write_access ?
$this->FormOpen( 'file', $this->GetPageTag(), 'POST', true ) .
'<input name="file" type="file" size="72">' .
'<input type="submit" value="upload">' .
$this->FormClose() . ' <br />'
: '' );
if ($data = $this->GetFile())
{
// Page contains a file
print '<p>';
print 'This page contains a ' . $data['extension'] . ' file.';
if ($data['image'] == 'true')
print ' This is an image, ';
print $data['width'] . ' pixels wide and ';
print $data['height'] . ' pixels high.';
$a = '<a href="' . $data['url'] . '">' . $data['url'] . '</a>';
print ' ' . substr($data['uploaded'],17) . ' has uploaded it on '; // user
print substr($data['uploaded'],0,16) . '.<br />'; // date and time
print 'It can be downloaded using the URL ' . $this->ReturnSafeHTML($a) . '.<br />';
print 'However, for using it in a Wikka page just place the following code in the page:<br />';
print '{{file page="' . $this->GetPageTag() . '"}}<br />';
print '</p>';
if( $has_write_access )
print '<p>You can <em>replace</em> it with another file using this form:</p>';
print $upload_form;
}
else
{
// Page does not contain a file
print '<p>There is no file in this page.</p>';
if( $has_write_access )
print '<p>You can store one file in this page using this form:</p>';
print $upload_form;
}
}
else
{
// no read access to page => no access to file
print '<div class="page"><em>Sorry, you are nor allowed to view this page.</em></div>';
}
Next, we will modify two existing Wikka program files. Be sure to keep **backup copies** of them!
Ok, return to the //actions// folder and open the //footer.php// file in your favorite text editor. Add three lines as described in the code box; this adds **File::** to the footer.
%%(php;1)
<div class="footer">
<?php
echo $this->FormOpen("", "TextSearch", "get");
echo $this->HasAccess("write") ? "<a href=\"".$this->href("edit")."\" title=\"Click to edit this page\">Edit page</a> ::\n" : "";
// footer.php should begin with the above lines.
// Insert the following three lines here:
echo ($this->HasAccess("write") || $this->HasAccess("read"))
? '<a href="' . $this->href("file"). '" title="Click to view/edit the file in this page">File</a> ::' . "\n"
: '';
// The rest of footer.php remains unchanged below
In the //libs// folder there is a huge file named //Wakka.class.php//. Open it and find the lines that start with function ""FormOpen"" (line no. 692) and end with a closing }. (Be careful since the next function, ""FormClose"", comes right after ""FormOpen""). Replace the ""FormOpen"" function with this extended version (it supports the //encoding// attribute which is necessary for file uploads):
%%(php;692)
function FormOpen($method = "", $tag = "", $formMethod = "post", $withFile = false )
{
$enctype = '';
if ($withFile) $enctype = ' enctype="multipart/form-data"';
$result = "<form action=\"".$this->Href($method, $tag)."\" method=\"".$formMethod."\"$enctype>\n";
if (!$this->config["rewrite_mode"]) $result .= "<input type=\"hidden\" name=\"wakka\" value=\"".$this->MiniHref($method, $tag)."\" />\n";
return $result;
}
And finally, insert the following four functions at the end of the //Wakka.class.php// (but //before// the final closing } brace):
%%(php;1040)
/**
* Return mime type for the given file extension.
* Slow, but useful if PHP's mime_content_type() cannot be used.
* Uses Wikka's mime_types.txt and some hardcoded associations.
*
* @author {@link http://wikkawiki.org/ChewBakka ChewBakka} (first draft)
* @input $extension file extension, e.g. 'png', 'jpg', 'ogg'
* @output mime content type, e.g. 'image/png', or empty string.
*/
function MimeTypeFromExtension( $extension )
{
// Quick resonse for most frequently used file types
if ($extension == 'png') return 'image/png';
if ($extension == 'jpg') return 'image/jpeg';
if ($extension == 'ogg') return 'application/ogg';
// If not recoginzed, use mime_types.txt
if (file_exists( $this->config['mime_types'] ))
{
foreach (explode("\n",file_get_contents($this->config['mime_types'])) as $line)
$line = trim($line);
if ($line != '' && substr($line,0,1) != '#' && strpos($line,$extension))
{
$a = explode( ' ', str_replace(chr(9),' ',$line) );
if (in_array( $extension, $a ))
{
return $a[0];
}
}
}
return ''; // if nothing was found
}
/**
* Return an array describing the file which is stored in a page.
*
* @author {@link http://wikkawiki.org/ChewBakka ChewBakka} (first draft)
* @input $tag name of the page; default = current page.
* @output Array or (if no file in page) null. Keys:
* extension file extension, e.g. 'png', 'jpg', 'ogg'
* content-type mime content type, e.g. 'image/png'
* uploaded when and who,. e.g. '2007-01-31 ChewBakka'
* image 'yes' or 'no'
* width Width in pixels (images only)
* height Height in pixels (images only)
* filename PageName.extension
* path upload_path/PageName.extension
* url 'http://..../PageName/file?action=get'
*/
function GetFile( $tag = '' )
{
$data = null; // this variable will be returned
if (!$tag) $tag = $this->tag;
$metafile = $this->config['upload_path'].'/'.$tag.'.file'; // metadata
if (file_exists($metafile) && $contents = file_get_contents($metafile))
{
$lines = explode( "\n", $contents );
// Lines look like "key: value" -> convert into array
$data = array(
'extension' => '',
'content-type' => '',
'uploaded' => '<unknown> <unknown>',
'image' => 'false',
'width' => '',
'height' => '',
'filename' => '',
'path' => '',
'url' => ''
);
foreach ($lines as $line)
$a = explode( ':', trim($line), 2 );
if( count($a) == 2 )
{
$data[ $a[0] ] = trim( $a[1] );
}
// Convenient attributes which can not be stored permanently
$data['filename'] = $tag . '.' . $data['extension'];
$data['path'] = $this->config['upload_path'] .'/' . $data['filename'];
$data['url'] = $this->config['base_url'] . $tag . '/file' .
($this->config['rewrite_mode']=='1' ? '?' : '&') .
'action=get';
// Final check: file must exist.
if (! file_exists( $data['path'] ) )
$data = null;
}
return $data;
}
/**
* Remove the file from the current page.
*
* @author {@link http://wikkawiki.org/ChewBakka ChewBakka} (first draft)
* @input none
* @output none
*/
function RemoveFile()
{
if ($data = $this->GetFile())
{
unlink( $this->config['upload_path'] . '/' . $this->tag . '.file' );
unlink( $this->config['upload_path'] . '/' . $data['filename'] );
}
}
/**
* Store an http-uploaded file in the current page.
* Any previous file will be replaced with the new file.
*
* @author {@link http://wikkawiki.org/ChewBakka ChewBakka} (first draft)
* @input $uploaded_file An item from PHP's $_FILES array (see there)
* @output None
*/
function SaveFile( $uploaded_file )
{
$this->RemoveFile();
$uploaded_file['name'] = strtolower( $uploaded_file['name'] );
$pathinfo = pathinfo( $uploaded_file['name'] );
$extension = $pathinfo['extension'];
if ($extension=='gz') {
if( count($a = explode( '.', $uploaded_file['name'])) > 2)
$extension = $a[count($a)-2] . '.gz';
}
}
$pathname = $this->config['upload_path'] . '/' . $this->tag;
$path = $pathname . '.' . $extension;
if (move_uploaded_file( $uploaded_file['tmp_name'], $path ))
{
$contenttype = mime_content_type($path);
if( ! $contenttype )
$contenttype = $this->MimeTypeFromExtension( $extension );
if (substr($path,-3)=='.gz')
$contenttype = 'application/octet-stream';
// build an array with metadata
$data = array(
'extension' => $extension,
'content-type' => $contenttype,
'uploaded' => date('Y-m-d H:i') . ' ' . $this->GetUserName(),
'image' => 'false'
);
if( substr($data['content-type'],0,6) == 'image/' )
$data['image'] = 'true';
$size = getimagesize($path);
$data['width'] = $size[0];
$data['height'] = $size[1];
// Create metadata file
$contents = '';
foreach ($data as $key => $value)
$contents .= ($key . ': ' . $value . "\n");
file_put_contents( $pathname . '.file', $contents );
}
}
%%(php;40)
This means that the Wikka root folder should contain a folder named //uploads//; please create this folder if it does not exist. Should the above line not be in your config file, please add the line too.
This page is in the category CategoryUserContributions.


Revision [19037]

Edited on 2008-01-28 00:13:52 by ChewBakka [Modified links pointing to docs server]

No Differences

Revision [16083]

Edited on 2007-02-07 02:44:46 by ChewBakka [fixed another typo]
Additions:
print 'However, for using it in a Wikka page just place the following code in the page:<br />';
Deletions:
print 'However, for using it a Wikka page just place the following code in the page:<br />';


Revision [16071]

Edited on 2007-02-05 15:41:22 by ChewBakka [} else { adapted to code guidelines]
Additions:
else
Deletions:
} else {


Revision [16070]

Edited on 2007-02-05 15:38:22 by ChewBakka [$data['image']]
Additions:
if ($data['image'] != 'true')
Deletions:
if ($data['image'] == '0' ) {


Revision [16069]

Edited on 2007-02-05 15:30:10 by ChewBakka [Improved download, gz handling, fixed bug]
Additions:
if ($_REQUEST['action'] == 'get')
header( 'Content-Type: ' . $data['content-type'] );
if ($data['image'] == '0' ) {
header( 'Content-Disposition: attachment; filename="' . $data['filename'] . '"');
elseif (isset($_FILES['file']))
} else {
$uploaded_file['name'] = strtolower( $uploaded_file['name'] );
$extension = $pathinfo['extension'];
if ($extension=='gz') {
if( count($a = explode( '.', $uploaded_file['name'])) > 2)
$extension = $a[count($a)-2] . '.gz';
}
if (substr($path,-3)=='.gz')
$contenttype = 'application/octet-stream';
=== History ===
2007-Feb-05
handlers/page/file.php: bugfix (switch without break, now if/elseif); sends filename with download (makes download easier)
libs/Wakka.class.php: supports *.*.gz
Deletions:
switch (True)
case $_REQUEST['action'] == 'get':
header('Content-Type: ' . $data['content-type'] );
case isset($_FILES['file']):
default:
$extension = strtolower( $pathinfo['extension'] );


Revision [16068]

Edited on 2007-02-05 01:46:05 by ChewBakka [removed typos]
Additions:
This means that the Wikka root folder should contain a folder named //uploads//; please create this folder if it does not exist. Should the above line not be in your config file, please add the line too.
Deletions:
This means that te Wikka root folder should contain a folder named //uploads//; please crate this folder if it does not exist. Should the above line not be in your config file, please add the line too.


Revision [16067]

Edited on 2007-02-05 01:44:01 by ChewBakka [uploads folder mentioned; actions spelled in quote signs]
Additions:
There are no folders and file names - any file is "contained" in a particular page and referenced using only the page name. If the file is an image, it is visible in the page along with explaining text which is writen in the page as usual, and can be embedded in other pages by just referencing the file's page name. The access rights for viewing and modifying files are just the page rights.
~& Photograph of the Millennium Falcon, last year on Tatooine.
~& ""{{file}}""
Now you can include it in the ""MillenniumFalcon"" page and any other page. Just write ""{{file page="MillenniumFalconOnTatooine"}}"" into it, and it shows up in the page.
We are going to add two program files to the Wikka software, modify two others, and create a folder.
And now for the really last step - read your wikka.config.php, it should contain a line like this:
%%(php;40)
'upload_path' => 'uploads',
This means that te Wikka root folder should contain a folder named //uploads//; please crate this folder if it does not exist. Should the above line not be in your config file, please add the line too.
**Ready!** If something does not work yet, leave me a comment. --ChewBakka
Deletions:
There are no folders and file names - any file is "contained" in a particular page and referenced using only the page name. If the file is an image, it is visible in the page (through the { {file} } action) along with explaining text which is writen in the page as usual. The access rights for viewing and modifying files are just the page rights.
//Photograph of the Millennium Falcon, last year on Tatooine.//
//{ {file} }//
Now you can include it in the ""MillenniumFalcon"" page and any other page. Just write { {file page="""MillenniumFalconOnTatooine"""} } into it, and it shows up in the page.
We are going to add two new program files to the Wikka software and modify two others.


Revision [16057]

Edited on 2007-02-04 10:06:09 by ChewBakka [Added installation description]
Additions:
In the //libs// folder there is a huge file named //Wakka.class.php//. Open it and find the lines that start with function ""FormOpen"" (line no. 692) and end with a closing }. (Be careful since the next function, ""FormClose"", comes right after ""FormOpen""). Replace the ""FormOpen"" function with this extended version (it supports the //encoding// attribute which is necessary for file uploads):
Deletions:
In the //libs// folder there is a huge file named //Wakka.class.php//. Open it and find the lines that start with function ""FormOpen"" (line no. 692) and end with a closing }. (Be careful since the next function, ""FormClose"", comes rightafter form open). Replace the FormOpen function with this extended version (it supports the //encoding// attribute which is necessary for file uploads):


Revision [16056]

Edited on 2007-02-04 10:03:53 by ChewBakka [Added installation description]
Additions:
I did everything in Wikka 1.1.6.2 so I can not tell whether it will work in older versions.
=== How to use it ===
Once installed in your Wikka wiki, users will find it very easy to put files in the wiki.
There are no folders and file names - any file is "contained" in a particular page and referenced using only the page name. If the file is an image, it is visible in the page (through the { {file} } action) along with explaining text which is writen in the page as usual. The access rights for viewing and modifying files are just the page rights.
=== How to install it ===
We are going to add two new program files to the Wikka software and modify two others.
Let us begin with the most easy step. In your Wikka root directory, there is a folder named //actions// which contains several php files. Save the following code (use the grab button) as //file.php// in the //actions// folder.
Also in your Wikka root directory, there is a folder named //handlers//, which in turn contains a folder names //page// which contains several php files. Save the following code (use the grab button) as //file.php// in the //handlers/page// folder. (Yes, we have two files with the same name, but in different locations and with different function).
Next, we will modify two existing Wikka program files. Be sure to keep **backup copies** of them!
Ok, return to the //actions// folder and open the //footer.php// file in your favorite text editor. Add three lines as described in the code box; this adds **File::** to the footer.
// footer.php should begin with the above lines.
// Insert the following three lines here:
// The rest of footer.php remains unchanged below
In the //libs// folder there is a huge file named //Wakka.class.php//. Open it and find the lines that start with function ""FormOpen"" (line no. 692) and end with a closing }. (Be careful since the next function, ""FormClose"", comes rightafter form open). Replace the FormOpen function with this extended version (it supports the //encoding// attribute which is necessary for file uploads):
And finally, insert the following four functions at the end of the //Wakka.class.php// (but //before// the final closing } brace):
=== How it works ===
Behind the scenes, an uploaded file is stored in the //uploads// directory along with a metadata file. In the example above, Wikka stores the uploaded file IMG_1234.JPG as ""MillenniumFalconOnTatooine"".jpg along with ""MillenniumFalconOnTatooine"".file which contains the metadata. The latter is a plain ascii file which tells Wikka that the actual file is a jpg file.
=== Credits ===
Deletions:
== Usage ==
In the wiki, there are no file names any more - any file is "contained" in a particular page and referenced using only the page name. If the file is an image, it is visible in the page (through the { {file} } action) along with explaining text which is writen in the page as usual. The access rights for viewing and modifying files are just the page rights.
== Code ==
Below are five pieces of code. The files Wakka.class.php and footer.php are parts of the Wikka software; I have extended them without changing existing functions (hopefully). I have also added two files: actions/file.php and handlers/page/file.php. I did everything in Wikka 1.1.6.2 so I can not tell whether it will work in older versions.
Behind the scenes, an uploaded file is stored in the //uploads// directory along with a metadata file. In the example above, Wikka stores the uploade file IMG_1234.JPG as ""MillenniumFalconOnTatooine"".jpg along with ""MillenniumFalconOnTatooine"".file which contains the metadata. The latter is a plain ascii file which tells Wikka that the actual file is a jpg file.
Here comes the modification of actions/footer.php; lines 5,6,7 are added, anything else remains unchanged. This adds **File::** to the footer.
In Wakka.class.php I have extended the ""FormOpen"" function, because the html form must include an //encoding// attribute if you want to upload files. I have added a fourth parameter named $withFiles. This is the extended function:
Also in Wakka.class.php I have added four functions which perform the most basic file handling without access right checking. (One function is actually only a workaround for probllems with mime_content_type() which I experienced). I have just added them and the end of the class, and they look like this:
The remaining two code pieces are two new files. Both are named file.php, but one is a handler and the other one is an action.
Here comes handlers/page/file.php:
And finally actions/file.php
== Credits ==


Revision [16049]

Edited on 2007-02-03 18:24:11 by NilsLindenberg [+heading]
Additions:
===== WikiFile action =====


Revision [16047]

Edited on 2007-02-03 14:54:08 by ChewBakka [Indentation]
Additions:
$this->FormOpen( 'file', $this->GetPageTag(), 'POST', true ) .
'<input name="file" type="file" size="72">' .
Deletions:
$this->FormOpen( 'file', $this->GetPageTag(), 'POST', true ) .
'<input name="file" type="file" size="72">' .


Revision [16046]

Edited on 2007-02-03 14:51:49 by ChewBakka [Handler improved; minor improvements in Wakka.class.php]
Additions:
'uploaded' => '<unknown> <unknown>',
$a = explode( ':', trim($line), 2 );
case $_REQUEST['action'] == 'get':
// ?action=get
if ($this->HasAccess('read') && $data = $this->GetFile())
header('Content-Type: ' . $data['content-type'] );
@readfile($data['path']);
exit();
case isset($_FILES['file']):
// User uploaded a file
if ($has_write_access)
$uploadedfile = $_FILES['file'];
if ($uploadedfile['error'] > 0)
// redirect to page
$this->redirect( $this->Href(), 'Transmitted file was damaged' );
}
$this->SaveFile( $uploadedfile );
$this->Redirect( $this->Href() );
default:
// Display file info and an upload form
if ($has_read_access)
$upload_form = ( $has_write_access ?
$this->FormOpen( 'file', $this->GetPageTag(), 'POST', true ) .
'<input name="file" type="file" size="72">' .
'<input type="submit" value="upload">' .
$this->FormClose() . ' <br />'
: '' );
// Page contains a file
print '<p>';
print 'This page contains a ' . $data['extension'] . ' file.';
if ($data['image'] == 'true')
print ' This is an image, ';
print $data['width'] . ' pixels wide and ';
print $data['height'] . ' pixels high.';
$a = '<a href="' . $data['url'] . '">' . $data['url'] . '</a>';
print ' ' . substr($data['uploaded'],17) . ' has uploaded it on '; // user
print substr($data['uploaded'],0,16) . '.<br />'; // date and time
print 'It can be downloaded using the URL ' . $this->ReturnSafeHTML($a) . '.<br />';
print 'However, for using it a Wikka page just place the following code in the page:<br />';
print '{{file page="' . $this->GetPageTag() . '"}}<br />';
print '</p>';
if( $has_write_access )
print '<p>You can <em>replace</em> it with another file using this form:</p>';
print $upload_form;
// Page does not contain a file
print '<p>There is no file in this page.</p>';
if( $has_write_access )
print '<p>You can store one file in this page using this form:</p>';
print $upload_form;
// no read access to page => no access to file
print '<div class="page"><em>Sorry, you are nor allowed to view this page.</em></div>';
Deletions:
'uploaded' => '',
$a = explode( ":", trim($line), 2 );
case $_REQUEST['action'] == 'get':
// ?action=get
if ($this->HasAccess('read') && $data = $this->GetFile())
header('Content-Type: ' . $data['content-type'] );
@readfile($data['path']);
exit();
case isset($_FILES['file']):
// User uploaded a file
if ($has_write_access)
$uploadedfile = $_FILES['file'];
if ($uploadedfile['error'] > 0)
// redirect to page
$this->redirect( $this->Href(), 'Transmitted file was damaged' );
}
else
$this->SaveFile( $uploadedfile );
$this->Redirect( $this->Href() );
default:
// Display file info and an upload form
$data = null;
if ($has_read_access)
if ($data = $this->GetFile())
print '<h3>Existing file</h3><p>';
foreach ($data as $key => $value)
if ($key != 'url')
print htmlspecialchars(htmlentities($key)) . ': ' .
htmlspecialchars(htmlentities($value)) . '<br />';
$a = '<a href="' . $data['url'] . '">' . $data['url'] . '</a>';
print 'url: ' . $this->ReturnSafeHTML($a) . '<br />';
print 'Wikka syntax: {{file page="' . $this->GetPageTag() . '"}}' . '<br />';
print '</p>';
else
print '<p>There is no file yet</p>';
print '<div class="page"><em>Sorry, you are nor allowed to view this file.</em></div>';
if ($has_write_access)
print '<h3>Upload form</h3><p>';
print $this->FormOpen( 'file', $this->GetPageTag(), 'POST', true );
print '<input name="file" type="file" size="72">';
print '<input type="submit" value="upload">';
print $this->FormClose();
if ($data) print '<p>Note: the uploaded file will <em>replace</em> the existing file.</p>';
print '<div class="page"><em>Sorry, you are nor allowed to put a file here.</em></div>';


Revision [16043]

Edited on 2007-02-03 10:14:59 by ChewBakka [Description improved]
Additions:
== Usage ==
In the wiki, there are no file names any more - any file is "contained" in a particular page and referenced using only the page name. If the file is an image, it is visible in the page (through the { {file} } action) along with explaining text which is writen in the page as usual. The access rights for viewing and modifying files are just the page rights.
**Example**: assume you have a photograph of the //Millennium Falcon// in a file named IMG_1234.JPG on your computer. You want to put it in the wiki and embed it in a general page about the Millennium Falcon. First you create another page for the image itself, say ""MillenniumFalconOnTatooine"", and type
//Photograph of the Millennium Falcon, last year on Tatooine.//
//{ {file} }//
into it, and save it.
The page footer reads **Edit page :: File :: Stats :: Referrers** and so on - note the addition of //File//. Clicking on it opens the file handler, which displays informations about the file (if there is already a file in the page) and an upload form;
Note that uploading a file into a page which already contains a file causes the old file to be replaced with the new file - there can be only one file per page.
Now you can include it in the ""MillenniumFalcon"" page and any other page. Just write { {file page="""MillenniumFalconOnTatooine"""} } into it, and it shows up in the page.
Behind the scenes, an uploaded file is stored in the //uploads// directory along with a metadata file. In the example above, Wikka stores the uploade file IMG_1234.JPG as ""MillenniumFalconOnTatooine"".jpg along with ""MillenniumFalconOnTatooine"".file which contains the metadata. The latter is a plain ascii file which tells Wikka that the actual file is a jpg file.
Deletions:
== Description ==
In the wiki, there are no file names any more - any file is "contained" in a particular page and referenced using only the page name. If the file is an image, it is visible in the page (through the { {file} } action) along with explaining text which is writen in the page as usual. The access rights for viewing and mpdifying files are just the page rights.
I order to add a screenshot (or any other file) to your wiki, you will first create a page for it. This is something youshould do anyway, because you should write some explaining text //about// your screenshot. The page should include a **{ {file} }** action to your page, although this is not necessary for being a file page - it is just for file pages what the { {category} } action is for category pages.
The page footer reads **Edit page :: File :: Stats :: Referrers** and so on - note the addition of //File//. Clicking on it opens the file handler, which displays informations about the file (if there is already a file in the page) and an upload form; uploading a file into a page which already contains a file causes the old file to be replaced with the new file - there can be only one file per page.
From now on you can use your screenshot on other wiki pages too. Just add { {file page="""MyScreenShot"""} } to the referring page.


Revision [16042]

Edited on 2007-02-03 09:57:50 by ChewBakka [Bugfixes]
Additions:
$path = $pathname . '.' . $extension;
$a = '<a href="' . $data['url'] . '">' . $data['url'] . '</a>';
Deletions:
$path = $pathname . '/' . $extension;
$a = '< href="' . $data['url'] . '">' . $data['url'] . '</a>';


Revision [16038]

Edited on 2007-02-02 18:07:23 by ChewBakka [Minor text corrections]
Additions:
In the wiki, there are no file names any more - any file is "contained" in a particular page and referenced using only the page name. If the file is an image, it is visible in the page (through the { {file} } action) along with explaining text which is writen in the page as usual. The access rights for viewing and mpdifying files are just the page rights.
From now on you can use your screenshot on other wiki pages too. Just add { {file page="""MyScreenShot"""} } to the referring page.
Deletions:
On the server side, there are no file names any more - any file is "contained" in a particular page and referenced using only the page name. If the file is an image, it is visible in the page (through the { {file} } action) along with explaining text which is writen in the page as usual. The access rights for viewing and mpdifying files are just the page rights.
From now on you can use your screenshot on othe wiki pages too. Just add { {file page="""MyScreenShot"""} } to the referring page.


Revision [16035]

Edited on 2007-02-02 17:50:48 by ChewBakka [Minor text corrections]
Additions:
----
This page is in the category CategoryUserContributions.


Revision [16034]

Edited on 2007-02-02 17:49:34 by ChewBakka [Minor text corrections]
Additions:
In Wikka, almost everything is a **page**.
For example, a **category** is a page to which other pages link. If you want to start a new category, you do not need to learn something new - just create the category page and link your pages to it.
Here I would like to present a solution where a **file** is represented by a page too. I will first give a description on how to use it, then the necessary pieces of code.
From now on you can use your screenshot on othe wiki pages too. Just add { {file page="""MyScreenShot"""} } to the referring page.
And of cause all of this works with other file types too. If a file is not an image, then the same action displays an URL through which you can download the file.
Below are five pieces of code. The files Wakka.class.php and footer.php are parts of the Wikka software; I have extended them without changing existing functions (hopefully). I have also added two files: actions/file.php and handlers/page/file.php. I did everything in Wikka 1.1.6.2 so I can not tell whether it will work in older versions.
The remaining two code pieces are two new files. Both are named file.php, but one is a handler and the other one is an action.
== Credits ==
While developing the above code, I browsed through many Wikka sources in order to learn how to write a good extension, and how to document it. They were too many to remember, so I just want to say thanks to all the people who made Wikka.
Deletions:
In Wikka, almost everything is a page.
For example, a category is a page to which other pages link. If you want to stat a new category, you do not need to learn something new - just create the category page and link your pages to it.
Here I would like to present a solution where files are represented by pages too. I will first give a description on how to use it, then the necessary pieces of code.
Below are five pieces of code. The files Wakka.class.php and footer.php are parts of the Wikka software; I have extended them without changing existing functions (hopefully). I have also added two files: actions/file.php and handlers/page/file.php.
The remaining two code pieces are two new files. Both are named file.php, but one is a handler and the other one is the action.
%%/php;1)


Revision [16033]

Edited on 2007-02-02 17:35:16 by ChewBakka [Minor text corrections]
Additions:
The remaining two code pieces are two new files. Both are named file.php, but one is a handler and the other one is the action.
Here comes handlers/page/file.php:
%%/php;1)
<?php
/**
* Display file info and a small upload form.
*
* @package Handlers
* @name File
*
* @author {@link http://wikkawiki.org/ChewBakka ChewBakka} (first draft)
*
* @input ?action=get returns the file via http
* uploading a file causes storage of the file "in the page",
* overwriting any previous page file.
*
*/
$has_read_access = $this->HasAccess('read');
$has_write_access = $this->HasAccess('write') && $has_read_access;
switch (True)
{
case $_REQUEST['action'] == 'get':
// ?action=get
if ($this->HasAccess('read') && $data = $this->GetFile())
header('Content-Type: ' . $data['content-type'] );
@readfile($data['path']);
exit();
case isset($_FILES['file']):
// User uploaded a file
if ($has_write_access)
$uploadedfile = $_FILES['file'];
if ($uploadedfile['error'] > 0)
// redirect to page
$this->redirect( $this->Href(), 'Transmitted file was damaged' );
}
else
$this->SaveFile( $uploadedfile );
$this->Redirect( $this->Href() );
default:
// Display file info and an upload form
$data = null;
if ($has_read_access)
if ($data = $this->GetFile())
print '<h3>Existing file</h3><p>';
foreach ($data as $key => $value)
if ($key != 'url')
print htmlspecialchars(htmlentities($key)) . ': ' .
htmlspecialchars(htmlentities($value)) . '<br />';
$a = '< href="' . $data['url'] . '">' . $data['url'] . '</a>';
print 'url: ' . $this->ReturnSafeHTML($a) . '<br />';
print 'Wikka syntax: {{file page="' . $this->GetPageTag() . '"}}' . '<br />';
print '</p>';
else
print '<p>There is no file yet</p>';
else
print '<div class="page"><em>Sorry, you are nor allowed to view this file.</em></div>';
if ($has_write_access)
print '<h3>Upload form</h3><p>';
print $this->FormOpen( 'file', $this->GetPageTag(), 'POST', true );
print '<input name="file" type="file" size="72">';
print '<input type="submit" value="upload">';
print $this->FormClose();
if ($data) print '<p>Note: the uploaded file will <em>replace</em> the existing file.</p>';
else
print '<div class="page"><em>Sorry, you are nor allowed to put a file here.</em></div>';
}
?>
And finally actions/file.php
<?php
/**
* Display the page's file, either inline or as link.
*
* If the file is an image, then it is displayed inline.
* For other file types, a download link is printed.
* Note that at most one file can be stored in a page.
*
* Syntax:
* {{file [page="SomeWikkaName"]}}
*
* @package Actions
* @name File
*
* @author {@link http://wikkawiki.org/ChewBakka ChewBakka} (first draft)
*
* @input string $page: name of the page whose file is to be displayed.
* optional; default is the current page itself.
*/
$tag = (is_array($vars) && array_key_exists('page',$vars)) ? $vars['page'] : $this->GetPageTag();
$output = '';
// Check whether current has read access and if there is a file.
if ($this->HasAccess( 'read', $tag ) && $data = $this->GetFile($tag))
{
if ($data['image'] == 'true')
// Image file - create an <img> tag
$output = '<img src="' . $data['url'] . '"' .
' width="' . $data['width'] . '"' .
' height="' . $data['height'] . '"' .
' alt="' . $tag . '">';
else
// Plain file - create a download link
$output = '<a href="' . $data['url'] . '">' . $data['url'] . '</a>';
}
print $this->ReturnSafeHTML($output);
?>


Revision [16032]

Edited on 2007-02-02 17:31:14 by ChewBakka [Minor text corrections]
Additions:
Below are five pieces of code. The files Wakka.class.php and footer.php are parts of the Wikka software; I have extended them without changing existing functions (hopefully). I have also added two files: actions/file.php and handlers/page/file.php.
// ...
%%
In Wakka.class.php I have extended the ""FormOpen"" function, because the html form must include an //encoding// attribute if you want to upload files. I have added a fourth parameter named $withFiles. This is the extended function:
%%(php;692)
function FormOpen($method = "", $tag = "", $formMethod = "post", $withFile = false )
{
$enctype = '';
if ($withFile) $enctype = ' enctype="multipart/form-data"';
$result = "<form action=\"".$this->Href($method, $tag)."\" method=\"".$formMethod."\"$enctype>\n";
if (!$this->config["rewrite_mode"]) $result .= "<input type=\"hidden\" name=\"wakka\" value=\"".$this->MiniHref($method, $tag)."\" />\n";
return $result;
}
%%
Also in Wakka.class.php I have added four functions which perform the most basic file handling without access right checking. (One function is actually only a workaround for probllems with mime_content_type() which I experienced). I have just added them and the end of the class, and they look like this:
%%(php;1040)
/**
* Return mime type for the given file extension.
* Slow, but useful if PHP's mime_content_type() cannot be used.
* Uses Wikka's mime_types.txt and some hardcoded associations.
*
* @author {@link http://wikkawiki.org/ChewBakka ChewBakka} (first draft)
* @input $extension file extension, e.g. 'png', 'jpg', 'ogg'
* @output mime content type, e.g. 'image/png', or empty string.
*/
function MimeTypeFromExtension( $extension )
{
// Quick resonse for most frequently used file types
if ($extension == 'png') return 'image/png';
if ($extension == 'jpg') return 'image/jpeg';
if ($extension == 'ogg') return 'application/ogg';
// If not recoginzed, use mime_types.txt
if (file_exists( $this->config['mime_types'] ))
{
foreach (explode("\n",file_get_contents($this->config['mime_types'])) as $line)
{
$line = trim($line);
if ($line != '' && substr($line,0,1) != '#' && strpos($line,$extension))
{
$a = explode( ' ', str_replace(chr(9),' ',$line) );
if (in_array( $extension, $a ))
{
return $a[0];
}
}
}
}
return ''; // if nothing was found
}
/**
* Return an array describing the file which is stored in a page.
*
* @author {@link http://wikkawiki.org/ChewBakka ChewBakka} (first draft)
* @input $tag name of the page; default = current page.
* @output Array or (if no file in page) null. Keys:
* extension file extension, e.g. 'png', 'jpg', 'ogg'
* content-type mime content type, e.g. 'image/png'
* uploaded when and who,. e.g. '2007-01-31 ChewBakka'
* image 'yes' or 'no'
* width Width in pixels (images only)
* height Height in pixels (images only)
* filename PageName.extension
* path upload_path/PageName.extension
* url 'http://..../PageName/file?action=get'
*/
function GetFile( $tag = '' )
{
$data = null; // this variable will be returned
if (!$tag) $tag = $this->tag;
$metafile = $this->config['upload_path'].'/'.$tag.'.file'; // metadata
if (file_exists($metafile) && $contents = file_get_contents($metafile))
{
$lines = explode( "\n", $contents );
// Lines look like "key: value" -> convert into array
$data = array(
'extension' => '',
'content-type' => '',
'uploaded' => '',
'image' => 'false',
'width' => '',
'height' => '',
'filename' => '',
'path' => '',
'url' => ''
);
foreach ($lines as $line)
{
$a = explode( ":", trim($line), 2 );
if( count($a) == 2 )
{
$data[ $a[0] ] = trim( $a[1] );
}
}
// Convenient attributes which can not be stored permanently
$data['filename'] = $tag . '.' . $data['extension'];
$data['path'] = $this->config['upload_path'] .'/' . $data['filename'];
$data['url'] = $this->config['base_url'] . $tag . '/file' .
($this->config['rewrite_mode']=='1' ? '?' : '&') .
'action=get';
// Final check: file must exist.
if (! file_exists( $data['path'] ) )
{
$data = null;
}
}
return $data;
}
/**
* Remove the file from the current page.
*
* @author {@link http://wikkawiki.org/ChewBakka ChewBakka} (first draft)
* @input none
* @output none
*/
function RemoveFile()
{
if ($data = $this->GetFile())
{
unlink( $this->config['upload_path'] . '/' . $this->tag . '.file' );
unlink( $this->config['upload_path'] . '/' . $data['filename'] );
}
}
/**
* Store an http-uploaded file in the current page.
* Any previous file will be replaced with the new file.
*
* @author {@link http://wikkawiki.org/ChewBakka ChewBakka} (first draft)
* @input $uploaded_file An item from PHP's $_FILES array (see there)
* @output None
*/
function SaveFile( $uploaded_file )
{
$this->RemoveFile();
$pathinfo = pathinfo( $uploaded_file['name'] );
$extension = strtolower( $pathinfo['extension'] );
$pathname = $this->config['upload_path'] . '/' . $this->tag;
$path = $pathname . '/' . $extension;
if (move_uploaded_file( $uploaded_file['tmp_name'], $path ))
{
$contenttype = mime_content_type($path);
if( ! $contenttype )
{
$contenttype = $this->MimeTypeFromExtension( $extension );
}
// build an array with metadata
$data = array(
'extension' => $extension,
'content-type' => $contenttype,
'uploaded' => date('Y-m-d H:i') . ' ' . $this->GetUserName(),
'image' => 'false'
);
if( substr($data['content-type'],0,6) == 'image/' )
{
$data['image'] = 'true';
$size = getimagesize($path);
$data['width'] = $size[0];
$data['height'] = $size[1];
}
// Create metadata file
$contents = '';
foreach ($data as $key => $value)
{
$contents .= ($key . ': ' . $value . "\n");
}
file_put_contents( $pathname . '.file', $contents );
}
}
%%
Deletions:
Below are five pieces of code. The files Wikka.class.php and footer.php are parts of the Wikka software; I have extended them without changing existing functions (hopefully). I have also added two files: actions/file.php and handlers/page/file.php.
// ...%%


Revision [16031]

The oldest known version of this page was created on 2007-02-02 17:22:14 by ChewBakka [Minor text corrections]
Valid XHTML :: Valid CSS: :: Powered by WikkaWiki