<?php


// Add function to selected hook with default priority 10
function hook_add_fn( $hook, $function, $priority = 10 ) {
    global $cms;
    $cms["hooks"][$hook][$priority][$function] = true; // true - enabled
    // fix warning
    if ( ! isset( $cms["hooks"][$hook]["next"] ) ) {
        $cms["hooks"][$hook]["next"] = "";
    }
}


function do_hook( $hook = "" ) {
    global $cms;
    
    if ( empty( $cms["hooks"][$hook] ) || ! empty( $cms["hooks"][$hook]["disabled"] ) ) {
        return;
    }
    
    ksort( $cms["hooks"][$hook] );
    
    foreach ( $cms["hooks"][$hook] as $priority => &$value ) {
        if ( is_array( $cms["hooks"][$hook][$priority] ) ) {
            foreach ( $cms["hooks"][$hook][$priority] as $function => &$enabled ) {
                if ( $enabled && function_exists( $function ) ) {
                    $function();
                }
            }
        }
    }

}


function cms_save_config() {
    global $cms;
    $r = file_put_contents( $cms["config_file"], '<?php $cms["config"] = ' . var_export( $cms["config"], true) . ";\n", LOCK_EX );
    if ( $r && function_exists( "opcache_invalidate" ) ) {
        opcache_invalidate( $cms["config_file"] );
    }
    return $r;
}


#region Функции отправки письма - это комментарий для схлопывания всех фукнций письма

function cms_email_callback2( $matches ) {
    global $email_images;
    $n = count( $email_images );
    $email_images[$n] = array( "ext" => $matches[1], "base64" => $matches[2] );
    return "cid:{$n}.{$matches[1]}";
}

function cms_email_callback1( $matches ) {
    $r2 = preg_replace_callback( "/data:image\/(\w+);base64,(.+)/u", "cms_email_callback2", $matches[1] );
    return "<img src=\"$r2\"";
}

// $data["to_name"]
// $data["to_email"]
// $data["subject"]
// $data["email_body"]
// $data["from_name"]
// $data["from_email"]
// $data["reply_name"]
// $data["reply_to"]
// $data["files"]
// $data["type"] ( text/html or text/plain (default) )
// $data["sender"] if empty, then noreply@$_SERVER["SERVER_NAME"]
// $data["bcc"]
// return "" if success of "error:..." if error
function cms_email( $data ) {
    global $email_images;

    // На пустую to_email не надо проверять, потому что возможна рассылка через скрытые копии
    if ( isset( $data["to_name"] ) ) {
        $to = "=?utf-8?b?" . base64_encode( $data["to_name"] ) . "?= <" . $data["to_email"] . ">";
    } else {
        $to = $data["to_email"];
    }

    $subject = "=?utf-8?b?" . base64_encode( $data["subject"] ) . "?=";

    if ( isset( $data["from_name"] ) ) {
        $from = "=?utf-8?b?" . base64_encode( $data["from_name"] ) . "?= <" . $data["from_email"] . ">";
    } else {
        $from = $data["from_email"];
    }

    if ( empty( $data["reply_to"] ) ) {
        $reply = $from;
    } else {
        $reply = $data["reply_to"];
        if ( ! empty( $data["reply_name"] ) ) {
            $reply = "=?utf-8?b?" . base64_encode( $data["reply_name"] ) . "?= <" . $data["reply_to"] . ">";
        }
    }

    $boundary = md5( uniqid( time() - 25 ) );
    $boundary_id = md5( uniqid( time() ) );

    if ( empty( $data["sender"] ) ) {
        $sender = "noreply@{$_SERVER['SERVER_NAME']}";
    } else {
        $sender = $data["sender"];
    }

    $headers  = "";
    $headers .= "Sender: {$sender}\r\n";
    $headers .= "From: {$from}\r\n";
    $headers .= "Reply-To: {$reply}\r\n";
    $headers .= "Content-Type: multipart/mixed; boundary=\"{$boundary}\"\r\n";

    if ( ! empty( $data["bcc"] ) ) {
        $headers .= "Bcc: {$data['bcc']}\r\n";
    }

    $email_images = array();
    $body2 = preg_replace_callback( '/<img\s[^>]*src="([^"]+)"/u', "cms_email_callback1", $data["email_body"] );

    if ( empty( $data["type"] ) ) {
        $type = "text/plain";
    } else {
        $type = $data["type"];
    }

    $body_all  = "";
    $body_all .= "--{$boundary}\r\n";
    $body_all .= "Content-Type: multipart/related; boundary=\"{$boundary_id}\"\r\n";
    $body_all .= "\r\n";
    
    $body_all .= "--{$boundary_id}\r\n";
    $body_all .= "Content-Type: {$type}; charset=utf-8;\r\n";
    $body_all .= "Content-Transfer-Encoding: base64\r\n";
    $body_all .= "\r\n";
    $body_all .= chunk_split( base64_encode( $body2 ) ) . "\r\n";
    $body_all .= "\r\n";

    foreach( $email_images as $ind => $image ) {
        $body_all .= "--{$boundary_id}\r\n";
        $body_all .= "Content-Type: image/{$image['ext']}; name=\"{$ind}.{$image['ext']}\"\r\n";
        $body_all .= "Content-ID: <{$ind}.{$image['ext']}>\r\n";
        $body_all .= "Content-Disposition: inline; filename=\"{$ind}.{$image['ext']}\"\r\n";
        $body_all .= "Content-transfer-encoding: base64\r\n";
        $body_all .= "\r\n";
        $body_all .= chunk_split( $image["base64"] ) . "\r\n";
        $body_all .= "\r\n";
    }

    if ( isset( $data["files"] ) && is_array( $data["files"] ) )
    foreach( $data["files"] as $file ) {
        $mime = mime_content_type( $file );
        $name = preg_replace( "/.*\//u", "", $file );
        $body_all .= "--{$boundary_id}\r\n";
        $body_all .= "Content-Type: {$mime}; name=\"{$name}\"\r\n";
        $body_all .= "Content-Transfer-Encoding: base64\r\n";
        $body_all .= "Content-Disposition: attachment; filename=\"{$name}\"\r\n";
        $body_all .= "\r\n";
        $body_all .= chunk_split( base64_encode( file_get_contents( $file ) ) ) . "\r\n";
        $body_all .= "\r\n";
    }

    $body_all .= "--{$boundary_id}--\r\n";
    $body_all .= "\r\n";
    $body_all .= "--{$boundary}--\r\n";
    $body_all .= "\r\n";

    if ( mail( $to, $subject, $body_all, $headers, "-f{$data['from_email']}" ) ) {
        return "";
    } else {
        return "error mail() function";
    }
}

//-$data["to_name"] (удалено чтобы перечислять получателей через запятую)
// $data["to_email"]
// $data["subject"]
// $data["email_body"]
// $data["from_name"]
// $data["from_email"]
// $data["reply_name"]
// $data["reply_to"]
// $data["files"]
// $data["type"] ( text/plain (default) or text/html )
// $data["sender"] if empty, then noreply@$_SERVER["SERVER_NAME"]
// $data["bcc"]
// $data["smtp_host"]
// $data["smtp_port"]
// $data["smtp_login"]
// $data["smtp_password"]
// return "" if success of "error:..." if error
function cms_smtp_email( $data ) {
    global $email_images, $cms;
    /*
    if ( isset( $data["to_name"] ) ) {
        $to = "=?utf-8?b?" . base64_encode( $data["to_name"] ) . "?= <" . $data["to_email"] . ">";
    } else {
        $to = $data["to_email"];
    }
    */
    if ( isset( $data["from_name"] ) ) {
        $from = "=?utf-8?b?" . base64_encode( $data["from_name"] ) . "?= <" . $data["from_email"] . ">";
    } else {
        $from = $data["from_email"];
    }

    if ( empty( $data["reply_to"] ) ) {
        $reply = $from;
    } else {
        $reply = $data["reply_to"];
        if ( ! empty( $data["reply_name"] ) ) {
            $reply = "=?utf-8?b?" . base64_encode( $data["reply_name"] ) . "?= <" . $data["reply_to"] . ">";
        }
    }

    $boundary = md5( uniqid( time() - 25 ) );
    $boundary_id = md5( uniqid( time() ) );

    if ( empty( $data["sender"] ) ) {
        $sender = $data["from_email"];
    } else {
        $sender = $data["sender"];
    }
    
    if ( empty( $data["return_path"] ) ) {
        $return_path = $data["from_email"];
    } else {
        $return_path = $data["return_path"];
    }


    /* start headers */
    $SEND  = "Date: " . date( "r" ) . "\r\n";
    $SEND .= "Sender: {$sender}\r\n";
    $SEND .= "Return-Path: {$return_path}\r\n";
    $SEND .= "Reply-To: {$reply}\r\n";
    $SEND .= "From: {$from}\r\n";
    $SEND .= "To: {$data['to_email']}\r\n";
    if ( ! empty( $data["bcc"] ) ) { $SEND .= "Bcc: {$data['bcc']}\r\n"; }
	$SEND .= "Subject: =?utf-8?b?" . base64_encode( $data["subject"] ) . "?=\r\n";
    $SEND .= "Content-Type: multipart/mixed; boundary=\"{$boundary}\"\r\n";
    $SEND .= "\r\n";
    /* end headers */

    /* Move images to appendix */
    $email_images = array();
    $body2 = preg_replace_callback( '/<img +src="([^"]+)"/u', "cms_email_callback1", $data["email_body"] );

    if ( empty( $data["type"] ) ) {
        $type = "text/plain";
    } else {
        $type = $data["type"];
    }

    $SEND .= "--{$boundary}\r\nContent-Type: multipart/related; boundary=\"{$boundary_id}\"\r\n\r\n";
    $SEND .= "--{$boundary_id}\r\nContent-Type: {$type}; charset=utf-8;\r\nContent-Transfer-Encoding: base64\r\n\r\n" . chunk_split( base64_encode( $body2 ) ) . "\r\n\r\n";

    foreach( $email_images as $ind => $image ) {
        $SEND .= "--{$boundary_id}\r\n";
        $SEND .= "Content-Type: image/{$image['ext']}; name=\"{$ind}.{$image['ext']}\"\r\n";
        $SEND .= "Content-ID: <{$ind}.{$image['ext']}>\r\n";
        $SEND .= "Content-Disposition: inline; filename=\"{$ind}.{$image['ext']}\"\r\n";
        $SEND .= "Content-transfer-encoding: base64\r\n\r\n";
        $SEND .= chunk_split( $image['base64'] );
        $SEND .= "\r\n\r\n";
    }

    if ( isset( $data["files"] ) && is_array( $data["files"] ) ) {
        foreach( $data["files"] as $file ) {
            $mime = mime_content_type( $file );
            $name = preg_replace( "/.*\//u", "", $file );
            $SEND .= "--{$boundary_id}\r\n";
            $SEND .= "Content-Type: {$mime}; name=\"{$name}\"\r\n";
            $SEND .= "Content-Transfer-Encoding: base64\r\n";
            $SEND .= "Content-Disposition: attachment; filename=\"{$name}\"\r\n\r\n";
            $SEND .= chunk_split( base64_encode( file_get_contents( $file ) ) ) . "\r\n\r\n";
        }
    }

    $SEND .= "--{$boundary_id}--\r\n\r\n";
    $SEND .= "--{$boundary}--\r\n\r\n";

    $debug_file = "{$cms['cms_dir']}/smtp_debug.txt";
    cms_debug( $debug_file, "\n---" );

    // Connect
    cms_debug( $debug_file, "fsockopen {$data['smtp_host']} {$data['smtp_port']}" );
    $socket = fsockopen( $data["smtp_host"], $data["smtp_port"], $errno, $errstr, 10 ); // 10 sec timeout
    if( $socket === false ) {
        cms_debug( $debug_file, "fsockopen error {$errno} {$errstr}" );
        return "{$errno} {$errstr}";
    }
    cms_debug( $debug_file, "fsockopen ok" );

    stream_set_timeout( $socket, 3 );
 
    // Receive data after connection
    $ok = false;
    while ( $r = fgets( $socket, 1000 ) ) {
        cms_debug( $debug_file, "SERVER: {$r}" );
        if ( substr( $r, 0, 3 ) === "220" ) { $ok = true; }
        if ( substr( $r, 3, 1 ) === " " ) { break; }
    }
	if ( $ok === false ) {
        return $r;
    }

    // HELLO
    cms_debug( $debug_file, "ME: EHLO {$_SERVER['SERVER_NAME']}" );
    fputs( $socket, "EHLO {$_SERVER['SERVER_NAME']}\r\n");

    // Receive data after HELLO
    $ok = false;
    while ( $r = fgets( $socket, 1000 ) ) {
        cms_debug( $debug_file, "SERVER: {$r}" );
        if ( preg_match( '/250.AUTH/', $r ) ) { $ok = true; }
        if ( substr( $r, 3, 1 ) === " " ) { break; }
    }
    if ( $ok === false ) {
        fclose( $socket );
        cms_debug( $debug_file, "The server does not greet us." );
		return $r."\nThe server does not greet us.";
    }
    
    // AUTH
    cms_debug( $debug_file, "ME: AUTH LOGIN" );
	fputs( $socket, "AUTH LOGIN\r\n" );

    // Receive data
    $ok = false;
    while ( $r = fgets( $socket, 1000 ) ) {
        cms_debug( $debug_file, "SERVER: {$r}" );
        if ( substr( $r, 0, 3 ) === "334" ) { $ok = true; }
        if ( substr( $r, 3, 1 ) === " " ) { break; }
    }
	if ( $ok === false ) {
		fclose( $socket );
        cms_debug( $debug_file, "Can't find the answer to the authorization request." );
		return "Can't find the answer to the authorization request.";
    }
    
    // Send login
    cms_debug( $debug_file, "ME: base64_encode( smtp_login )" );
	fputs( $socket, base64_encode( $data["smtp_login"] ) . "\r\n" );

    // Receive data
    $ok = false;
    while ( $r = fgets( $socket, 1000 ) ) {
        cms_debug( $debug_file, "SERVER: {$r}" );
        if ( substr( $r, 0, 3 ) === "334" ) { $ok = true; }
        if ( substr( $r, 3, 1 ) === " " ) { break; }
    }
	if ( $ok === false ) {
		fclose( $socket );
        cms_debug( $debug_file, "The authorization login was not accepted by the server." );
		return "The authorization login was not accepted by the server.";
    }

    // Send password
    cms_debug( $debug_file, "ME: base64_encode( smtp_password )" );
	fputs( $socket, base64_encode( $data["smtp_password"] ) . "\r\n" );

    // Receive data
    $ok = false;
    while ( $r = fgets( $socket, 1000 ) ) {
        cms_debug( $debug_file, "SERVER: {$r}" );
        if ( substr( $r, 0, 3 ) === "235" ) { $ok = true; }
        if ( substr( $r, 3, 1 ) === " " ) { break; }
    }
	if ( $ok === false ) {
		fclose( $socket );
        cms_debug( $debug_file, "The password was not accepted by the server as correct." );
		return "The password was not accepted by the server as correct.";
    }

    // Send FROM
    cms_debug( $debug_file, "ME: MAIL FROM: <{$data['from_email']}>" );
	fputs( $socket, "MAIL FROM: <{$data['from_email']}>\r\n" );

    // Receive data
    $ok = false;
    while ( $r = fgets( $socket, 1000 ) ) {
        cms_debug( $debug_file, "SERVER: {$r}" );
        if ( substr( $r, 0, 3 ) === "250" ) { $ok = true; }
        if ( substr( $r, 3, 1 ) === " " ) { break; }
    }
	if ( $ok === false ) {
		fclose( $socket );
        cms_debug( $debug_file, "Can't send command MAIL FROM" );
		return "Can't send command MAIL FROM";
    }

    // Send recipient
    // Через запятую можно указать несколько получателей
    foreach ( explode( ",", $data["to_email"] ) as $rcpt ) {
        cms_debug( $debug_file, "ME: RCPT TO: {$rcpt}" );
        fputs( $socket, "RCPT TO: {$rcpt}\r\n" );

        // Receive data
        $ok = false;
        while ( $r = fgets( $socket, 1000 ) ) {
            cms_debug( $debug_file, "SERVER: {$r}" );
            if ( substr( $r, 0, 3 ) === "250" ) { $ok = true; }
            if ( substr( $r, 3, 1 ) === " " ) { break; }
        }
        if ( $ok === false ) {
            fclose( $socket );
            cms_debug( $debug_file, "Can't send RCPT TO command" );
            return "Can't send RCPT TO command";
        }
    }

    // BCC
    // Через запятую можно указать несколько получателей
    if ( ! empty( $data["bcc"] ) ) {
        foreach ( explode( ",", $data["bcc"] ) as $rcpt ) {
            cms_debug( $debug_file, "ME (bcc): RCPT TO: {$rcpt}" );
            fputs( $socket, "RCPT TO: {$rcpt}\r\n" );

            // Receive data
            $ok = false;
            while ( $r = fgets( $socket, 1000 ) ) {
                cms_debug( $debug_file, "SERVER: {$r}" );
                if ( substr( $r, 0, 3 ) === "250" ) { $ok = true; }
                if ( substr( $r, 3, 1 ) === " " ) { break; }
            }
            if ( $ok === false ) {
                fclose( $socket );
                cms_debug( $debug_file, "Can't send RCPT TO (bcc) command" );
                return "Can't send RCPT TO (bcc) command";
            }
        }
    }
    
    // Email body command
    cms_debug( $debug_file, "ME: DATA" );
	fputs( $socket, "DATA\r\n" );

    // Receive data
    $ok = false;
    while ( $r = fgets( $socket, 1000 ) ) {
        cms_debug( $debug_file, "SERVER: {$r}" );
        if ( substr( $r, 0, 3 ) === "354" ) { $ok = true; }
        if ( substr( $r, 3, 1 ) === " " ) { break; }
    }
    if ( $ok === false ) {
        fclose( $socket );
        cms_debug( $debug_file, "Can't send DATA command" );
        return "Can't send DATA command";
    }

    // Send email body
    cms_debug( $debug_file, "ME SEND DATA" );
	fputs( $socket, "{$SEND}\r\n.\r\n" );

    // Receive data
    $ok = false;
    while ( $r = fgets( $socket, 1000 ) ) {
        cms_debug( $debug_file, "SERVER: {$r}" );
        if ( substr( $r, 0, 3 ) === "250" ) { $ok = true; }
        if ( substr( $r, 3, 1 ) === " " ) { break; }
    }
    if ( $ok === false ) {
        fclose( $socket );
        cms_debug( $debug_file, "I can not send the body of the letter." );
        return "I can not send the body of the letter.";
    }

    // Quit command
    cms_debug( $debug_file, "ME: QUIT\n" );
	fputs( $socket, "QUIT\r\n" );
	fclose( $socket );
	return "";
}

#endregion Функции отправки письма


function cms_debug( $debug_file, $string ) {
    global $cms;
    if ( empty( $cms["config"]["debug"] ) ) {
        return;
    }
    // Следим за размером файла
    if ( is_file( $debug_file ) && filesize( $debug_file ) > 16384 ) {
        rename( $debug_file, $debug_file . ".old" );
    }
    // Сбрасываем инфу
    if ( substr( $string, -1 ) !== "\n" ) { $string .= "\n"; }
    file_put_contents( $debug_file, $string, FILE_APPEND );
}


// Функция для отправки файла браузеру малыми порциями,
// чтобы не было ошибок с закончившейся памятью
function cms_readfile( $file, $headers = true ) {
    if ( file_exists( $file ) ) {
        /*
        if (ob_get_level()) {
            ob_end_clean();
        }
        */
        if ( $headers ) {
            header( "Content-Description: File Transfer" );
            $mime = mime_content_type( $file );
            header( "Content-Type: {$mime}" );
            $basename = basename( $file );
            header( "Content-Disposition: attachment; filename=\"{$basename}\"" );
            header( "Content-Transfer-Encoding: binary" );
            header( "Expires: 0" );
            header( "Cache-Control: must-revalidate, post-check=0, pre-check=0" );
            header( "Pragma: public" );
            $filesize = filesize( $file );
            header( "Content-Length: {$filesize}" );
            ob_clean();
            flush();
        }
        if ( $handle = fopen( $file, "rb" ) ) {
            while ( ! feof( $handle ) ) {
              print fread( $handle, 1024 );
            }
            return fclose( $handle );
        } else {
            return false;
        }
    } else {
        return false;
    }
}


// Принимает строку, которую нужно перевести
// и модуль ("page.mod.php") если нужно дернуть перевод из другого
function __( $string, $module = "" ) {
    global $cms;

    // Определяем вызвавший файл
    $backtrace = debug_backtrace();
    $basename = pathinfo( $backtrace[0]["file"], PATHINFO_BASENAME );
    $basedir = basename( pathinfo( $backtrace[0]["file"], PATHINFO_DIRNAME ) );
    if ( $module === "" ) {
        $module = $basename;
        // Автовыбор модуля для шаблона админки
        if ( $basedir === "admin.cms" && $basename === "html.php" ) {
            $module = "admin.mod.php";
        }
    }

    // Загрузка файла перевода если еще не загружен
    if ( ! isset( $cms["lang"][$module][ $cms["config"]["locale"] ] ) ) {
        $file = $cms["cms_dir"] . "/lang/" . $cms["config"]["locale"] . "/" . $module;
        if ( is_file( $file ) ) {
            include_once( $file );
        } else {
            $cms["lang"][$module][ $cms["config"]["locale"] ] = array();
        }
        // load translit
        if ( ! isset( $cms["tr"] ) ) $cms["tr"] = array();
        $translit = $cms["cms_dir"] . "/lang/" . $cms["config"]["locale"] . "/translit.php";
        if ( is_file( $translit ) ) {
            include_once( $translit );
        }
    }

    // Translate
    if ( isset( $cms["lang"][$module][ $cms["config"]["locale"] ][$string] ) ) {
        return $cms["lang"][$module][ $cms["config"]["locale"] ][$string];
    } else {
        // Чтобы узнать какие переводы отсутствуют, нужно включить отладку в config.php
        //     $cms["config"]["debug"] = true;
        // Результаты буду в файле .cms/debug.log.php
        if ( ! empty( $cms["config"]["debug"] ) && empty( $cms["debug"]["translate"][$string] ) ) {
            $line = $backtrace[0]["line"];
            $t = "translate to {$cms["config"]["locale"]}";
            $f = "{$basename}:{$line}";
            $cms["debug"][$t][$f] = $string;
        }
        return $string;
    }
}


function cms_translit( $string, $trim_dash = true ) {
    global $cms;
    $tr1 = strtr( $string, $cms["tr"] );
    $tr2 = strtr( $tr1, array( " " => "-" ) );
    $tr3 = preg_replace( "/[^-A-Za-z0-9_]+/u", "", $tr2 );
    if ( $trim_dash ) {
        $tr3 = trim( $tr3, "-_" );
    }
    return $tr3;
}


function cms_translit_file( $string ) {
    global $cms;
    $tr1 = strtr( $string, $cms["tr"] );
    $tr2 = strtr( $tr1, array( " " => "_" ) );
    $tr3 = preg_replace( "/[^-A-Za-z0-9_]+/u", "", $tr2 );
    return $tr3;
}


// Вспомогательная функция для последующей cms_asort()
function cms_uasort( $a, $b ) {
    if ( ! isset( $a["sort"] ) || ! isset( $b["sort"] ) ) {
        return 0;
    }
    if ( $a["sort"] <= $b["sort"] ) {
        return -1;
    } else {
        return 1;
    }
}
// Сортирует массив из элементов, которые тоже являются массивами
// и содержат ключ sort
function cms_asort( &$array ) {
    if ( ! is_array( $array ) ) return false;
    return uasort( $array, "cms_uasort" );
}


// Рекурсивное удаление папок
function recurse_rm( $src ) /* bool */ {
    if ( ! is_dir( $src ) ) {
        return false;
    }
    $dir = opendir( $src );
    // readdir может вернуть аналог false, поэтому строгая проверка
    while( false !== ( $file = readdir( $dir ) ) ) {
        if ( ( $file != "." ) && ( $file != ".." ) ) {
            if ( is_dir( "{$src}/{$file}" ) ) {
                recurse_rm( "{$src}/{$file}" );
            } else {
                if ( ! unlink( "{$src}/{$file}" ) ) {
                    return false;
                }
            }
        }
    }
    closedir( $dir );
    return rmdir( $src );
}


function is_email( $str ) {
    return preg_match( "/^([a-zA-Z0-9_\-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,9})(\]?)$/", $str );
}


// Returns a file size limit in bytes based on the PHP upload_max_filesize
// and post_max_size
function file_upload_max_size() {
    $max_size = -1;
  
    if ( $max_size < 0 ) {
        // Start with post_max_size.
        $post_max_size = parse_size( ini_get( "post_max_size" ) );
        if ( $post_max_size > 0 ) {
            $max_size = $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 );
    }
}


// Возвращает true только если это пустая папка
function is_dir_and_empty( $dir ) {
    if ( ! is_dir( $dir ) ) {
        return false;
    }
    $handle = opendir( $dir );
    while ( false !== ( $entry = readdir( $handle ) ) ) {
        if ( $entry != "." && $entry != ".." ) {
            closedir( $handle );
            return false;
        }
    }
    closedir( $handle );
    return true;
}


// Генерация uid для всяких нужд
function cms_admin_pass_gen( $count = 8 ) {
    $chars = "0123456789AaBbCcDdEeFfGgHhiJjKkLMmNnOoPpQqRrSsTtUuVvWwXxYyZz";
    $strlen = strlen( $chars ) - 1;
    $password = "";
    while ( $count-- ) {
        $password .= $chars[ rand( 0, $strlen ) ];
    }
    return $password;
}


// Генерация uid для всяких нужд
function cms_uid( $count = 8 ) {
    $chars = "0123456789AaBbCcDdEeFfGgHhiJjKkLMmNnOoPpQqRrSsTtUuVvWwXxYyZz";
    $strlen = strlen( $chars ) - 1;
    $password = "";
    while ( $count-- ) {
        $password .= $chars[ rand( 0, $strlen ) ];
    }
    return $password;
}
