From 06ccd650e464a37d54124a34e6f8ba04eb807cae Mon Sep 17 00:00:00 2001 From: Alexander Ebert Date: Fri, 15 Jul 2011 19:43:23 +0200 Subject: [PATCH] Moved language server administration into commercial package com.woltlab.wcf.acp.language --- com.woltlab.wcf/acpmenu.xml | 569 ++++----- com.woltlab.wcf/groupoptions.xml | 400 +++--- .../files/acp/templates/languageServerAdd.tpl | 63 - .../acp/templates/languageServerList.tpl | 74 -- .../acp/form/LanguageServerAddForm.class.php | 107 -- .../acp/form/LanguageServerEditForm.class.php | 90 -- .../acp/page/LanguageServerListPage.class.php | 61 - .../files/lib/util/StringUtil.class.php | 1126 ++++++++--------- 8 files changed, 1035 insertions(+), 1455 deletions(-) delete mode 100644 wcfsetup/install/files/acp/templates/languageServerAdd.tpl delete mode 100644 wcfsetup/install/files/acp/templates/languageServerList.tpl delete mode 100644 wcfsetup/install/files/lib/acp/form/LanguageServerAddForm.class.php delete mode 100644 wcfsetup/install/files/lib/acp/form/LanguageServerEditForm.class.php delete mode 100644 wcfsetup/install/files/lib/acp/page/LanguageServerListPage.class.php diff --git a/com.woltlab.wcf/acpmenu.xml b/com.woltlab.wcf/acpmenu.xml index 20ee7e9090..febcd646ac 100644 --- a/com.woltlab.wcf/acpmenu.xml +++ b/com.woltlab.wcf/acpmenu.xml @@ -1,297 +1,272 @@ - - - - - icon/systemL.png - 1 - - - - - wcf.acp.menu.link.system - 1 - admin.system.canEditOption - - - - wcf.acp.menu.link.option - 1 - - - - wcf.acp.menu.link.option - 2 - - - - wcf.acp.menu.link.option.management - 1 - index.php?form=OptionImport - - - - - - wcf.acp.menu.link.system - 2 - admin.system.package.canInstallPackage,admin.system.package.canUpdatePackage,admin.system.package.canUninstallPackage,admin.system.package.canEditServer - - - - wcf.acp.menu.link.package - 1 - - - - icon/packageM.png - index.php?page=PackageList - wcf.acp.menu.link.package.management - admin.system.package.canUpdatePackage,admin.system.package.canUninstallPackage - 1 - - - - index.php?form=PackageStartInstall&action=install - wcf.acp.menu.link.package.management - admin.system.package.canInstallPackage - 2 - - - - wcf.acp.menu.link.package - 2 - - - - icon/updateM.png - index.php?page=PackageAutoUpdateList - wcf.acp.menu.link.package.update - admin.system.package.canUpdatePackage - 1 - - - - index.php?form=PackageUpdateSearch - wcf.acp.menu.link.package.update - admin.system.package.canInstallPackage,admin.system.package.canUpdatePackage - 2 - - - - wcf.acp.menu.link.package - 3 - - - - icon/updateServerM.png - index.php?page=UpdateServerList - wcf.acp.menu.link.package.server - admin.system.package.canEditServer - 1 - - - - index.php?form=UpdateServerAdd - wcf.acp.menu.link.package.server - admin.system.package.canEditServer - 2 - - - - - - wcf.acp.menu.link.system - 3 - - - - - - wcf.acp.menu.link.system - 4 - - - - wcf.acp.menu.link.log - - - - wcf.acp.menu.link.log - - - - icon/sessionLogM.png - index.php?page=ACPSessionLogList - wcf.acp.menu.link.log.system - admin.system.canViewLog - - - - index.php?page=CacheList - wcf.acp.menu.link.log.system - admin.system.canViewLog - - - - - - wcf.acp.menu.link.maintenance - - - - icon/cronjobsM.png - index.php?page=CronjobList - wcf.acp.menu.link.cronjobs - admin.system.cronjobs.canEditCronjob,admin.system.cronjobs.canDeleteCronjob,admin.system.cronjobs.canEnableDisableCronjob - 1 - - - - index.php?form=CronjobAdd - wcf.acp.menu.link.cronjobs - admin.system.cronjobs.canAddCronjob - 2 - - - - index.php?page=CronjobLogList - wcf.acp.menu.link.log.system - admin.system.cronjobs.canEditCronjob,admin.system.cronjobs.canDeleteCronjob - - - - - icon/usersL.png - 2 - - - - - wcf.acp.menu.link.user - 1 - - - - wcf.acp.menu.link.user.management - 1 - - - - icon/usersM.png - index.php?page=UserList - wcf.acp.menu.link.user.management.general - admin.user.canSearchUser - 1 - - - - icon/searchM.png - index.php?form=UserSearch - wcf.acp.menu.link.user.management.general - admin.user.canSearchUser - 2 - - - - index.php?form=UserAdd - wcf.acp.menu.link.user.management.general - admin.user.canAddUser - 3 - - - - wcf.acp.menu.link.user.management - 2 - - - - index.php?form=UsersMassProcessing - wcf.acp.menu.link.user.management.additional - admin.user.canEditUser,admin.user.canDeleteUser,admin.user.canMailUser - 1 - - - - index.php?form=UserMail&action=all - wcf.acp.menu.link.user.management.additional - admin.user.canMailUser - 2 - - - - - - wcf.acp.menu.link.user - 2 - - - - wcf.acp.menu.link.group - 1 - - - - icon/userGroupM.png - index.php?page=UserGroupList - wcf.acp.menu.link.group.general - admin.user.canEditGroup,admin.user.canDeleteGroup - 1 - - - - index.php?form=UserGroupAdd - wcf.acp.menu.link.group.general - admin.user.canAddGroup - 2 - - - - wcf.acp.menu.link.group - 2 - - - - icon/emailM.png - index.php?form=UserMail&action=group - wcf.acp.menu.link.group.additional - admin.user.canMailUser - 1 - - - - - icon/displayL.png - 3 - - - - - wcf.acp.menu.link.display - - - - wcf.acp.menu.link.language - - - - icon/languageServerM.png - index.php?page=LanguageServerList - wcf.acp.menu.link.language.server - admin.language.canEditServer - 1 - - - - index.php?form=LanguageServerAdd - wcf.acp.menu.link.language.server - admin.language.canEditServer - 2 - - - - - icon/contentL.png - 4 - - - + + + + + icon/systemL.png + 1 + + + + + wcf.acp.menu.link.system + 1 + admin.system.canEditOption + + + + wcf.acp.menu.link.option + 1 + + + + wcf.acp.menu.link.option + 2 + + + + wcf.acp.menu.link.option.management + 1 + index.php?form=OptionImport + + + + + + wcf.acp.menu.link.system + 2 + admin.system.package.canInstallPackage,admin.system.package.canUpdatePackage,admin.system.package.canUninstallPackage,admin.system.package.canEditServer + + + + wcf.acp.menu.link.package + 1 + + + + icon/packageM.png + index.php?page=PackageList + wcf.acp.menu.link.package.management + admin.system.package.canUpdatePackage,admin.system.package.canUninstallPackage + 1 + + + + index.php?form=PackageStartInstall&action=install + wcf.acp.menu.link.package.management + admin.system.package.canInstallPackage + 2 + + + + wcf.acp.menu.link.package + 2 + + + + icon/updateM.png + index.php?page=PackageAutoUpdateList + wcf.acp.menu.link.package.update + admin.system.package.canUpdatePackage + 1 + + + + index.php?form=PackageUpdateSearch + wcf.acp.menu.link.package.update + admin.system.package.canInstallPackage,admin.system.package.canUpdatePackage + 2 + + + + wcf.acp.menu.link.package + 3 + + + + icon/updateServerM.png + index.php?page=UpdateServerList + wcf.acp.menu.link.package.server + admin.system.package.canEditServer + 1 + + + + index.php?form=UpdateServerAdd + wcf.acp.menu.link.package.server + admin.system.package.canEditServer + 2 + + + + + + wcf.acp.menu.link.system + 3 + + + + + + wcf.acp.menu.link.system + 4 + + + + wcf.acp.menu.link.log + + + + wcf.acp.menu.link.log + + + + icon/sessionLogM.png + index.php?page=ACPSessionLogList + wcf.acp.menu.link.log.system + admin.system.canViewLog + + + + index.php?page=CacheList + wcf.acp.menu.link.log.system + admin.system.canViewLog + + + + + + wcf.acp.menu.link.maintenance + + + + icon/cronjobsM.png + index.php?page=CronjobList + wcf.acp.menu.link.cronjobs + admin.system.cronjobs.canEditCronjob,admin.system.cronjobs.canDeleteCronjob,admin.system.cronjobs.canEnableDisableCronjob + 1 + + + + index.php?form=CronjobAdd + wcf.acp.menu.link.cronjobs + admin.system.cronjobs.canAddCronjob + 2 + + + + index.php?page=CronjobLogList + wcf.acp.menu.link.log.system + admin.system.cronjobs.canEditCronjob,admin.system.cronjobs.canDeleteCronjob + + + + + icon/usersL.png + 2 + + + + + wcf.acp.menu.link.user + 1 + + + + wcf.acp.menu.link.user.management + 1 + + + + icon/usersM.png + index.php?page=UserList + wcf.acp.menu.link.user.management.general + admin.user.canSearchUser + 1 + + + + icon/searchM.png + index.php?form=UserSearch + wcf.acp.menu.link.user.management.general + admin.user.canSearchUser + 2 + + + + index.php?form=UserAdd + wcf.acp.menu.link.user.management.general + admin.user.canAddUser + 3 + + + + wcf.acp.menu.link.user.management + 2 + + + + index.php?form=UsersMassProcessing + wcf.acp.menu.link.user.management.additional + admin.user.canEditUser,admin.user.canDeleteUser,admin.user.canMailUser + 1 + + + + index.php?form=UserMail&action=all + wcf.acp.menu.link.user.management.additional + admin.user.canMailUser + 2 + + + + + + wcf.acp.menu.link.user + 2 + + + + wcf.acp.menu.link.group + 1 + + + + icon/userGroupM.png + index.php?page=UserGroupList + wcf.acp.menu.link.group.general + admin.user.canEditGroup,admin.user.canDeleteGroup + 1 + + + + index.php?form=UserGroupAdd + wcf.acp.menu.link.group.general + admin.user.canAddGroup + 2 + + + + wcf.acp.menu.link.group + 2 + + + + icon/emailM.png + index.php?form=UserMail&action=group + wcf.acp.menu.link.group.additional + admin.user.canMailUser + 1 + + + + + icon/displayL.png + 3 + + + + icon/contentL.png + 4 + + + diff --git a/com.woltlab.wcf/groupoptions.xml b/com.woltlab.wcf/groupoptions.xml index 2ae959a904..6fbf3625d7 100644 --- a/com.woltlab.wcf/groupoptions.xml +++ b/com.woltlab.wcf/groupoptions.xml @@ -1,200 +1,200 @@ - - - - - - - - - admin - - - admin - - - admin.system - - - admin.system - - - admin.system - - - admin - - - admin.user - - - admin.user - - - - admin - - - admin - - - admin.display - - - admin.display - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + admin + + + admin + + + admin.system + + + admin.system + + + admin.system + + + admin + + + admin.user + + + admin.user + + + + admin + + + admin + + + admin.display + + + admin.display + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/wcfsetup/install/files/acp/templates/languageServerAdd.tpl b/wcfsetup/install/files/acp/templates/languageServerAdd.tpl deleted file mode 100644 index 1dc70ac07a..0000000000 --- a/wcfsetup/install/files/acp/templates/languageServerAdd.tpl +++ /dev/null @@ -1,63 +0,0 @@ -{include file='header'} - -
- -
-

{lang}wcf.acp.languageServer.{$action}{/lang}

-
-
- -{if $errorField} -

{lang}wcf.global.form.error{/lang}

-{/if} - -{if $success|isset} -

{lang}wcf.acp.languageServer.{$action}.success{/lang}

-{/if} - -
- -
-
-
-
- -
- {lang}wcf.acp.languageServer.data{/lang} - -
-
- -
-
- - {if $errorField == 'server'} -

- {if $errorType == 'empty'}{lang}wcf.global.error.empty{/lang}{/if} - {if $errorType == 'notValid'}{lang}wcf.acp.languageServer.server.error.notValid{/lang}{/if} -

- {/if} -
- -
- - - {if $additionalFields|isset}{@$additionalFields}{/if} -
-
-
- -
- - - {@SID_INPUT_TAG} -
-
- -{include file='footer'} diff --git a/wcfsetup/install/files/acp/templates/languageServerList.tpl b/wcfsetup/install/files/acp/templates/languageServerList.tpl deleted file mode 100644 index e2ddfa003b..0000000000 --- a/wcfsetup/install/files/acp/templates/languageServerList.tpl +++ /dev/null @@ -1,74 +0,0 @@ -{include file='header'} - - - -
- -
-

{lang}wcf.acp.languageServer.view{/lang}

-
-
- -
- -
- -{if !$languageServers|count} -
-
-

{lang}wcf.acp.languageServer.view.noneAvailable{/lang}

-
-
-{else} -
-

{lang}wcf.acp.languageServer.list.available{/lang}

-
-
- - - - - - - {if $additionalHeadColumns|isset}{@$additionalHeadColumns}{/if} - - - - {foreach from=$languageServers item=languageServer} - - - - - {if $additionalColumns[$languageServer->languageServerID]|isset}{@$additionalColumns[$languageServer->languageServerID]}{/if} - - {/foreach} - -
- - - - - {if $additionalButtons[$languageServer->languageServerID]|isset}{@$additionalButtons[$languageServer->languageServerID]}{/if} - {@$languageServer->languageServerID} - - {@$languageServer->serverURL} - -
-
-
- -
-{/if} - -{include file='footer'} diff --git a/wcfsetup/install/files/lib/acp/form/LanguageServerAddForm.class.php b/wcfsetup/install/files/lib/acp/form/LanguageServerAddForm.class.php deleted file mode 100644 index 929cb4a293..0000000000 --- a/wcfsetup/install/files/lib/acp/form/LanguageServerAddForm.class.php +++ /dev/null @@ -1,107 +0,0 @@ - - * @package com.woltlab.wcf - * @subpackage acp.form - * @category Community Framework - */ -class LanguageServerAddForm extends ACPForm { - /** - * @see wcf\page\AbstractPage::$templateName - */ - public $templateName = 'languageServerAdd'; - - /** - * @see wcf\acp\form\ACPForm::$activeMenuItem - */ - public $activeMenuItem = 'wcf.acp.menu.link.language.server.add'; - - /** - * @see wcf\page\AbstractPage::$neededPermissions - */ - public $neededPermissions = array('admin.language.canEditServer'); - - /** - * server url - * @var string - */ - public $server = ''; - - /** - * @see wcf\form\Form::readFormParameters() - */ - public function readFormParameters() { - parent::readFormParameters(); - - if (isset($_POST['server'])) $this->server = StringUtil::trim($_POST['server']); - } - - /** - * @see wcf\form\Form::validate() - */ - public function validate() { - parent::validate(); - - if (empty($this->server)) { - throw new UserInputException('server'); - } - - if (!PackageUpdateServer::isValidServerURL($this->server)) { - throw new UserInputException('server', 'notValid'); - } - } - - /** - * @see Form::save() - */ - public function save() { - parent::save(); - - // save server - $languageServerAction = new LanguageServerAction(array(), 'create', array('data' => array( - 'serverURL' => $this->server - ))); - $languageServerAction->executeAction(); - $this->saved(); - - // reset values - $this->server = ''; - - // show success message - WCF::getTPL()->assign('success', true); - } - - /** - * @see Page::assignVariables() - */ - public function assignVariables() { - parent::assignVariables(); - - WCF::getTPL()->assign(array( - 'server' => $this->server, - 'action' => 'add' - )); - } - - /** - * @see Page::assignVariables() - */ - public function show() { - // check master password - WCFACP::checkMasterPassword(); - - parent::show(); - } -} diff --git a/wcfsetup/install/files/lib/acp/form/LanguageServerEditForm.class.php b/wcfsetup/install/files/lib/acp/form/LanguageServerEditForm.class.php deleted file mode 100644 index 4434d2c15f..0000000000 --- a/wcfsetup/install/files/lib/acp/form/LanguageServerEditForm.class.php +++ /dev/null @@ -1,90 +0,0 @@ - - * @package com.woltlab.wcf - * @subpackage acp.form - * @category Community Framework - */ -class LanguageServerEditForm extends LanguageServerAddForm { - /** - * @see wcf\acp\form\ACPForm::$activeMenuItem - */ - public $activeMenuItem = 'wcf.acp.menu.link.language.server'; - - /** - * language server id - * @var integer - */ - public $languageServerID = 0; - - /** - * active language server - * @var wcf\data\language\server\LanguageServer - */ - public $languageServer = null; - - /** - * @see wcf\page\Page::readParameters() - */ - public function readParameters() { - parent::readParameters(); - - if (isset($_REQUEST['languageServerID'])) $this->languageServerID = intval($_REQUEST['languageServerID']); - $this->languageServer = new LanguageServer($this->languageServerID); - if (!$this->languageServer->languageServerID) { - throw new IllegalLinkException(); - } - } - - /** - * @see wcf\form\Form::save() - */ - public function save() { - AbstractForm::save(); - - // save server - $languageServerAction = new LanguageServerAction(array($this->languageServerID), 'update', array('data' => array( - 'serverURL' => $this->server - ))); - $languageServerAction->executeAction(); - $this->saved(); - - // show success message - WCF::getTPL()->assign('success', true); - } - - /** - * @see Page::readData() - */ - public function readData() { - parent::readData(); - - if (!count($_POST)) { - $this->server = $this->languageServer->serverURL; - } - } - - /** - * @see Page::assignVariables() - */ - public function assignVariables() { - parent::assignVariables(); - - WCF::getTPL()->assign(array( - 'languageServerID' => $this->languageServerID, - 'languageServer' => $this->languageServer, - 'action' => 'edit' - )); - } -} diff --git a/wcfsetup/install/files/lib/acp/page/LanguageServerListPage.class.php b/wcfsetup/install/files/lib/acp/page/LanguageServerListPage.class.php deleted file mode 100644 index 9642cc8278..0000000000 --- a/wcfsetup/install/files/lib/acp/page/LanguageServerListPage.class.php +++ /dev/null @@ -1,61 +0,0 @@ - - * @package com.woltlab.wcf - * @subpackage acp.page - * @category Community Framework - */ -class LanguageServerListPage extends SortablePage { - // system - public $templateName = 'languageServerList'; - public $neededPermissions = array('admin.language.canEditServer'); - public $defaultSortField = 'serverURL'; - - /** - * @see wcf\page\MultipleLinkPage::$objectListClassName - */ - public $objectListClassName = 'wcf\data\language\server\LanguageServerList'; - - /** - * @see wcf\page\Page::assignVariables() - */ - public function assignVariables() { - parent::assignVariables(); - - WCF::getTPL()->assign(array( - 'languageServers' => $this->objectList->getObjects() - )); - } - - /** - * @see wcf\page\Page::show() - */ - public function show() { - // enable menu item - ACPMenu::getInstance()->setActiveMenuItem('wcf.acp.menu.link.language.server.list'); - - parent::show(); - } - - /** - * @see wcf\page\SortablePage::validateSortField() - */ - public function validateSortField() { - parent::validateSortField(); - - switch ($this->sortField) { - case 'languageServerID': - case 'serverURL': break; - default: $this->sortField = $this->defaultSortField; - } - } -} diff --git a/wcfsetup/install/files/lib/util/StringUtil.class.php b/wcfsetup/install/files/lib/util/StringUtil.class.php index f83fae4773..67961b8181 100644 --- a/wcfsetup/install/files/lib/util/StringUtil.class.php +++ b/wcfsetup/install/files/lib/util/StringUtil.class.php @@ -1,564 +1,564 @@ - - * @package com.woltlab.wcf - * @subpackage util - * @category Community Framework - */ -class StringUtil { - const HTML_PATTERN = '~] - ))*\s*/?>~ix'; - - /** - * Returns a salted hash of the given value. - * - * @param string $value - * @param string $salt - * @return string $hash - */ - public static function getSaltedHash($value, $salt) { - if (!defined('ENCRYPTION_ENABLE_SALTING') || ENCRYPTION_ENABLE_SALTING) { - $hash = ''; - // salt - if (!defined('ENCRYPTION_SALT_POSITION') || ENCRYPTION_SALT_POSITION == 'before') { - $hash .= $salt; - } - - // value - if (!defined('ENCRYPTION_ENCRYPT_BEFORE_SALTING') || ENCRYPTION_ENCRYPT_BEFORE_SALTING) { - $hash .= self::encrypt($value); - } - else { - $hash .= $value; - } - - // salt - if (defined('ENCRYPTION_SALT_POSITION') && ENCRYPTION_SALT_POSITION == 'after') { - $hash .= $salt; - } - - return self::encrypt($hash); - } - else { - return self::encrypt($value); - } - } - - /** - * Returns a double salted hash of the given value. - * - * @param string $value - * @param string $salt - * @return string $hash - */ - public static function getDoubleSaltedHash($value, $salt) { - return self::encrypt($salt . self::getSaltedHash($value, $salt)); - } - - /** - * encrypts the given value. - * - * @param string $value - * @return string $hash - */ - public static function encrypt($value) { - if (defined('ENCRYPTION_METHOD')) { - switch (ENCRYPTION_METHOD) { - case 'sha1': return sha1($value); - case 'md5': return md5($value); - case 'crc32': return crc32($value); - case 'crypt': return crypt($value); - } - } - return sha1($value); - } - - /** - * alias to php sha1() function. - * - * @param string $value - * @return string $hash - */ - public static function getHash($value) { - return sha1($value); - } - - /** - * Creates a random hash. - * - * @return string a random hash - */ - public static function getRandomID() { - return self::getHash(microtime() . uniqid(mt_rand(), true)); - } - - /** - * Converts dos to unix newlines. - * - * @param string $string - * @return string $string - */ - public static function unifyNewlines($string) { - return preg_replace("%(\r\n)|(\r)%", "\n", $string); - } - - /** - * alias to php trim() function - * - * @param string $string - * @return string $string - */ - public static function trim($text) { - return trim($text); - } - - /** - * Converts html special characters. - * - * @param string $string - * @return string $string - */ - public static function encodeHTML($string) { - if (is_object($string)) - $string = $string->__toString(); - - return @htmlspecialchars($string, ENT_COMPAT, 'UTF-8'); - } - - /** - * Decodes html entities. - * - * @param string $string - * @return string $string - */ - public static function decodeHTML($string) { - if (is_object($string)) - $string = $string->__toString(); - - $string = str_ireplace(' ', ' ', $string); // convert non-breaking spaces to ascii 32; not ascii 160 - return @html_entity_decode($string, ENT_COMPAT, 'UTF-8'); - } - - /** - * Formats a numeric. - * - * @param numeric $numeric - * @return string - */ - public static function formatNumeric($numeric) { - if (is_int($numeric)) - return self::formatInteger($numeric); - - else if (is_float($numeric)) - return self::formatDouble($numeric); - - else { - if (floatval($numeric) - (float) intval($numeric)) - return self::formatDouble($numeric); - else - return self::formatInteger(intval($numeric)); - } - } - - /** - * Formats an integer. - * - * @param integer $integer - * @return string - */ - public static function formatInteger($integer) { - $integer = self::addThousandsSeparator($integer); - - return $integer; - } - - /** - * Formats a double. - * - * @param double $double - * @param integer $minDecimals - * @return string - */ - public static function formatDouble($double, $minDecimals = 0) { - // consider as integer, if no decimal places found - if (!$minDecimals && preg_match('~^(-?\d+)(?:\.(?:0*|00[0-4]\d*))?$~', $double, $match)) { - return self::formatInteger($match[1]); - } - - // round - $double = round($double, ($minDecimals > 2 ? $minDecimals : 2)); - - // remove last 0 - if ($minDecimals < 2 && substr($double, -1) == '0') $double = substr($double, 0, -1); - - // replace decimal point - $double = str_replace('.', WCF::getLanguage()->get('wcf.global.decimalPoint'), $double); - - // add thousands separator - $double = self::addThousandsSeparator($double); - - return $double; - } - - /** - * Adds thousands separators to a given number. - * - * @param mixed $number - * @return string - */ - public static function addThousandsSeparator($number) { - if ($number >= 1000 || $number <= -1000) { - $number = preg_replace('~(?<=\d)(?=(\d{3})+(?!\d))~', WCF::getLanguage()->get('wcf.global.thousandsSeparator'), $number); - } - - return $number; - } - - /** - * Sorts an array of strings and maintain index association. - * - * @param array $strings - * @return boolean - */ - public static function sort(&$strings) { - return asort($strings, SORT_LOCALE_STRING); - } - - /** - * alias to php strlen() function. - */ - public static function length($string) { - return mb_strlen($string); - } - - /** - * alias to php strpos() function. - */ - public static function indexOf($hayStack, $needle, $offset = 0) { - return mb_strpos($hayStack, $needle, $offset); - } - - /** - * alias to php stripos() function. - */ - public static function indexOfIgnoreCase($hayStack, $needle, $offset = 0) { - return mb_strpos(self::toLowerCase($hayStack), self::toLowerCase($needle), $offset); - } - - /** - * alias to php strrpos() function. - */ - public static function lastIndexOf($hayStack, $needle) { - return mb_strrpos($hayStack, $needle); - } - - /** - * alias to php substr() function. - */ - public static function substring($string, $start, $length = null) { - if ($length !== null) return mb_substr($string, $start, $length); - return mb_substr($string, $start); - } - - /** - * alias to php strtolower() function. - */ - public static function toLowerCase($string) { - return mb_strtolower($string); - } - - /** - * alias to php strtoupper() function. - */ - public static function toUpperCase($string) { - return mb_strtoupper($string); - } - - /** - * alias to php substr_count() function. - */ - public static function countSubstring($hayStack, $needle) { - return mb_substr_count($hayStack, $needle); - } - - /** - * alias to php ucfirst() function. - */ - public static function firstCharToUpperCase($string) { - return self::toUpperCase(self::substring($string, 0, 1)).self::substring($string, 1); - } - - /** - * alias to php lcfirst() function. - */ - public static function firstCharToLowerCase($string) { - return self::toLowerCase(self::substring($string, 0, 1)).self::substring($string, 1); - } - - /** - * alias to php ucwords() function. - */ - public static function wordsToUpperCase($string) { - return mb_convert_case($string, MB_CASE_TITLE); - } - - /** - * alias to php str_replace() function. - */ - public static function replace($search, $replace, $subject, &$count = null) { - return str_replace($search, $replace, $subject, $count); - } - - /** - * alias to php str_ireplace() function. - */ - public static function replaceIgnoreCase($search, $replace, $subject, &$count = 0) { - $startPos = self::indexOf(self::toLowerCase($subject), self::toLowerCase($search)); - if ($startPos === false) return $subject; - else { - $endPos = $startPos + self::length($search); - $count++; - return self::substring($subject, 0, $startPos) . $replace . self::replaceIgnoreCase($search, $replace, self::substring($subject, $endPos), $count); - } - } - - /** - * Unescapes escaped characters in a string. - * - * @param string $string - * @param string $chars - * @return string - */ - public static function unescape($string, $chars = '"') { - for ($i = 0, $j = strlen($chars); $i < $j; $i++) { - $string = self::replace('\\'.$chars[$i], $chars[$i], $string); - } - - return $string; - } - - /** - * Takes a numeric HTML entity value and returns the appropriate UTF-8 bytes. - * - * @param integer $dec html entity value - * @return string utf-8 bytes - */ - public static function getCharacter($dec) { - if ($dec < 128) { - $utf = chr($dec); - } - else if ($dec < 2048) { - $utf = chr(192 + (($dec - ($dec % 64)) / 64)); - $utf .= chr(128 + ($dec % 64)); - } - else { - $utf = chr(224 + (($dec - ($dec % 4096)) / 4096)); - $utf .= chr(128 + ((($dec % 4096) - ($dec % 64)) / 64)); - $utf .= chr(128 + ($dec % 64)); - } - return $utf; - } - - /** - * Converts UTF-8 to Unicode - * @see http://www1.tip.nl/~t876506/utf8tbl.html - * - * @param string $c - * @return integer unicode value of $c - */ - public static function getCharValue($c) { - $ud = 0; - if (ord($c{0}) >= 0 && ord($c{0}) <= 127) - $ud = ord($c{0}); - if (ord($c{0}) >= 192 && ord($c{0}) <= 223) - $ud = (ord($c{0}) - 192) * 64 + (ord($c{1}) - 128); - if (ord($c{0}) >= 224 && ord($c{0}) <= 239) - $ud = (ord($c{0}) - 224) * 4096 + (ord($c{1}) - 128) * 64 + (ord($c{2}) - 128); - if (ord($c{0}) >= 240 && ord($c{0}) <= 247) - $ud = (ord($c{0}) - 240) * 262144 + (ord($c{1}) - 128) * 4096 + (ord($c{2}) - 128) * 64 + (ord($c{3}) - 128); - if (ord($c{0}) >= 248 && ord($c{0}) <= 251) - $ud = (ord($c{0}) - 248) * 16777216 + (ord($c{1}) - 128) * 262144 + (ord($c{2}) - 128) * 4096 + (ord($c{3}) - 128) * 64 + (ord($c{4}) - 128); - if (ord($c{0}) >= 252 && ord($c{0}) <= 253) - $ud = (ord($c{0}) - 252) * 1073741824 + (ord($c{1}) - 128) * 16777216 + (ord($c{2}) - 128) * 262144 + (ord($c{3}) - 128) * 4096 + (ord($c{4}) - 128) * 64 + (ord($c{5}) - 128); - if (ord($c{0}) >= 254 && ord($c{0}) <= 255) - $ud = false; // error - return $ud; - } - - /** - * Returns html entities of all characters in the given string. - * - * @param string $string - * @return string - */ - public static function encodeAllChars($string) { - $result = ''; - for ($i = 0, $j = StringUtil::length($string); $i < $j; $i++) { - $char = StringUtil::substring($string, $i, 1); - $result .= '&#'.StringUtil::getCharValue($char).';'; - } - - return $result; - } - - /** - * Returns true, if the given string contains only ASCII characters. - * - * @param string $string - * @return boolean - */ - public static function isASCII($string) { - return preg_match('/^[\x00-\x7F]*$/', $string); - } - - /** - * Returns true, if the given string is utf-8 encoded. - * @see http://www.w3.org/International/questions/qa-forms-utf-8 - * - * @param string $string - * @return boolean - */ - public static function isUTF8($string) { - /*return preg_match('/^( - [\x09\x0A\x0D\x20-\x7E]* # ASCII - | [\xC2-\xDF][\x80-\xBF] # non-overlong 2-byte - | \xE0[\xA0-\xBF][\x80-\xBF] # excluding overlongs - | [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2} # straight 3-byte - | \xED[\x80-\x9F][\x80-\xBF] # excluding surrogates - | \xF0[\x90-\xBF][\x80-\xBF]{2} # planes 1-3 - | [\xF1-\xF3][\x80-\xBF]{3} # planes 4-15 - | \xF4[\x80-\x8F][\x80-\xBF]{2} # plane 16 - )*$/x', $string); - */ - return preg_match('/( - [\xC2-\xDF][\x80-\xBF] # non-overlong 2-byte - | \xE0[\xA0-\xBF][\x80-\xBF] # excluding overlongs - | [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2} # straight 3-byte - | \xED[\x80-\x9F][\x80-\xBF] # excluding surrogates - | \xF0[\x90-\xBF][\x80-\xBF]{2} # planes 1-3 - | [\xF1-\xF3][\x80-\xBF]{3} # planes 4-15 - | \xF4[\x80-\x8F][\x80-\xBF]{2} # plane 16 - )/x', $string); - } - - /** - * Extracts the class name from a standardised class path. - * - * @param string $classPath - * @return string class name - */ - public static function getClassName($classPath) { - return preg_replace('~(?:.*/)?([^/]+).class.php~i', '\\1', $classPath); - } - - /** - * Escapes the closing cdata tag. - * - * @param string $string - * @return string - */ - public static function escapeCDATA($string) { - return str_replace(']]>', ']]]]>', $string); - } - - /** - * Converts a string to requested character encoding. - * @see mb_convert_encoding() - * - * @param string $inCharset - * @param string $outCharset - * @param string $string - * @return string converted string - */ - public static function convertEncoding($inCharset, $outCharset, $string) { - if ($inCharset == 'ISO-8859-1' && $outCharset == 'UTF-8') return utf8_encode($string); - if ($inCharset == 'UTF-8' && $outCharset == 'ISO-8859-1') return utf8_decode($string); - - return mb_convert_encoding($string, $outCharset, $inCharset); - } - - /** - * Strips HTML tags from a string. - * - * @param string $string - * @return string - */ - public static function stripHTML($string) { - return preg_replace(self::HTML_PATTERN, '', $string); - } - - /** - * Returns false, if the given word is forbidden by given word filter. - * - * @param string $word - * @param string $filter - * @return boolean - */ - public static function executeWordFilter($word, $filter) { - $word = self::toLowerCase($word); - - if ($filter != '') { - $forbiddenNames = explode("\n", self::toLowerCase(self::unifyNewlines($filter))); - foreach ($forbiddenNames as $forbiddenName) { - if (self::indexOf($forbiddenName, '*') !== false) { - $forbiddenName = self::replace('\*', '.*', preg_quote($forbiddenName, '/')); - if (preg_match('/^'.$forbiddenName.'$/s', $word)) { - return false; - } - } - else { - if ($word == $forbiddenName) { - return false; - } - } - } - } - - return true; - } - - /** - * Splits given string into smaller chunks. - * - * @param string $string - * @param integer $length - * @param string $break - * @return string - */ - public static function splitIntoChunks($string, $length = 75, $break = "\r\n") { - return mb_ereg_replace('.{'.$length.'}', "\\0".$break, $string); - } - - /** - * Generates a random user password with the given character length. - * - * @param integer $length - * @return string new password - */ - public static function getRandomPassword($length = 8) { - $availableCharacters = array( - 0 => 'abcdefghijklmnopqrstuvwxyz', - 1 => 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', - 2 => '0123456789', - 3 => '+#-.,;:?!' - ); - - $password = ''; - $type = 0; - for ($i = 0; $i < $length; $i++) { - $type = ($i % 4 == 0) ? 0 : ($type + 1); - $password .= substr($availableCharacters[$type], MathUtil::getRandomValue(0, strlen($availableCharacters[$type]) - 1), 1); - } - - return str_shuffle($password); - } + + * @package com.woltlab.wcf + * @subpackage util + * @category Community Framework + */ +class StringUtil { + const HTML_PATTERN = '~] + ))*\s*/?>~ix'; + + /** + * Returns a salted hash of the given value. + * + * @param string $value + * @param string $salt + * @return string $hash + */ + public static function getSaltedHash($value, $salt) { + if (!defined('ENCRYPTION_ENABLE_SALTING') || ENCRYPTION_ENABLE_SALTING) { + $hash = ''; + // salt + if (!defined('ENCRYPTION_SALT_POSITION') || ENCRYPTION_SALT_POSITION == 'before') { + $hash .= $salt; + } + + // value + if (!defined('ENCRYPTION_ENCRYPT_BEFORE_SALTING') || ENCRYPTION_ENCRYPT_BEFORE_SALTING) { + $hash .= self::encrypt($value); + } + else { + $hash .= $value; + } + + // salt + if (defined('ENCRYPTION_SALT_POSITION') && ENCRYPTION_SALT_POSITION == 'after') { + $hash .= $salt; + } + + return self::encrypt($hash); + } + else { + return self::encrypt($value); + } + } + + /** + * Returns a double salted hash of the given value. + * + * @param string $value + * @param string $salt + * @return string $hash + */ + public static function getDoubleSaltedHash($value, $salt) { + return self::encrypt($salt . self::getSaltedHash($value, $salt)); + } + + /** + * encrypts the given value. + * + * @param string $value + * @return string $hash + */ + public static function encrypt($value) { + if (defined('ENCRYPTION_METHOD')) { + switch (ENCRYPTION_METHOD) { + case 'sha1': return sha1($value); + case 'md5': return md5($value); + case 'crc32': return crc32($value); + case 'crypt': return crypt($value); + } + } + return sha1($value); + } + + /** + * alias to php sha1() function. + * + * @param string $value + * @return string $hash + */ + public static function getHash($value) { + return sha1($value); + } + + /** + * Creates a random hash. + * + * @return string a random hash + */ + public static function getRandomID() { + return self::getHash(microtime() . uniqid(mt_rand(), true)); + } + + /** + * Converts dos to unix newlines. + * + * @param string $string + * @return string $string + */ + public static function unifyNewlines($string) { + return preg_replace("%(\r\n)|(\r)%", "\n", $string); + } + + /** + * alias to php trim() function + * + * @param string $string + * @return string $string + */ + public static function trim($text) { + return trim($text); + } + + /** + * Converts html special characters. + * + * @param string $string + * @return string $string + */ + public static function encodeHTML($string) { + if (is_object($string)) + $string = $string->__toString(); + + return @htmlspecialchars($string, ENT_COMPAT, 'UTF-8'); + } + + /** + * Decodes html entities. + * + * @param string $string + * @return string $string + */ + public static function decodeHTML($string) { + if (is_object($string)) + $string = $string->__toString(); + + $string = str_ireplace(' ', ' ', $string); // convert non-breaking spaces to ascii 32; not ascii 160 + return @html_entity_decode($string, ENT_COMPAT, 'UTF-8'); + } + + /** + * Formats a numeric. + * + * @param numeric $numeric + * @return string + */ + public static function formatNumeric($numeric) { + if (is_int($numeric)) + return self::formatInteger($numeric); + + else if (is_float($numeric)) + return self::formatDouble($numeric); + + else { + if (floatval($numeric) - (float) intval($numeric)) + return self::formatDouble($numeric); + else + return self::formatInteger(intval($numeric)); + } + } + + /** + * Formats an integer. + * + * @param integer $integer + * @return string + */ + public static function formatInteger($integer) { + $integer = self::addThousandsSeparator($integer); + + return $integer; + } + + /** + * Formats a double. + * + * @param double $double + * @param integer $minDecimals + * @return string + */ + public static function formatDouble($double, $minDecimals = 0) { + // consider as integer, if no decimal places found + if (!$minDecimals && preg_match('~^(-?\d+)(?:\.(?:0*|00[0-4]\d*))?$~', $double, $match)) { + return self::formatInteger($match[1]); + } + + // round + $double = round($double, ($minDecimals > 2 ? $minDecimals : 2)); + + // remove last 0 + if ($minDecimals < 2 && substr($double, -1) == '0') $double = substr($double, 0, -1); + + // replace decimal point + $double = str_replace('.', WCF::getLanguage()->get('wcf.global.decimalPoint'), $double); + + // add thousands separator + $double = self::addThousandsSeparator($double); + + return $double; + } + + /** + * Adds thousands separators to a given number. + * + * @param mixed $number + * @return string + */ + public static function addThousandsSeparator($number) { + if ($number >= 1000 || $number <= -1000) { + $number = preg_replace('~(?<=\d)(?=(\d{3})+(?!\d))~', WCF::getLanguage()->get('wcf.global.thousandsSeparator'), $number); + } + + return $number; + } + + /** + * Sorts an array of strings and maintain index association. + * + * @param array $strings + * @return boolean + */ + public static function sort(&$strings) { + return asort($strings, SORT_LOCALE_STRING); + } + + /** + * alias to php strlen() function. + */ + public static function length($string) { + return mb_strlen($string); + } + + /** + * alias to php strpos() function. + */ + public static function indexOf($hayStack, $needle, $offset = 0) { + return mb_strpos($hayStack, $needle, $offset); + } + + /** + * alias to php stripos() function. + */ + public static function indexOfIgnoreCase($hayStack, $needle, $offset = 0) { + return mb_strpos(self::toLowerCase($hayStack), self::toLowerCase($needle), $offset); + } + + /** + * alias to php strrpos() function. + */ + public static function lastIndexOf($hayStack, $needle) { + return mb_strrpos($hayStack, $needle); + } + + /** + * alias to php substr() function. + */ + public static function substring($string, $start, $length = null) { + if ($length !== null) return mb_substr($string, $start, $length); + return mb_substr($string, $start); + } + + /** + * alias to php strtolower() function. + */ + public static function toLowerCase($string) { + return mb_strtolower($string); + } + + /** + * alias to php strtoupper() function. + */ + public static function toUpperCase($string) { + return mb_strtoupper($string); + } + + /** + * alias to php substr_count() function. + */ + public static function countSubstring($hayStack, $needle) { + return mb_substr_count($hayStack, $needle); + } + + /** + * alias to php ucfirst() function. + */ + public static function firstCharToUpperCase($string) { + return self::toUpperCase(self::substring($string, 0, 1)).self::substring($string, 1); + } + + /** + * alias to php lcfirst() function. + */ + public static function firstCharToLowerCase($string) { + return self::toLowerCase(self::substring($string, 0, 1)).self::substring($string, 1); + } + + /** + * alias to php ucwords() function. + */ + public static function wordsToUpperCase($string) { + return mb_convert_case($string, MB_CASE_TITLE); + } + + /** + * alias to php str_replace() function. + */ + public static function replace($search, $replace, $subject, &$count = null) { + return str_replace($search, $replace, $subject, $count); + } + + /** + * alias to php str_ireplace() function. + */ + public static function replaceIgnoreCase($search, $replace, $subject, &$count = 0) { + $startPos = self::indexOf(self::toLowerCase($subject), self::toLowerCase($search)); + if ($startPos === false) return $subject; + else { + $endPos = $startPos + self::length($search); + $count++; + return self::substring($subject, 0, $startPos) . $replace . self::replaceIgnoreCase($search, $replace, self::substring($subject, $endPos), $count); + } + } + + /** + * Unescapes escaped characters in a string. + * + * @param string $string + * @param string $chars + * @return string + */ + public static function unescape($string, $chars = '"') { + for ($i = 0, $j = strlen($chars); $i < $j; $i++) { + $string = self::replace('\\'.$chars[$i], $chars[$i], $string); + } + + return $string; + } + + /** + * Takes a numeric HTML entity value and returns the appropriate UTF-8 bytes. + * + * @param integer $dec html entity value + * @return string utf-8 bytes + */ + public static function getCharacter($dec) { + if ($dec < 128) { + $utf = chr($dec); + } + else if ($dec < 2048) { + $utf = chr(192 + (($dec - ($dec % 64)) / 64)); + $utf .= chr(128 + ($dec % 64)); + } + else { + $utf = chr(224 + (($dec - ($dec % 4096)) / 4096)); + $utf .= chr(128 + ((($dec % 4096) - ($dec % 64)) / 64)); + $utf .= chr(128 + ($dec % 64)); + } + return $utf; + } + + /** + * Converts UTF-8 to Unicode + * @see http://www1.tip.nl/~t876506/utf8tbl.html + * + * @param string $c + * @return integer unicode value of $c + */ + public static function getCharValue($c) { + $ud = 0; + if (ord($c{0}) >= 0 && ord($c{0}) <= 127) + $ud = ord($c{0}); + if (ord($c{0}) >= 192 && ord($c{0}) <= 223) + $ud = (ord($c{0}) - 192) * 64 + (ord($c{1}) - 128); + if (ord($c{0}) >= 224 && ord($c{0}) <= 239) + $ud = (ord($c{0}) - 224) * 4096 + (ord($c{1}) - 128) * 64 + (ord($c{2}) - 128); + if (ord($c{0}) >= 240 && ord($c{0}) <= 247) + $ud = (ord($c{0}) - 240) * 262144 + (ord($c{1}) - 128) * 4096 + (ord($c{2}) - 128) * 64 + (ord($c{3}) - 128); + if (ord($c{0}) >= 248 && ord($c{0}) <= 251) + $ud = (ord($c{0}) - 248) * 16777216 + (ord($c{1}) - 128) * 262144 + (ord($c{2}) - 128) * 4096 + (ord($c{3}) - 128) * 64 + (ord($c{4}) - 128); + if (ord($c{0}) >= 252 && ord($c{0}) <= 253) + $ud = (ord($c{0}) - 252) * 1073741824 + (ord($c{1}) - 128) * 16777216 + (ord($c{2}) - 128) * 262144 + (ord($c{3}) - 128) * 4096 + (ord($c{4}) - 128) * 64 + (ord($c{5}) - 128); + if (ord($c{0}) >= 254 && ord($c{0}) <= 255) + $ud = false; // error + return $ud; + } + + /** + * Returns html entities of all characters in the given string. + * + * @param string $string + * @return string + */ + public static function encodeAllChars($string) { + $result = ''; + for ($i = 0, $j = StringUtil::length($string); $i < $j; $i++) { + $char = StringUtil::substring($string, $i, 1); + $result .= '&#'.StringUtil::getCharValue($char).';'; + } + + return $result; + } + + /** + * Returns true, if the given string contains only ASCII characters. + * + * @param string $string + * @return boolean + */ + public static function isASCII($string) { + return preg_match('/^[\x00-\x7F]*$/', $string); + } + + /** + * Returns true, if the given string is utf-8 encoded. + * @see http://www.w3.org/International/questions/qa-forms-utf-8 + * + * @param string $string + * @return boolean + */ + public static function isUTF8($string) { + /*return preg_match('/^( + [\x09\x0A\x0D\x20-\x7E]* # ASCII + | [\xC2-\xDF][\x80-\xBF] # non-overlong 2-byte + | \xE0[\xA0-\xBF][\x80-\xBF] # excluding overlongs + | [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2} # straight 3-byte + | \xED[\x80-\x9F][\x80-\xBF] # excluding surrogates + | \xF0[\x90-\xBF][\x80-\xBF]{2} # planes 1-3 + | [\xF1-\xF3][\x80-\xBF]{3} # planes 4-15 + | \xF4[\x80-\x8F][\x80-\xBF]{2} # plane 16 + )*$/x', $string); + */ + return preg_match('/( + [\xC2-\xDF][\x80-\xBF] # non-overlong 2-byte + | \xE0[\xA0-\xBF][\x80-\xBF] # excluding overlongs + | [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2} # straight 3-byte + | \xED[\x80-\x9F][\x80-\xBF] # excluding surrogates + | \xF0[\x90-\xBF][\x80-\xBF]{2} # planes 1-3 + | [\xF1-\xF3][\x80-\xBF]{3} # planes 4-15 + | \xF4[\x80-\x8F][\x80-\xBF]{2} # plane 16 + )/x', $string); + } + + /** + * Extracts the class name from a standardised class path. + * + * @param string $classPath + * @return string class name + */ + public static function getClassName($classPath) { + return preg_replace('~(?:.*/)?([^/]+).class.php~i', '\\1', $classPath); + } + + /** + * Escapes the closing cdata tag. + * + * @param string $string + * @return string + */ + public static function escapeCDATA($string) { + return str_replace(']]>', ']]]]>', $string); + } + + /** + * Converts a string to requested character encoding. + * @see mb_convert_encoding() + * + * @param string $inCharset + * @param string $outCharset + * @param string $string + * @return string converted string + */ + public static function convertEncoding($inCharset, $outCharset, $string) { + if ($inCharset == 'ISO-8859-1' && $outCharset == 'UTF-8') return utf8_encode($string); + if ($inCharset == 'UTF-8' && $outCharset == 'ISO-8859-1') return utf8_decode($string); + + return mb_convert_encoding($string, $outCharset, $inCharset); + } + + /** + * Strips HTML tags from a string. + * + * @param string $string + * @return string + */ + public static function stripHTML($string) { + return preg_replace(self::HTML_PATTERN, '', $string); + } + + /** + * Returns false, if the given word is forbidden by given word filter. + * + * @param string $word + * @param string $filter + * @return boolean + */ + public static function executeWordFilter($word, $filter) { + $word = self::toLowerCase($word); + + if ($filter != '') { + $forbiddenNames = explode("\n", self::toLowerCase(self::unifyNewlines($filter))); + foreach ($forbiddenNames as $forbiddenName) { + if (self::indexOf($forbiddenName, '*') !== false) { + $forbiddenName = self::replace('\*', '.*', preg_quote($forbiddenName, '/')); + if (preg_match('/^'.$forbiddenName.'$/s', $word)) { + return false; + } + } + else { + if ($word == $forbiddenName) { + return false; + } + } + } + } + + return true; + } + + /** + * Splits given string into smaller chunks. + * + * @param string $string + * @param integer $length + * @param string $break + * @return string + */ + public static function splitIntoChunks($string, $length = 75, $break = "\r\n") { + return mb_ereg_replace('.{'.$length.'}', "\\0".$break, $string); + } + + /** + * Generates a random user password with the given character length. + * + * @param integer $length + * @return string new password + */ + public static function getRandomPassword($length = 8) { + $availableCharacters = array( + 0 => 'abcdefghijklmnopqrstuvwxyz', + 1 => 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', + 2 => '0123456789', + 3 => '+#-.,;:?!' + ); + + $password = ''; + $type = 0; + for ($i = 0; $i < $length; $i++) { + $type = ($i % 4 == 0) ? 0 : ($type + 1); + $password .= substr($availableCharacters[$type], MathUtil::getRandomValue(0, strlen($availableCharacters[$type]) - 1), 1); + } + + return str_shuffle($password); + } } -- 2.20.1