2015-10-18 12:23:02 +00:00
< ? php
register_module ([
" name " => " Uploader " ,
2015-11-08 21:15:08 +00:00
" version " => " 0.2 " ,
2015-10-18 12:23:02 +00:00
" author " => " Starbeamrainbowlabs " ,
" description " => " Adds the ability to upload files to Pepperminty Wiki. Uploaded files act as pages and have the special 'File:' prefix. " ,
" id " => " feature-upload " ,
" code " => function () {
add_action ( " upload " , function () {
2015-10-22 07:38:50 +00:00
global $settings , $env , $pageindex ;
2015-10-18 12:23:02 +00:00
switch ( $_SERVER [ " REQUEST_METHOD " ])
{
case " GET " :
// Send upload page
2015-10-18 20:01:18 +00:00
2015-10-22 07:38:50 +00:00
if ( ! $settings -> upload_enabled )
exit ( page_renderer :: render ( " Upload Disabled - $setting->sitename " , " <p>You can't upload anything at the moment because $settings->sitename has uploads disabled. Try contacting " . $settings -> admindetails [ " name " ] . " , your site Administrator. <a href='javascript:history.back();'>Go back</a>.</p> " ));
if ( ! $env -> is_logged_in )
exit ( page_renderer :: render ( " Upload Error - $settings->sitename " , " <p>You are not currently logged in, so you can't upload anything.</p>
< p > Try < a href = '?action=login&returnto=" . rawurlencode("?action=upload") . "' > logging in </ a > first .</ p > " ));
2015-10-24 13:28:56 +00:00
exit ( page_renderer :: render ( " Upload - $settings->sitename " , " <p>Select an image below, and then type a name for it in the box. This server currently supports uploads up to " . human_filesize ( get_max_upload_size ()) . " in size.</p>
2015-10-19 07:03:38 +00:00
< p > $settings -> sitename currently supports uploading of the following file types : " . implode( " , " , $settings->upload_allowed_file_types ) . " .</ p >
< form method = 'post' action = '?action=upload' enctype = 'multipart/form-data' >
2015-10-18 20:01:18 +00:00
< label for = 'file' > Select a file to upload .</ label >
< input type = 'file' name = 'file' />
< br />
2015-10-22 07:38:50 +00:00
< label for = 'name' > Name :</ label >
< input type = 'text' name = 'name' />
< br />
< label for = 'description' > Description :</ label >
< textarea name = 'description' ></ textarea >
2015-10-18 20:01:18 +00:00
< br />
< input type = 'submit' value = 'Upload' />
</ form > " ));
2015-10-18 12:23:02 +00:00
break ;
case " POST " :
// Recieve file
2015-10-22 07:38:50 +00:00
// Make sure uploads are enabled
if ( ! $settings -> upload_enabled )
2015-10-19 07:03:38 +00:00
{
unlink ( $_FILES [ " file " ][ " tmp_name " ]);
http_response_code ( 412 );
exit ( page_renderer :: render ( " Upload failed - $settings->sitename " , " <p>Your upload couldn't be processed because uploads are currently disabled on $settings->sitename . <a href='index.php'>Go back to the main page</a>.</p> " ));
}
2015-10-18 12:23:02 +00:00
2015-10-22 07:38:50 +00:00
// Make sure that the user is logged in
2015-10-19 07:03:38 +00:00
if ( ! $env -> is_logged_in )
{
unlink ( $_FILES [ " file " ][ " tmp_name " ]);
http_response_code ( 401 );
exit ( page_renderer :: render ( " Upload failed - $settings->sitename " , " <p>Your upload couldn't be processed because you are not logged in.</p><p>Try <a href='?action=login&returnto= " . rawurlencode ( " ?action=upload " ) . " '>logging in</a> first. " ));
}
2015-10-22 07:38:50 +00:00
// Calculate the target ename, removing any characters we
2015-10-19 07:03:38 +00:00
// are unsure about.
2015-10-22 07:38:50 +00:00
$target_name = makepathsafe ( $_POST [ " name " ]);
$temp_filename = $_FILES [ " file " ][ " tmp_name " ];
2015-10-22 07:43:29 +00:00
$mimechecker = finfo_open ( FILEINFO_MIME_TYPE );
2015-10-22 07:38:50 +00:00
$mime_type = finfo_file ( $mimechecker , $temp_filename );
2015-10-22 07:44:55 +00:00
finfo_close ( $mimechecker );
2015-10-22 07:38:50 +00:00
// Perform appropriate checks based on the *real* filetype
switch ( substr ( $mime_type , 0 , strpos ( $mime_type , " / " )))
{
case " image " :
$extra_data = [];
$imagesize = getimagesize ( $temp_filename , $extra_data );
// Make sure that the image size is defined
2015-10-22 07:47:21 +00:00
if ( ! is_int ( $imagesize [ 0 ]) or ! is_int ( $imagesize [ 1 ]))
2015-10-24 13:28:56 +00:00
{
http_response_code ( 415 );
2015-10-22 07:38:50 +00:00
exit ( page_renderer :: render ( " Upload Error - $settings->sitename " , " <p>The file that you uploaded doesn't appear to be an image. $settings->sitename currently only supports uploading images (videos coming soon). <a href='?action=upload'>Go back to try again</a>.</p> " ));
2015-10-24 13:28:56 +00:00
}
2015-10-22 07:38:50 +00:00
break ;
case " video " :
2015-10-24 13:28:56 +00:00
http_response_code ( 501 );
2015-10-22 07:38:50 +00:00
exit ( page_renderer :: render ( " Upload Error - $settings->sitename " , " <p>You uploaded a video, but $settings->sitename doesn't support them yet. Please try again later.</p> " ));
default :
2015-10-24 13:28:56 +00:00
http_response_code ( 415 );
2015-10-22 07:43:29 +00:00
exit ( page_renderer :: render ( " Upload Error - $settings->sitename " , " <p>You uploaded an unnknown file type which couldn't be processed. $settings->sitename thinks that the file you uploaded was a(n) ' $mime_type ', which isn't supported.</p> " ));
2015-10-22 07:38:50 +00:00
}
$file_extension = system_mime_type_extension ( $mime_type );
2015-11-08 21:15:08 +00:00
$new_filename = " $paths->upload_file_prefix $target_name . $file_extension " ;
2015-10-22 07:59:03 +00:00
$new_description_filename = " $new_filename .md " ;
2015-10-22 07:38:50 +00:00
if ( isset ( $pageindex -> $new_filename ))
exit ( page_renderer :: render ( " Upload Error - $settings->sitename " , " <p>A page or file has already been uploaded with the name ' $new_filename '. Try deleting it first. If you do not have permission to delete things, try contacting one of the moderators.</p> " ));
if ( ! file_exists ( " Files " ))
mkdir ( " Files " , 0664 );
2015-11-08 21:15:08 +00:00
if ( ! move_uploaded_file ( $temp_filename , $env -> storage_prefix . $new_filename ))
2015-10-24 13:28:56 +00:00
{
http_response_code ( 409 );
2015-10-22 07:38:50 +00:00
exit ( page_renderer :: render ( " Upload Error - $settings->sitename " , " <p>The file you uploaded was valid, but $settings->sitename couldn't verify that it was tampered with during the upload process. This probably means that $settings->sitename has been attacked. Please contact " . $settings -> admindetails . " , your $settings->sitename Administrator.</p> " ));
2015-10-24 13:28:56 +00:00
}
2015-10-22 07:38:50 +00:00
$description = $_POST [ " description " ];
2015-11-08 21:15:08 +00:00
// Escape the raw html in the provided description if the setting is enabled
2015-10-22 07:38:50 +00:00
if ( $settings -> clean_raw_html )
$description = htmlentities ( $description , ENT_QUOTES );
2015-11-08 21:15:08 +00:00
file_put_contents ( $env -> storage_prefix . $new_description_filename , $description );
2015-10-22 07:38:50 +00:00
// Construct a new entry for the pageindex
$entry = new stdClass ();
2015-10-22 07:41:01 +00:00
// Point to the description's filepath since this property
// should point to a markdown file
$entry -> filename = $new_description_filename ;
2015-10-22 07:38:50 +00:00
$entry -> size = strlen ( $description );
$entry -> lastmodified = time ();
$entry -> lasteditor = $env -> user ;
$entry -> uploadedfile = true ;
$entry -> uploadedfilepath = $new_filename ;
2015-10-22 08:56:42 +00:00
$entry -> uploadedfilemime = $mime_type ;
2015-10-22 07:38:50 +00:00
// Add the new entry to the pageindex
2015-10-22 07:41:01 +00:00
// Assign the new entry to the image's filepath as that
// should be the page name.
2015-10-22 07:38:50 +00:00
$pageindex -> $new_filename = $entry ;
// Save the pageindex
2015-11-08 21:15:08 +00:00
file_put_contents ( $paths -> pageindex , json_encode ( $pageindex , JSON_PRETTY_PRINT ));
2015-10-18 12:23:02 +00:00
2015-10-22 08:03:31 +00:00
header ( " location: ?action=view&page= $new_filename &upload=success " );
2015-10-22 07:54:59 +00:00
2015-10-18 12:23:02 +00:00
break ;
}
});
add_action ( " preview " , function () {
2015-10-22 08:56:42 +00:00
global $settings , $env , $pageindex ;
2015-11-08 21:15:08 +00:00
$filepath = $env -> storage_prefix . $pageindex -> { $env -> page } -> uploadedfilepath ;
2015-10-22 08:56:42 +00:00
$mime_type = $pageindex -> { $env -> page } -> uploadedfilemime ;
2015-11-08 21:15:08 +00:00
if ( isset ( $_GET [ " size " ]) and $_GET [ " size " ] == " original " )
{
// Get the file size
$filesize = filesize ( $filepath );
// Send some headers
header ( " content-length: $filesize " );
header ( " content-type: $mime_type " );
// Open the file and send it to the user
$handle = fopen ( $filepath , " rb " );
fpassthru ( $handle );
fclose ( $handle );
exit ();
}
2015-10-24 09:04:24 +00:00
// Determine the target size of the image
$target_size = 512 ;
if ( isset ( $_GET [ " size " ]))
$target_size = intval ( $_GET [ " size " ]);
if ( $target_size < $settings -> min_preview_size )
$target_size = $settings -> min_preview_size ;
if ( $target_size > $settings -> max_preview_size )
$target_size = $settings -> max_preview_size ;
// Determine the output file type
$output_mime = $settings -> preview_file_type ;
if ( isset ( $_GET [ " type " ]) and in_array ( $_GET [ " type " ], [ " image/png " , " image/jpeg " , " image/webp " ]))
$output_mime = $_GET [ " type " ];
2015-10-22 08:56:42 +00:00
switch ( substr ( $mime_type , 0 , strpos ( $mime_type , " / " )))
{
case " image " :
2015-10-24 09:04:24 +00:00
$image = false ;
2015-10-22 08:56:42 +00:00
switch ( $mime_type )
{
case " image/jpeg " :
2015-10-24 09:04:24 +00:00
$image = imagecreatefromjpeg ( $filepath );
2015-10-22 08:56:42 +00:00
break ;
case " image/gif " :
2015-10-24 09:04:24 +00:00
$image = imagecreatefromgif ( $filepath );
2015-10-22 08:56:42 +00:00
break ;
case " image/png " :
2015-10-24 09:04:24 +00:00
$image = imagecreatefrompng ( $filepath );
2015-10-22 08:56:42 +00:00
break ;
case " image/webp " :
2015-10-24 09:04:24 +00:00
$image = imagecreatefromwebp ( $filepath );
2015-10-22 08:56:42 +00:00
break ;
default :
2015-10-24 13:28:56 +00:00
http_response_code ( 415 );
2015-10-24 09:04:24 +00:00
$image = errorimage ( " Unsupported image type. " );
2015-10-22 08:56:42 +00:00
break ;
}
2015-10-24 09:04:24 +00:00
$raw_width = imagesx ( $image );
$raw_height = imagesy ( $image );
2015-10-23 20:04:58 +00:00
2015-10-24 13:28:56 +00:00
$preview_image = resize_image ( $image , $target_size );
2015-10-24 09:04:24 +00:00
header ( " content-type: $output_mime " );
switch ( $output_mime )
2015-10-23 20:04:58 +00:00
{
2015-10-24 09:04:24 +00:00
case " image/jpeg " :
2015-10-24 13:28:56 +00:00
imagejpeg ( $preview_image );
2015-10-24 09:04:24 +00:00
break ;
case " image/png " :
2015-10-24 13:28:56 +00:00
imagepng ( $preview_image );
2015-10-24 09:04:24 +00:00
break ;
default :
case " image/webp " :
2015-10-24 13:28:56 +00:00
imagewebp ( $preview_image );
2015-10-24 09:04:24 +00:00
break ;
2015-10-23 20:04:58 +00:00
}
2015-10-24 13:28:56 +00:00
imagedestroy ( $preview_image );
2015-10-22 08:56:42 +00:00
break ;
2015-10-23 20:04:58 +00:00
default :
http_response_code ( 501 );
exit ( " Unrecognised file type. " );
2015-10-22 08:56:42 +00:00
}
2015-10-18 12:23:02 +00:00
});
page_renderer :: register_part_preprocessor ( function ( & $parts ) {
2015-10-24 13:28:56 +00:00
global $pageindex , $env , $settings ;
// Todo add the preview to the top of the page here, but only if the current action is view and we are on a page that is a file
if ( isset ( $pageindex -> { $env -> page } -> uploadedfile ) and $pageindex -> { $env -> page } -> uploadedfile == true )
{
// We are looking at a page that is paired with an uploaded file
$filepath = $pageindex -> { $env -> page } -> uploadedfilepath ;
$mime_type = $pageindex -> { $env -> page } -> uploadedfilemime ;
2015-10-24 20:03:18 +00:00
$image_link = " // " . $_SERVER [ " SERVER_NAME " ] . dirname ( $_SERVER [ " SCRIPT_NAME " ]) . $filepath ;
2015-11-08 21:15:08 +00:00
if ( $env -> storage_prefix !== " ./ " )
$image_link = " ?action=preview&size=original&page= " . rawurlencode ( $env -> page );
2015-10-24 13:28:56 +00:00
$preview_sizes = [ 256 , 512 , 768 , 1024 , 1536 ];
$preview_html = " <figure class='preview'>
< img src = '?action=preview&size=$settings->default_preview_size&page=" . rawurlencode($env->page) . "' />
< nav class = 'image-controls' >
< ul >< li >< a href = '$filepath' >& #x01f304; Original image</a></li>
< li > Other Sizes : " ;
foreach ( $preview_sizes as $size )
$preview_html .= " <a href='?action=preview&size=' $size > $size " . " px</a> " ;
2015-10-24 20:03:18 +00:00
$preview_html .= " </li>
< li >< label class = 'link-display-label' for = 'image-link' > Link :</ label > < input class = 'link-display' type = 'text' value = '$image_link' title = 'Press CTRL + C to copy.' onclick = 'this.select();' readonly /></ li ></ ul ></ nav >
2015-10-24 13:28:56 +00:00
</ figure >
< h2 > File Information </ h2 >
< table >< tr >< th > Name </ th >< td > " . str_replace( " File / " , " " , $filepath ) . " </ td >
< tr >< th > Type </ th >< td > $mime_type </ td ></ tr >
< tr >< th > Size </ th >< td > " . human_filesize(filesize( $filepath )) . " </ td ></ tr >
< tr >< th > Uploaded by </ th >< td > " . $pageindex -> { $env -> page } ->lasteditor . " </ td ></ tr ></ table >
< h2 > Description </ h2 > " ;
$parts [ " { content} " ] = str_replace ( " </h1> " , " </h1> \n $preview_html " , $parts [ " { content} " ]);
}
2015-10-18 12:23:02 +00:00
});
}
]);
2015-10-18 20:01:18 +00:00
//// Pair of functions to calculate the actual maximum upload size supported by the server
//// Lifted from Drupal by @meustrus from Stackoverflow. Link to answer:
//// http://stackoverflow.com/a/25370978/1460422
// Returns a file size limit in bytes based on the PHP upload_max_filesize
// and post_max_size
2015-10-19 07:03:38 +00:00
function get_max_upload_size ()
2015-10-18 20:01:18 +00:00
{
static $max_size = - 1 ;
if ( $max_size < 0 ) {
// Start with post_max_size.
$max_size = parse_size ( ini_get ( 'post_max_size' ));
// If upload_max_size is less, then reduce. Except if upload_max_size is
// zero, which indicates no limit.
$upload_max = parse_size ( ini_get ( 'upload_max_filesize' ));
if ( $upload_max > 0 && $upload_max < $max_size ) {
$max_size = $upload_max ;
}
}
return $max_size ;
}
function parse_size ( $size ) {
$unit = preg_replace ( '/[^bkmgtpezy]/i' , '' , $size ); // Remove the non-unit characters from the size.
$size = preg_replace ( '/[^0-9\.]/' , '' , $size ); // Remove the non-numeric characters from the size.
if ( $unit ) {
// Find the position of the unit in the ordered string which is the power of magnitude to multiply a kilobyte by.
return round ( $size * pow ( 1024 , stripos ( 'bkmgtpezy' , $unit [ 0 ])));
} else {
return round ( $size );
}
}
2015-10-22 08:56:42 +00:00
function errorimage ( $text )
{
$width = 640 ;
$height = 480 ;
$image = imagecreatetruecolor ( $width , $height );
imagefill ( $image , 0 , 0 , imagecolorallocate ( $image , 238 , 232 , 242 )); // Set the background to #eee8f2
$fontwidth = imagefontwidth ( 3 );
imagetext ( $image , 3 ,
( $width / 2 ) - (( $fontwidth * strlen ( $text )) / 2 ),
( $height / 2 ) - ( imagefontheight ( 3 ) / 2 ),
$text ,
imagecolorallocate ( $image , 17 , 17 , 17 ) // #111111
);
return $image ;
}
2015-10-24 09:04:24 +00:00
function resize_image ( $image , $size )
{
$cur_width = imagesx ( $image );
$cur_height = imagesy ( $image );
if ( $cur_width < $size and $cur_height < $size )
return $image ;
$width_ratio = $size / $cur_width ;
$height_ratio = $size / $cur_height ;
$ratio = min ( $width_ratio , $height_ratio );
2015-10-24 13:28:56 +00:00
$new_height = floor ( $cur_height * $ratio );
$new_width = floor ( $cur_width * $ratio );
header ( " x-resize-to: $new_width x $new_height\n " );
2015-10-24 09:04:24 +00:00
return imagescale ( $image , $new_width , $new_height );
}
2015-10-18 12:23:02 +00:00
?>