2023-01-25 22:29:19 +01:00
< ? php
2023-01-31 22:34:58 +01:00
define ( 'W2APP' , true );
2023-01-25 22:29:19 +01:00
/*
* W2
*
* Copyright ( C ) 2007 - 2011 Steven Frank < http :// stevenf . com />
*
* Code may be re - used as long as the above copyright notice is retained .
* See README . txt for full details .
*
* Written with Coda : < http :// panic . com / coda />
*
*/
// Install PSR-4-compatible class autoloader
spl_autoload_register ( function ( $class ){
require str_replace ( '\\' , DIRECTORY_SEPARATOR , ltrim ( $class , '\\' )) . '.php' ;
});
// Get Markdown class
2023-01-31 22:34:58 +01:00
use md\MarkdownExtra ;
2023-01-25 22:29:19 +01:00
// User configurable options:
2023-01-31 22:34:58 +01:00
require_once " config.php " ;
2023-01-25 22:29:19 +01:00
2023-01-31 22:34:58 +01:00
// Load configured localization:
require_once 'locales/' . W2_LOCALE . '.php' ;
2023-01-25 22:29:19 +01:00
2023-01-31 22:34:58 +01:00
/**
* Get translated word
*
* String $label Key for locale word
* String $alt_word Alternative word
* return String
*/
function __ ( $label , $alt_word = null )
{
global $w2_word_set ;
if ( empty ( $w2_word_set [ $label ]) )
{
return is_null ( $alt_word ) ? $label : $alt_word ;
}
return htmlspecialchars ( $w2_word_set [ $label ], ENT_QUOTES );
}
2023-01-25 22:29:19 +01:00
2023-01-31 22:34:58 +01:00
if ( REQUIRE_PASSWORD )
{
ini_set ( 'session.gc_maxlifetime' , W2_SESSION_LIFETIME );
session_set_cookie_params ( W2_SESSION_LIFETIME );
}
2023-01-25 22:29:19 +01:00
session_name ( W2_SESSION_NAME );
session_start ();
2023-01-31 22:34:58 +01:00
2023-01-25 22:29:19 +01:00
if ( count ( $allowedIPs ) > 0 )
{
$ip = $_SERVER [ 'REMOTE_ADDR' ];
$accepted = false ;
foreach ( $allowedIPs as $allowed )
{
if ( strncmp ( $allowed , $ip , strlen ( $allowed )) == 0 )
{
$accepted = true ;
break ;
}
}
if ( ! $accepted )
{
2023-01-31 22:34:58 +01:00
print " <html><body>Access from IP address $ip is not allowed</body></html> " ;
2023-01-25 22:29:19 +01:00
exit ;
}
}
2023-01-31 22:34:58 +01:00
function printHeader ( $title , $action , $bodyclass = " " )
{
print " <!doctype html> \n " ;
print " <html lang= \" " . W2_LOCALE . " \" > \n " ;
print " <head> \n " ;
print " <meta charset= \" " . W2_CHARSET . " \" > \n " ;
2023-02-03 16:40:18 +01:00
print " <link rel= \" icon \" href= \" /icons/fav.png \" /> \n " ;
2023-01-31 22:34:58 +01:00
print " <meta name= \" viewport \" content= \" width=device-width, initial-scale=1 \" /> \n " ;
print " <link type= \" text/css \" rel= \" stylesheet \" href= \" " . BASE_URI . " / " . CSS_FILE . " \" /> \n " ;
print " <title> " . PAGE_TITLE . " $title </title> \n " ;
print " </head> \n " ;
print " <body " . ( $bodyclass != " " ? " class= \" $bodyclass\ " " : " " ). " > \n " ;
}
function printFooter ()
{
print " </body> \n " ;
print " </html> " ;
}
function printDrawer ()
{
print " <div id= \" drawer \" class= \" inactive \" > \n " .
" <a href= \" \" onclick= \" toggleDrawer(); return false; \" ><img src= \" /icons/close.svg \" alt= \" " . __ ( 'Close' ) . " \" title= \" " . __ ( 'Close' ) . " \" class= \" icon rightaligned \" /></a> \n " .
" <div> \n " .
" # " . __ ( 'Header' ) . " 1<br/> " .
" ## " . __ ( 'Header' ) . " 2<br/> " .
" ### " . __ ( 'Header' ) . " 3<br/> " .
" #### " . __ ( 'Header' ) . " 4<br/> " .
" ##### " . __ ( 'Header' ) . " 5<br/> " .
" ###### " . __ ( 'Header' ) . " 6<br/> " .
" <br/> " .
" * " . __ ( 'Emphasize' ) . " * - <em> " . __ ( 'Emphasize' ) . " </em><br/> " .
" _ " . __ ( 'Emphasize' ) . " * - <em> " . __ ( 'Emphasize' ) . " </em><br/> " .
" ** " . __ ( 'Bold' ) . " ** - <strong> " . __ ( 'Bold' ) . " </strong><br/> " .
" __ " . __ ( 'Bold' ) . " __ - <strong> " . __ ( 'Bold' ) . " </strong><br/> " .
" <br/> " .
" [[Link to page]]<br/> " .
" <http://example.com/><br/> " .
" [link text](http://url)<br/><br/> " .
" { { image.jpg}}<br/> " .
" ![Alt text](/images/image.jpg)<br/> " .
" ![Alt text](/images/image.jpg \" Optional title \" )<br/> " .
" <br/> " .
" - Unordered list<br/> " .
" + Unordered list<br/> " .
" * Unordered list<br/> " .
" 1. Ordered list<br/> " .
" <br/> " .
" > Blockquote<br/> " .// < blockquote > Blockquotes </ blockquote > \n " .
" ```Code```<br/> " . //<pre>Code</pre>\n\n".
" `inline-code`<br/><br/> " .
" *** Horizontal rule<br/> " .
" --- Horizontal rule<br/> \n " .
" </div> \n " .
" </div> \n " .
" <a id= \" drawer-control \" href= \" \" onclick= \" toggleDrawer(); return false; \" > \n " .
" </a> \n " ;
}
2023-01-25 22:29:19 +01:00
if ( REQUIRE_PASSWORD && ! isset ( $_SESSION [ 'password' ]) )
{
if ( ! defined ( 'W2_PASSWORD_HASH' ) || W2_PASSWORD_HASH == '' )
define ( 'W2_PASSWORD_HASH' , sha1 ( W2_PASSWORD ));
if ( ( isset ( $_POST [ 'p' ])) && ( sha1 ( $_POST [ 'p' ]) == W2_PASSWORD_HASH ) )
$_SESSION [ 'password' ] = W2_PASSWORD_HASH ;
else
{
2023-01-31 22:34:58 +01:00
printHeader ( __ ( 'Log In' ), '' , " login " );
print " <h1> " . __ ( 'Log In' ) . " </h1> \n " ;
print " <form method= \" post \" > \n " ;
print " " . __ ( 'Password' ) . " : <input type= \" password \" name= \" p \" > \n " ;
print " <input type= \" submit \" value= \" " . __ ( 'Log In' ) . " \" > \n " ;
print " </form> \n " ;
printFooter ();
2023-01-25 22:29:19 +01:00
exit ;
}
}
// Support functions
2023-01-31 22:34:58 +01:00
function descLengthSort ( $val_1 , $val_2 )
2023-01-25 22:29:19 +01:00
{
2023-01-31 22:34:58 +01:00
$firstVal = strlen ( $val_1 );
$secondVal = strlen ( $val_2 );
return ( $firstVal > $secondVal ) ?
- 1 : ( ( $firstVal < $secondVal ) ? 1 : 0 );
2023-01-25 22:29:19 +01:00
}
2023-01-31 22:34:58 +01:00
function getAllPageNames ( $path = " " )
2023-01-25 22:29:19 +01:00
{
2023-01-31 22:34:58 +01:00
$filenames = array ();
$dir = opendir ( PAGES_PATH . " / $path " );
while ( $filename = readdir ( $dir ) )
{
if ( $filename [ 0 ] == " . " )
{
continue ;
}
if ( is_dir ( PAGES_PATH . " / $path / $filename " ) )
{
array_push ( $filenames , ... getAllPageNames ( " $path / $filename " ) );
continue ;
}
if ( preg_match ( " / " . PAGES_EXT . " $ / " , $filename ) != 1 )
{
continue ;
}
$filename = substr ( $filename , 0 , - ( strlen ( PAGES_EXT ) + 1 ) );
$filenames [] = substr ( " $path / $filename " , 1 );
}
closedir ( $dir );
return $filenames ;
2023-01-25 22:29:19 +01:00
}
2023-01-31 22:34:58 +01:00
function fileNameForPage ( $page )
2023-01-25 22:29:19 +01:00
{
2023-01-31 22:34:58 +01:00
return PAGES_PATH . " / $page . " . PAGES_EXT ;
2023-01-25 22:29:19 +01:00
}
2023-01-31 22:34:58 +01:00
function imageLinkText ( $imgName )
2023-01-25 22:29:19 +01:00
{
2023-05-09 19:37:40 +02:00
return " ![ " . __ ( " Image Description " ) . " ](/pages/ " . UPLOAD_FOLDER . " / $imgName ) " ;
2023-01-25 22:29:19 +01:00
}
2023-01-31 22:34:58 +01:00
function sanitizeFilename ( $inFileName )
2023-01-25 22:29:19 +01:00
{
2023-01-31 22:34:58 +01:00
return str_replace ( array ( '~' , '..' , '\\' , ':' , '|' , '&' ), '-' , $inFileName );
2023-01-25 22:29:19 +01:00
}
2023-01-31 22:34:58 +01:00
function pageURL ( $page )
{
return SELF . VIEW . " / " . str_replace ( " %2F " , " / " , str_replace ( " %23 " , " # " , urlencode ( sanitizeFilename ( $page ))));
}
2023-01-25 22:29:19 +01:00
2023-01-31 22:34:58 +01:00
function pageLink ( $page , $title , $attributes = " " )
2023-01-25 22:29:19 +01:00
{
2023-01-31 22:34:58 +01:00
return " <a href= \" " . pageURL ( $page ) . " \" $attributes > $title </a> " ;
/* wip
$link_page = $match [ 1 ];
$link_filename = PAGES_PATH . " / $link_page .txt " ;
$link_page_exists = file_exists ( $link_filename );
if ( $link_page_exists )
return " <a href= \" " . pageURL ( $page ) . " \" $attributes > $title </a> " ;
else
//return "<a href=\"" . SELF . VIEW . "/" . htmlentities($link_page) . "\" class=\"missing-link\">" . htmlentities($link_page) . "</a>";
return " <a href= \" " . pageURL ( $page ) . " \" class= \" missing-link \" . $attributes > $title </a> " ;
*/
}
2023-01-25 22:29:19 +01:00
2023-01-31 22:34:58 +01:00
function redirectWithMessage ( $page , $msg )
{
$_SESSION [ " msg " ] = $msg ;
header ( " HTTP/1.1 303 See Other " );
header ( " Location: " . pageURL ( $page ) );
exit ;
}
2023-01-25 22:29:19 +01:00
2023-01-31 22:34:58 +01:00
function checkedExecute ( & $msg , $cmd )
{
$returnValue = 0 ;
$output = '' ;
exec ( $cmd , $output , $returnValue );
if ( $returnValue != 0 )
2023-01-25 22:29:19 +01:00
{
2023-01-31 22:34:58 +01:00
$msg .= " <br/>Error executing command " . $cmd . " (return value: " . $returnValue . " ): " . implode ( " " , $output );
2023-01-25 22:29:19 +01:00
}
2023-01-31 22:34:58 +01:00
return ( $returnValue == 0 );
}
2023-01-25 22:29:19 +01:00
2023-01-31 22:34:58 +01:00
function gitChangeHandler ( $commitmsg , & $msg )
{
if ( ! GIT_COMMIT_ENABLED )
2023-01-25 22:29:19 +01:00
{
2023-01-31 22:34:58 +01:00
return ;
}
if ( checkedExecute ( $msg , " cd " . PAGES_PATH . " && git add -A && git commit -m " . escapeshellarg ( $commitmsg )))
{
if ( ! GIT_PUSH_ENABLED )
2023-01-25 22:29:19 +01:00
{
2023-01-31 22:34:58 +01:00
return ;
2023-01-25 22:29:19 +01:00
}
2023-01-31 22:34:58 +01:00
checkedExecute ( $msg , " cd " . PAGES_PATH . " && git push " );
2023-01-25 22:29:19 +01:00
}
2023-01-31 22:34:58 +01:00
}
2023-01-25 22:29:19 +01:00
2023-01-31 22:34:58 +01:00
function toHTMLID ( $noid )
{ // in HTML5, only spaces aren't allowed
return str_replace ( " " , " - " , $noid );
2023-01-25 22:29:19 +01:00
}
2023-01-31 22:34:58 +01:00
function toHTML ( $inText )
2023-01-25 22:29:19 +01:00
{
2023-01-31 22:34:58 +01:00
$parser = new MarkdownExtra ;
$parser -> no_markup = true ;
$outHTML = $parser -> transform ( $inText );
if ( AUTOLINK_PAGE_TITLES )
{
$pagenames = getAllPageNames ();
uasort ( $pagenames , " descLengthSort " );
foreach ( $pagenames as $pageName )
{
// match pageName, but only if it isn't inside another word or inside braces (as in "[$pageName]").
$outHTML = preg_replace ( " /(?<![ \ [a-zA-Z]) $pageName (?![ \ ]a-zA-Z])/i " , " [[ $pageName ]] " , $outHTML );
}
}
preg_match_all (
" / \ [ \ [(.*?) \ ] \ ]/ " ,
$outHTML ,
$matches ,
PREG_PATTERN_ORDER
);
for ( $i = 0 ; $i < count ( $matches [ 0 ]); $i ++ )
{
$fullLinkText = $matches [ 1 ][ $i ];
$linkTitleSplit = explode ( '|' , $fullLinkText );
$linkedPage = $linkTitleSplit [ 0 ]; // split away an eventual link text
$linkText = ( count ( $linkTitleSplit ) > 1 ) ? $linkTitleSplit [ 1 ] : $linkedPage ;
$pagePart = explode ( '#' , $linkedPage )[ 0 ]; // split away an eventual anchor part
$linkedFilename = fileNameForPage ( sanitizeFilename ( $pagePart ));
$exists = file_exists ( $linkedFilename );
$outHTML = str_replace ( " [[ $fullLinkText ]] " ,
pageLink ( $linkedPage , $linkText , ( $exists ? " " : " class= \" noexist \" " )), $outHTML );
}
$outHTML = preg_replace ( " / \ { \ { (.*?) \ } \ }/ " , " <img src= \" " . BASE_URI . " /images/ \\ 1 \" alt= \" \\ 1 \" /> " , $outHTML );
// add an anchor in all title tags (h1/2/3/4):
preg_match_all (
" /<h([1-4])>(.*?)< \ /h \\ 1>/ " ,
$outHTML ,
$matches ,
PREG_PATTERN_ORDER
);
for ( $i = 0 ; $i < count ( $matches [ 0 ]); $i ++ )
{
$prefix = " <h " . $matches [ 1 ][ $i ] . " > " ;
$caption = $matches [ 2 ][ $i ];
$suffix = substr_replace ( $prefix , " / " , 1 , 0 );
$outHTML = str_replace ( " $prefix $caption $suffix " ,
" $prefix <a id= \" " . toHTMLID ( $caption ) . " \" > $caption </a> $suffix " , $outHTML );
}
return $outHTML ;
2023-01-25 22:29:19 +01:00
}
function destroy_session ()
{
if ( isset ( $_COOKIE [ session_name ()]) )
2023-01-31 22:34:58 +01:00
{
2023-01-25 22:29:19 +01:00
setcookie ( session_name (), '' , time () - 42000 , '/' );
2023-01-31 22:34:58 +01:00
}
2023-01-25 22:29:19 +01:00
session_destroy ();
unset ( $_SESSION [ " password " ]);
unset ( $_SESSION );
}
2023-01-31 22:34:58 +01:00
function getPageActions ( $page , $action , $imgSuffix )
2023-01-25 22:29:19 +01:00
{
2023-01-31 22:34:58 +01:00
$pageActions = array ( 'edit' , 'delete' , 'rename' );
$pageActionNames = array ( __ ( 'Edit' ), __ ( 'Delete' ), __ ( 'Rename' ));
$result = '' ;
for ( $i = 0 ; $i < count ( $pageActions ); $i ++ )
{
if ( $action != $pageActions [ $i ])
2023-01-25 22:29:19 +01:00
{
2023-01-31 22:34:58 +01:00
$result .= " <a href= \" " . SELF . " ?action= " . $pageActions [ $i ] .
" &page= " . urlencode ( $page ) . " \" ><img src= \" /icons/ " . $pageActions [ $i ] . $imgSuffix . " .svg \" alt= \" " . $pageActionNames [ $i ] . " \" title= \" " . $pageActionNames [ $i ] . " \" class= \" icon \" ></a> \n " ;
2023-01-25 22:29:19 +01:00
}
2023-01-31 22:34:58 +01:00
}
$result .= " <a href= \" " . SELF . " ?action=view&page= $page &linkshere=true \" ><img src= \" /icons/link " . $imgSuffix . " .svg \" alt= \" " . __ ( 'Show links here' ) . " \" title= \" " . __ ( 'Show links here' ) . " \" class= \" icon \" /></a> \n " ;
return $result ;
2023-01-25 22:29:19 +01:00
}
// Main code
2023-01-31 22:34:58 +01:00
$action = isset ( $_REQUEST [ 'action' ]) ? $_REQUEST [ 'action' ] : 'view' ;
$newPage = " " ;
$text = " " ;
$html = " " ;
if ( $action === 'view' || $action === 'edit' || $action === 'save' || $action === 'rename' || $action === 'delete' )
2023-01-25 22:29:19 +01:00
{
2023-01-31 22:34:58 +01:00
// Look for page name following the script name in the URL, like this:
// http://stevenf.com/w2demo/index.php/Markdown%20Syntax
//
// Otherwise, get page name from 'page' request variable.
$page = preg_match ( '@^/@' , @ $_SERVER [ " PATH_INFO " ]) ?
urldecode ( substr ( $_SERVER [ " PATH_INFO " ], 1 )) : urldecode ( @ $_REQUEST [ 'page' ]);
$page = sanitizeFilename ( $page );
if ( $page == " " )
{
$page = DEFAULT_PAGE ;
}
$filename = fileNameForPage ( $page );
2023-01-25 22:29:19 +01:00
}
2023-01-31 22:34:58 +01:00
if ( $action === 'view' || $action === 'edit' )
2023-01-25 22:29:19 +01:00
{
2023-01-31 22:34:58 +01:00
if ( file_exists ( $filename ) )
{
$text = file_get_contents ( $filename );
}
else
{
$newPage = $page ;
$action = 'new' ;
}
}
$oldgitmsg = " " ;
$triedSave = false ;
if ( $action == 'save' )
{
$msg = '' ;
$newText = $_REQUEST [ 'newText' ];
$isNew = $_REQUEST [ 'isNew' ];
if ( $isNew )
{
$page = str_replace ( array ( '|' , '#' ), '' , $page );
$filename = fileNameForPage ( $page );
}
if ( $isNew && file_exists ( $filename ))
{
$msg .= " Error creating page ' $page ' - it already exists! Please choose a different name, or <a href= \" ?action=edit&page= " . urlencode ( $page ) . " \" >edit</a> the existing page (this discards current text!)!</div> \n " ;
$action = 'new' ;
$text = $newText ;
$newPage = $page ;
if ( GIT_COMMIT_ENABLED )
{
$oldgitmsg = $_REQUEST [ 'gitmsg' ];
}
$triedSave = true ;
}
else
2023-01-25 22:29:19 +01:00
{
2023-01-31 22:34:58 +01:00
$errLevel = error_reporting ( 0 );
if ( ! file_exists ( dirname ( $filename ) ) ) {
mkdir ( dirname ( $filename ), 0755 , true );
}
$success = file_put_contents ( $filename , $newText );
error_reporting ( $errLevel );
if ( $success === FALSE )
{
$msg .= " Error saving changes! Make sure your web server has write access to " . PAGES_PATH . " \n " ;
$action = ( $isNew ? 'new' : 'edit' );
$text = $newText ;
$newPage = $page ;
if ( GIT_COMMIT_ENABLED )
{
$oldgitmsg = $_REQUEST [ 'gitmsg' ];
}
$triedSave = true ;
}
else
{
$msg .= ( $isNew ? __ ( 'Created' ) : __ ( 'Saved' ));
$usermsg = $_REQUEST [ 'gitmsg' ];
$commitmsg = $page . ( $usermsg !== '' ? ( " : " . $usermsg ) : ( $isNew ? " created " : " changed " ));
gitChangeHandler ( $commitmsg , $msg );
}
2023-01-25 22:29:19 +01:00
}
2023-01-31 22:34:58 +01:00
redirectWithMessage ( $page , $msg );
2023-01-25 22:29:19 +01:00
}
2023-01-31 22:34:58 +01:00
if ( $action === 'edit' || $action === 'new' )
2023-01-25 22:29:19 +01:00
{
2023-01-31 22:34:58 +01:00
$formAction = SELF . (( $action === 'edit' ) ? " / $page " : " " );
$html .= " <form id= \" edit \" method= \" post \" action= \" $formAction\ " > \n " ;
2023-01-25 22:29:19 +01:00
2023-01-31 22:34:58 +01:00
if ( $action === 'edit' )
{
2023-01-25 22:29:19 +01:00
$html .= " <input type= \" hidden \" name= \" page \" value= \" $page\ " /> \n " ;
2023-01-31 22:34:58 +01:00
}
2023-01-25 22:29:19 +01:00
else
2023-01-31 22:34:58 +01:00
{
if ( $newPage != " " && ! $triedSave )
{
$html .= " <div class= \" note \" > " . __ ( 'Creating new page since no page with given title exists!' ) ;
// check if similar page exists...
$pageNames = getAllPageNames ();
foreach ( $pageNames as $pageName )
{
if ( levenshtein ( strtoupper ( $newPage ), strtoupper ( $pageName )) < sqrt ( min ( strlen ( $newPage ), strlen ( $pageName ))) )
{
$html .= " <br/><strong>Note:</strong> Found similar page " . pageLink ( $pageName , $pageName ) . " . Maybe you meant to edit this instead? " ;
}
}
$html .= " </div> \n " ;
}
$html .= " <p> " . __ ( 'Title' ) . " : <input id= \" title \" title= \" " . __ ( " Character restrictions: '#' and '|' have a special meaning in page links, they will therefore be removed; also, characters '~', '..', ' \\ ', ':', '|', '&' might cause trouble in filenames and are therefore replaced by '-'. " ) . " \" type= \" text \" name= \" page \" value= \" $newPage\ " class = \ " pagename \" placeholder= \" " . __ ( 'Name of new page (restrictions in tip)' ) . " \" /></p> \n " ;
2023-01-25 22:29:19 +01:00
2023-01-31 22:34:58 +01:00
}
2023-01-25 22:29:19 +01:00
2023-01-31 22:34:58 +01:00
$html .= " <p><textarea id= \" text \" name= \" newText \" rows= \" " . EDIT_ROWS . " \" autocomplete= \" off \" autocorrect= \" off \" autocapitalize= \" off \" spellcheck= \" false \" > $text </textarea></p> \n " ;
if ( GIT_COMMIT_ENABLED )
{
$html .= " <p>Message: <input type= \" text \" id= \" gitmsg \" name= \" gitmsg \" value= \" $oldgitmsg\ " /></ p > \n " ;
}
$html .= " <p><input type= \" hidden \" name= \" action \" value= \" save \" /> \n " ;
$html .= " <input type= \" hidden \" name= \" isNew \" value= \" " . (( $action === 'new' ) ? " true " : " " ) . " \" /> \n " ;
$html .= '<input id="save" type="submit" value="' . __ ( 'Save' ) . '" />' . " \n " ;
$html .= '<input id="cancel" type="button" onclick="history.go(-1);" value="' . __ ( 'Cancel' ) . '" />' . " \n " ;
$html .= " </p></form> \n " ;
2023-01-25 22:29:19 +01:00
}
2023-01-31 22:34:58 +01:00
else if ( $action === 'logout' )
2023-01-25 22:29:19 +01:00
{
destroy_session ();
header ( " Location: " . SELF );
exit ;
}
2023-01-31 22:34:58 +01:00
else if ( $action === 'upload' )
2023-01-25 22:29:19 +01:00
{
if ( DISABLE_UPLOADS )
{
2023-01-31 22:34:58 +01:00
$html .= '<p>' . __ ( 'Image uploading has been disabled on this installation.' ) . '</p>' ;
2023-01-25 22:29:19 +01:00
}
else
{
2023-01-31 22:34:58 +01:00
$html .= " <form id= \" upload \" method= \" post \" action= \" " . SELF . " \" enctype= \" multipart/form-data \" ><p> \n " .
" <input type= \" hidden \" name= \" action \" value= \" uploaded \" /> " .
" <input id= \" file \" type= \" file \" name= \" userfile \" /> \n " .
'<input id="resize" type="checkbox" checked="checked" name="resize" value="true">' .
'<label for="resize">' . __ ( 'Shrink if larger than ' ) . '</label>' .
'<input id="maxsize" type="number" name="maxsize" min="20" max="8192" value="1200">' .
'<label for="maxsize" id="maxsizelabel">' . __ ( 'Pixels' ) . '</label>' .
'<input id="upload" type="submit" value="' . __ ( 'Upload' ) . '" />' . " \n " .
'<input id="cancel" type="button" onclick="history.go(-1);" value="' . __ ( 'Cancel' ) . '" />' . " \n " ;
" </p></form> \n " ;
}
// list files in UPLOAD_FOLDER
$path = PAGES_PATH . " / " . UPLOAD_FOLDER . " /* " ;
$imgNames = glob ( $path );
natcasesort ( $imgNames );
$html .= " <p> " . __ ( 'Total' ) . " : " . count ( $imgNames ) . " " . __ ( 'images' ) . " </p> " ;
$html .= " <table><thead> " ;
$html .= " <tr> " .
/*
" <td> " . (( $sortBy != 'name' ) ? ( " <a href= \" " . SELF . " ?action=all&sortBy=name \" >Name</a> " ) : " <span class= \" sortBy \" >Name</span> " ) . " </td> " .
" <td> " . (( $sortBy != 'recent' ) ? ( " <a href= \" " . SELF . " ?action=all&sortBy=recent \" >Modified</a> " ) : " <span class= \" sortBy \" >Modified</span> " ) . " </td> " .
*/ " <td> " . __ ( " Name " ) . " </td><td> " . __ ( " Usage " ) . " </td><td> " . __ ( " Modified " ) . " </td><td> " . __ ( " Action " ) . " </td> " .
" </tr></thead><tbody> " ;
$date_format = __ ( 'date_format' , TITLE_DATE );
foreach ( $imgNames as $imgName )
{
$html .= " <tr> " .
" <td> " . basename ( $imgName ) . " </td> " .
" <td><pre> " . imageLinkText ( basename ( $imgName )) . " </pre></td> " .
" <td><nobr> " . date ( $date_format , filemtime ( $imgName )) . " </nobr></td> " .
" <td><a href= \" " . SELF . " ?action=imgDelete " . " &imgName= " . urlencode ( basename ( $imgName )) . " \" > " . __ ( 'Delete' ) . " </a></td> " .
" </tr> \n " ;
2023-01-25 22:29:19 +01:00
}
2023-01-31 22:34:58 +01:00
$html .= " </tbody></table> \n " ;
2023-01-25 22:29:19 +01:00
}
2023-01-31 22:34:58 +01:00
else if ( $action === 'uploaded' )
2023-01-25 22:29:19 +01:00
{
2023-01-31 22:34:58 +01:00
if ( DISABLE_UPLOADS )
2023-01-25 22:29:19 +01:00
{
2023-01-31 22:34:58 +01:00
die ( 'Invalid access. Uploads are disabled in the configuration.' );
}
$dstName = sanitizeFilename ( $_FILES [ 'userfile' ][ 'name' ]);
$dstName = str_replace ( " " , " _ " , $dstName ); // image display currently doesn't like spaces!
$fileType = $_FILES [ 'userfile' ][ 'type' ];
preg_match ( '/\.([^.]+)$/' , $dstName , $matches );
$fileExt = isset ( $matches [ 1 ]) ? $matches [ 1 ] : null ;
$imgExts = array ( 'jpg' , 'jpeg' , 'png' , 'gif' );
$msg = '' ;
if ( in_array ( $fileType , explode ( ',' , VALID_UPLOAD_TYPES )) &&
in_array ( $fileExt , explode ( ',' , VALID_UPLOAD_EXTS )))
{
$path = PAGES_PATH . " / " . UPLOAD_FOLDER . " / $dstName " ;
$resize = isset ( $_POST [ 'resize' ]) && $_POST [ 'resize' ] === 'true' ;
$doResize = $resize && in_array ( $fileExt , $imgExts );
if ( $doResize )
2023-01-25 22:29:19 +01:00
{
2023-01-31 22:34:58 +01:00
$exif = exif_read_data ( $_FILES [ 'userfile' ][ 'tmp_name' ]);
$size = getimagesize ( $_FILES [ 'userfile' ][ 'tmp_name' ]);
$maxsize = intval ( $_POST [ 'maxsize' ]);
$doResize = ( $size [ 0 ] > $maxsize || $size [ 1 ] > $maxsize );
if ( $doResize )
2023-01-25 22:29:19 +01:00
{
2023-01-31 22:34:58 +01:00
$msg .= " trying to resize " ;
$finalPath = $path ;
$path = substr ( $path , 0 , strlen ( $path ) - strlen ( $fileExt ) - 1 ) . " -tmp-resize. " . $fileExt ;
2023-01-25 22:29:19 +01:00
}
2023-01-31 22:34:58 +01:00
}
$errLevel = error_reporting ( 0 );
if ( move_uploaded_file ( $_FILES [ 'userfile' ][ 'tmp_name' ], $path ) === true )
{
$msg = " File ' $dstName ' uploaded! " ;
if ( $doResize )
2023-01-25 22:29:19 +01:00
{
2023-01-31 22:34:58 +01:00
$newSize = array ( 0 , 0 );
$idx0 = ( $size [ 0 ] > $size [ 1 ]) ? 0 : 1 ;
$idx1 = ( $idx0 == 0 ) ? 1 : 0 ;
$newSize [ $idx0 ] = $maxsize ;
$newSize [ $idx1 ] = ( int ) round ( $size [ $idx1 ] * $maxsize / $size [ $idx0 ]);
$src = imagecreatefromstring ( file_get_contents ( $path ));
$dst = imagecreatetruecolor ( $newSize [ 0 ], $newSize [ 1 ]);
if ( ! imagecopyresampled ( $dst , $src , 0 , 0 , 0 , 0 , $newSize [ 0 ], $newSize [ 1 ], $size [ 0 ], $size [ 1 ]))
{
$msg .= " Resizing file failed! " ;
}
imagedestroy ( $src );
if ( ! empty ( $exif [ 'Orientation' ]))
{
switch ( $exif [ 'Orientation' ])
{
case 8 :
$msg .= " Image rotated by +90°. " ;
$rot = imagerotate ( $dst , 90 , 0 );
break ;
case 3 :
$msg .= " Image rotated by 180°. " ;
$rot = imagerotate ( $dst , 180 , 0 );
break ;
case 6 :
$msg .= " Image rotated by -90°. " ;
$rot = imagerotate ( $dst , - 90 , 0 );
break ;
default :
$msg .= " Unknown EXIF orientation specification: " . $exif [ 'Orientation' ] . " ! " ;
break ;
}
if ( $rot === false )
{
$msg .= " Rotation failed! " ;
}
else
{
imagedestroy ( $dst );
$dst = $rot ;
}
}
if ( $fileExt === 'png' )
{
imagepng ( $dst , $finalPath );
}
else if ( $fileExt === 'jpg' || $fileExt === 'jpeg' )
{
imagejpeg ( $dst , $finalPath );
}
else if ( $fileExt === 'gif' )
{
imagegif ( $dst , $finalPath );
}
unlink ( $path );
imagedestroy ( $dst );
2023-01-25 22:29:19 +01:00
}
2023-01-31 22:34:58 +01:00
gitChangeHandler ( $msg , $msg );
$msg .= " ( $size[0] x $size[1] " . (( $doResize ) ? " , resized to $newSize[0] x $newSize[1] " : " " ) . " ) successfully! Use <pre> " . imageLinkText ( $dstName ) . " </pre> to refer to it! " ;
2023-01-25 22:29:19 +01:00
}
2023-01-31 22:34:58 +01:00
else
{
$error_code = $_FILES [ 'userfile' ][ 'error' ];
if ( $error_code === 0 ) {
// Likely a permissions issue
$msg .= __ ( 'Upload error' ) . " : Can't write to " . $path . " <br/><br/> \n " .
" Check that your permissions are set correctly. " ;
} else {
// Give generic error message
$msg .= __ ( 'Upload error' ) . " , error # " . $error_code . " <br/><br/> \n " .
" Please see <a href= \" https://www.php.net/manual/en/features.file-upload.errors.php \" >here</a> for more information.<br/><br/> \n " .
" If you see this message, please <a href= \" https://github.com/codeling/w2wiki/issues \" >file a bug to improve w2wiki</a> " ;
}
}
error_reporting ( $errLevel );
2023-01-25 22:29:19 +01:00
}
else
2023-01-31 22:34:58 +01:00
{
$msg .= __ ( 'Upload error: invalid file type' );
}
redirectWithMessage ( DEFAULT_PAGE , $msg );
2023-01-25 22:29:19 +01:00
}
2023-01-31 22:34:58 +01:00
else if ( $action === 'rename' || $action === 'delete' || $action === 'imgDelete' )
2023-01-25 22:29:19 +01:00
{
2023-01-31 22:34:58 +01:00
if ( $action === 'imgDelete' )
{
$page = sanitizeFilename ( urldecode ( $_REQUEST [ 'imgName' ]));
}
$actionName = ( $action === 'delete' || $action === 'imgDelete' ) ? __ ( 'Delete' ) : __ ( 'Rename' );
$html .= " <form id= \" $action\ " method = \ " post \" action= \" " . SELF . " \" > " ;
$html .= " <p> " . $actionName . " $page " .
(( $action === 'rename' ) ? ( __ ( 'to' ) . " <input id= \" newPageName \" type= \" text \" name= \" newPageName \" value= \" " . htmlspecialchars ( $page ) . " \" class= \" pagename \" /> " ) : " ? " ) . " </p> " ;
$html .= " <p><input id= \" $action\ " type = \ " submit \" value= \" $actionName\ " > " ;
2023-01-25 22:29:19 +01:00
$html .= " <input id= \" cancel \" type= \" button \" onclick= \" history.go(-1); \" value= \" Cancel \" /> \n " ;
2023-01-31 22:34:58 +01:00
$html .= " <input type= \" hidden \" name= \" action \" value= \" ${ action } d \" /> " ;
$html .= " <input type= \" hidden \" name= \" oldPageName \" value= \" " . htmlspecialchars ( $page ) . " \" /> " ;
2023-01-25 22:29:19 +01:00
$html .= " </p></form> " ;
}
2023-01-31 22:34:58 +01:00
else if ( $action === 'renamed' || $action === 'deleted' )
2023-01-25 22:29:19 +01:00
{
2023-01-31 22:34:58 +01:00
// TODO: prevent relative filenames from being injected
$oldPageName = sanitizeFilename ( $_POST [ 'oldPageName' ]);
$newPageName = ( $action === 'deleted' ) ? " " : sanitizeFilename ( $_POST [ 'newPageName' ]);
$msg = '' ;
if ( $action === 'deleted' )
2023-01-25 22:29:19 +01:00
{
2023-01-31 22:34:58 +01:00
$success = unlink ( fileNameForPage ( $oldPageName ));
}
else
{
$success = rename ( fileNameForPage ( $oldPageName ), fileNameForPage ( $newPageName ));
}
if ( $success )
{
$message = ( $action === 'deleted' ) ? " Removed $oldPageName . " :
" Renamed $oldPageName to $newPageName . " ;
$msg .= $message ;
// Change links in all pages to point to new page
$pagenames = getAllPageNames ();
$changedPages = array ();
foreach ( $pagenames as $replacePage )
2023-01-25 22:29:19 +01:00
{
2023-01-31 22:34:58 +01:00
$content = file_get_contents ( fileNameForPage ( $replacePage ));
$count = 0 ;
$regexSaveOldPageName = str_replace ( " / " , " \\ / " , $oldPageName );
$newContent = preg_replace ( " / \ [ \ [ $regexSaveOldPageName ([|#].* \ ] \ ]| \ ] \ ])/ " ,
(( $action === 'deleted' ) ? " " : " [[ $newPageName\\1 " ),
$content , - 1 , $count );
if ( $count > 0 ) // if something changed
2023-01-25 22:29:19 +01:00
{
2023-01-31 22:34:58 +01:00
$changedPages [] = $replacePage . " ( $count " . __ ( 'matches' ) . " ) " ;
file_put_contents ( fileNameForPage ( $replacePage ), $newContent );
2023-01-25 22:29:19 +01:00
}
}
2023-01-31 22:34:58 +01:00
if ( count ( $changedPages ) > 0 )
{
$msg .= " <br/> \n " . __ ( 'Updated links in the following pages:' ) . " \n <ul><li> " ;
$msg .= implode ( " </li><li> " , $changedPages );
$msg .= " </li></ul> " ;
}
gitChangeHandler ( $message , $msg );
$page = $newPageName ;
2023-01-25 22:29:19 +01:00
}
else
{
2023-01-31 22:34:58 +01:00
$msg .= ( $action === 'deleted' ) ? __ ( 'Error deleting file' ) : __ ( 'Error renaming file' );
$page = $oldPageName ;
}
if ( $action === 'deleted' && $success )
{
$page = DEFAULT_PAGE ;
2023-01-25 22:29:19 +01:00
}
2023-01-31 22:34:58 +01:00
redirectWithMessage ( $page , $msg );
2023-01-25 22:29:19 +01:00
}
2023-01-31 22:34:58 +01:00
else if ( $action === 'imgDeleted' )
2023-01-25 22:29:19 +01:00
{
2023-01-31 22:34:58 +01:00
// TODO: prevent relative filenames from being injected
$oldPageName = sanitizeFilename ( $_REQUEST [ 'oldPageName' ]);
$imgPath = PAGES_PATH . " / " . UPLOAD_FOLDER . " / " . $oldPageName ;
$success = unlink ( $imgPath );
if ( $success )
2023-01-25 22:29:19 +01:00
{
2023-01-31 22:34:58 +01:00
$msg = __ ( 'Image deleted' );
gitChangeHandler ( $msg , $msg );
$msg .= " ( " . $imgPath . " ) " ;
2023-01-25 22:29:19 +01:00
}
2023-01-31 22:34:58 +01:00
else
2023-01-25 22:29:19 +01:00
{
2023-01-31 22:34:58 +01:00
$msg = __ ( 'Error deleting image' );
$msg .= " ( " . $imgPath . " ) " ;
2023-01-25 22:29:19 +01:00
}
2023-01-31 22:34:58 +01:00
redirectWithMessage ( DEFAULT_PAGE , $msg );
2023-01-25 22:29:19 +01:00
}
2023-01-31 22:34:58 +01:00
else if ( $action === 'all' )
2023-01-25 22:29:19 +01:00
{
2023-01-31 22:34:58 +01:00
$pageNames = getAllPageNames ();
2023-01-25 22:29:19 +01:00
$filelist = array ();
2023-01-31 22:34:58 +01:00
$sortBy = isset ( $_REQUEST [ 'sortBy' ]) ? $_REQUEST [ 'sortBy' ] : 'name' ;
if ( ! in_array ( $sortBy , array ( 'name' , 'recent' )))
2023-01-25 22:29:19 +01:00
{
2023-01-31 22:34:58 +01:00
$sortBy = 'name' ;
2023-01-25 22:29:19 +01:00
}
2023-01-31 22:34:58 +01:00
if ( $sortBy === 'name' )
2023-01-25 22:29:19 +01:00
{
2023-01-31 22:34:58 +01:00
natcasesort ( $pageNames );
foreach ( $pageNames as $page )
{
$filelist [ $page ] = filemtime ( fileNameForPage ( $page ));
}
2023-01-25 22:29:19 +01:00
}
2023-01-31 22:34:58 +01:00
else
2023-01-25 22:29:19 +01:00
{
2023-01-31 22:34:58 +01:00
foreach ( $pageNames as $page )
2023-01-25 22:29:19 +01:00
{
2023-01-31 22:34:58 +01:00
$filelist [ $page ] = filemtime ( fileNameForPage ( $page ));
}
arsort ( $filelist , SORT_NUMERIC );
}
$html .= " <p> " . __ ( 'Total' ) . " : " . count ( $pageNames ) . " " . __ ( " pages " ) . " </p> " ;
$html .= " <table><thead> " ;
$html .= " <tr> " .
" <td> " . (( $sortBy != 'name' ) ? ( " <a href= \" " . SELF . " ?action=all&sortBy=name \" >Name</a> " ) : " <span class= \" sortBy \" > " . __ ( 'Name' ) . " </span> " ) . " </td> " .
" <td> " . (( $sortBy != 'recent' ) ? ( " <a href= \" " . SELF . " ?action=all&sortBy=recent \" > " . __ ( 'Modified' ) . " </a> " ) : " <span class= \" sortBy \" > " . __ ( 'Modified' ) . " </span> " ) . " </td> " .
" <td> " . __ ( 'Action' ) . " </td> " .
" </tr></thead><tbody> " ;
$date_format = __ ( 'date_format' , TITLE_DATE );
foreach ( $filelist as $pageName => $pageDate )
{
$html .= " <tr> " .
" <td> " . pageLink ( $pageName , $pageName ) . " </td> " .
" <td valign= \" top \" ><nobr> " . date ( $date_format , $pageDate ) . " </nobr></td> " .
//"<td class=\"pageActions\">".getPageActions($pageName, $action,"-dark")."</td>". /* dark mode */
" <td class= \" pageActions \" > " . getPageActions ( $pageName , $action , " " ) . " </td> " . /* light mode */
" </tr> \n " ;
}
$html .= " </tbody></table> \n " ;
}
else if ( $action === 'search' )
{
$matches = 0 ;
$q = $_REQUEST [ 'q' ];
$html .= " <h1>Search: $q </h1> \n " ;
2023-01-25 22:29:19 +01:00
2023-01-31 22:34:58 +01:00
if ( trim ( $q ) != " " )
{
$html .= " <ul> \n " ;
$pagenames = getAllPageNames ();
$found = FALSE ;
$matchingPages = array ();
foreach ( $pagenames as $searchPage )
{
if ( $searchPage === $q )
{
$found = TRUE ;
}
if ( preg_match ( " / { $q } /i " , $searchPage ))
{
array_unshift ( $matchingPages , $searchPage );
++ $matches ;
}
else
{
$text = file_get_contents ( fileNameForPage ( $searchPage ));
if ( preg_match ( " / { $q } /i " , $text ) )
{
$matchingPages [] = $searchPage ;
++ $matches ;
}
}
}
foreach ( $matchingPages as $page )
{
$link = pageLink ( $page , $page , ( $page === $q ) ? " class= \" literalMatch \" " : " " );
$html .= " <li> $link </li> \n " ;
}
if ( ! $found )
2023-01-25 22:29:19 +01:00
{
2023-01-31 22:34:58 +01:00
$html .= " <li> " . pageLink ( $q , __ ( 'Create page' ) . " ' $q ' " , " class= \" noexist \" " ) . " </li> " ;
2023-01-25 22:29:19 +01:00
}
2023-01-31 22:34:58 +01:00
$html .= " </ul> \n " ;
2023-01-25 22:29:19 +01:00
}
2023-01-31 22:34:58 +01:00
$html .= " <p> $matches " . __ ( 'matches' ) . " </p> \n " ;
}
else
{
$html .= empty ( $text ) ? '' : toHTML ( $text );
}
$datetime = '' ;
2023-01-25 22:29:19 +01:00
2023-01-31 22:34:58 +01:00
if ( ( $action === 'all' ))
{
$title = __ ( " All " );
}
else if ( $action === 'upload' )
{
$title = __ ( " Upload " );
2023-01-25 22:29:19 +01:00
}
2023-01-31 22:34:58 +01:00
else if ( $action === 'new' )
{
$title = __ ( " New " );
}
else if ( $action === 'search' )
{
$title = __ ( " Search " );
}
else if ( $filename != '' )
{
$title = (( $action === 'edit' ) ? ( __ ( 'Edit' ) . " : " ) : " " ) . $page ;
$date_format = __ ( 'date_format' , TITLE_DATE );
if ( $date_format )
{
$datetime = " <span class= \" titledate \" > " . date ( $date_format , @ filemtime ( $filename )) . " </span> " ;
}
}
else
{
$title = __ ( $action );
}
// Disable caching on the client (the iPhone is pretty agressive about this
// and it can cause problems with the editing function)
2023-01-25 22:29:19 +01:00
2023-01-31 22:34:58 +01:00
header ( " Cache-Control: no-cache, must-revalidate " ); // HTTP/1.1
header ( " Expires: Mon, 26 Jul 1997 05:00:00 GMT " ); // Date in the past
printHeader ( $title , $action );
print " <div class= \" titlebar \" ><span class= \" title \" > $title </span> $datetime " ;
if ( $action === 'view' || $action === 'rename' || $action === 'delete' || $action === 'edit' )
{
print ( getPageActions ( $page , $action , " " ));
}
print " </div> \n " ;
print " <div class= \" toolbar \" > \n " ;
print " <a href= \" " . SELF . " \" ><img src= \" /icons/home.svg \" alt= \" " . __ ( DEFAULT_PAGE ) . " \" title= \" " . __ ( DEFAULT_PAGE ) . " \" class= \" icon \" ></a> \n " ;
print " <a href= \" " . SELF . " ?action=all \" ><img src= \" /icons/list.svg \" alt= \" " . __ ( 'All' ) . " \" title= \" " . __ ( 'All' ) . " \" class= \" icon \" ></a> \n " ;
print " <a href= \" " . SELF . " ?action=new \" ><img src= \" /icons/new.svg \" alt= \" " . __ ( 'New' ) . " \" title= \" " . __ ( 'New' ) . " \" class= \" icon \" ></a> \n " ;
if ( ! DISABLE_UPLOADS )
{
print " <a href= \" " . SELF . VIEW . " ?action=upload \" ><img src= \" /icons/upload.svg \" alt= \" " . __ ( 'Upload' ) . " \" title= \" " . __ ( 'Upload' ) . " \" class= \" icon \" /></a> \n " ;
2023-01-25 22:29:19 +01:00
}
2023-01-31 22:34:58 +01:00
if ( REQUIRE_PASSWORD )
2023-01-25 22:29:19 +01:00
{
2023-01-31 22:34:58 +01:00
print " <a href= \" " . SELF . " ?action=logout \" > " . __ ( 'Log out' ) . " </a> " ;
2023-01-25 22:29:19 +01:00
}
2023-01-31 22:34:58 +01:00
print " <form method= \" post \" action= \" " . SELF . " ?action=search \" > \n " ;
print " <input class= \" search \" placeholder= \" " . __ ( 'Search' ) . " \" size= \" 20 \" id= \" search \" type= \" text \" name= \" q \" /> \n </form> \n " ;
if ( $action === 'edit' )
2023-01-25 22:29:19 +01:00
{
2023-01-31 22:34:58 +01:00
printDrawer ();
}
print " </div> \n " ;
if ( SIDEBAR_PAGE != '' )
{
print " <div class= \" sidebar \" > \n \n " ;
$sidebarFile = fileNameForPage ( SIDEBAR_PAGE );
if ( file_exists ( $sidebarFile ))
{
$text = file_get_contents ( $sidebarFile );
}
else
2023-01-25 22:29:19 +01:00
{
2023-01-31 22:34:58 +01:00
$text = __ ( 'Sidebar file could not be found' ) . " ( $sidebarFile ) " ;
2023-01-25 22:29:19 +01:00
}
2023-01-31 22:34:58 +01:00
print toHTML ( $text );
print " </div> \n " ;
}
if ( $action === 'view' && $_GET [ 'linkshere' ])
{
print " <div class= \" linkshere \" > " . __ ( 'What links here:' ) . " <ul> " ;
$pagenames = getAllPageNames ();
foreach ( $pagenames as $searchPage )
{
$text = file_get_contents ( fileNameForPage ( $searchPage ));
$regexSavePage = str_replace ( " / " , " \\ / " , $page );
if ( preg_match ( " / \ [ \ [ $regexSavePage /i " , $text ) )
{
$link = pageLink ( $searchPage , $searchPage , " " );
print ( " <li> $link </li> \n " );
}
}
print " </ul></div> " ;
}
print " <div class= \" main \" > \n \n " ;
if ( isset ( $_SESSION [ 'msg' ]) && $_SESSION [ 'msg' ] != '' )
{
print " <div class= \" note \" > " . $_SESSION [ 'msg' ] . " </div> " ;
unset ( $_SESSION [ 'msg' ]);
2023-01-25 22:29:19 +01:00
}
print " $html\n " ;
2023-01-31 22:34:58 +01:00
print " </div> \n " ;
printFooter ();