diff --git a/include/functions.php b/include/functions.php
index 67595e2..fce3165 100644
--- a/include/functions.php
+++ b/include/functions.php
@@ -1,263 +1,270 @@
.
/**
* Require a certain page from the template directory
*
* It will eventually echo something.
*
* @param $name string page name (to be sanitized)
* @param $args mixed arguments to be passed to the page scope
*/
function template( $template_name, $template_args = [] ) {
extract( $template_args, EXTR_SKIP );
return require TEMPLATE_PATH . __ . "$template_name.php";
}
/**
* Get the template output
*
* It will echo nothing.
*
* @param $name string page name (to be sanitized)
* @param $args mixed arguments to be passed to the page scope
* @see template()
* @return string The template output
*/
function template_content( $name, $args = [] ) {
ob_start();
template( $name, $args );
$text = ob_get_contents();
ob_end_clean();
return $text;
}
/**
* Print an e-mail (safe for bots)
*
* @param $email string
*/
function email_blur( $email ) {
$dot = strip_tags( __( " dot " ) );
$at = strip_tags( __( " at " ) );
$email = esc_html( $email );
echo str_replace( [ '.', '@' ], [ $dot, $at ], $email );
}
/**
* Send an e-mail to someone
*
* @param $subject string E-mail subject
* @param $message string E-mail message
* @param $to string E-mail recipient (from current logged-in user as default)
*/
function send_email( $subject, $message, $to = false ) {
if( ! $to ) {
if( ! is_logged() ) {
die( "can't retrieve e-mail address from anon user" );
}
$to = get_user( 'user_email' );
}
return SMTPMail::instance()
->to( $to )
->message( $subject, $message )
->disconnect();
}
/**
* Require a certain permission
*
* @param $permission string An internal permission like 'edit-all-user'
* @param $redirect boolean Enable or disable the redirect
*/
function require_permission( $permission, $redirect = true ) {
if( ! has_permission( $permission ) ) {
require_more_privileges( $redirect );
}
}
/**
* Require more privileges then actual ones
*/
function require_more_privileges( $redirect = true ) {
if( is_logged() ) {
Header::spawn( [
'title' => __( "Permission denied" ),
] );
Footer::spawn();
exit;
} else {
$login = menu_entry( 'login' );
$url = $login->getAbsoluteURL();
if( $redirect && isset( $_SERVER[ 'REQUEST_URI' ] ) ) {
$url = http_build_get_query( $url, [
'redirect' => $_SERVER[ 'REQUEST_URI' ],
] );
}
http_redirect( $url, 307 );
}
}
/**
* Get URL parts from the PATH_INFO
*
* It spawn a "bad request" page if something goes wrong.
*
* @param $max int If $min is specified, this is the maximum number of parameters. When unspecified, this is the exact number of parameters.
* @param $min int Mininum number of parameters.
* @return array
* @see https://httpd.apache.org/docs/2.4/mod/core.html#acceptpathinfo
*/
function url_parts( $max, $min = false ) {
if( $min === false ) {
$min = $max;
}
// split the PATH_INFO parts
$parts = explode( _, $_SERVER['PATH_INFO'] ?? '' );
array_shift( $parts );
// eventually spawn the "bad request"
$n = count( $parts );
if( $n > $max || $n < $min ) {
BadRequest::spawn( __( "unexpected URL" ) );
}
// eventually fill expected fields
for( $i = $n; $i < $max; $i++ ) {
$parts[] = null;
}
return $parts;
}
/**
* Link to an existing page from the menu
*
* @param $uid string E.g. 'index'
* @param $args mixed Arguments
*/
function the_menu_link( $uid, $args = [] ) {
$page = menu_entry( $uid );
the_link( $page->getURL(), $page->name, $args );
}
/**
* Link to a whatever page
*
* P.S. link() is a reserved function
*
* @param $url string
* @param $title string
* @param $args mixed Arguments
*/
function the_link( $url, $title, $args = [] ) {
+
+ $classes = "";
+ if( isset( $args[ 'disabled' ] ) && $args[ 'disabled' ] ) {
+ $classes .= "disabled";
+ }
+
template( 'link', [
- 'title' => $title,
- 'url' => $url,
- 'args' => $args,
+ 'title' => $title,
+ 'url' => $url,
+ 'args' => $args,
+ 'classes' => $classes,
] );
}
/**
* Generate a password
*
* @param $bytes int
*/
function generate_password( $bytes = 8 ) {
return rtrim( base64_encode( bin2hex( openssl_random_pseudo_bytes( $bytes ) ) ), '=' );
}
/**
* Validate a mailbox username
*
* @param $mailbox string
* @return bool
*/
function validate_mailbox_username( $mailbox ) {
return 1 === preg_match( '/^[a-z][a-z0-9-_.]+$/', $mailbox );
}
/**
* A certain value must be an e-mail
*
* @param $email string
* @return string filtered e-mail
*/
function require_email( $email ) {
$email = luser_input( $email, 128 );
if( filter_var( $email, FILTER_VALIDATE_EMAIL ) === false ) {
BadRequest::spawn( __( "fail e-mail validation" ) );
}
return $email;
}
/**
* Require a strictly safe file/directory name or throw an exception
*
* This method is designed to prevend known filesystem exploitations
* that may also occurr if a database is compromised and with malicous
* data inside domain names, etc. This also removes a wide rang of valid
* characters in Unix but this way we reduce every possible risk in other
* operating systems.
*
* Note that an empty directory is NOT a valid directory name so '///'
* is not valid even if it's a safe pathname resolution in Unix-like systems.
* This is because I don't like it. No other reasons.
*
* @param string $dirname
*/
function require_safe_dirname( $dirname ) {
if( !$dirname || $dirname === '.' || $dirname === '..' || !preg_match( '/^[a-zA-Z0-9-.]+$/', $dirname ) ) {
throw new Exception( sprintf(
"the directory name '%s' is weird for me",
$dirname
) );
}
}
/**
* Check if a pathname can be considered a valid sub-directory of something else
*
* The pathname is valid if it starts with a slash.
* The pathname will be normalized after the validation.
*
* @param string $pathname Pathname to be validated like '/my-site/www'
*/
function validate_subdirectory( & $pathname ) {
// assure that the string starts with just a slash and does not end with slashes
$pathname = trim( $pathname, '/' );
// validate each directory (if any)
$directories = [];
if( $pathname ) {
$directories = explode( '/', $pathname );
foreach( $directories as $directory ) {
try {
require_safe_dirname( $directory );
} catch( Exception $e ) {
throw new Exception( sprintf(
"apologies but I do not like the pathname '%s': %s",
$pathname,
$e->getMessage()
) );
}
}
}
// merge all the directories
$pathname = '/' . implode( '/', $directories );
}
diff --git a/template/link.php b/template/link.php
index 412ba68..d769bbe 100644
--- a/template/link.php
+++ b/template/link.php
@@ -1,33 +1,34 @@
.
/*
* This is the template for a link
*
* Called from
* include/functions.php - the_link() function
*
* Available variables:
* $title string e.g. "Home"
* $url string e.g. "/"
+ * $classes string e.g. "disabled"
* $args mixed
*/
// unuseful when load directly
defined( 'BOZ_PHP' ) or die;
-?>
+?>= esc_html( $title ) ?>